#include <linux/clk.h>\r
#include <linux/cpufreq.h>\r
#include <mach/gpio.h>\r
+#include <mach/irqs.h>\r
#include <linux/dma-mapping.h>\r
#include <asm/dma.h>\r
-\r
+#include <linux/preempt.h>\r
#include "rk29_spim.h"\r
#include <linux/spi/spi.h>\r
#include <mach/board.h>\r
*/\r
\r
//#define QUICK_TRANSFER \r
-\r
#if 0\r
#define DBG printk\r
+//#define PRINT_TRANS_DATA\r
#else\r
#define DBG(x...)\r
#endif\r
\r
-#define DMA_MIN_BYTES 8\r
+#define DMA_BUFFER_SIZE PAGE_SIZE\r
+#define DMA_MIN_BYTES 32 //>32x16bits FIFO\r
\r
\r
#define START_STATE ((void *)0)\r
u8 cs; /* chip select pin */\r
u8 n_bytes; /* current is a 1/2/4 byte op */\r
u8 tmode; /* TR/TO/RO/EEPROM */\r
+ u8 mode; /* ??? */\r
u8 type; /* SPI/SSP/MicroWire */\r
\r
u8 poll_mode; /* 1 means use poll mode */\r
-\r
+ u8 slave_enable;\r
u32 dma_width;\r
u32 rx_threshold;\r
u32 tx_threshold;\r
#define RXBUSY (1<<2)\r
#define TXBUSY (1<<3)\r
\r
+//\r
+#ifdef CONFIG_LCD_USE_SPIM_CONTROL\r
+void rk29_lcd_spim_spin_lock(void)\r
+{\r
+#ifdef CONFIG_LCD_USE_SPI0\r
+ disable_irq(IRQ_SPI0);\r
+#endif\r
+\r
+#ifdef CONFIG_LCD_USE_SPI1\r
+ disable_irq(IRQ_SPI1);\r
+#endif\r
+\r
+ preempt_disable();\r
+}\r
+\r
+void rk29_lcd_spim_spin_unlock(void)\r
+{\r
+ preempt_enable();\r
+ \r
+#ifdef CONFIG_LCD_USE_SPI0\r
+ enable_irq(IRQ_SPI0);\r
+#endif\r
+\r
+#ifdef CONFIG_LCD_USE_SPI1\r
+ enable_irq(IRQ_SPI1);\r
+#endif\r
+}\r
+#else\r
+void rk29_lcd_spim_spin_lock(void)\r
+{\r
+ return;\r
+}\r
+\r
+void rk29_lcd_spim_spin_unlock(void)\r
+{\r
+ return;\r
+}\r
+#endif\r
+\r
+#if defined(PRINT_TRANS_DATA)\r
+static void printk_transfer_data(unsigned char *buf, int len)\r
+{\r
+ int i = 0;\r
+ for(i=0; i<len; i++)\r
+ printk("0x%x,",*buf++);\r
+\r
+ printk("\n");\r
+\r
+}\r
+#endif\r
+\r
+#if 0\r
static void spi_dump_regs(struct rk29xx_spi *dws) {\r
DBG("MRST SPI0 registers:\n");\r
DBG("=================================\n");\r
DBG("=================================\n");\r
\r
}\r
+#endif\r
\r
#ifdef CONFIG_DEBUG_FS\r
static int spi_show_regs_open(struct inode *inode, struct file *file)\r
}\r
#endif /* CONFIG_DEBUG_FS */\r
\r
+static void dma_transfer(struct rk29xx_spi *dws) ;\r
+static void transfer_complete(struct rk29xx_spi *dws);\r
+\r
static void wait_till_not_busy(struct rk29xx_spi *dws)\r
{\r
unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);\r
-\r
+ //if spi was slave, it is SR_BUSY always. \r
+ if(dws->cur_chip) {\r
+ if(dws->cur_chip->slave_enable == 1)\r
+ return;\r
+ }\r
+ \r
while (time_before(jiffies, end)) {\r
if (!(rk29xx_readw(dws, SPIM_SR) & SR_BUSY))\r
return;\r
rk29xx_writel(dws, SPIM_SER, 0);\r
return;\r
#else\r
+ \r
+ #error "Warning: not support"\r
struct rk29xx_spi_platform_data *pdata = dws->master->dev.platform_data;\r
struct spi_cs_gpio *cs_gpios = pdata->chipselect_gpios;\r
\r
\r
static int u8_writer(struct rk29xx_spi *dws)\r
{ \r
- spi_dump_regs(dws);\r
+ //spi_dump_regs(dws)\r
+#if defined(PRINT_TRANS_DATA)\r
DBG("tx: 0x%02x\n", *(u8 *)(dws->tx));\r
+#endif\r
if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)\r
|| (dws->tx == dws->tx_end))\r
return 0;\r
\r
static int u8_reader(struct rk29xx_spi *dws)\r
{\r
- spi_dump_regs(dws);\r
+ //spi_dump_regs(dws);\r
while (!(rk29xx_readw(dws, SPIM_SR) & SR_RF_EMPT)\r
&& (dws->rx < dws->rx_end)) {\r
*(u8 *)(dws->rx) = rk29xx_readw(dws, SPIM_RXDR) & 0xFFU;\r
+#if defined(PRINT_TRANS_DATA)\r
DBG("rx: 0x%02x\n", *(u8 *)(dws->rx));\r
+#endif\r
++dws->rx;\r
}\r
\r
}\r
\r
static int u16_writer(struct rk29xx_spi *dws)\r
-{\r
+{ \r
+#if defined(PRINT_TRANS_DATA)\r
+ DBG("tx: 0x%04x\n", *(u16 *)(dws->tx));\r
+#endif\r
if ((rk29xx_readw(dws, SPIM_SR) & SR_TF_FULL)\r
|| (dws->tx == dws->tx_end))\r
return 0;\r
&& (dws->rx < dws->rx_end)) {\r
temp = rk29xx_readw(dws, SPIM_RXDR);\r
*(u16 *)(dws->rx) = temp;\r
- //DBG("rx: 0x%04x\n", *(u16 *)(dws->rx));\r
+#if defined(PRINT_TRANS_DATA)\r
+ DBG("rx: 0x%04x\n", *(u16 *)(dws->rx));\r
+#endif\r
dws->rx += 2;\r
}\r
\r
struct rk29xx_spi *dws = buf_id;\r
unsigned long flags;\r
\r
+ DBG("func: %s, line: %d\n", __FUNCTION__, __LINE__);\r
+ \r
spin_lock_irqsave(&dws->lock, flags);\r
\r
if (res == RK29_RES_OK)\r
dws->state &= ~RXBUSY;\r
else\r
- dev_err(&dws->master->dev, "DmaAbrtRx-%d, size: %d\n", res, size);\r
+ dev_err(&dws->master->dev, "error:DmaAbrtRx-%d, size: %d,res=%d\n", res, size,res);\r
\r
+ //copy data from dma to transfer buf\r
+ if(dws->cur_transfer && (dws->cur_transfer->rx_buf != NULL))\r
+ {\r
+ memcpy(dws->cur_transfer->rx_buf, dws->buffer_rx_dma, dws->cur_transfer->len);\r
+ \r
+ #if defined(PRINT_TRANS_DATA)\r
+ printk("dma rx:");\r
+ printk_transfer_data(dws->cur_transfer->rx_buf, dws->cur_transfer->len);\r
+ #endif\r
+ }\r
+ \r
+ spin_unlock_irqrestore(&dws->lock, flags);\r
+ \r
/* If the other done */\r
if (!(dws->state & TXBUSY))\r
- complete(&dws->xfer_completion);\r
+ {\r
+ //complete(&dws->xfer_completion); \r
+ DBG("func: %s, line: %d,dma transfer complete\n", __FUNCTION__, __LINE__);\r
+ //DMA could not lose intterupt\r
+ transfer_complete(dws);\r
+ }\r
\r
- spin_unlock_irqrestore(&dws->lock, flags);\r
}\r
\r
static void rk29_spi_dma_txcb(void *buf_id,\r
unsigned long flags;\r
\r
DBG("func: %s, line: %d\n", __FUNCTION__, __LINE__);\r
-\r
+ \r
spin_lock_irqsave(&dws->lock, flags);\r
\r
if (res == RK29_RES_OK)\r
dws->state &= ~TXBUSY;\r
else\r
- dev_err(&dws->master->dev, "DmaAbrtTx-%d, size: %d \n", res, size);\r
+ dev_err(&dws->master->dev, "error:DmaAbrtTx-%d, size: %d,res=%d \n", res, size,res);\r
\r
+ spin_unlock_irqrestore(&dws->lock, flags);\r
+ \r
/* If the other done */\r
if (!(dws->state & RXBUSY)) \r
- complete(&dws->xfer_completion);\r
+ {\r
+ //complete(&dws->xfer_completion);\r
+ \r
+ DBG("func: %s, line: %d,dma transfer complete\n", __FUNCTION__, __LINE__);\r
+ //DMA could not lose intterupt\r
+ transfer_complete(dws);\r
+ }\r
\r
- spin_unlock_irqrestore(&dws->lock, flags);\r
}\r
\r
\r
return 0;\r
}\r
\r
+ dws->buffer_tx_dma = dma_alloc_coherent(&dws->pdev->dev, DMA_BUFFER_SIZE, &dws->tx_dma, GFP_KERNEL | GFP_DMA);\r
+ if (!dws->buffer_tx_dma)\r
+ {\r
+ dev_err(&dws->pdev->dev, "fail to dma tx buffer alloc\n");\r
+ return -1;\r
+ }\r
+\r
+ dws->buffer_rx_dma = dma_alloc_coherent(&dws->pdev->dev, DMA_BUFFER_SIZE, &dws->rx_dma, GFP_KERNEL | GFP_DMA);\r
+ if (!dws->buffer_rx_dma)\r
+ {\r
+ dev_err(&dws->pdev->dev, "fail to dma rx buffer alloc\n");\r
+ return -1;\r
+ }\r
+\r
if(rk29_dma_request(dws->rx_dmach, \r
&rk29_spi_dma_client, NULL) < 0) {\r
dev_err(&dws->master->dev, "dws->rx_dmach : %d, cannot get RxDMA\n", dws->rx_dmach);\r
rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client);\r
return -1;\r
}\r
- \r
- dws->dma_inited = 1;\r
- return 0;\r
-}\r
-\r
-static void release_dma(struct rk29xx_spi *dws)\r
-{\r
- if(!dws && dws->dma_inited) {\r
- rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client);\r
- rk29_dma_free(dws->tx_dmach, &rk29_spi_dma_client);\r
- }\r
-}\r
-\r
-/*\r
- * Note: first step is the protocol driver prepares\r
- * a dma-capable memory, and this func just need translate\r
- * the virt addr to physical\r
- */\r
-static int map_dma_buffers(struct rk29xx_spi *dws)\r
-{\r
- if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited\r
- || !dws->cur_chip->enable_dma)\r
- return -1;\r
\r
- if (dws->cur_transfer->tx_dma) {\r
- dws->tx_dma = dws->cur_transfer->tx_dma;\r
+ if (dws->tx_dma) {\r
if (rk29_dma_set_buffdone_fn(dws->tx_dmach, rk29_spi_dma_txcb)) {\r
dev_err(&dws->master->dev, "rk29_dma_set_buffdone_fn fail\n");\r
return -1;\r
}\r
}\r
\r
- if (dws->cur_transfer->rx_dma) {\r
- dws->rx_dma = dws->cur_transfer->rx_dma;\r
+ if (dws->rx_dma) {\r
if (rk29_dma_set_buffdone_fn(dws->rx_dmach, rk29_spi_dma_rxcb)) {\r
dev_err(&dws->master->dev, "rk29_dma_set_buffdone_fn fail\n");\r
return -1;\r
return -1;\r
}\r
}\r
+ \r
+ dws->dma_inited = 1;\r
+ return 0;\r
+}\r
+\r
+static void release_dma(struct rk29xx_spi *dws)\r
+{\r
+ if(!dws && dws->dma_inited) {\r
+ rk29_dma_free(dws->rx_dmach, &rk29_spi_dma_client);\r
+ rk29_dma_free(dws->tx_dmach, &rk29_spi_dma_client);\r
+ }\r
+}\r
+\r
+/*\r
+ * Note: first step is the protocol driver prepares\r
+ * a dma-capable memory, and this func just need translate\r
+ * the virt addr to physical\r
+ */\r
+static int map_dma_buffers(struct rk29xx_spi *dws)\r
+{\r
+ if (!dws->dma_inited || !dws->cur_chip->enable_dma)\r
+ {\r
+ printk("%s:error\n",__func__);\r
+ return -1;\r
+ }\r
\r
+ if(dws->cur_transfer->tx_buf)\r
+ {\r
+ memcpy(dws->buffer_tx_dma,dws->cur_transfer->tx_buf,dws->cur_transfer->len);\r
+ }\r
+ \r
+ dws->cur_transfer->tx_dma = dws->tx_dma;\r
+ dws->cur_transfer->rx_dma = dws->rx_dma;\r
+ \r
return 0;\r
}\r
\r
dws->prev_chip = dws->cur_chip;\r
dws->cur_chip = NULL;\r
dws->dma_mapped = 0;\r
+\r
+ \r
+ /*it is important to close intterrupt*/\r
+ spi_mask_intr(dws, 0xff);\r
+ rk29xx_writew(dws, SPIM_DMACR, 0);\r
+ \r
queue_work(dws->workqueue, &dws->pump_messages);\r
spin_unlock_irqrestore(&dws->lock, flags);\r
\r
msg->state = NULL;\r
if (msg->complete)\r
msg->complete(msg->context);\r
+\r
+ DBG("%s ok\n",__func__);\r
+\r
}\r
\r
static void int_error_stop(struct rk29xx_spi *dws, const char *msg)\r
u16 irq_status, irq_mask = 0x1f;\r
u32 int_level = dws->fifo_len / 2;\r
u32 left;\r
- \r
+\r
irq_status = rk29xx_readw(dws, SPIM_ISR) & irq_mask;\r
/* Error handling */\r
if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {\r
rk29xx_writew(dws, SPIM_ICR, SPI_CLEAR_INT_TXOI | SPI_CLEAR_INT_RXOI | SPI_CLEAR_INT_RXUI);\r
int_error_stop(dws, "interrupt_transfer: fifo overrun");\r
+ mutex_unlock(&dws->dma_lock); \r
return IRQ_HANDLED;\r
}\r
\r
else {\r
transfer_complete(dws);\r
}\r
- }\r
+ \r
+ } \r
\r
return IRQ_HANDLED;\r
}\r
/* Must be called inside pump_transfers() */\r
static void poll_transfer(struct rk29xx_spi *dws)\r
{\r
+#if defined(PRINT_TRANS_DATA)\r
+ DBG("%s\n",__func__);\r
+#endif\r
while (dws->write(dws)) {\r
wait_till_not_busy(dws);\r
dws->read(dws);\r
u32 speed = 0;\r
u32 cr0 = 0;\r
\r
- DBG(KERN_INFO "pump_transfers\n");\r
+ if((dws->cur_chip->enable_dma) && (dws->cur_transfer->len > DMA_MIN_BYTES) && (dws->cur_transfer->len < DMA_BUFFER_SIZE)){ \r
+ dma_transfer(dws);\r
+ return;\r
+ } \r
+ \r
+ DBG(KERN_INFO "pump_transfers,len=%d\n",dws->cur_transfer->len);\r
\r
/* Get current state information */\r
message = dws->cur_msg;\r
dws->dma_width = chip->dma_width;\r
dws->cs_control = chip->cs_control;\r
\r
- dws->rx_dma = transfer->rx_dma;\r
- dws->tx_dma = transfer->tx_dma;\r
+ //dws->rx_dma = transfer->rx_dma;\r
+ //dws->tx_dma = transfer->tx_dma;\r
dws->tx = (void *)transfer->tx_buf;\r
dws->tx_end = dws->tx + transfer->len;\r
- dws->rx = transfer->rx_buf;\r
+ dws->rx = (void *)transfer->rx_buf;\r
dws->rx_end = dws->rx + transfer->len;\r
dws->write = dws->tx ? chip->write : null_writer;\r
dws->read = dws->rx ? chip->read : null_reader;\r
if (transfer->speed_hz != speed) {\r
speed = transfer->speed_hz;\r
if (speed > clk_get_rate(dws->clock_spim)) {\r
- dev_err(&dws->master->dev, "MRST SPI0: unsupported"\r
+ dev_err(&dws->master->dev, "MRST SPI0: unsupported "\r
"freq: %dHz\n", speed);\r
message->status = -EIO;\r
goto early_exit;\r
else\r
chip->tmode = SPI_TMOD_TO;\r
\r
- cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
+ cr0 &= ~(0x3 << SPI_MODE_OFFSET); \r
+ cr0 &= ~(0x3 << SPI_TMOD_OFFSET);\r
+ cr0 &= ~(0x1 << SPI_OPMOD_OFFSET); \r
+ cr0 |= (spi->mode << SPI_MODE_OFFSET);\r
cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
+ cr0 |= ((chip->slave_enable & 1) << SPI_OPMOD_OFFSET);\r
} \r
\r
/*\r
* Interrupt mode\r
* we only need set the TXEI IRQ, as TX/RX always happen syncronizely\r
*/\r
- if (!dws->dma_mapped && !chip->poll_mode) {\r
+ if (!dws->dma_mapped && !chip->poll_mode) { \r
int templen ;\r
\r
if (chip->tmode == SPI_TMOD_RO) {\r
* 2. clk_div is changed\r
* 3. control value changes\r
*/\r
- if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0 || cs_change || clk_div || imask) {\r
+ if ((rk29xx_readl(dws, SPIM_CTRLR0) != cr0) || cs_change || clk_div || imask) {\r
spi_enable_chip(dws, 0);\r
- if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0)\r
- rk29xx_writew(dws, SPIM_CTRLR0, cr0);\r
+ if (rk29xx_readl(dws, SPIM_CTRLR0) != cr0)\r
+ rk29xx_writel(dws, SPIM_CTRLR0, cr0);\r
\r
spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); \r
spi_chip_sel(dws, spi->chip_select);\r
\r
rk29xx_writew(dws, SPIM_CTRLR1, dws->len-1);\r
- spi_enable_chip(dws, 1);\r
-\r
+ \r
if (txint_level)\r
rk29xx_writew(dws, SPIM_TXFTLR, txint_level);\r
+ spi_enable_chip(dws, 1); \r
+ \r
if (rxint_level)\r
rk29xx_writew(dws, SPIM_RXFTLR, rxint_level);\r
/* Set the interrupt mask, for poll mode just diable all int */\r
return;\r
}\r
\r
-static void dma_transfer(struct rk29xx_spi *dws) //int cs_change)\r
+static void dma_transfer(struct rk29xx_spi *dws) \r
{\r
struct spi_message *message = NULL;\r
struct spi_transfer *transfer = NULL;\r
struct spi_transfer *previous = NULL;\r
struct spi_device *spi = NULL;\r
struct chip_data *chip = NULL;\r
- unsigned long val;\r
- int ms;\r
+ //unsigned long val; \r
+ //unsigned long flags;\r
+ //int ms;\r
int iRet;\r
- int burst;\r
+ //int burst;\r
u8 bits = 0;\r
u8 spi_dfs = 0;\r
u8 cs_change = 0;\r
u32 speed = 0;\r
u32 cr0 = 0;\r
u32 dmacr = 0;\r
-\r
- DBG(KERN_INFO "dma_transfer\n");\r
-\r
+ \r
+ DBG(KERN_INFO "dma_transfer,len=%d\n",dws->cur_transfer->len); \r
+ \r
if (acquire_dma(dws)) {\r
dev_err(&dws->master->dev, "acquire dma failed\n");\r
goto err_out;\r
dws->dma_width = chip->dma_width;\r
dws->cs_control = chip->cs_control;\r
\r
- dws->rx_dma = transfer->rx_dma;\r
- dws->tx_dma = transfer->tx_dma;\r
+ //dws->rx_dma = transfer->rx_dma;\r
+ //dws->tx_dma = transfer->tx_dma;\r
dws->tx = (void *)transfer->tx_buf;\r
dws->tx_end = dws->tx + transfer->len;\r
- dws->rx = transfer->rx_buf;\r
+ dws->rx = (void *)transfer->rx_buf;\r
dws->rx_end = dws->rx + transfer->len;\r
dws->write = dws->tx ? chip->write : null_writer;\r
dws->read = dws->rx ? chip->read : null_reader;\r
cs_change = 1;\r
\r
cr0 = chip->cr0;\r
-\r
+ \r
/* Handle per transfer options for bpw and speed */\r
if (transfer->speed_hz) {\r
speed = chip->speed_hz;\r
-\r
if (transfer->speed_hz != speed) {\r
speed = transfer->speed_hz;\r
if (speed > clk_get_rate(dws->clock_spim)) {\r
- dev_err(&dws->master->dev, "MRST SPI0: unsupported"\r
+ dev_err(&dws->master->dev, "MRST SPI0: unsupported "\r
"freq: %dHz\n", speed);\r
message->status = -EIO;\r
goto err_out;\r
}\r
}\r
\r
+ \r
if (transfer->bits_per_word) {\r
bits = transfer->bits_per_word;\r
\r
chip->tmode = SPI_TMOD_TO;\r
\r
cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
+ cr0 &= ~(0x3 << SPI_TMOD_OFFSET);\r
+ cr0 &= ~(0x1 << SPI_OPMOD_OFFSET); \r
+ cr0 |= (spi->mode << SPI_MODE_OFFSET);\r
cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
+ cr0 |= ((chip->slave_enable & 1) << SPI_OPMOD_OFFSET);\r
}\r
\r
/*\r
* 2. clk_div is changed\r
* 3. control value changes\r
*/\r
- if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0 || cs_change || clk_div) {\r
+ if ((rk29xx_readl(dws, SPIM_CTRLR0) != cr0) || cs_change || clk_div) {\r
spi_enable_chip(dws, 0);\r
- if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0) {\r
- rk29xx_writew(dws, SPIM_CTRLR0, cr0);\r
+ if (rk29xx_readl(dws, SPIM_CTRLR0) != cr0) {\r
+ rk29xx_writel(dws, SPIM_CTRLR0, cr0);\r
}\r
-\r
spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); \r
spi_chip_sel(dws, spi->chip_select);\r
/* Set the interrupt mask, for poll mode just diable all int */\r
if (transfer->rx_buf != NULL) {\r
dmacr |= SPI_DMACR_RX_ENABLE;\r
rk29xx_writew(dws, SPIM_DMARDLR, 0);\r
- rk29xx_writew(dws, SPIM_CTRLR1, transfer->len-1);\r
+ rk29xx_writew(dws, SPIM_CTRLR1, transfer->len-1); \r
}\r
rk29xx_writew(dws, SPIM_DMACR, dmacr);\r
spi_enable_chip(dws, 1);\r
dws->prev_chip = chip;\r
} \r
\r
- INIT_COMPLETION(dws->xfer_completion);\r
+ //INIT_COMPLETION(dws->xfer_completion);\r
+\r
+ //spi_dump_regs(dws);\r
+ \r
+ 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); \r
+ 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); \r
\r
- spi_dump_regs(dws);\r
- 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);\r
- if (transfer->tx_buf != NULL) {\r
- dws->state |= TXBUSY;\r
+ if (transfer->tx_buf != NULL) \r
+ dws->state |= TXBUSY; \r
+ if (transfer->rx_buf != NULL) \r
+ dws->state |= RXBUSY;\r
+\r
+ if (transfer->tx_buf != NULL) { \r
+ DBG("%s:start dma tx,dws->state=0x%x\n",__func__,dws->state);\r
+ #if defined(PRINT_TRANS_DATA)\r
+ printk("dma tx:");\r
+ printk_transfer_data(dws->buffer_tx_dma, dws->cur_transfer->len);\r
+ #endif\r
/*if (transfer->len & 0x3) {\r
burst = 1;\r
}\r
burst = 4;\r
}\r
if (rk29_dma_config(dws->tx_dmach, burst)) {*/\r
- if (rk29_dma_config(dws->tx_dmach, 1)) {//there is not dma burst but bitwide, set it 1 alwayss\r
+ if (rk29_dma_config(dws->tx_dmach, dws->dma_width, 1)) {//there is not dma burst but bitwide, set it 1 alwayss\r
dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
goto err_out;\r
}\r
rk29_dma_ctrl(dws->tx_dmach, RK29_DMAOP_FLUSH); \r
\r
iRet = rk29_dma_enqueue(dws->tx_dmach, (void *)dws,\r
- transfer->tx_dma, transfer->len);\r
+ dws->tx_dma, transfer->len);\r
if (iRet) {\r
dev_err(&dws->master->dev, "function: %s, line: %d, iRet: %d(dws->tx_dmach: %d, transfer->tx_dma: 0x%x)\n", __FUNCTION__, __LINE__, iRet, \r
dws->tx_dmach, (unsigned int)transfer->tx_dma);\r
}\r
}\r
\r
- wait_till_not_busy(dws);\r
-\r
- if (transfer->rx_buf != NULL) {\r
- dws->state |= RXBUSY;\r
- if (rk29_dma_config(dws->rx_dmach, 1)) {\r
+ //wait_till_not_busy(dws);\r
+ \r
+ if (transfer->rx_buf != NULL) { \r
+ DBG("%s:start dma rx,dws->state=0x%x\n",__func__,dws->state);\r
+ if (rk29_dma_config(dws->rx_dmach, dws->dma_width, 1)) {\r
dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
goto err_out;\r
}\r
rk29_dma_ctrl(dws->rx_dmach, RK29_DMAOP_FLUSH); \r
\r
iRet = rk29_dma_enqueue(dws->rx_dmach, (void *)dws,\r
- transfer->rx_dma, transfer->len);\r
+ dws->rx_dma, transfer->len);\r
if (iRet) {\r
dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
goto err_out;\r
goto err_out;\r
}\r
}\r
-\r
- /* millisecs to xfer 'len' bytes @ 'cur_speed' */\r
- ms = transfer->len * 8 / dws->cur_chip->speed_hz;\r
- ms += 10; \r
-\r
- val = msecs_to_jiffies(ms) + 10;\r
- if (!wait_for_completion_timeout(&dws->xfer_completion, val)) {\r
- if (transfer->rx_buf != NULL && (dws->state & RXBUSY)) {\r
- rk29_dma_ctrl(dws->rx_dmach, RK29_DMAOP_FLUSH);\r
- dws->state &= ~RXBUSY;\r
- dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
- goto NEXT_TRANSFER;\r
- }\r
- if (transfer->tx_buf != NULL && (dws->state & TXBUSY)) {\r
- rk29_dma_ctrl(dws->tx_dmach, RK29_DMAOP_FLUSH);\r
- dws->state &= ~TXBUSY;\r
- dev_err(&dws->master->dev, "function: %s, line: %d\n", __FUNCTION__, __LINE__);\r
- goto NEXT_TRANSFER;\r
- }\r
- }\r
-\r
- wait_till_not_busy(dws);\r
-\r
-NEXT_TRANSFER:\r
- /* Update total byte transfered return count actual bytes read */\r
- dws->cur_msg->actual_length += dws->len;\r
-\r
- /* Move to next transfer */\r
- dws->cur_msg->state = next_transfer(dws);\r
-\r
- /* Handle end of message */\r
- if (dws->cur_msg->state == DONE_STATE) {\r
- dws->cur_msg->status = 0;\r
- giveback(dws);\r
- } else\r
- dma_transfer(dws);\r
+ \r
+ //wait_till_not_busy(dws);\r
\r
return;\r
\r
container_of(work, struct rk29xx_spi, pump_messages);\r
unsigned long flags;\r
\r
- DBG(KERN_INFO "pump_messages\n");\r
-\r
+ DBG(KERN_INFO "pump_messages,line=%d\n",__LINE__);\r
+ \r
/* Lock queue and check for queue work */\r
spin_lock_irqsave(&dws->lock, flags);\r
if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {\r
dws->busy = 0;\r
spin_unlock_irqrestore(&dws->lock, flags);\r
+ DBG("%s:line=%d,list_empty\n",__func__,__LINE__);\r
return;\r
}\r
\r
/* Make sure we are not already running a message */\r
if (dws->cur_msg) {\r
- spin_unlock_irqrestore(&dws->lock, flags);\r
+ spin_unlock_irqrestore(&dws->lock, flags); \r
+ DBG("%s:line=%d,dws->cur_msg\n",__func__,__LINE__);\r
return;\r
}\r
\r
struct spi_transfer,\r
transfer_list);\r
dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);\r
- dws->prev_chip = NULL; //ÿ¸öpump messageʱǿÖƸüÐÂcs dxj\r
- \r
- /* Mark as busy and launch transfers */\r
- if(dws->cur_msg->is_dma_mapped /*&& dws->cur_transfer->len > DMA_MIN_BYTES*/) {\r
- dws->busy = 1;\r
- spin_unlock_irqrestore(&dws->lock, flags);\r
- dma_transfer(dws);\r
- return;\r
- }\r
- else {\r
- tasklet_schedule(&dws->pump_transfers);\r
- }\r
+ dws->prev_chip = NULL; //ÿ¸öpump messageʱǿÖƸüÐÂcs dxj\r
\r
+ \r
+ /* Mark as busy and launch transfers */\r
+ tasklet_schedule(&dws->pump_transfers);\r
dws->busy = 1;\r
spin_unlock_irqrestore(&dws->lock, flags);\r
+ \r
}\r
\r
#if defined(QUICK_TRANSFER)\r
chip->tmode = SPI_TMOD_TO;\r
\r
cr0 &= ~(0x3 << SPI_MODE_OFFSET);\r
+ cr0 &= ~(0x3 << SPI_TMOD_OFFSET);\r
+ cr0 |= (spi->mode << SPI_MODE_OFFSET);\r
cr0 |= (chip->tmode << SPI_TMOD_OFFSET);\r
}\r
\r
* 3. control value changes\r
*/\r
spi_enable_chip(dws, 0);\r
- if (rk29xx_readw(dws, SPIM_CTRLR0) != cr0)\r
- rk29xx_writew(dws, SPIM_CTRLR0, cr0);\r
+ if (rk29xx_readl(dws, SPIM_CTRLR0) != cr0)\r
+ rk29xx_writel(dws, SPIM_CTRLR0, cr0);\r
\r
DBG(KERN_INFO "clk_div: 0x%x, chip->clk_div: 0x%x\n", clk_div, chip->clk_div);\r
spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); \r
else {\r
/* If no other data transaction in air, just go */\r
spin_unlock_irqrestore(&dws->lock, flags);\r
- pump_messages(&dws->pump_messages);\r
+ pump_messages(&dws->pump_messages); \r
return 0;\r
}\r
}\r
return -ENOMEM;\r
\r
chip->cs_control = spi_cs_control;\r
- chip->enable_dma = 1; //0;\r
+ chip->enable_dma = 0; //0;\r
}\r
\r
/*\r
\r
chip->poll_mode = chip_info->poll_mode;\r
chip->type = chip_info->type;\r
-\r
+ chip->slave_enable = chip_info->slave_enable;\r
chip->rx_threshold = 0;\r
chip->tx_threshold = 0;\r
\r
if (dws->workqueue == NULL)\r
return -EBUSY;\r
\r
+\r
return 0;\r
}\r
\r
}\r
\r
spi_enable_chip(dws, 1);\r
- flush(dws);\r
+ //flush(dws);\r
}\r
\r
/* cpufreq driver support */\r
dev_err(&pdev->dev, "clk_get for spi fail(%p)\n", dws->clock_spim);\r
return PTR_ERR(dws->clock_spim);\r
}\r
+\r
+ dws->pclk = clk_get(&pdev->dev, "pclk_spi");\r
+ clk_enable(dws->pclk);\r
+ \r
+ mutex_init(&dws->dma_lock);\r
\r
dws->regs = ioremap(regs->start, (regs->end - regs->start) + 1);\r
if (!dws->regs){\r
return -EBUSY;\r
}\r
DBG(KERN_INFO "dws->regs: %p\n", dws->regs);\r
- dws->irq = irq;\r
+ dws->irq = irq;\r
dws->irq_polarity = IRQF_TRIGGER_NONE;\r
dws->master = master;\r
dws->type = SSI_MOTO_SPI;\r
dws->pdev = pdev;\r
/* Basic HW init */\r
spi_hw_init(dws);\r
+ flush(dws);\r
/* Initial and start queue */\r
ret = init_queue(dws);\r
if (ret) {\r
dev_err(&master->dev, "rk29xx spim failed to init cpufreq support\n");\r
goto err_queue_alloc;\r
}\r
- DBG(KERN_INFO "rk29xx_spim: driver initialized, fifo_len: %d\n", dws->fifo_len);\r
+ printk(KERN_INFO "rk29xx_spim: driver initialized, fifo_len=%d,bus_num=%d\n", dws->fifo_len,master->bus_num);\r
mrst_spi_debugfs_init(dws);\r
return 0;\r
\r
rk29xx_spim_cpufreq_deregister(dws);\r
mrst_spi_debugfs_remove(dws);\r
\r
+ if(dws->buffer_tx_dma)\r
+ dma_free_coherent(&pdev->dev, DMA_BUFFER_SIZE, dws->buffer_tx_dma, dws->tx_dma);\r
+ if(dws->buffer_rx_dma)\r
+ dma_free_coherent(&pdev->dev, DMA_BUFFER_SIZE, dws->buffer_rx_dma, dws->rx_dma);\r
release_dma(dws);\r
\r
/* Remove the queue */\r
if (status != 0)\r
dev_err(&dws->master->dev, "rk29xx_spi_remove: workqueue will not "\r
"complete, message memory not freed\n");\r
- clk_put(dws->clock_spim);\r
+ \r
clk_disable(dws->clock_spim);\r
+ clk_put(dws->clock_spim);\r
+ clk_disable(dws->pclk);\r
+ clk_put(dws->pclk);\r
spi_enable_chip(dws, 0);\r
/* Disable clk */\r
spi_set_clk(dws, 0);\r
struct rk29xx_spi *dws = spi_master_get_devdata(master);\r
struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data;\r
int status;\r
-\r
+ \r
+ flush(dws);\r
status = stop_queue(dws);\r
if (status != 0)\r
return status;\r
{\r
pdata->io_fix_leakage_bug( );\r
}\r
+ clk_disable(dws->pclk);\r
return 0;\r
}\r
\r
struct rk29xx_spi *dws = spi_master_get_devdata(master);\r
struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data;\r
int ret;\r
- \r
+\r
+ clk_enable(dws->pclk);\r
clk_enable(dws->clock_spim); \r
spi_hw_init(dws);\r
ret = start_queue(dws);\r
platform_driver_unregister(&rk29xx_platform_spim_driver);\r
}\r
\r
-subsys_initcall(rk29xx_spim_init);\r
+arch_initcall_sync(rk29xx_spim_init);\r
module_exit(rk29xx_spim_exit);\r
\r
MODULE_AUTHOR("www.rock-chips.com");\r