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

📄 dm355_spi_master.c

📁 TI的达芬奇系列dm355使用的spi模块驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
                                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 + -