⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gspi_io_cpu_new.c

📁 linux 基于mips 架构cpu 的红外驱动
💻 C
📖 第 1 页 / 共 2 页
字号:

#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 + -