📄 gspi_io_cpu_new.c
字号:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/spi.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-spi.h>
#include "gspi_io.h"
gspihost_info_p G_gspiinfo;
int g_dummy_clk_reg = 0x00;
EXPORT_SYMBOL(g_dummy_clk_reg);
int g_dummy_clk_ioport = 0x00;
EXPORT_SYMBOL(g_dummy_clk_ioport);
int g_bus_mode_reg = 0x02;
EXPORT_SYMBOL(g_bus_mode_reg);
/*************************************************************************/
#define SPCON_COMMON (S3C2410_SPCON_MSTR | S3C2410_SPCON_ENSCK | \
S3C2410_SPCON_CPOL_LOW | S3C2410_SPCON_CPHA_FMTA)
#define DCON_COMMON (S3C2410_DCON_CH1_SPI | S3C2410_DCON_HANDSHAKE | S3C2410_DCON_SYNC_PCLK)
#define SPI_DMA_CHAN 1
#define MAX_DMA_SIZE 32768
#define MAX_TIMEOUT 0xff
//1----4 uS
static my_delay_us(unsigned int count)
{
int i,j;
for(i=0; i<count; i++)
for(j=0; j<400; j++)
;
}
static void spi_poll_setup(struct s3c24xx_spi *spi)
{
writeb(S3C2410_SPCON_SMOD_POLL | SPCON_COMMON, spi->regs + S3C2410_SPCON);
}
static void spi_chipsel(struct s3c24xx_spi *spi, int state)
{
//if (!spi->pdata->set_cs)
s3c2410_gpio_setpin(S3C2410_GPG2, state);
}
static struct s3c2410_dma_client spi_dma_client = {
.name = "S3C24XX SPI DMA",
};
static int spi_dma_map(struct s3c24xx_spi *spi)
{
spi->dma_addr = dma_map_single(spi->dev, spi->dma_map, spi->dma_size,
(spi->dma_src == S3C2410_DMASRC_MEM ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
if (dma_mapping_error(spi->dma_addr))
return 0;
return spi->dma_size;
}
static void spi_dma_unmap(struct s3c24xx_spi *spi)
{
dma_unmap_single(spi->dev, spi->dma_addr, spi->dma_size,
(spi->dma_src == S3C2410_DMASRC_MEM ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
}
static void spi_dma_buffdone(struct s3c2410_dma_chan *ch,
void *buf, int size,
enum s3c2410_dma_buffresult result)
{
struct s3c24xx_spi *spi = (struct s3c24xx_spi *)buf;
spi_dma_unmap(spi);
spi_poll_setup(spi);
complete(&spi->dma_done);
}
static void spi_dma_setup(struct s3c24xx_spi *spi, enum s3c2410_dmasrc dmasrc, char *data, u16 reg, int size)
{
unsigned long devaddr;
unsigned long spcon;
int i;
spcon = S3C2410_SPCON_SMOD_DMA | SPCON_COMMON;
if (dmasrc == S3C2410_DMASRC_MEM) {
spi->dma_map[0] = reg >> 8;
spi->dma_map[1] = reg & 0xff;
//printk("dma_setup:spi->dma_map[0]=0x%x\n", spi->dma_map[0]);
//printk("dma_setup:spi->dma_map[1]=0x%x\n", spi->dma_map[1]);
for (i = 0; i < size - 1; i++) {
spi->dma_map[i * 2 + 3] = *data++;
spi->dma_map[i * 2 + 2] = *data++;
//printk("dma_setup:spi->dma_map[%d]=0x%x\n", i*2+2, spi->dma_map[i * 2 + 2]);
//printk("dma_setup:spi->dma_map[%d]=0x%x\n", i*2+3, spi->dma_map[i * 2 + 3]);
}
devaddr = spi->ioarea->start + S3C2410_SPTDAT;
}
else {
spcon |= S3C2410_SPCON_TAGD;
devaddr = spi->ioarea->start + S3C2410_SPRDAT;
}
spi->dma_size = size * 2;
spi->dma_src = dmasrc;
writeb(spcon, spi->regs + S3C2410_SPCON);
spi_dma_map(spi);
s3c2410_dma_devconfig(spi->dma_chan, dmasrc, 0x03, devaddr);
s3c2410_dma_config(spi->dma_chan, 0x01, DCON_COMMON);
s3c2410_dma_set_buffdone_fn(spi->dma_chan, spi_dma_buffdone);
s3c2410_dma_setflags(spi->dma_chan, S3C2410_DMAF_AUTOSTART);
}
static int spi_dma_start(struct s3c24xx_spi *spi)
{
int ret;
ret = s3c2410_dma_enqueue(spi->dma_chan, spi, spi->dma_addr, spi->dma_size);
wait_for_completion(&spi->dma_done);
return ret;
}
static u8 spi_ready(struct s3c24xx_spi *spi)
{
unsigned int spsta = readb(spi->regs + S3C2410_SPSTA);
if (spsta & S3C2410_SPSTA_DCOL) {
dev_dbg(spi->dev, "data-collision\n");
return 0;
}
if (!(spsta & S3C2410_SPSTA_READY)) {
dev_dbg(spi->dev, "spi not ready for tx?\n");
return 0;
}
return 1;
}
static u8 spi_read8(struct s3c24xx_spi *spi)
{
writeb(S3C2410_SPCON_SMOD_POLL | S3C2410_SPCON_TAGD | SPCON_COMMON, spi->regs + S3C2410_SPCON);
while(!spi_ready(spi));
return readb(spi->regs + S3C2410_SPRDAT);
}
/*************************************************************************/
int gspi_read_data_direct(gspi_card_rec_p cardp, u8 * data, u16 reg, u16 n)
{
struct s3c24xx_spi *spi = cardp->ctrlr;
int dummy_clk = g_dummy_clk_reg;
char dummy[2];
int i;
// unsigned char iodata[20];
disable_irq(spi->irq);
spi_chipsel(spi, 0);
//printk("read:\n");
//-------------
//printk("start write address!\n");
//spi_dma_setup(spi, S3C2410_DMASRC_MEM, NULL, reg, 1);
//spi_dma_start(spi);
//------------write address start
{
int i;
spi->dma_map[0] = reg >> 8;
spi->dma_map[1] = reg & 0xff;
/*
for(i=0; i < (1 * 2); i++) {
printk("when wiriting---iodata[%d]=0x%x\n", i,iodata[i]);
}
*/
}
wmb();
{
int i;
for (i = 0; i < 2; i++) {
writeb(spi->dma_map[i], spi->regs + S3C2410_SPTDAT);
my_delay_us(2);
//printk("spi_SPSR=0x%x\n", readb(spi_base+REG_SPSR));
//while(!(readb(spi_base+REG_SPSR) & 0x04)); //wait until empty
}
}
//--------------write address end
udelay(10);
//dummy[0] = spi_read8(spi);
//dummy[1] = spi_read8(spi);
//printk("1:read:dummy[0]=0x%x, dummy[1]=0x%x\n", dummy[0], dummy[1]);
//---------------------------------------------------------------------
writeb(S3C2410_SPCON_SMOD_POLL | SPCON_COMMON | (0<<0), spi->regs+S3C2410_SPCON);
{ int i;
int count = ((n - 1) * 2);
for (i = 0; i < count; i++) {
writeb(0x55, spi->regs+S3C2410_SPTDAT);
while(!spi_ready(spi));
//my_delay_us(2);
spi->dma_map[i] = readb(spi->regs+S3C2410_SPRDAT);
//printk("read data:iodata[%d]=0x%2x\n", i, iodata[i]);
//dummy[0] = spi_read8(spi);
//printk("read data:0x%x\n", dummy[0]);
}
}
//-----------------------------------------------------------------------
/*
dummy[0] = spi_read8(spi);
dummy[1] = spi_read8(spi);
printk("2:read:dummy[0]=0x%x, dummy[1]=0x%x\n", dummy[0], dummy[1]);
*/
/*
spi_dma_setup(spi, S3C2410_DMASRC_HW, NULL, reg, n + dummy_clk - 1);
spi_dma_start(spi);
if(spi_ready(spi))
readb(spi->regs + S3C2410_SPRDAT);
else
printk("%s >> no last byte with dma be received!\n", __FUNCTION__);
*/
spi_chipsel(spi, 1);
enable_irq(spi->irq);
for (i = 0; i < (n + dummy_clk - 1); i++) {
unsigned short *p_data;
p_data = (unsigned short *)data;
*data++ = spi->dma_map[(dummy_clk + i) * 2 + 1];
*data++ = spi->dma_map[(dummy_clk + i) * 2];
//printk("read data:spi->dma_map[%d]=0x%x\n", (dummy_clk + i) * 2, spi->dma_map[(dummy_clk + i) * 2]);
//printk("read data:spi->dma_map[%d]=0x%x\n", (dummy_clk + i) * 2 + 1, spi->dma_map[(dummy_clk + i) * 2 + 1]);
//printk("read data:0x%x\n", *p_data);
}
spi_chipsel(spi, 1);
return 0;
}
EXPORT_SYMBOL(gspi_read_data_direct);
int gspi_write_data_direct(gspi_card_rec_p cardp, u8 * data, u16 reg, u16 n)
{
struct s3c24xx_spi *spi = cardp->ctrlr;
//unsigned char iodata[200];
reg |= 0x8000;
disable_irq(spi->irq);
spi_chipsel(spi, 0);
//printk("write:\n");
/*
spi_dma_setup(spi, S3C2410_DMASRC_MEM, data, reg, n);
spi_dma_start(spi);
*/
reg |= 0x8000;
{
int i;
spi->dma_map[0] = reg >> 8;
spi->dma_map[1] = reg & 0xff;
for (i = 0; i < (n - 1); i++) {
spi->dma_map[i * 2 + 3] = *data++;
spi->dma_map[i * 2 + 2] = *data++;
}
/*
for(i=0; i < (n * 2); i++) {
printk("when wiriting---iodata[%d]=0x%x\n", i,iodata[i]);
}
*/
}
wmb();
{
int i;
n = n * 2;
for (i = 0; i < n; i++) {
writeb(spi->dma_map[i], spi->regs + S3C2410_SPTDAT);
my_delay_us(2);
//printk("spi_SPSR=0x%x\n", readb(spi_base+REG_SPSR));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -