📄 gspi_io.c
字号:
#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 + -