#include <linux/jiffies.h>\r
#include <linux/i2c.h>\r
#include <mach/rk2818_iomap.h>\r
-\r
+#include <linux/poll.h>\r
#include <mach/spi_fpga.h>\r
\r
#if defined(CONFIG_SPI_FPGA_INIT_DEBUG)\r
\r
struct spi_fpga_port *pFpgaPort;\r
\r
+#if SPI_FPGA_TRANS_WORK\r
+#define ID_SPI_FPGA_WRITE 1\r
+#define ID_SPI_FPGA_READ 2\r
+struct spi_fpga_transfer\r
+{\r
+ const u8 *txbuf;\r
+ unsigned n_tx;\r
+ u8 *rxbuf;\r
+ unsigned n_rx;\r
+ int id;\r
+ struct list_head queue;\r
+};\r
+\r
+static void spi_fpga_trans_work_handler(struct work_struct *work)\r
+{\r
+ struct spi_fpga_port *port =\r
+ container_of(work, struct spi_fpga_port, fpga_trans_work);\r
+\r
+ while (!list_empty(&port->trans_queue)) \r
+ {\r
+ struct spi_fpga_transfer *t = NULL;\r
+ list_for_each_entry(t, &port->trans_queue, queue)\r
+ {\r
+\r
+ if (t->id == 0) \r
+ break; \r
+ DBG("%s:id=%d,txbuf=0x%x\n",__FUNCTION__,t->id,(int)t->txbuf);\r
+ switch(t->id)\r
+ {\r
+ case ID_SPI_FPGA_WRITE:\r
+ spi_write(port->spi, t->txbuf, t->n_tx);\r
+ break;\r
+ default:\r
+ break;\r
+ \r
+ }\r
+ kfree(t);\r
+ kfree(t->txbuf);\r
+ }\r
+ list_del_init(&port->trans_queue);\r
+ }\r
+\r
+}\r
+\r
+int spi_write_work(struct spi_device *spi, const u8 *buf, size_t len)\r
+{\r
+ struct spi_fpga_port *port = spi_get_drvdata(spi);\r
+ struct spi_fpga_transfer *t;\r
+ unsigned long flags;\r
+\r
+ t = kzalloc(sizeof(struct spi_fpga_transfer), GFP_KERNEL);\r
+ if (!t)\r
+ {\r
+ printk("err:%s:ENOMEM\n",__FUNCTION__);\r
+ return ;\r
+ }\r
+\r
+ t->txbuf = (char *)kmalloc(32, GFP_KERNEL);\r
+ if(t->txbuf == NULL)\r
+ {\r
+ printk("%s:t->txbuf kzalloc err!!!\n",__FUNCTION__);\r
+ return -ENOMEM;\r
+ }\r
+\r
+ memcpy(t->txbuf, buf, len);\r
+ t->n_tx = len;\r
+ t->id = ID_SPI_FPGA_WRITE;\r
+\r
+ spin_lock_irqsave(&port->work_lock, flags);\r
+ list_add_tail(&t->queue, &port->trans_queue);\r
+ queue_work(port->fpga_trans_workqueue, &port->fpga_trans_work);\r
+ spin_unlock_irqrestore(&port->work_lock, flags);\r
+\r
+ return 0;\r
+\r
+}\r
+\r
+#endif\r
+\r
+\r
+#if SPI_FPGA_POLL_WAIT\r
+\r
+#define SPI_BUFSIZE 1028\r
+static void spi_fpga_complete(void *arg)\r
+{\r
+ struct spi_fpga_port *port = pFpgaPort;\r
+ msleep(5);\r
+ wake_up_interruptible(&port->spi_wait_q);\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+}\r
+\r
+int spi_fpga_write(struct spi_device *spi, const u8 *buf, size_t len)\r
+{\r
+ struct spi_transfer t = {\r
+ .tx_buf = buf,\r
+ .len = len,\r
+ };\r
+ struct spi_message m;\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+ spi_message_init(&m);\r
+ spi_message_add_tail(&t, &m);\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+ return spi_async(spi, &m);\r
+}\r
+\r
+struct poll_table_struct wait;\r
+struct file filp;\r
+int spi_fpga_write_then_read(struct spi_device *spi,\r
+ const u8 *txbuf, unsigned n_tx,\r
+ u8 *rxbuf, unsigned n_rx)\r
+{\r
+ struct spi_fpga_port *port = spi_get_drvdata(spi);\r
+ int status;\r
+ struct spi_message message;\r
+ struct spi_transfer x[2];\r
+ u8 *local_buf;\r
+ printk("%s:line=%d,n_tx+n_rx=%d\n",__FUNCTION__,__LINE__,(n_tx + n_rx));\r
+ /* Use preallocated DMA-safe buffer. We can't avoid copying here,\r
+ * (as a pure convenience thing), but we can keep heap costs\r
+ * out of the hot path ...\r
+ */\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+\r
+ if ((n_tx + n_rx) > SPI_BUFSIZE)\r
+ return -EINVAL;\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+\r
+ spi_message_init(&message);\r
+ memset(x, 0, sizeof x);\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+ if (n_tx) {\r
+ x[0].len = n_tx;\r
+ spi_message_add_tail(&x[0], &message);\r
+ }\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+\r
+ if (n_rx) {\r
+ x[1].len = n_rx;\r
+ spi_message_add_tail(&x[1], &message);\r
+ }\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+ /* ... unless someone else is using the pre-allocated buffer */\r
+\r
+ local_buf = kmalloc(SPI_BUFSIZE, GFP_KERNEL);\r
+ if (!local_buf)\r
+ return -ENOMEM;\r
+\r
+ memcpy(local_buf, txbuf, n_tx);\r
+ x[0].tx_buf = local_buf;\r
+ x[1].rx_buf = local_buf + n_tx;\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+ message.complete = spi_fpga_complete;\r
+\r
+ /* do the i/o */\r
+ status = spi_async(spi, &message);\r
+#if 1\r
+ //poll_wait(&filp, &port->spi_wait_q, &wait);\r
+\r
+ //if (status == 0)\r
+ memcpy(rxbuf, x[1].rx_buf, n_rx);\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+ kfree(local_buf);\r
+ printk("%s:line=%d\n",__FUNCTION__,__LINE__);\r
+#endif\r
+ return status;\r
+}\r
+\r
+#define spi_write spi_fpga_write\r
+#define spi_write_then_read spi_fpga_write_then_read \r
+\r
+#endif\r
+\r
/*------------------------spi¶ÁдµÄ»ù±¾º¯Êý-----------------------*/\r
unsigned int spi_in(struct spi_fpga_port *port, int reg, int type)\r
{\r
{\r
unsigned char index = 0;\r
unsigned char tx_buf[3];\r
- //printk("index2=%d,",index);\r
+ int reg_temp = reg;\r
switch(type)\r
{\r
#if defined(CONFIG_SPI_FPGA_UART)\r
tx_buf[0] = reg & 0xff;\r
tx_buf[1] = (value>>8) & 0xff;\r
tx_buf[2] = value & 0xff;\r
+ if(reg_temp == UART_IER)\r
+ spi_write_work(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));\r
+ else\r
spi_write(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));\r
DBG("%s,SEL_UART reg=0x%x,value=0x%x\n",__FUNCTION__,reg&0xff,value&0xffff);\r
break;\r
if (!port)\r
return -ENOMEM;\r
DBG("port=0x%x\n",(int)port);\r
-\r
- spin_lock_init(&port->work_lock);\r
+ \r
mutex_init(&port->spi_lock);\r
-\r
+ spin_lock_init(&port->work_lock);\r
+ \r
spi_open_sysclk(GPIO_HIGH);\r
\r
+#if SPI_FPGA_TRANS_WORK\r
+ init_waitqueue_head(&port->wait_wq);\r
+ init_waitqueue_head(&port->wait_rq);\r
+ port->write_en = TRUE;\r
+ port->read_en = TRUE;\r
+ sprintf(b, "fpga_trans_workqueue");\r
+ port->fpga_trans_workqueue = create_freezeable_workqueue(b);\r
+ if (!port->fpga_trans_workqueue) {\r
+ printk("cannot create workqueue\n");\r
+ return -EBUSY;\r
+ }\r
+ INIT_WORK(&port->fpga_trans_work, spi_fpga_trans_work_handler);\r
+ INIT_LIST_HEAD(&port->trans_queue);\r
+#endif\r
+\r
spi_fpga_rst();\r
sprintf(b, "fpga_irq_workqueue");\r
port->fpga_irq_workqueue = create_freezeable_workqueue(b);\r
#endif\r
\r
#define SPI_UART_TEST 0\r
-\r
+int gBaud = 0;\r
#define SPI_UART_FIFO_LEN 32\r
#define SPI_UART_TXRX_BUF 1 //send or recieve several bytes one time\r
\r
}\r
//quot = (2 * uart->uartclk + baud) / (2 * baud);\r
quot = (uart->uartclk / baud);\r
+ //gBaud = baud;\r
printk("baud=%d,quot=0x%x\n",baud,quot);\r
if (baud < 2400)\r
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;\r
*/\r
uart->ier &= ~UART_IER_MSI;\r
if ((termios->c_cflag & CRTSCTS) || !(termios->c_cflag & CLOCAL))\r
- {\r
- //uart->ier |= UART_IER_MSI;\r
- //uart->mcr = UART_MCR_RTS;//mcr = UART_MCR_RTS while start RTSCTS\r
- }\r
+ uart->ier |= UART_IER_MSI;\r
\r
uart->lcr = cval;\r
-\r
- spi_out(port, UART_IER, uart->ier, SEL_UART);\r
+ \r
spi_out(port, UART_LCR, cval | UART_LCR_DLAB, SEL_UART);\r
spi_out(port, UART_DLL, quot & 0xff, SEL_UART);\r
spi_out(port, UART_DLM, quot >> 8, SEL_UART);\r
spi_out(port, UART_LCR, cval, SEL_UART);\r
spi_out(port, UART_FCR, fcr, SEL_UART);\r
+ spi_out(port, UART_IER, uart->ier, SEL_UART);//slow\r
+\r
DBG("%s:LINE=%d,baud=%d,uart->ier=0x%x,cval=0x%x,fcr=0x%x,quot=0x%x\n",\r
__FUNCTION__,__LINE__,baud,uart->ier,cval,fcr,quot);\r
spi_uart_write_mctrl(uart, uart->mctrl);\r
static void spi_uart_start_tx(struct spi_uart *uart)\r
{\r
struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
-#if 1\r
- //unsigned long flags;\r
if (!(uart->ier & UART_IER_THRI)) {\r
- //spin_lock_irqsave(&uart->write_lock, flags);\r
uart->ier |= UART_IER_THRI;\r
spi_out(port, UART_IER, uart->ier, SEL_UART);\r
- //spin_unlock_irqrestore(&uart->write_lock, flags); \r
printk("t,");\r
} \r
\r
DBG("%s:UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
-#endif\r
+\r
}\r
\r
static void spi_uart_stop_tx(struct spi_uart *uart)\r
{\r
struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
- //unsigned long flags;\r
if (uart->ier & UART_IER_THRI) {\r
- //spin_lock_irqsave(&uart->write_lock, flags);\r
uart->ier &= ~UART_IER_THRI;\r
spi_out(port, UART_IER, uart->ier, SEL_UART);\r
- //spin_unlock_irqrestore(&uart->write_lock, flags); \r
- //printk("p");\r
}\r
DBG("%s:UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
}\r
struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
unsigned int ch, flag;\r
int max_count = 1024;\r
-\r
+ //printk("rx:");\r
#if SPI_UART_TXRX_BUF\r
int ret,count,stat = 0,num = 0;\r
+ int i;\r
unsigned char buf[SPI_UART_FIFO_LEN];\r
while (max_count >0 )\r
{\r
+ stat = spi_in(port, UART_LSR, SEL_UART);\r
+ if((((stat >> 8) & 0x3f) != 0) && (!(stat & UART_LSR_DR)))\r
+ printk("%s:warning:no receive data but count =%d \n",__FUNCTION__,((stat >> 8) & 0x3f));\r
+ if(!(stat & UART_LSR_DR))\r
+ break;\r
ret = spi_in(port, UART_RX, SEL_UART);\r
count = (ret >> 8) & 0x3f; \r
DBG("%s:count=%d\n",__FUNCTION__,count);\r
printk("err:%s:stat=%d,fail to read uart data because of spi bus error!\n",__FUNCTION__,stat); \r
}\r
max_count -= count;\r
- while (count-- >0 )\r
+ for(i=0;i<count;i++)\r
{\r
flag = TTY_NORMAL;\r
uart->icount.rx++;\r
ch = buf[num++];\r
tty_insert_flip_char(tty, ch, flag);\r
- //printk("%c,",ch);\r
+ //if(gBaud == 1500000)\r
+ //printk("0x%x,",ch);\r
}\r
//printk("\n");\r
- }\r
+ } \r
\r
tty_flip_buffer_push(tty); \r
+ //if(gBaud == 1500000)\r
+ //printk("\n");\r
\r
#else \r
- //printk("rx:");\r
while (--max_count >0 )\r
{\r
ch = spi_in(port, UART_RX, SEL_UART);//\r
if (circ_empty(xmit))\r
break;\r
buf[SPI_UART_FIFO_LEN - count] = xmit->buf[xmit->tail];\r
+ //if(gBaud == 1500000)\r
+ //printk("0x%x,",buf[SPI_UART_FIFO_LEN - count]&0xff);\r
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);\r
uart->icount.tx++;\r
--count;\r
+\r
}\r
+ //if(gBaud == 1500000)\r
+ //printk("\n");\r
if(SPI_UART_FIFO_LEN - count > 0)\r
spi_uart_write_buf(uart,buf,SPI_UART_FIFO_LEN - count);\r
#else\r
DBG("uart->tty->hw_stopped = %d\n",uart->tty->hw_stopped);\r
}\r
\r
-#if 0\r
+#if 1\r
static void spi_uart_check_modem_status(struct spi_uart *uart)\r
{\r
int status;\r
spi_uart_receive_chars(uart, &lsr); \r
}\r
\r
- //spi_uart_check_modem_status(uart);\r
+ spi_uart_check_modem_status(uart);\r
\r
\r
if (lsr & UART_LSR_THRE)\r