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

📄 gspi_io.c

📁 marvell wifi driver GSPI-8385-LINUX-OMAP1510-5.0.10.p0-144-src.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/errno.h>

#include <asm/system.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/dma.h>

#include "gspi_io.h"
#include "gspi_debug.h"

#define __GSPI_IO_CORE__

static struct gspihost_info     *g_gspiinfo;
static int                      major = 240;
/* Use default clock rate of 20 Mhz for GSPI. So, clkdiv as 0 */
static int			clkdiv = 0; 
int				g_dummy_clk_reg = 0;
int				g_dummy_clk_ioport = 0;
int				g_bus_mode_reg = 0x02;

#ifdef OMAP1510_TIMER_DEBUG
unsigned long times[10][10];
int tm_ind[10]={0,0,0,0,0,0,0,0,0,0};
#endif

static __inline__ void gpio_dir_output(u8 gpio_num)
{
        u16 gpio_reg;

        ENTER();

        gpio_reg = inw(GPIO_DIR_CONTROL_REG);
        outw(gpio_reg & ~(gpio_num), GPIO_DIR_CONTROL_REG);

        LEAVE();
}

static __inline__ void gpio_set_high(u8 gpio_num)
{
        u16 gpio_reg;

        ENTER();

        gpio_reg = inw(GPIO_DATA_OUTPUT_REG);
        outw(gpio_reg | gpio_num, GPIO_DATA_OUTPUT_REG);
        gpio_reg = inw(GPIO_DATA_OUTPUT_REG);

        LEAVE();
}

static __inline__ void gpio_set_low(u8 gpio_num)
{
        u16 gpio_reg;

        ENTER();

        gpio_reg = inw(GPIO_DATA_OUTPUT_REG);
        outw(gpio_reg & ~(gpio_num), GPIO_DATA_OUTPUT_REG);
        gpio_reg = inw(GPIO_DATA_OUTPUT_REG);

        LEAVE();
}

static __inline__ void dma_callback_tx(void* data)
{
	struct gspihost_info* gspiinfo;

	gspiinfo = (struct gspihost_info*) data;

	ENTER();

	spin_lock(&gspiinfo->lock);

	del_timer(&gspiinfo->dmatimer);
	gspiinfo -> d . dma_txack = 1;
	wake_up_interruptible(&(gspiinfo -> d . queue_tx));

	spin_unlock(&gspiinfo->lock);

	LEAVE();
}

static __inline__ void dma_callback_rx(void* data)
{
	struct gspihost_info* gspiinfo;

	gspiinfo = (struct gspihost_info*) data;

	ENTER();

	spin_lock(&gspiinfo->lock);

	del_timer(&gspiinfo->dmatimer);
	gspiinfo -> d . dma_rxack = 1;
	wake_up_interruptible(&(gspiinfo -> d . queue_rx));

	spin_unlock(&gspiinfo->lock);

	LEAVE();
}

int dma_init(struct gspihost_info* gspiinfo)
{
	ENTER();

	if(omap_request_dma(eModemDataTx,"McBSP2 SPI Tx", dma_callback_tx, 
				gspiinfo, &(gspiinfo -> d . dma_regs_tx)) < 0) {
		PRINTK("Error in omap_request_dma\n"); 
		return -1;
	}

	gspiinfo -> d . dma_regs_tx -> csdp 	= CSDP_DST_TIPB | CSDP_DATA_TYPE_16;
	gspiinfo -> d . dma_regs_tx -> ccr 	= CCR_SRC_POST_INCREMENTAL_ADDR | CCR_AUTO_INIT | MCBSP2_DEVID_TX; 	
	gspiinfo -> d . dma_regs_tx -> cicr 	= CICR_BLOCK_IE | CICR_DROP_IE | CICR_TOUT_IE;
	gspiinfo -> d . dma_regs_tx -> cdsa_l 	= ((OMAP1510_MCBSP2_BASE + 0x006) & 0xffff);
	gspiinfo -> d . dma_regs_tx -> cdsa_u 	= ((OMAP1510_MCBSP2_BASE + 0x006) >> 16);
	gspiinfo -> d . dma_regs_tx -> cfn 	= 0x0001;

	if(omap_dma_setup(eModemDataTx, eDmaOut) < 0) {
		PRINTK("omap_dma_setup failed\n");
		return -1;
	}

	if(omap_request_dma(eModemDataRx, "McBSP2 SPI Rx", dma_callback_rx, 
				gspiinfo, &(gspiinfo -> d . dma_regs_rx)) < 0) {
		PRINTK("Error in omap_request_dma\n"); 
		return -1;
	}

	gspiinfo -> d . dma_regs_rx -> csdp 	= CSDP_SRC_TIPB | CSDP_DATA_TYPE_16;
	gspiinfo -> d . dma_regs_rx -> ccr 	= CCR_DST_POST_INCREMENTAL_ADDR | CCR_AUTO_INIT | MCBSP2_DEVID_RX;
	gspiinfo -> d . dma_regs_rx -> cicr 	= CICR_BLOCK_IE | CICR_DROP_IE | CICR_TOUT_IE;
	gspiinfo -> d . dma_regs_rx -> cssa_l 	= ((OMAP1510_MCBSP2_BASE + 0x002) & 0xffff);
	gspiinfo -> d . dma_regs_rx -> cssa_u 	= ((OMAP1510_MCBSP2_BASE + 0x002) >> 16);
	gspiinfo -> d . dma_regs_rx -> cfn 	= 0x0001;

	if(omap_dma_setup(eModemDataRx, eDmaIn) < 0) {
		PRINTK("omap_dma_setup failed\n");
		return -1;
	}

	gspiinfo -> d . dmabuf_tx = consistent_alloc(GFP_KERNEL | GFP_DMA, 
			BUFSIZE, &(gspiinfo -> d . dmaphys_tx));
	if(!gspiinfo -> d . dmabuf_tx) {
		PRINTK("Cannot allocate DMA for tx\n");
		return -1;
	}

	gspiinfo -> d . dmabuf_tx_rx = consistent_alloc(GFP_KERNEL | GFP_DMA, 
			BUFSIZE, &(gspiinfo -> d . dmaphys_tx_rx));
	if(!gspiinfo -> d . dmabuf_tx_rx) {
		PRINTK("Cannot allocate DMA for tx\n");
		return -1;
	}

	memset(gspiinfo -> d . dmabuf_tx_rx, 0xff, BUFSIZE);

	gspiinfo -> d . dmabuf_rx = consistent_alloc(GFP_KERNEL | GFP_DMA,
			BUFSIZE, &(gspiinfo -> d . dmaphys_rx));
	if(!gspiinfo -> d . dmabuf_rx) {
		PRINTK("Cannot allocate DMA for rx\n");
		return -1;
	}

	LEAVE();

	return 0;
}

static int gspihost_init_hw(struct gspihost_info* gspiinfo)
{
	ENTER();

        outw(FSXM | FSRM | CLKXM | CLKRM | FSXP | FSRP, MCBSP2_PCR0);
        outw(XWDLEN1(0x02), MCBSP2_XCR1);
        outw(XDATDLY(0x01), MCBSP2_XCR2);
        outw(XWDLEN1(0x02), MCBSP2_RCR1);
        outw(XDATDLY(0x01), MCBSP2_RCR2);
	outw(CLKSTP(0x03) | RINTM(0x03), MCBSP2_SPCR1);
        outw(XINTM(0x03), MCBSP2_SPCR2);

	printk("GSPI clock is %dMHz\n", 20/(clkdiv+1));
	outw(clkdiv, MCBSP2_SRGR1);
	
	gpio_dir_output(GPIO(0));
	gpio_set_high(GPIO(0));

	if(dma_init(gspiinfo) < 0)
		return -1;

	LEAVE();

	return 0;
}

int reinitialize_hw(gspihost_info_p gspiinfo)
{
        outw(FSXM | FSRM | CLKXM | CLKRM | FSXP | FSRP, MCBSP2_PCR0);
        outw(XWDLEN1(0x02), MCBSP2_XCR1);
        outw(XDATDLY(0x01), MCBSP2_XCR2);
        outw(XWDLEN1(0x02), MCBSP2_RCR1);
        outw(XDATDLY(0x01), MCBSP2_RCR2);
	outw(CLKSTP(0x03) | RINTM(0x03), MCBSP2_SPCR1);
        outw(XINTM(0x03), MCBSP2_SPCR2);
	outw(0, MCBSP2_SRGR1);

	return 0;
}

static void gspihost_close_hw(struct gspihost_info* gspiinfo)
{
	ENTER1();


	LEAVE1();
}

static void gspihost_timeout(unsigned long d)
{
	struct gspihost_info* gspiinfo = (struct gspihost_info*)d;

	ENTER();

	PRINTK("### GSPIHost Timeout Happened ###\n");

	spin_lock_irq(&gspiinfo->lock);

	complete(&gspiinfo->complete);
	++gspiinfo->d.error;

	spin_unlock(&gspiinfo->lock);

	LEAVE();
}

static void gspihost_dma_timeout(unsigned long d)
{
	struct gspihost_info* gspiinfo = (struct gspihost_info*)d;

	ENTER();

	PRINTK("### GSPIHost DMA Timeout Happened ###\n");

	spin_lock_irq(&gspiinfo->lock);

	complete(&gspiinfo->dmacomplete);
	++gspiinfo->d.error;

	spin_unlock(&gspiinfo->lock);

	LEAVE();
}

static int gspihost_open(struct inode* inode, struct file* filp)
{
	ENTER1();

	MOD_INC_USE_COUNT;

	filp->private_data = NULL;

	LEAVE1();

	return 0;
}

static int gspihost_release(struct inode* inode, struct file* filp)
{
	ENTER1();

	MOD_DEC_USE_COUNT;

	filp->private_data = NULL;

	LEAVE1();

	return 0;
}

static int gspihost_ioctl(struct inode* inode, struct file* filp,
			unsigned int cmd, unsigned long arg)
{
	ENTER1();

	LEAVE1();

	return -ENOIOCTLCMD;
}

static struct file_operations gspihost_fops = {
	owner:		THIS_MODULE,
	open:		gspihost_open,
	ioctl:		gspihost_ioctl,
	release:	gspihost_release,
};

static inline int gspi_acquire_io(gspihost_info_p gspiinfop)
{
	int	ret;

	ENTER1();

	if (!gspiinfop) {
		ret = -EINVAL;
		goto error;
  	}
  	
	down(&gspiinfop->host_sem);
	
	GSPI_DEBUG("Acquired Semaphore@ %lu\n", jiffies);

	ret = GSPI_OK;

error:	LEAVE1();
	return ret;
}

static inline void gspi_release_io(gspihost_info_p gspiinfop)
{
	ENTER1();
  	
	if (!gspiinfop) {
    		goto error;
  	}

	up(&gspiinfop->host_sem);

	GSPI_DEBUG("Released Semaphore@ %lu\n", jiffies);

error:	LEAVE1();
	return;
}

int gspi_read_reg(gspi_card_rec_p cardp, u16 reg, u16 *data)
{
  	int 			ret;
	u16 			read_data[2];

	ENTER1();

	read_data[0] = reg;

	if((ret = gspi_read_data(cardp, read_data, 2) != GSPI_OK)) {
		GSPI_DEBUG1("gspi_read_data failed\n");
		goto error;
	} 

	*data = read_data[1];
	ret = 0;

error:	LEAVE1();
	return ret;
}

int gspi_write_reg(gspi_card_rec_p cardp, u16 reg, u16 data)
{
  	int 		ret;
	u16 		write_data[2];

	ENTER1();

	write_data[0] = reg;
	write_data[1] = data;

	if((ret = gspi_write_data(cardp, write_data, 2)) != GSPI_OK) {
		GSPI_DEBUG1("gspi_write_data failed\n");
		goto error;
	}

	ret = 0;
error:
	LEAVE1();
	return ret;
}

void gspi_write_for_read(gspihost_info_p gspiinfop, u16 data, int now)
{
	gspiinfop -> d . dmabuf_tx_rx[0] = data;
	gspiinfop -> d . dmabuf_tx_rx[1] = data >> 8;

	omap_start_dma(gspiinfop -> d . dma_regs_tx, 
			gspiinfop -> d . dmaphys_tx_rx, now * 2);	

	wait_event_interruptible(gspiinfop -> d . queue_tx, gspiinfop -> d . dma_txack);
	gspiinfop -> d.dma_txack = 0;
}

void mcbsp_set_transmitter(void)
{
	outw(FRST | GRST | XINTM(0x11) | XRST, MCBSP2_SPCR2);
}

void mcbsp_reset_transmitter(void)
{
	outw(XINTM(0x11), MCBSP2_SPCR2);
}

void mcbsp_set_receiver(void)
{
	outw(CLKSTP(0x03) | RINTM(0x11) | RRST, MCBSP2_SPCR1);
} 

void mcbsp_reset_receiver(void)
{
	outw(CLKSTP(0x03) | RINTM(0x11), MCBSP2_SPCR1);
}

int gspi_read_data_direct(gspi_card_rec_p cardp, 
			u8 *data, u16 reg, u16 size)
{
	int    		ret;
	gspihost_info_p	gspiinfop;

	ENTER();

	if(!cardp) {
		ret = -EINVAL;
		goto error;
	}

	gspiinfop = cardp->ctrlr;

	if((ret = gspi_acquire_io(gspiinfop)) != GSPI_OK){
		GSPI_DEBUG("gspi_acquire_io failed\n");
		goto error;
	}

#ifdef OMAP1510_TIMER_DEBUG
	if(tm_ind[3] + 1 < 10)
		times[3][(tm_ind[3])++] = inw(0xFFFEC500 + 0x08);
#endif

	gpio_set_low(GPIO(0));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -