diff options
author | Alison Wang <b18965@freescale.com> | 2012-09-12 15:13:01 +0800 |
---|---|---|
committer | Andy Voltz <andy.voltz@timesys.com> | 2012-10-17 14:37:23 -0400 |
commit | ba9f7d89d3872246f61af0f867fbe7bdadb289ad (patch) | |
tree | f49fbf543173b2e5a0f25919f06304cd38f72374 /drivers | |
parent | 684e7945da98ee5c820542b578278bd4632b6888 (diff) |
ENGR00180953-2: dspi: update dspi driver support for Vybrid
Update dspi driver support for Vybrid after debugging on board.
Signed-off-by: Jason Jin <jason.jin@freescale.com>
Alison Wang <b18965@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/spi/spi_mvf_dspi.c | 150 |
2 files changed, 61 insertions, 91 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 161b6596ff4b..78e8e1d53a68 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -203,7 +203,7 @@ config SPI_MVF config SPI_MVF_DSPI_EDMA boolean "Faraday DSPI driver uses eDMA" - depends on ARCH_MVF && SPI_MVF && MCF_EDMA + depends on ARCH_MVF && SPI_MVF && MVF_EDMA default n help Say "yes" if you want DSPI driver to use eDMA dor transfers. diff --git a/drivers/spi/spi_mvf_dspi.c b/drivers/spi/spi_mvf_dspi.c index ae0f228a39fd..21dc672975be 100644 --- a/drivers/spi/spi_mvf_dspi.c +++ b/drivers/spi/spi_mvf_dspi.c @@ -30,6 +30,7 @@ #include <linux/workqueue.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/clk.h> #include <linux/dma-mapping.h> #include <linux/time.h> #include <mach/spi-mvf.h> @@ -48,7 +49,7 @@ #define TRAN_STATE_TX_VOID 0x02 #define TRAN_STATE_WORD_ODD_NUM 0x04 -#define DSPI_FIFO_SIZE 16 +#define DSPI_FIFO_SIZE 4 #if defined(CONFIG_SPI_MVF_DSPI_EDMA) #define SPI_DSPI_EDMA @@ -58,39 +59,39 @@ #endif struct DSPI_MCR { - unsigned master:1; - unsigned cont_scke:1; - unsigned dconf:2; - unsigned frz:1; - unsigned mtfe:1; - unsigned pcsse:1; - unsigned rooe:1; - unsigned pcsis:8; - unsigned reserved15:1; - unsigned mdis:1; - unsigned dis_tx:1; - unsigned dis_rxf:1; - unsigned clr_tx:1; - unsigned clr_rxf:1; - unsigned smpl_pt:2; - unsigned reserved71:7; unsigned halt:1; + unsigned reserved71:7; + unsigned smpl_pt:2; + unsigned clr_rxf:1; + unsigned clr_tx:1; + unsigned dis_rxf:1; + unsigned dis_tx:1; + unsigned mdis:1; + unsigned reserved15:1; + unsigned pcsis:8; + unsigned rooe:1; + unsigned pcsse:1; + unsigned mtfe:1; + unsigned frz:1; + unsigned dconf:2; + unsigned cont_scke:1; + unsigned master:1; }; struct DSPI_CTAR { - unsigned dbr:1; - unsigned fmsz:4; - unsigned cpol:1; - unsigned cpha:1; - unsigned lsbfe:1; - unsigned pcssck:2; - unsigned pasc:2; - unsigned pdt:2; - unsigned pbr:2; - unsigned cssck:4; - unsigned asc:4; - unsigned dt:4; unsigned br:4; + unsigned dt:4; + unsigned asc:4; + unsigned cssck:4; + unsigned pbr:2; + unsigned pdt:2; + unsigned pasc:2; + unsigned pcssck:2; + unsigned lsbfe:1; + unsigned cpha:1; + unsigned cpol:1; + unsigned fmsz:4; + unsigned dbr:1; }; struct chip_data { @@ -116,6 +117,7 @@ struct spi_mvf_data { void *base; int irq; + struct clk *clk; /* Driver message queue */ struct workqueue_struct *workqueue; @@ -220,7 +222,7 @@ static unsigned char hz_to_spi_baud(int pbr, int dbr, int speed_hz) return 15; /* cpu core clk need to check */ - temp = ((((452000000 / 2) / pbr_tbl[pbr]) * (1 + dbr)) / speed_hz); + temp = ((((66000000 / 2) / pbr_tbl[pbr]) * (1 + dbr)) / speed_hz); while (temp > brs[index]) if (index++ >= 15) @@ -303,12 +305,11 @@ static int write(struct spi_mvf_data *spi_mvf) #endif tx_count++; } - #if defined(SPI_DSPI_EDMA) if (tx_count > 0) { mcf_edma_set_tcd_params(spi_mvf->tx_chan, - virt_to_phys((void *)spi_mvf->edma_tx_buf), - (u32)(spi_mvf->base + SPI_PUSHR), + spi_mvf->edma_tx_buf_pa, + 0x4002c034, MCF_EDMA_TCD_ATTR_SSIZE_32BIT | MCF_EDMA_TCD_ATTR_DSIZE_32BIT, 4, /* soff */ @@ -318,13 +319,13 @@ static int write(struct spi_mvf_data *spi_mvf) 1, /* biter */ 0, /* doff */ 0, /* dlastsga */ - 0, /* major_int */ - 1, /* disable_req */ + 1, /* major_int */ + 0, /* disable_req */ 0); /* enable sg */ mcf_edma_set_tcd_params(spi_mvf->rx_chan, - (u32)(spi_mvf->base + SPI_POPR), - virt_to_phys((void *)spi_mvf->edma_rx_buf), + 0x4002c038, + spi_mvf->edma_rx_buf_pa, MCF_EDMA_TCD_ATTR_SSIZE_32BIT | MCF_EDMA_TCD_ATTR_DSIZE_32BIT, 0, /* soff */ @@ -334,8 +335,8 @@ static int write(struct spi_mvf_data *spi_mvf) 1, /* biter */ 4, /* doff */ 0, /* dlastsga */ - 0, /* major_int */ - 1, /* disable_req */ + 1, /* major_int */ + 0, /* disable_req */ 0); /* enable sg */ mcf_edma_start_transfer(spi_mvf->tx_chan); @@ -407,7 +408,7 @@ static irqreturn_t edma_tx_handler(int channel, void *dev) { struct spi_mvf_data *spi_mvf = dspi_drv_data; - if (channel == DSPI_DMA_TX_TCD) + if (channel == spi_mvf->tx_chan) mcf_edma_stop_transfer(spi_mvf->tx_chan); return IRQ_HANDLED; } @@ -415,61 +416,12 @@ static irqreturn_t edma_tx_handler(int channel, void *dev) static irqreturn_t edma_rx_handler(int channel, void *dev) { struct spi_mvf_data *spi_mvf = dspi_drv_data; - int rx_count = 0; - int rx_word = is_word_transfer(spi_mvf); - u16 d; - u32 *rx_edma = (u32 *) spi_mvf->edma_rx_buf; - struct spi_message *msg = spi_mvf->cur_msg; - if (channel == DSPI_DMA_RX_TCD) { + if (channel == spi_mvf->rx_chan) { mcf_edma_stop_transfer(spi_mvf->tx_chan); mcf_edma_stop_transfer(spi_mvf->rx_chan); } - if (!(spi_mvf->flags & TRAN_STATE_RX_VOID)) { - while ((spi_mvf->rx < spi_mvf->rx_end) - && (rx_count < DSPI_FIFO_SIZE)) { - if (rx_word) { - if ((spi_mvf->rx_end - spi_mvf->rx) == 1) - break; - d = SPI_POPR_RXDATA(*rx_edma); - rx_edma++; - *(u16 *)spi_mvf->rx = d; - spi_mvf->rx += 2; - - } else { - d = SPI_POPR_RXDATA(*rx_edma); - rx_edma++; - *(u8 *)spi_mvf->rx = d; - spi_mvf->rx++; - } - rx_count++; - } - } else { /* rx void by upper */ - if ((spi_mvf->rx_end - spi_mvf->rx) > DSPI_FIFO_SIZE) - spi_mvf->rx += DSPI_FIFO_SIZE; - else - spi_mvf->rx = spi_mvf->rx_end - - (spi_mvf->tx_end - spi_mvf->tx); - } - if (spi_mvf->rx == spi_mvf->rx_end) { - /* - * * Finished now - fall through and schedule next - * * transfer tasklet - * */ - if (spi_mvf->flags & TRAN_STATE_WORD_ODD_NUM) - set_16bit_transfer_mode(spi_mvf); - - msg->state = next_transfer(spi_mvf); - } else { - /* not finished yet - keep going */ - msg->actual_length += write(spi_mvf); - - return IRQ_HANDLED; - } - - tasklet_schedule(&spi_mvf->pump_transfers); - return IRQ_HANDLED; } #endif @@ -949,6 +901,13 @@ static int spi_mvf_probe(struct platform_device *pdev) goto out_error_irq_alloc; } + spi_mvf->clk = clk_get(&pdev->dev, "dspi_clk"); + if (IS_ERR(spi_mvf->clk)) { + dev_err(&pdev->dev, "unable to get clock\n"); + goto out_error_irq_alloc; + } + clk_enable(spi_mvf->clk); + #if defined(SPI_DSPI_EDMA) spi_mvf->edma_tx_buf = dma_alloc_coherent(NULL, EDMA_BUFSIZE_KMALLOC, &spi_mvf->edma_tx_buf_pa, GFP_DMA); @@ -1023,9 +982,13 @@ out_error_master_alloc: static int spi_mvf_remove(struct platform_device *pdev) { struct spi_mvf_data *spi_mvf = platform_get_drvdata(pdev); + struct resource *res; int irq; int ret = 0; + clk_disable(spi_mvf->clk); + clk_put(spi_mvf->clk); + if (!spi_mvf) return 0; @@ -1044,8 +1007,15 @@ static int spi_mvf_remove(struct platform_device *pdev) if (irq >= 0) free_irq(irq, spi_mvf); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + release_mem_region(res->start, resource_size(res)); + iounmap(spi_mvf->base); + /* Disconnect from the SPI framework */ spi_unregister_master(spi_mvf->master); + spi_master_put(spi_mvf->master); /* Prevent double remove */ platform_set_drvdata(pdev, NULL); |