#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