📄 gspi_io.c
字号:
mcbsp_set_transmitter();
mcbsp_set_receiver();
omap_start_dma(gspiinfop -> d . dma_regs_rx, gspiinfop -> d . dmaphys_rx,
(size + g_dummy_clk_ioport) * 2);
gspi_write_for_read(gspiinfop, reg, size + g_dummy_clk_ioport);
wait_event_interruptible(gspiinfop -> d . queue_rx,
gspiinfop -> d . dma_rxack);
gspiinfop -> d.dma_rxack = 0;
gpio_set_high(GPIO(0));
mcbsp_reset_receiver();
mcbsp_reset_transmitter();
memcpy(data,gspiinfop -> d . dmabuf_rx + (g_dummy_clk_ioport + 1) * 2,
size * 2);
#ifdef OMAP1510_TIMER_DEBUG
if(tm_ind[4] + 1 < 10)
times[4][(tm_ind[4])++] = inw(0xFFFEC500 + 0x08);
#endif
gspi_release_io(gspiinfop);
ret = 0;
error: LEAVE();
return ret;
}
int gspi_read_data(gspi_card_rec_p cardp,
u16 *data, 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;
}
gpio_set_low(GPIO(0));
mcbsp_set_transmitter();
mcbsp_set_receiver();
omap_start_dma(gspiinfop -> d . dma_regs_rx, gspiinfop -> d . dmaphys_rx,
(size + g_dummy_clk_reg) * 2);
gspi_write_for_read(gspiinfop, data[0], size + g_dummy_clk_reg);
wait_event_interruptible(gspiinfop -> d . queue_rx, gspiinfop -> d . dma_rxack);
gspiinfop -> d.dma_rxack = 0;
gpio_set_high(GPIO(0));
mcbsp_reset_receiver();
mcbsp_reset_transmitter();
memcpy(data, gspiinfop -> d . dmabuf_rx + (g_dummy_clk_reg * 2), size * 2);
gspi_release_io(gspiinfop);
ret = 0;
error: LEAVE();
return ret;
}
int gspi_write_data(gspi_card_rec_p cardp,
u16 *data, 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;
}
gpio_set_low(GPIO(0));
mcbsp_set_transmitter();
data[0] |= GSPI_WRITE;
memcpy(gspiinfop -> d . dmabuf_tx, data, size * 2);
omap_start_dma(gspiinfop -> d . dma_regs_tx, gspiinfop -> d . dmaphys_tx, size * 2);
wait_event_interruptible(gspiinfop -> d . queue_tx, gspiinfop -> d . dma_txack);
gspiinfop -> d.dma_txack = 0;
gpio_set_high(GPIO(0));
mcbsp_reset_transmitter();
gspi_release_io(gspiinfop);
ret = 0;
error: LEAVE();
return ret;
}
int gspi_write_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[1] + 1 < 10)
times[1][(tm_ind[1])++] = inw(0xFFFEC500 + 0x08);
#endif
mcbsp_set_transmitter();
gpio_set_low(GPIO(0));
reg |= GSPI_WRITE;
memcpy(gspiinfop -> d . dmabuf_tx, ®, 2);
memcpy(gspiinfop -> d . dmabuf_tx + 2, data, (size-1) * 2);
omap_start_dma(gspiinfop -> d . dma_regs_tx, gspiinfop -> d . dmaphys_tx, size * 2);
wait_event_interruptible(gspiinfop -> d . queue_tx, gspiinfop -> d . dma_txack);
gspiinfop -> d.dma_txack = 0;
mcbsp_reset_transmitter();
gpio_set_high(GPIO(0));
#ifdef OMAP1510_TIMER_DEBUG
if(tm_ind[2] + 1 < 10)
times[2][(tm_ind[2])++] = inw(0xFFFEC500 + 0x08);
#endif
gspi_release_io(gspiinfop);
ret = 0;
error: LEAVE();
return ret;
}
static __inline__ void gspihost_exit(struct gspihost_info *gspiinfo)
{
ENTER1();
del_timer(&gspiinfo->timer);
gspihost_close_hw(gspiinfo);
unregister_chrdev(major, "gspihost");
omap_free_dma(gspiinfo -> d . dma_regs_tx);
omap_free_dma(gspiinfo -> d . dma_regs_rx);
if(gspiinfo -> d . dmabuf_tx)
consistent_free(gspiinfo -> d . dmabuf_tx, BUFSIZE, gspiinfo -> d . dmaphys_tx);
if(gspiinfo -> d . dmabuf_tx_rx)
consistent_free(gspiinfo -> d . dmabuf_tx_rx, BUFSIZE, gspiinfo -> d . dmaphys_tx_rx);
if(gspiinfo -> d . dmabuf_rx)
consistent_free(gspiinfo -> d . dmabuf_rx, BUFSIZE, gspiinfo -> d . dmaphys_rx);
if (gspiinfo->card)
kfree(gspiinfo->card);
if (gspiinfo)
kfree(gspiinfo);
LEAVE1();
}
static struct gspihost_info *gspihost_init(void)
{
struct gspihost_info *gspiinfo;
ENTER();
if ((gspiinfo = kmalloc(sizeof(gspihost_info_t), GFP_KERNEL)) == NULL) {
GSPI_DEBUG("No memory for gspiinfo!!!\n");
return NULL;
}
memset(gspiinfo, 0, sizeof *gspiinfo);
gspihost_init_hw(gspiinfo);
init_timer(&gspiinfo->timer);
init_timer(&gspiinfo->dmatimer);
init_MUTEX(&gspiinfo->host_sem);
gspiinfo -> d.dma_txack = 0;
gspiinfo -> d.dma_rxack = 0;
gspiinfo -> timer.function = gspihost_timeout;
gspiinfo -> timer.data = (unsigned long)gspiinfo;
gspiinfo -> dmatimer.function = gspihost_dma_timeout;
gspiinfo -> dmatimer.data = (unsigned long)gspiinfo;
LEAVE();
return gspiinfo;
}
gspi_notifier_rec_p register_user(gspi_notifier_rec_p notifierp)
{
gspi_notifier_rec_p ret;
struct gspihost_info *gspiinfo = g_gspiinfo;
gspi_card_rec_p cardp = gspiinfo->card;
ENTER();
if (!notifierp) {
ret = NULL;
goto done;
}
if (!notifierp->add || !notifierp->remove || !notifierp->user_isr) {
ret = NULL;
goto done;
}
cardp->add = notifierp->add;
cardp->remove = notifierp->remove;
cardp->user_isr = notifierp->user_isr;
if (notifierp->add(cardp)) {
ret = NULL;
goto done;
}
ret = notifierp;
done:
LEAVE();
return ret;
}
void unregister_user(gspi_notifier_rec_p notifierp)
{
struct gspihost_info *gspiinfo = g_gspiinfo;
gspi_card_rec_p cardp = gspiinfo->card;
if (notifierp->add == cardp->add) {
cardp->remove(cardp);
cardp->add =
cardp->remove = NULL;
cardp->user_isr = NULL;
cardp->user_arg = NULL;
}
}
int gspi_init_card(gspi_card_rec_p cardp)
{
ENTER();
/* Take the card out of reset */
gpio_dir_output(GPIO(2));
gpio_set_high(GPIO(2));
LEAVE();
return 0;
}
static void *register_card(gspi_card_rec_p cardp)
{
void *ret;
ENTER1();
if (gspi_init_card(cardp))
ret = NULL;
else
ret = cardp;
LEAVE1();
return ret;
}
void gspi_reset(void)
{
gpio_set_low(GPIO(2));
udelay(10);
gpio_set_high(GPIO(2));
}
void enable_int_gpio(int gpio_num)
{
int gpio_reg;
gpio_reg = inw(GPIO_INT_MASK_REG);
outw(gpio_reg & ~(gpio_num) , GPIO_INT_MASK_REG);
}
void disable_int_gpio(int gpio_num)
{
int gpio_reg;
gpio_reg = inw(GPIO_INT_MASK_REG);
outw(gpio_reg | gpio_num , GPIO_INT_MASK_REG);
}
int gspi_register_irq(gspihost_info_p gspiinfo)
{
gspi_card_rec_p cardp = gspiinfo -> card;
gspiinfo -> irq = INT_GPIO1;
if(request_irq(gspiinfo->irq, cardp->user_isr, 0, "GPIO-IRQ", cardp->user_arg) < 0) {
printk("gpio_irq failed \n");
return -1;
}
enable_int_gpio(GPIO(1));
schedule_timeout(3*HZ);
return 0;
}
void gspi_unregister_irq(gspihost_info_p gspihost)
{
gspi_card_rec_p cardp = gspihost -> card;
disable_int_gpio(GPIO(1));
free_irq(gspihost -> irq, cardp -> user_arg);
}
void omap1510_timertest(void)
{
unsigned long times1[10];
int i=0, j;
outl(0x22, OMAP1510_TIMER1_BASE + CNTL_TIMER);
outl(0xFFFFFFFF, OMAP1510_TIMER1_BASE + LOAD_TIM);
outl(0x23, OMAP1510_TIMER1_BASE + CNTL_TIMER);
times1[i++] = inl(OMAP1510_TIMER1_BASE + READ_TIM);
udelay(1000);
times1[i++] = inl(OMAP1510_TIMER1_BASE + READ_TIM);
mdelay(10);
times1[i++] = inl(OMAP1510_TIMER1_BASE + READ_TIM);
outl(0x2A, OMAP1510_TIMER1_BASE + CNTL_TIMER);
times1[i++] = inl(OMAP1510_TIMER1_BASE + READ_TIM);
for(j=0;j < i-1; ++j)
printk("The diff b/w %d and %d is %lu\n", j, j+1, times1[j]-times1[j+1]);
}
static int __init gspihost_module_init(void)
{
int ret = -ENODEV;
struct gspihost_info *gspiinfo;
gspi_card_rec_p cardp;
ENTER();
if(!(gspiinfo = gspihost_init())) {
GSPI_DEBUG("gspihost_init failed\n");
goto out;
}
g_gspiinfo = gspiinfo;
if(!(cardp = kmalloc(sizeof(io_card_rec_t), GFP_KERNEL))) {
GSPI_DEBUG("No memory for Card Record!!!\n");
ret = -ENOMEM;
goto out;
}
if (register_chrdev(major, "gspihost", &gspihost_fops) < 0) {
GSPI_DEBUG1("register_chrdev failed\n");
goto err_free;
}
memset(cardp, 0, sizeof(io_card_rec_t));
memcpy(cardp->magic, "GSPI", 4);
init_waitqueue_head(&gspiinfo -> d . queue_tx);
init_waitqueue_head(&gspiinfo -> d . queue_rx);
cardp->ctrlr = gspiinfo;
gspiinfo->card = cardp;
if (!register_card(cardp)) {
GSPI_DEBUG("gspihost_register failed\n");
goto err_free;
}
ret = 0;
goto out;
err_free:
kfree(cardp);
gspiinfo->card = NULL;
out:
LEAVE();
return ret;
}
static void __exit gspihost_module_exit(void)
{
ENTER();
gspihost_exit(g_gspiinfo);
printk("GSPI Host Controller Driver for Linux removed.\n");
LEAVE();
}
module_init(gspihost_module_init);
module_exit(gspihost_module_exit);
MODULE_LICENSE("Proprietary");
MODULE_PARM(clkdiv, "i");
MODULE_PARM_DESC(clkdiv, "Will specify SPI bus CLKDIV(Clock divisor) value."
"Usage insmod gspi.o clkdiv=0 / 1 / 2...(20 Mhz, 10 Mhz, 5 Mhz ..) ");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -