X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fspi%2Frk29_spim.c;h=e8a02cbe28a79574fe702ce736ecdddc9698e790;hb=6f1b688f7971145091170b96f6eb4990dad7d5c9;hp=e940e37550eccfe0b24db55a5fdfc4f689d246f6;hpb=8629f700ae19767f404f7704fe0915c333d55412;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/spi/rk29_spim.c b/drivers/spi/rk29_spim.c index e940e37550ec..e8a02cbe28a7 100755 --- a/drivers/spi/rk29_spim.c +++ b/drivers/spi/rk29_spim.c @@ -21,9 +21,10 @@ #include #include #include +#include #include #include - +#include #include "rk29_spim.h" #include #include @@ -39,14 +40,15 @@ QUICK_TRANSFER */ //#define QUICK_TRANSFER - #if 0 #define DBG printk +//#define PRINT_TRANS_DATA #else #define DBG(x...) #endif -#define DMA_MIN_BYTES 8 +#define DMA_BUFFER_SIZE PAGE_SIZE +#define DMA_MIN_BYTES 32 //>32x16bits FIFO #define START_STATE ((void *)0) @@ -67,10 +69,11 @@ struct chip_data { u8 cs; /* chip select pin */ u8 n_bytes; /* current is a 1/2/4 byte op */ u8 tmode; /* TR/TO/RO/EEPROM */ + u8 mode; /* ??? */ u8 type; /* SPI/SSP/MicroWire */ u8 poll_mode; /* 1 means use poll mode */ - + u8 slave_enable; u32 dma_width; u32 rx_threshold; u32 tx_threshold; @@ -88,6 +91,58 @@ struct chip_data { #define RXBUSY (1<<2) #define TXBUSY (1<<3) +// +#ifdef CONFIG_LCD_USE_SPIM_CONTROL +void rk29_lcd_spim_spin_lock(void) +{ +#ifdef CONFIG_LCD_USE_SPI0 + disable_irq(IRQ_SPI0); +#endif + +#ifdef CONFIG_LCD_USE_SPI1 + disable_irq(IRQ_SPI1); +#endif + + preempt_disable(); +} + +void rk29_lcd_spim_spin_unlock(void) +{ + preempt_enable(); + +#ifdef CONFIG_LCD_USE_SPI0 + enable_irq(IRQ_SPI0); +#endif + +#ifdef CONFIG_LCD_USE_SPI1 + enable_irq(IRQ_SPI1); +#endif +} +#else +void rk29_lcd_spim_spin_lock(void) +{ + return; +} + +void rk29_lcd_spim_spin_unlock(void) +{ + return; +} +#endif + +#if defined(PRINT_TRANS_DATA) +static void printk_transfer_data(unsigned char *buf, int len) +{ + int i = 0; + for(i=0; icur_chip) { + if(dws->cur_chip->slave_enable == 1) + return; + } + while (time_before(jiffies, end)) { if (!(rk29xx_readw(dws, SPIM_SR) & SR_BUSY)) return; @@ -251,6 +315,8 @@ static void spi_cs_control(struct rk29xx_spi *dws, u32 cs, u8 flag) rk29xx_writel(dws, SPIM_SER, 0); return; #else + + #error "Warning: not support" struct rk29xx_spi_platform_data *pdata = dws->master->dev.platform_data; struct spi_cs_gpio *cs_gpios = pdata->chipselect_gpios; @@ -292,8 +358,10 @@ static int null_reader(struct rk29xx_spi *dws) static int u8_writer(struct rk29xx_spi *dws) { - spi_dump_regs(dws); + //spi_dump_regs(dws) +#if defined(PRINT_TRANS_DATA) DBG("tx: 0x%02x\n", *(u8 *)(dws->tx)); +#endif if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL) || (dws->tx == dws->tx_end)) return 0; @@ -306,11 +374,13 @@ static int u8_writer(struct rk29xx_spi *dws) static int u8_reader(struct rk29xx_spi *dws) { - spi_dump_regs(dws); + //spi_dump_regs(dws); while (!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT) && (dws->rx < dws->rx_end)) { *(u8 *)(dws->rx) = rk29xx_readw(dws, SPIM_RXDR) & 0xFFU; +#if defined(PRINT_TRANS_DATA) DBG("rx: 0x%02x\n", *(u8 *)(dws->rx)); +#endif ++dws->rx; } @@ -319,7 +389,10 @@ static int u8_reader(struct rk29xx_spi *dws) } static int u16_writer(struct rk29xx_spi *dws) -{ +{ +#if defined(PRINT_TRANS_DATA) + DBG("tx: 0x%04x\n", *(u16 *)(dws->tx)); +#endif if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL) || (dws->tx == dws->tx_end)) return 0; @@ -339,7 +412,9 @@ static int u16_reader(struct rk29xx_spi *dws) && (dws->rx < dws->rx_end)) { temp = rk29xx_readw(dws, SPIM_RXDR); *(u16 *)(dws->rx) = temp; - //DBG("rx: 0x%04x\n", *(u16 *)(dws->rx)); +#if defined(PRINT_TRANS_DATA) + DBG("rx: 0x%04x\n", *(u16 *)(dws->rx)); +#endif dws->rx += 2; } @@ -369,18 +444,37 @@ static void rk29_spi_dma_rxcb(void *buf_id, struct rk29xx_spi *dws = buf_id; unsigned long flags; + DBG("func: %s, line: %d\n", __FUNCTION__, __LINE__); + spin_lock_irqsave(&dws->lock, flags); if (res == RK29_RES_OK) dws->state &= ~RXBUSY; else - dev_err(&dws->master->dev, "DmaAbrtRx-%d, size: %d\n", res, size); + dev_err(&dws->master->dev, "error:DmaAbrtRx-%d, size: %d,res=%d\n", res, size,res); + //copy data from dma to transfer buf + if(dws->cur_transfer && (dws->cur_transfer->rx_buf != NULL)) + { + memcpy(dws->cur_transfer->rx_buf, dws->buffer_rx_dma, dws->cur_transfer->len); + + #if defined(PRINT_TRANS_DATA) + printk("dma rx:"); + printk_transfer_data(dws->cur_transfer->rx_buf, dws->cur_transfer->len); + #endif + } + + spin_unlock_irqrestore(&dws->lock, flags); + /* If the other done */ if (!(dws->state & TXBUSY)) - complete(&dws->xfer_completion); + { + //complete(&dws->xfer_completion); + DBG("func: %s, line: %d,dma transfer complete\n", __FUNCTION__, __LINE__); + //DMA could not lose intterupt + transfer_complete(dws); + } - spin_unlock_irqrestore(&dws->lock, flags); } static void rk29_spi_dma_txcb(void *buf_id, @@ -390,19 +484,26 @@ static void rk29_spi_dma_txcb(void *buf_id, unsigned long flags; DBG("func: %s, line: %d\n", __FUNCTION__, __LINE__); - + spin_lock_irqsave(&dws->lock, flags); if (res == RK29_RES_OK) dws->state &= ~TXBUSY; else - dev_err(&dws->master->dev, "DmaAbrtTx-%d, size: %d \n", res, size); + dev_err(&dws->master->dev, "error:DmaAbrtTx-%d, size: %d,res=%d \n", res, size,res); + spin_unlock_irqrestore(&dws->lock, flags); + /* If the other done */ if (!(dws->state & RXBUSY)) - complete(&dws->xfer_completion); + { + //complete(&dws->xfer_completion); + + DBG("func: %s, line: %d,dma transfer complete\n", __FUNCTION__, __LINE__); + //DMA could not lose intterupt + transfer_complete(dws); + } - spin_unlock_irqrestore(&dws->lock, flags); } @@ -416,6 +517,20 @@ static int acquire_dma(struct rk29xx_spi *dws) return 0; } + dws->buffer_tx_dma = dma_alloc_coherent(&dws->pdev->dev, DMA_BUFFER_SIZE, &dws->tx_dma, GFP_KERNEL | GFP_DMA); + if (!dws->buffer_tx_dma) + { + dev_err(&dws->pdev->dev, "fail to dma tx buffer alloc\n"); + return -1; + } + + dws->buffer_rx_dma = dma_alloc_coherent(&dws->pdev->dev, DMA_BUFFER_SIZE, &dws->rx_dma, GFP_KERNEL | GFP_DMA); + if (!dws->buffer_rx_dma) + { + dev_err(&dws->pdev->dev, "fail to dma rx buffer alloc\n"); + return -1; + } + if(rk29_dma_request(dws->rx_dmach, &rk29_spi_dma_client, NULL) < 0) { dev_err(&dws->master->dev, "dws->rx_dmach : %d, cannot get RxDMA\n", dws->rx_dmach); @@ -428,32 +543,8 @@ static int acquire_dma(struct rk29xx_spi *dws) rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client); return -1; } - - dws->dma_inited = 1; - return 0; -} - -static void release_dma(struct rk29xx_spi *dws) -{ - if(!dws && dws->dma_inited) { - rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client); - rk29_dma_free(dws->tx_dmach, &rk29_spi_dma_client); - } -} - -/* - * Note: first step is the protocol driver prepares - * a dma-capable memory, and this func just need translate - * the virt addr to physical - */ -static int map_dma_buffers(struct rk29xx_spi *dws) -{ - if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited - || !dws->cur_chip->enable_dma) - return -1; - if (dws->cur_transfer->tx_dma) { - dws->tx_dma = dws->cur_transfer->tx_dma; + if (dws->tx_dma) { if (rk29_dma_set_buffdone_fn(dws->tx_dmach, rk29_spi_dma_txcb)) { dev_err(&dws->master->dev, "rk29_dma_set_buffdone_fn fail\n"); return -1; @@ -465,8 +556,7 @@ static int map_dma_buffers(struct rk29xx_spi *dws) } } - if (dws->cur_transfer->rx_dma) { - dws->rx_dma = dws->cur_transfer->rx_dma; + if (dws->rx_dma) { if (rk29_dma_set_buffdone_fn(dws->rx_dmach, rk29_spi_dma_rxcb)) { dev_err(&dws->master->dev, "rk29_dma_set_buffdone_fn fail\n"); return -1; @@ -477,7 +567,40 @@ static int map_dma_buffers(struct rk29xx_spi *dws) return -1; } } + + dws->dma_inited = 1; + return 0; +} + +static void release_dma(struct rk29xx_spi *dws) +{ + if(!dws && dws->dma_inited) { + rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client); + rk29_dma_free(dws->tx_dmach, &rk29_spi_dma_client); + } +} + +/* + * Note: first step is the protocol driver prepares + * a dma-capable memory, and this func just need translate + * the virt addr to physical + */ +static int map_dma_buffers(struct rk29xx_spi *dws) +{ + if (!dws->dma_inited || !dws->cur_chip->enable_dma) + { + printk("%s:error\n",__func__); + return -1; + } + if(dws->cur_transfer->tx_buf) + { + memcpy(dws->buffer_tx_dma,dws->cur_transfer->tx_buf,dws->cur_transfer->len); + } + + dws->cur_transfer->tx_dma = dws->tx_dma; + dws->cur_transfer->rx_dma = dws->rx_dma; + return 0; } @@ -495,6 +618,12 @@ static void giveback(struct rk29xx_spi *dws) dws->prev_chip = dws->cur_chip; dws->cur_chip = NULL; dws->dma_mapped = 0; + + + /*it is important to close intterrupt*/ + spi_mask_intr(dws, 0xff); + rk29xx_writew(dws, SPIM_DMACR, 0); + queue_work(dws->workqueue, &dws->pump_messages); spin_unlock_irqrestore(&dws->lock, flags); @@ -508,6 +637,9 @@ static void giveback(struct rk29xx_spi *dws) msg->state = NULL; if (msg->complete) msg->complete(msg->context); + + DBG("%s ok\n",__func__); + } static void int_error_stop(struct rk29xx_spi *dws, const char *msg) @@ -542,12 +674,13 @@ static irqreturn_t interrupt_transfer(struct rk29xx_spi *dws) u16 irq_status, irq_mask = 0x1f; u32 int_level = dws->fifo_len / 2; u32 left; - + irq_status = rk29xx_readw(dws, SPIM_ISR) & irq_mask; /* Error handling */ if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { rk29xx_writew(dws, SPIM_ICR, SPI_CLEAR_INT_TXOI | SPI_CLEAR_INT_RXOI | SPI_CLEAR_INT_RXUI); int_error_stop(dws, "interrupt_transfer: fifo overrun"); + mutex_unlock(&dws->dma_lock); return IRQ_HANDLED; } @@ -588,7 +721,8 @@ static irqreturn_t interrupt_transfer(struct rk29xx_spi *dws) else { transfer_complete(dws); } - } + + } return IRQ_HANDLED; } @@ -609,6 +743,9 @@ static irqreturn_t rk29xx_spi_irq(int irq, void *dev_id) /* Must be called inside pump_transfers() */ static void poll_transfer(struct rk29xx_spi *dws) { +#if defined(PRINT_TRANS_DATA) + DBG("%s\n",__func__); +#endif while (dws->write(dws)) { wait_till_not_busy(dws); dws->read(dws); @@ -644,7 +781,12 @@ static void pump_transfers(unsigned long data) u32 speed = 0; u32 cr0 = 0; - DBG(KERN_INFO "pump_transfers\n"); + if((dws->cur_chip->enable_dma) && (dws->cur_transfer->len > DMA_MIN_BYTES) && (dws->cur_transfer->len < DMA_BUFFER_SIZE)){ + dma_transfer(dws); + return; + } + + DBG(KERN_INFO "pump_transfers,len=%d\n",dws->cur_transfer->len); /* Get current state information */ message = dws->cur_msg; @@ -677,11 +819,11 @@ static void pump_transfers(unsigned long data) dws->dma_width = chip->dma_width; dws->cs_control = chip->cs_control; - dws->rx_dma = transfer->rx_dma; - dws->tx_dma = transfer->tx_dma; + //dws->rx_dma = transfer->rx_dma; + //dws->tx_dma = transfer->tx_dma; dws->tx = (void *)transfer->tx_buf; dws->tx_end = dws->tx + transfer->len; - dws->rx = transfer->rx_buf; + dws->rx = (void *)transfer->rx_buf; dws->rx_end = dws->rx + transfer->len; dws->write = dws->tx ? chip->write : null_writer; dws->read = dws->rx ? chip->read : null_reader; @@ -699,7 +841,7 @@ static void pump_transfers(unsigned long data) if (transfer->speed_hz != speed) { speed = transfer->speed_hz; if (speed > clk_get_rate(dws->clock_spim)) { - dev_err(&dws->master->dev, "MRST SPI0: unsupported" + dev_err(&dws->master->dev, "MRST SPI0: unsupported " "freq: %dHz\n", speed); message->status = -EIO; goto early_exit; @@ -764,15 +906,19 @@ static void pump_transfers(unsigned long data) else chip->tmode = SPI_TMOD_TO; - cr0 &= ~(0x3 << SPI_MODE_OFFSET); + cr0 &= ~(0x3 << SPI_MODE_OFFSET); + cr0 &= ~(0x3 << SPI_TMOD_OFFSET); + cr0 &= ~(0x1 << SPI_OPMOD_OFFSET); + cr0 |= (spi->mode << SPI_MODE_OFFSET); cr0 |= (chip->tmode << SPI_TMOD_OFFSET); + cr0 |= ((chip->slave_enable & 1) << SPI_OPMOD_OFFSET); } /* * Interrupt mode * we only need set the TXEI IRQ, as TX/RX always happen syncronizely */ - if (!dws->dma_mapped && !chip->poll_mode) { + if (!dws->dma_mapped && !chip->poll_mode) { int templen ; if (chip->tmode == SPI_TMOD_RO) { @@ -796,19 +942,20 @@ static void pump_transfers(unsigned long data) * 2. clk_div is changed * 3. control value changes */ - if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0 || cs_change || clk_div || imask) { + if ((rk29xx_readl(dws, SPIM_CTRLR0) != cr0) || cs_change || clk_div || imask) { spi_enable_chip(dws, 0); - if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0) - rk29xx_writew(dws, SPIM_CTRLR0, cr0); + if (rk29xx_readl(dws, SPIM_CTRLR0) != cr0) + rk29xx_writel(dws, SPIM_CTRLR0, cr0); spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); spi_chip_sel(dws, spi->chip_select); rk29xx_writew(dws, SPIM_CTRLR1, dws->len-1); - spi_enable_chip(dws, 1); - + if (txint_level) rk29xx_writew(dws, SPIM_TXFTLR, txint_level); + spi_enable_chip(dws, 1); + if (rxint_level) rk29xx_writew(dws, SPIM_RXFTLR, rxint_level); /* Set the interrupt mask, for poll mode just diable all int */ @@ -830,17 +977,18 @@ early_exit: return; } -static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) +static void dma_transfer(struct rk29xx_spi *dws) { struct spi_message *message = NULL; struct spi_transfer *transfer = NULL; struct spi_transfer *previous = NULL; struct spi_device *spi = NULL; struct chip_data *chip = NULL; - unsigned long val; - int ms; + //unsigned long val; + //unsigned long flags; + //int ms; int iRet; - int burst; + //int burst; u8 bits = 0; u8 spi_dfs = 0; u8 cs_change = 0; @@ -848,9 +996,9 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) u32 speed = 0; u32 cr0 = 0; u32 dmacr = 0; - - DBG(KERN_INFO "dma_transfer\n"); - + + DBG(KERN_INFO "dma_transfer,len=%d\n",dws->cur_transfer->len); + if (acquire_dma(dws)) { dev_err(&dws->master->dev, "acquire dma failed\n"); goto err_out; @@ -892,11 +1040,11 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) dws->dma_width = chip->dma_width; dws->cs_control = chip->cs_control; - dws->rx_dma = transfer->rx_dma; - dws->tx_dma = transfer->tx_dma; + //dws->rx_dma = transfer->rx_dma; + //dws->tx_dma = transfer->tx_dma; dws->tx = (void *)transfer->tx_buf; dws->tx_end = dws->tx + transfer->len; - dws->rx = transfer->rx_buf; + dws->rx = (void *)transfer->rx_buf; dws->rx_end = dws->rx + transfer->len; dws->write = dws->tx ? chip->write : null_writer; dws->read = dws->rx ? chip->read : null_reader; @@ -906,15 +1054,14 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) cs_change = 1; cr0 = chip->cr0; - + /* Handle per transfer options for bpw and speed */ if (transfer->speed_hz) { speed = chip->speed_hz; - if (transfer->speed_hz != speed) { speed = transfer->speed_hz; if (speed > clk_get_rate(dws->clock_spim)) { - dev_err(&dws->master->dev, "MRST SPI0: unsupported" + dev_err(&dws->master->dev, "MRST SPI0: unsupported " "freq: %dHz\n", speed); message->status = -EIO; goto err_out; @@ -929,6 +1076,7 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) } } + if (transfer->bits_per_word) { bits = transfer->bits_per_word; @@ -972,7 +1120,11 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) chip->tmode = SPI_TMOD_TO; cr0 &= ~(0x3 << SPI_MODE_OFFSET); + cr0 &= ~(0x3 << SPI_TMOD_OFFSET); + cr0 &= ~(0x1 << SPI_OPMOD_OFFSET); + cr0 |= (spi->mode << SPI_MODE_OFFSET); cr0 |= (chip->tmode << SPI_TMOD_OFFSET); + cr0 |= ((chip->slave_enable & 1) << SPI_OPMOD_OFFSET); } /* @@ -981,12 +1133,11 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) * 2. clk_div is changed * 3. control value changes */ - if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0 || cs_change || clk_div) { + if ((rk29xx_readl(dws, SPIM_CTRLR0) != cr0) || cs_change || clk_div) { spi_enable_chip(dws, 0); - if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0) { - rk29xx_writew(dws, SPIM_CTRLR0, cr0); + if (rk29xx_readl(dws, SPIM_CTRLR0) != cr0) { + rk29xx_writel(dws, SPIM_CTRLR0, cr0); } - spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); spi_chip_sel(dws, spi->chip_select); /* Set the interrupt mask, for poll mode just diable all int */ @@ -999,7 +1150,7 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) if (transfer->rx_buf != NULL) { dmacr |= SPI_DMACR_RX_ENABLE; rk29xx_writew(dws, SPIM_DMARDLR, 0); - rk29xx_writew(dws, SPIM_CTRLR1, transfer->len-1); + rk29xx_writew(dws, SPIM_CTRLR1, transfer->len-1); } rk29xx_writew(dws, SPIM_DMACR, dmacr); spi_enable_chip(dws, 1); @@ -1007,12 +1158,24 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) dws->prev_chip = chip; } - INIT_COMPLETION(dws->xfer_completion); + //INIT_COMPLETION(dws->xfer_completion); + + //spi_dump_regs(dws); + + DBG("dws->tx_dmach: %d, dws->rx_dmach: %d, dws->tx_dma: 0x%x,dws->rx_dma: 0x%x\n", dws->tx_dmach, dws->rx_dmach, (unsigned int)dws->tx_dma,(unsigned int)dws->rx_dma); + DBG("dws->buffer_tx_dma: 0x%p, dws->buffer_rx_dma: 0x%p,dws->dma_width=%d\n", dws->buffer_tx_dma, dws->buffer_rx_dma,dws->dma_width); - spi_dump_regs(dws); - DBG("dws->tx_dmach: %d, dws->rx_dmach: %d, transfer->tx_dma: 0x%x\n", dws->tx_dmach, dws->rx_dmach, (unsigned int)transfer->tx_dma); - if (transfer->tx_buf != NULL) { - dws->state |= TXBUSY; + if (transfer->tx_buf != NULL) + dws->state |= TXBUSY; + if (transfer->rx_buf != NULL) + dws->state |= RXBUSY; + + if (transfer->tx_buf != NULL) { + DBG("%s:start dma tx,dws->state=0x%x\n",__func__,dws->state); + #if defined(PRINT_TRANS_DATA) + printk("dma tx:"); + printk_transfer_data(dws->buffer_tx_dma, dws->cur_transfer->len); + #endif /*if (transfer->len & 0x3) { burst = 1; } @@ -1020,7 +1183,7 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) burst = 4; } if (rk29_dma_config(dws->tx_dmach, burst)) {*/ - if (rk29_dma_config(dws->tx_dmach, 1)) {//there is not dma burst but bitwide, set it 1 alwayss + if (rk29_dma_config(dws->tx_dmach, dws->dma_width, 1)) {//there is not dma burst but bitwide, set it 1 alwayss dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__); goto err_out; } @@ -1028,7 +1191,7 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) rk29_dma_ctrl(dws->tx_dmach, RK29_DMAOP_FLUSH); iRet = rk29_dma_enqueue(dws->tx_dmach, (void *)dws, - transfer->tx_dma, transfer->len); + dws->tx_dma, transfer->len); if (iRet) { dev_err(&dws->master->dev, "function: %s, line: %d, iRet: %d(dws->tx_dmach: %d, transfer->tx_dma: 0x%x)\n", __FUNCTION__, __LINE__, iRet, dws->tx_dmach, (unsigned int)transfer->tx_dma); @@ -1041,11 +1204,11 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) } } - wait_till_not_busy(dws); - - if (transfer->rx_buf != NULL) { - dws->state |= RXBUSY; - if (rk29_dma_config(dws->rx_dmach, 1)) { + //wait_till_not_busy(dws); + + if (transfer->rx_buf != NULL) { + DBG("%s:start dma rx,dws->state=0x%x\n",__func__,dws->state); + if (rk29_dma_config(dws->rx_dmach, dws->dma_width, 1)) { dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__); goto err_out; } @@ -1053,7 +1216,7 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) rk29_dma_ctrl(dws->rx_dmach, RK29_DMAOP_FLUSH); iRet = rk29_dma_enqueue(dws->rx_dmach, (void *)dws, - transfer->rx_dma, transfer->len); + dws->rx_dma, transfer->len); if (iRet) { dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__); goto err_out; @@ -1064,42 +1227,8 @@ static void dma_transfer(struct rk29xx_spi *dws) //int cs_change) goto err_out; } } - - /* millisecs to xfer 'len' bytes @ 'cur_speed' */ - ms = transfer->len * 8 / dws->cur_chip->speed_hz; - ms += 10; - - val = msecs_to_jiffies(ms) + 10; - if (!wait_for_completion_timeout(&dws->xfer_completion, val)) { - if (transfer->rx_buf != NULL && (dws->state & RXBUSY)) { - rk29_dma_ctrl(dws->rx_dmach, RK29_DMAOP_FLUSH); - dws->state &= ~RXBUSY; - dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__); - goto NEXT_TRANSFER; - } - if (transfer->tx_buf != NULL && (dws->state & TXBUSY)) { - rk29_dma_ctrl(dws->tx_dmach, RK29_DMAOP_FLUSH); - dws->state &= ~TXBUSY; - dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__); - goto NEXT_TRANSFER; - } - } - - wait_till_not_busy(dws); - -NEXT_TRANSFER: - /* Update total byte transfered return count actual bytes read */ - dws->cur_msg->actual_length += dws->len; - - /* Move to next transfer */ - dws->cur_msg->state = next_transfer(dws); - - /* Handle end of message */ - if (dws->cur_msg->state == DONE_STATE) { - dws->cur_msg->status = 0; - giveback(dws); - } else - dma_transfer(dws); + + //wait_till_not_busy(dws); return; @@ -1115,19 +1244,21 @@ static void pump_messages(struct work_struct *work) container_of(work, struct rk29xx_spi, pump_messages); unsigned long flags; - DBG(KERN_INFO "pump_messages\n"); - + DBG(KERN_INFO "pump_messages,line=%d\n",__LINE__); + /* Lock queue and check for queue work */ spin_lock_irqsave(&dws->lock, flags); if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) { dws->busy = 0; spin_unlock_irqrestore(&dws->lock, flags); + DBG("%s:line=%d,list_empty\n",__func__,__LINE__); return; } /* Make sure we are not already running a message */ if (dws->cur_msg) { - spin_unlock_irqrestore(&dws->lock, flags); + spin_unlock_irqrestore(&dws->lock, flags); + DBG("%s:line=%d,dws->cur_msg\n",__func__,__LINE__); return; } @@ -1141,21 +1272,14 @@ static void pump_messages(struct work_struct *work) struct spi_transfer, transfer_list); dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi); - dws->prev_chip = NULL; //ÿ¸öpump messageʱǿÖƸüÐÂcs dxj - - /* Mark as busy and launch transfers */ - if(dws->cur_msg->is_dma_mapped /*&& dws->cur_transfer->len > DMA_MIN_BYTES*/) { - dws->busy = 1; - spin_unlock_irqrestore(&dws->lock, flags); - dma_transfer(dws); - return; - } - else { - tasklet_schedule(&dws->pump_transfers); - } + dws->prev_chip = NULL; //ÿ¸öpump messageʱǿÖƸüÐÂcs dxj + + /* Mark as busy and launch transfers */ + tasklet_schedule(&dws->pump_transfers); dws->busy = 1; spin_unlock_irqrestore(&dws->lock, flags); + } #if defined(QUICK_TRANSFER) @@ -1421,6 +1545,8 @@ static int rk29xx_pump_transfers(struct rk29xx_spi *dws, int mode) chip->tmode = SPI_TMOD_TO; cr0 &= ~(0x3 << SPI_MODE_OFFSET); + cr0 &= ~(0x3 << SPI_TMOD_OFFSET); + cr0 |= (spi->mode << SPI_MODE_OFFSET); cr0 |= (chip->tmode << SPI_TMOD_OFFSET); } @@ -1434,8 +1560,8 @@ static int rk29xx_pump_transfers(struct rk29xx_spi *dws, int mode) * 3. control value changes */ spi_enable_chip(dws, 0); - if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0) - rk29xx_writew(dws, SPIM_CTRLR0, cr0); + if (rk29xx_readl(dws, SPIM_CTRLR0) != cr0) + rk29xx_writel(dws, SPIM_CTRLR0, cr0); DBG(KERN_INFO "clk_div: 0x%x, chip->clk_div: 0x%x\n", clk_div, chip->clk_div); spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); @@ -1569,7 +1695,7 @@ static int rk29xx_spi_transfer(struct spi_device *spi, struct spi_message *msg) else { /* If no other data transaction in air, just go */ spin_unlock_irqrestore(&dws->lock, flags); - pump_messages(&dws->pump_messages); + pump_messages(&dws->pump_messages); return 0; } } @@ -1599,7 +1725,7 @@ static int rk29xx_spi_setup(struct spi_device *spi) return -ENOMEM; chip->cs_control = spi_cs_control; - chip->enable_dma = 1; //0; + chip->enable_dma = 0; //0; } /* @@ -1615,7 +1741,7 @@ static int rk29xx_spi_setup(struct spi_device *spi) chip->poll_mode = chip_info->poll_mode; chip->type = chip_info->type; - + chip->slave_enable = chip_info->slave_enable; chip->rx_threshold = 0; chip->tx_threshold = 0; @@ -1685,6 +1811,7 @@ static int __devinit init_queue(struct rk29xx_spi *dws) if (dws->workqueue == NULL) return -EBUSY; + return 0; } @@ -1766,7 +1893,7 @@ static void spi_hw_init(struct rk29xx_spi *dws) } spi_enable_chip(dws, 1); - flush(dws); + //flush(dws); } /* cpufreq driver support */ @@ -1854,6 +1981,11 @@ static int __init rk29xx_spim_probe(struct platform_device *pdev) dev_err(&pdev->dev, "clk_get for spi fail(%p)\n", dws->clock_spim); return PTR_ERR(dws->clock_spim); } + + dws->pclk = clk_get(&pdev->dev, "pclk_spi"); + clk_enable(dws->pclk); + + mutex_init(&dws->dma_lock); dws->regs = ioremap(regs->start, (regs->end - regs->start) + 1); if (!dws->regs){ @@ -1861,7 +1993,7 @@ static int __init rk29xx_spim_probe(struct platform_device *pdev) return -EBUSY; } DBG(KERN_INFO "dws->regs: %p\n", dws->regs); - dws->irq = irq; + dws->irq = irq; dws->irq_polarity = IRQF_TRIGGER_NONE; dws->master = master; dws->type = SSI_MOTO_SPI; @@ -1893,6 +2025,7 @@ static int __init rk29xx_spim_probe(struct platform_device *pdev) dws->pdev = pdev; /* Basic HW init */ spi_hw_init(dws); + flush(dws); /* Initial and start queue */ ret = init_queue(dws); if (ret) { @@ -1918,7 +2051,7 @@ static int __init rk29xx_spim_probe(struct platform_device *pdev) dev_err(&master->dev, "rk29xx spim failed to init cpufreq support\n"); goto err_queue_alloc; } - DBG(KERN_INFO "rk29xx_spim: driver initialized, fifo_len: %d\n", dws->fifo_len); + printk(KERN_INFO "rk29xx_spim: driver initialized, fifo_len=%d,bus_num=%d\n", dws->fifo_len,master->bus_num); mrst_spi_debugfs_init(dws); return 0; @@ -1945,6 +2078,10 @@ static void __exit rk29xx_spim_remove(struct platform_device *pdev) rk29xx_spim_cpufreq_deregister(dws); mrst_spi_debugfs_remove(dws); + if(dws->buffer_tx_dma) + dma_free_coherent(&pdev->dev, DMA_BUFFER_SIZE, dws->buffer_tx_dma, dws->tx_dma); + if(dws->buffer_rx_dma) + dma_free_coherent(&pdev->dev, DMA_BUFFER_SIZE, dws->buffer_rx_dma, dws->rx_dma); release_dma(dws); /* Remove the queue */ @@ -1952,8 +2089,11 @@ static void __exit rk29xx_spim_remove(struct platform_device *pdev) if (status != 0) dev_err(&dws->master->dev, "rk29xx_spi_remove: workqueue will not " "complete, message memory not freed\n"); - clk_put(dws->clock_spim); + clk_disable(dws->clock_spim); + clk_put(dws->clock_spim); + clk_disable(dws->pclk); + clk_put(dws->pclk); spi_enable_chip(dws, 0); /* Disable clk */ spi_set_clk(dws, 0); @@ -1973,7 +2113,8 @@ static int rk29xx_spim_suspend(struct platform_device *pdev, pm_message_t mesg) struct rk29xx_spi *dws = spi_master_get_devdata(master); struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data; int status; - + + flush(dws); status = stop_queue(dws); if (status != 0) return status; @@ -1982,6 +2123,7 @@ static int rk29xx_spim_suspend(struct platform_device *pdev, pm_message_t mesg) { pdata->io_fix_leakage_bug( ); } + clk_disable(dws->pclk); return 0; } @@ -1991,7 +2133,8 @@ static int rk29xx_spim_resume(struct platform_device *pdev) struct rk29xx_spi *dws = spi_master_get_devdata(master); struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data; int ret; - + + clk_enable(dws->pclk); clk_enable(dws->clock_spim); spi_hw_init(dws); ret = start_queue(dws); @@ -2031,7 +2174,7 @@ static void __exit rk29xx_spim_exit(void) platform_driver_unregister(&rk29xx_platform_spim_driver); } -subsys_initcall(rk29xx_spim_init); +arch_initcall_sync(rk29xx_spim_init); module_exit(rk29xx_spim_exit); MODULE_AUTHOR("www.rock-chips.com");