📄 dm355_spi_master.c
字号:
while ( (flg_val=dm355_spi->base->SPIBUF) & ( 0x80000000 ) ); tx_data = dm355_spi->base->SPIBUF; if ( (i > dm355_spi->count) || (i == 3 && flag == 1)) break; } } } else { DEBUG_SPI("In receive\n"); #ifdef CONFIG_SPI_INTERRUPT spi_cfg->op_mode = 1; #else spi_cfg->op_mode = 0; #endif if (!spi_cfg->op_mode) { /*In Polling mode receive */ i = 0; while (1) { flg_val = dm355_spi->base->SPIFLG; buf_val = dm355_spi->base->SPIBUF; DEBUG_SPI ("flg_val = 0x%8x & buf_val = 0x%8x\n", flg_val, buf_val); if ((buf_val & 0x20000000) == 0) { if ( ++i <= dm355_spi->count ) dm355_spi->base->SPIDAT1 = data1_reg_val; else dm355_spi->base->SPIDAT1 = ( data1_reg_val & 0x0ffcffff); while ( (buf_val = dm355_spi->base->SPIBUF) & 0x80000000 ); rx_data = dm355_spi->base->SPIBUF; dm355_spi->get_rx(rx_data, dm355_spi); DEBUG_SPI ("I have got it... RCD = 0x%x after %d iteration buf_val = 0x%8x\nflg_val = 0x%8x\n", rx_data, i, buf_val, flg_val); if ( i > dm355_spi->count ) break; } } } else { /*Receive in Interrupt mode */ for ( i = 0; i<= dm355_spi->count; i++) { if ( i == dm355_spi->count ) dm355_spi->base->SPIDAT1 = ( data1_reg_val & 0x0ffcffff); else { dm355_spi->base->SPIINT |= SPI_SPIFLG_BITERRFLG_MASK | SPI_SPIFLG_OVRNINTFLG_MASK | SPI_SPIFLG_RXINTFLAG_MASK; dm355_spi->base->SPIDAT1 = ( data1_reg_val ); while ( (flg_val = dm355_spi->base->SPIINT) & SPI_SPIFLG_RXINTFLAG_MASK ); } } } } /* Check for bit error, desync error,parity error,timeout error and receive overflow errors */ intStatus = dm355_spi->base->SPIFLG; if ((intStatus & SPI_SPIINT_TIMEOUT_INTR) == SPI_SPIINT_TIMEOUT_INTR) { printk("SPI Time-out Error\n"); return SPI_TIMEOUT_ERR; } /* De-Synchronization error, holds only in master mode */ else if ((intStatus & SPI_SPIINT_DESYNC_INTR) == SPI_SPIINT_DESYNC_INTR) { printk("SPI Desynchronization Error\n"); return SPI_DESYNC_ERR; } /* Bit error error */ else if ((intStatus & SPI_SPIINT_BITERR_INTR) == SPI_SPIINT_BITERR_INTR) { printk("SPI Bit error\n"); return SPI_BIT_ERR; /**/} /* SPI Framework maintains the count only in bytes so convert back to bytes */ dm355_spi->count *= conv; EXIT return t->len;}/** * dm355_spi_irq - probe function for SPI Master Controller * @irq: IRQ number for this SPI Master * @context_data: structure for SPI Master controller dm355_spi * @ptregs: * * ISR will determine that interrupt arrives either for READ or WRITE command. * According to command it will do the appropriate action. It will check * transfer length and if it is not zero then dispatch transfer command again. * If transfer length is zero then it will indicate the COMPLETION so that * dm355_spi_bufs function can go ahead. */irqreturn_t dm355_spi_irq(s32 irq, void *context_data, struct pt_regs * ptregs){ struct dm355_spi *dm355_spi = context_data; volatile u32 intStatus = 0; u32 rx_data = 0; DEBUG_SPI("IN_IRQ\n"); intStatus = dm355_spi->base->SPIFLG; DEBUG_SPI("received interrupt = 0x%8x\n", intStatus); while (intStatus != 0) { /*Time out Error */ if ((intStatus & SPI_SPIINT_TIMEOUT_INTR) == SPI_SPIINT_TIMEOUT_INTR) { printk("SPI Time-out Error\n"); return SPI_TIMEOUT_ERR; } /* De-Synchronization interrupt, holds only in master mode */ else if ((intStatus & SPI_SPIINT_DESYNC_INTR) == SPI_SPIINT_DESYNC_INTR) { printk("SPI Desynchronization Error\n"); return SPI_DESYNC_ERR; } /* Bit error Interrupt */ else if ((intStatus & SPI_SPIINT_BITERR_INTR) == SPI_SPIINT_BITERR_INTR) { printk("SPI Bit error\n"); return SPI_BIT_ERR; /**/} /*Receive Interrupt */ else if (intStatus & SPI_SPIINT_RX_INTR) { rx_data = dm355_spi->base->SPIBUF; dm355_spi->get_rx(rx_data, dm355_spi); DEBUG_SPI("IRQ rx_data = 0x16%x\n", rx_data); /*Disable Receive Interrupt */ dm355_spi->base->SPIINT = ~SPI_SPIINT_RX_INTR; return IRQ_HANDLED; } } return -1;}/** * dm355_spi_probe - probe function for SPI Master Controller * @dev: platform_device structure which contains plateform specific data * * According to Linux Deviced Model this function will be invoked by Linux * with plateform_device struct which contains the device specific info * like bus_num, max_chipselect (how many slave devices can be connected), * clock freq. of SPI controller, SPI controller's memory range, IRQ number etc. * * According to Linux Deviced Model this function will be invoked by Linux * with plateform_device struct which contains the device specific info * like bus_num, max_chipselect (how many slave devices can be connected), * clock freq. of SPI controller, SPI controller's memory range, IRQ number etc. * This info will be provided by board specific code which will reside in * linux-2.6.10/arch/mips/mips-boards/dm355_dm355/dm355_yamuna code. * This function will map the SPI controller's memory, register IRQ, * Reset SPI controller and setting its registers to default value. * It will invoke spi_bitbang_start to create work queue so that client driver * can register transfer method to work queue. */static int dm355_spi_probe(struct device *d){ struct platform_device *dev = container_of(d, struct platform_device, dev); struct spi_master *master; struct dm355_spi *dm355_spi; struct dm355_spi_platform_data *pdata; struct resource *r; int i = 0, ret = 0, prescale = 0, clk_freq = 0;; /* Get resources(memory, IRQ) associated with the device */ master = spi_alloc_master(&dev->dev, sizeof(struct dm355_spi)); if (master == NULL) { ret = -ENOMEM; goto err; } dev_set_drvdata(&(dev)->dev, (master)); pdata = dev->dev.platform_data; if (pdata == NULL) { ret = -ENODEV; goto free_master; } r = platform_get_resource(dev, IORESOURCE_MEM, 0); if (r == NULL) { ret = -ENODEV; goto free_master; } dm355_spi = spi_master_get_devdata(master); dm355_spi->bitbang.master = spi_master_get(master); dm355_spi->bitbang.chipselect = dm355_spi_chipselect; dm355_spi->bitbang.setup_transfer = dm355_spi_setup_transfer; dm355_spi->bitbang.txrx_bufs = dm355_spi_bufs; dm355_spi->sysclk = pdata->sysclk; dm355_spi->activate_cs = pdata->activate_cs; dm355_spi->deactivate_cs = pdata->deactivate_cs; dm355_spi->get_rx = dm355_spi_rx_buf_u8; dm355_spi->get_tx = dm355_spi_tx_buf_u8; dm355_spi->bitbang.master->setup = dm355_spi_setup; init_completion(&dm355_spi->done); ENTER dm355_spi->base = (struct dm355_spi_reg __iomem *) ioremap(r->start, (r->end - r->start)); if (dm355_spi->base == NULL) { ret = -ENOMEM; goto put_master; } dm355_spi->irq = platform_get_irq(dev, 0); if (dm355_spi->irq < 0) { ret = -ENXIO; goto unmap_io; } /* Register for SPI Interrupt */ ret = request_irq(dm355_spi->irq, dm355_spi_irq, SA_INTERRUPT, "dm_spi", dm355_spi); if (ret != 0) { DEBUG_SPI("request_irq fails\n"); goto unmap_io; } master->bus_num = pdata->bus_num; master->num_chipselect = pdata->max_chipselect; /* SPI controller initializations */ //SP0_MUX_SEL_LINE; //mdelay(500); clk_freq = 216000000 / 2; prescale = (clk_freq / SPI_BUS_FREQ) + 1; /*Reset In/OUT SPI modle */ (dm355_spi->base->SPIGCR0) = 0x0; udelay(100); (dm355_spi->base->SPIGCR0) = 0x1; for (i = 0; i < 4; i++) { dm355_spi->base->SPIFMT[i] &= 0xFFFF00FF; /* clear the old value */ dm355_spi->base->SPIFMT[i] |= (prescale << 8); /* clear the old value */ } ret = dm355_spi_bitbang_start(&dm355_spi->bitbang); if (ret != 0) goto free_irq; printk(KERN_INFO "%s: dm355 SPI Controller driver at 0x%p (irq = %d)\n", dev->dev.bus_id, dm355_spi->base, dm355_spi->irq); EXIT return ret; free_irq: free_irq(dm355_spi->irq, dm355_spi); unmap_io: iounmap(dm355_spi->base); put_master: spi_master_put(master); free_master: kfree(master); err: return ret;}/** * dm355_spi_remove - remove function for SPI Master Controller * @dev: platform_device structure which contains plateform specific data * * This function will do the reverse action of dm355_spi_probe function * It will free the IRQ and SPI controller's memory region. * It will also call spi_bitbang_stop to destroy the work queue which was * created by spi_bitbang_start. */static int __devexit dm355_spi_remove(struct device *d){ struct platform_device *dev = container_of(d, struct platform_device, dev); struct dm355_spi *dm355_spi; struct spi_master *master; master = dev_get_drvdata(&(dev)->dev); dm355_spi = spi_master_get_devdata(master); dm355_spi_bitbang_stop(&dm355_spi->bitbang); free_irq(dm355_spi->irq, dm355_spi); iounmap(dm355_spi->base); spi_master_put(dm355_spi->bitbang.master); return 0;}static struct device_driver dm355_spi_driver = { .name = "dm_spi", .bus = &platform_bus_type, .probe = dm355_spi_probe, .remove = __devexit_p(dm355_spi_remove),};static int __init dm355_spi_init(void){ return driver_register(&dm355_spi_driver);}static void __exit dm355_spi_exit(void){ driver_unregister(&dm355_spi_driver);}module_init(dm355_spi_init);module_exit(dm355_spi_exit);MODULE_AUTHOR("Dhruval Shah & Varun Shah");MODULE_DESCRIPTION("DM355 SPI Master Controller Driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -