*.lzma
*.patch
*.gcno
+Untitled Project.*
#
# Top-level generic files
.cfg_gpio = rk2818_i2c1_cfg_gpio,
};
+struct rk2818_i2c_platform_data default_i2c2_data = {
+ .bus_num = 2,
+ .flags = 0,
+ .slave_addr = 0xff,
+ .scl_rate = 400*1000,
+
+};
+struct rk2818_i2c_platform_data default_i2c3_data = {
+
+ .bus_num = 3,
+ .flags = 0,
+ .slave_addr = 0xff,
+ .scl_rate = 400*1000,
+
+};
static struct i2c_board_info __initdata board_i2c0_devices[] = {
#if defined (CONFIG_RK1000_CONTROL)
{
{},
};
+static struct i2c_board_info __initdata board_i2c2_devices[] = {
+
+};
+static struct i2c_board_info __initdata board_i2c3_devices[] = {
+
+};
/*****************************************************************************************
* SPI devices
*author: lhh
*****************************************************************************************/
static struct spi_board_info board_spi_devices[] = {
+#if defined(CONFIG_SPI_FPGA)
+ { /* fpga ice65l08xx */
+ .modalias = "spi_fpga",
+ .chip_select = 1,
+ .max_speed_hz = 8 * 1000 * 1000,
+ .bus_num = 0,
+ .mode = SPI_MODE_0,
+ },
+#endif
#if defined(CONFIG_ENC28J60)
{ /* net chip */
.modalias = "enc28j60",
#ifdef CONFIG_I2C1_RK2818
&rk2818_device_i2c1,
#endif
+#ifdef CONFIG_SPI_I2C
+ &rk2818_device_i2c2,
+#endif
+#ifdef CONFIG_SPI_I2C
+ &rk2818_device_i2c3,
+#endif
#ifdef CONFIG_SDMMC0_RK2818
&rk2818_device_sdmmc0,
#endif
#ifdef CONFIG_I2C1_RK2818
i2c_register_board_info(default_i2c1_data.bus_num, board_i2c1_devices,
ARRAY_SIZE(board_i2c1_devices));
+#endif
+#ifdef CONFIG_SPI_I2C
+ i2c_register_board_info(default_i2c2_data.bus_num, board_i2c2_devices,
+ ARRAY_SIZE(board_i2c2_devices));
+ i2c_register_board_info(default_i2c3_data.bus_num, board_i2c3_devices,
+ ARRAY_SIZE(board_i2c3_devices));
#endif
platform_add_devices(devices, ARRAY_SIZE(devices));
spi_register_board_info(board_spi_devices, ARRAY_SIZE(board_spi_devices));
.cfg_gpio = rk2818_i2c1_cfg_gpio,
};
+struct rk2818_i2c_platform_data default_i2c2_data = {
+ .bus_num = 2,
+ .flags = 0,
+ .slave_addr = 0xff,
+ .scl_rate = 400*1000,
+
+};
+struct rk2818_i2c_platform_data default_i2c3_data = {
+
+ .bus_num = 3,
+ .flags = 0,
+ .slave_addr = 0xff,
+ .scl_rate = 400*1000,
+
+};
static struct i2c_board_info __initdata board_i2c0_devices[] = {
#if defined (CONFIG_RK1000_CONTROL)
{
.addr = 0x79,
.flags = 0,
},
+#endif
+#if defined (CONFIG_GS_MMA7660)
+ {
+ .type = "gs_mma7660",
+ .addr = 0x4c,
+ .flags = 0,
+ .irq = RK2818_PIN_PE3,
+ },
#endif
{},
};
+static struct i2c_board_info __initdata board_i2c2_devices[] = {
+
+};
+static struct i2c_board_info __initdata board_i2c3_devices[] = {
+
+};
/*****************************************************************************************
* SPI devices
*author: lhh
*****************************************************************************************/
static struct spi_board_info board_spi_devices[] = {
+#if defined(CONFIG_SPI_FPGA)
+ { /* fpga ice65l08xx */
+ .modalias = "spi_fpga",
+ .chip_select = 1,
+ .max_speed_hz = 8 * 1000 * 1000,
+ .bus_num = 0,
+ .mode = SPI_MODE_0,
+ },
+#endif
#if defined(CONFIG_ENC28J60)
{ /* net chip */
.modalias = "enc28j60",
#ifdef CONFIG_I2C1_RK2818
&rk2818_device_i2c1,
#endif
+#ifdef CONFIG_SPI_I2C
+ &rk2818_device_i2c2,
+#endif
+#ifdef CONFIG_SPI_I2C
+ &rk2818_device_i2c3,
+#endif
#ifdef CONFIG_SDMMC0_RK2818
&rk2818_device_sdmmc0,
#endif
#ifdef CONFIG_I2C1_RK2818
i2c_register_board_info(default_i2c1_data.bus_num, board_i2c1_devices,
ARRAY_SIZE(board_i2c1_devices));
+#endif
+#ifdef CONFIG_SPI_I2C
+ i2c_register_board_info(default_i2c2_data.bus_num, board_i2c2_devices,
+ ARRAY_SIZE(board_i2c2_devices));
+ i2c_register_board_info(default_i2c3_data.bus_num, board_i2c3_devices,
+ ARRAY_SIZE(board_i2c3_devices));
#endif
platform_add_devices(devices, ARRAY_SIZE(devices));
spi_register_board_info(board_spi_devices, ARRAY_SIZE(board_spi_devices));
.platform_data = &default_i2c1_data,
},
};
-
+struct platform_device rk2818_device_i2c2 = {
+ .name = "fpga_i2c",
+ .id = 2,
+ .dev = {
+ .platform_data = &default_i2c2_data,
+ },
+};
+struct platform_device rk2818_device_i2c3 = {
+ .name = "fpga_i2c",
+ .id = 3,
+ .dev = {
+ .platform_data = &default_i2c3_data,
+ },
+};
struct platform_device rk2818_device_uart0 = {
.name = "rk2818_serial",
.id = 0,
source "drivers/spi/Kconfig"
+source "drivers/fpga/Kconfig"
+
source "drivers/pps/Kconfig"
source "drivers/gpio/Kconfig"
obj-$(CONFIG_ATA) += ata/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
+obj-$(CONFIG_SPI_FPGA) += fpga/
obj-y += net/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_FUSION) += message/
--- /dev/null
+#\r
+# FPGA driver configuration\r
+#\r
+# NOTE: This FPGA(ice65l08xx) support spi2uart,spi2gpio,spi2i2c and spi2dpram.\r
+#\r
+\r
+menuconfig SPI_FPGA\r
+ bool "SPI FPGA(ice65l08xx) support"\r
+ #depends on SPI && SPIM_RK2818\r
+ help\r
+ This fpga(ice65l08xx) is used for spi2uart,spi2gpio,spi2i2c,spi2dpram.\r
+ \r
+if SPI_FPGA\r
+\r
+config SPI_FPGA_INIT\r
+ tristate "spi fpga init support"\r
+ depends on SPI && SPIM_RK2818\r
+ help\r
+ fpga driver for spi init.\r
+\r
+if SPI_FPGA_INIT\r
+ config SPI_FPGA_INIT_DEBUG\r
+ boolean "Debug support for spi fpga init drivers"\r
+ depends on DEBUG_KERNEL\r
+ help\r
+ Say "yes" to enable debug messaging in spi fpga init drivers.\r
+endif\r
+\r
+config SPI_UART\r
+ tristate "spi to uart support"\r
+ depends on SPI && SPIM_RK2818\r
+ help\r
+ fpga driver for spi to uart.\r
+ \r
+if SPI_UART\r
+ config SPI_UART_DEBUG\r
+ boolean "Debug support for spi to uart drivers"\r
+ depends on DEBUG_KERNEL\r
+ help\r
+ Say "yes" to enable debug messaging in spi to uart drivers.\r
+endif\r
+\r
+config SPI_GPIO\r
+ tristate "spi to gpio support"\r
+ depends on SPI && SPIM_RK2818\r
+ help\r
+ fpga driver for spi to gpio.\r
+\r
+if SPI_GPIO\r
+ config SPI_GPIO_DEBUG\r
+ boolean "Debug support for spi to gpio drivers"\r
+ depends on DEBUG_KERNEL\r
+ help\r
+ Say "yes" to enable debug messaging in spi to gpio drivers.\r
+endif\r
+\r
+config SPI_I2C\r
+ tristate "spi to i2c support"\r
+ depends on SPI && SPIM_RK2818\r
+ help\r
+ fpga driver for spi to i2c.\r
+\r
+if SPI_I2C\r
+ config SPI_I2C_DEBUG\r
+ boolean "Debug support for spi to i2c drivers"\r
+ depends on DEBUG_KERNEL\r
+ help\r
+ Say "yes" to enable debug messaging in spi to i2c drivers.\r
+endif\r
+\r
+config SPI_DPRAM\r
+ tristate "spi to dpram support"\r
+ depends on SPI && SPIM_RK2818\r
+ help\r
+ fpga driver for spi to dpram.\r
+\r
+if SPI_DPRAM\r
+ config SPI_DPRAM_DEBUG\r
+ boolean "Debug support for spi to dpram drivers"\r
+ depends on DEBUG_KERNEL\r
+ help\r
+ Say "yes" to enable debug messaging in spi to dpram drivers.\r
+endif\r
+\r
+endif\r
+\r
--- /dev/null
+#\r
+# Makefile for fpga(ice65l08xx) drivers.\r
+#\r
+\r
+# fpga drivers\r
+obj-$(CONFIG_SPI_FPGA_INIT) += spi_fpga_init.o\r
+obj-$(CONFIG_SPI_UART) += spi_uart.o\r
+obj-$(CONFIG_SPI_GPIO) += spi_gpio.o\r
+obj-$(CONFIG_SPI_I2C) += spi_i2c.o\r
+obj-$(CONFIG_SPI_DPRAM) += spi_dpram.o
\ No newline at end of file
--- /dev/null
+#include <linux/module.h>\r
+#include <linux/init.h>\r
+#include <linux/kernel.h>\r
+#include <linux/mutex.h>\r
+#include <linux/serial_reg.h>\r
+#include <linux/circ_buf.h>\r
+#include <linux/gfp.h>\r
+#include <linux/tty.h>\r
+#include <linux/tty_flip.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/spi/spi.h>\r
+#include <linux/delay.h>\r
+#include <linux/module.h>\r
+#include <linux/ioport.h>\r
+#include <linux/console.h>\r
+#include <linux/sysrq.h>\r
+#include <mach/gpio.h>\r
+#include <mach/iomux.h>\r
+#include <asm/io.h>\r
+#include <asm/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/poll.h>\r
+#include <linux/sched.h>\r
+#include <linux/kthread.h>\r
+#include <linux/jiffies.h>\r
+#include <linux/i2c.h>\r
+#include <mach/rk2818_iomap.h>\r
+\r
+#include "spi_fpga.h"\r
+\r
+#if defined(CONFIG_SPI_DPRAM_DEBUG)\r
+#define DBG(x...) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define SPI_DPRAM_TEST 0\r
+/*****RAM0 for bp write and ap read*****/\r
+#define SPI_DPRAM_BPWRITE_START 0\r
+#define SPI_DPRAM_BPWRITE_END 0x0fff\r
+#define SPI_DPRAM_BPWRITE_SIZE 0x1000 // 4K*16bits\r
+/*****RAM1 for ap write and bp read*****/\r
+#define SPI_DPRAM_APWRITE_START 0x1000\r
+#define SPI_DPRAM_APWRITE_END 0x17ff\r
+#define SPI_DPRAM_APWRITE_SIZE 0x0800 // 2K*16bits\r
+/*****RAM2 for log of bp write and ap read*****/\r
+#define SPI_DPRAM_LOG_BPWRITE_START 0x2000\r
+#define SPI_DPRAM_LOG_BPWRITE_END 0x23ff\r
+#define SPI_DPRAM_LOG_BPWRITE_SIZE 0x0400 // 1K*16bits\r
+/*****RAM3 for log of ap write and bp read*****/\r
+#define SPI_DPRAM_LOG_APWRITE_START 0x3000\r
+#define SPI_DPRAM_LOG_APWRITE_END 0x33ff\r
+#define SPI_DPRAM_LOG_APWRITE_SIZE 0x0400 // 1K*16bits\r
+\r
+/*\r
+#define BP_SEND_IN_PTR 0x3FEE\r
+#define BP_SEND_OUT_PTR 0x3FF0\r
+\r
+#define BP_READ_IN_PTR 0x3FF2\r
+#define BP_READ_OUT_PTR 0x3FF4\r
+\r
+#define BP_SEND_IN_PTR 0x3FF6\r
+#define BP_SEND_OUT_PTR 0x3FF8\r
+\r
+#define BP_READ_IN_PTR 0x3FFA\r
+#define BP_READ_OUT_PTR 0x3FFC\r
+\r
+#define BP_SEND_AP_Mailbox£º0x3ffe\r
+#define AP_SEND_BP_Mailbox£º0x3fff\r
+\r
+*/\r
+\r
+#define SPI_DPRAM_PTR0_BPWRITE_APREAD 0X3fee\r
+#define SPI_DPRAM_PTR0_APWRITE_BPREAD 0X3ff0\r
+\r
+#define SPI_DPRAM_PTR1_BPWRITE_APREAD 0x3ff2\r
+#define SPI_DPRAM_PTR1_APWRITE_BPREAD 0x3ff4\r
+\r
+#define SPI_DPRAM_PTR2_BPWRITE_APREAD 0x3ff6\r
+#define SPI_DPRAM_PTR2_APWRITE_BPREAD 0x3ff8\r
+\r
+#define SPI_DPRAM_PTR3_BPWRITE_APREAD 0x3ffa\r
+#define SPI_DPRAM_PTR3_APWRITE_BPREAD 0x3ffc\r
+\r
+#define SPI_DPRAM_MAILBOX_BPWRITE 0x3ffe\r
+#define SPI_DPRAM_MAILBOX_APWRITE 0x3fff\r
+\r
+/*mailbox comminication's definition*/\r
+#define MAILBOX_BPWRITE_DATA 0x01\r
+#define MAILBOX_BPREAD_DATA 0x02\r
+#define MAILBOX_APSEND_IRQ 0x03\r
+#define MAILBOX_APSEND_ACK 0x04\r
+\r
+#define TRUE 1\r
+#define FALSE 0\r
+\r
+static int spi_dpram_write_buf(struct spi_dpram *dpram, unsigned short int addr, unsigned char *buf, unsigned int len)\r
+{ \r
+ struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);\r
+ unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL) | ICE_SEL_DPRAM_WRITE);\r
+ unsigned char *tx_buf = port->dpram.ptx; \r
+ int ret;\r
+ *(port->dpram.ptx) = opt;\r
+ *(port->dpram.ptx+1) = ((addr << 1) >> 8) & 0xff;\r
+ *(port->dpram.ptx+2) = ((addr << 1) & 0xff);\r
+ memcpy((port->dpram.ptx + 3), buf, len);\r
+ \r
+ DBG("%s:tx_buf=0x%x,port->dpram.ptx=0x%x,opt=0x%x,addr=0x%x,len=%d\n",__FUNCTION__,(int)tx_buf, (int)port->dpram.ptx, opt, addr&0xffff, len);\r
+ ret = spi_write(port->spi, tx_buf, len+3);\r
+ if(ret)\r
+ printk("spi_write err!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n\n");\r
+ return 0;\r
+}\r
+\r
+static int spi_dpram_read_buf(struct spi_dpram *dpram, unsigned short int addr, unsigned char *buf, unsigned int len)\r
+{\r
+ struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);\r
+ unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL & ICE_SEL_DPRAM_READ));\r
+ unsigned char tx_buf[3];\r
+ unsigned char stat;\r
+ \r
+ tx_buf[0] = opt;\r
+ tx_buf[1] = ((addr << 1) >> 8) & 0xff;\r
+ tx_buf[2] = ((addr << 1) & 0xff);\r
+ \r
+ stat = spi_write_then_read(port->spi, tx_buf, sizeof(tx_buf), buf, len); \r
+ if(stat)\r
+ {\r
+ printk("%s:spi_write_then_read is error!,err=%d\n\n",__FUNCTION__,stat);\r
+ return -1;\r
+ }\r
+ DBG("%s:opt=0x%x,addr=0x%x,len=%d\n",__FUNCTION__, opt, addr&0xffff, len);\r
+ return 0;\r
+\r
+}\r
+\r
+\r
+int spi_dpram_write_ptr(struct spi_dpram *dpram, unsigned short int addr, unsigned int size)\r
+{\r
+ int ret;\r
+ //int i;\r
+ struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);\r
+ unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL) | ICE_SEL_DPRAM_WRITE);\r
+ unsigned char tx_buf[5];\r
+ \r
+ tx_buf[0] = opt;\r
+ tx_buf[1] = ((addr << 1) >> 8) & 0xff;\r
+ tx_buf[2] = ((addr << 1) & 0xff);\r
+ tx_buf[3] = (size>>8);\r
+ tx_buf[4] = (size&0xff);\r
+\r
+ //for(i=0;i<5;i++)\r
+ //{\r
+ // printk("%s:tx_buf[%d]=0x%x\n",__FUNCTION__,i,tx_buf[i]);\r
+ //}\r
+\r
+ ret = spi_write(port->spi, tx_buf, sizeof(tx_buf));\r
+ if(ret)\r
+ {\r
+ printk("%s:spi_write err!\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+ \r
+ return 0;\r
+\r
+}\r
+\r
+\r
+int spi_dpram_read_ptr(struct spi_dpram *dpram, unsigned short int addr)\r
+{\r
+ int ret;\r
+ struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);\r
+ unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL & ICE_SEL_DPRAM_READ));\r
+ unsigned char tx_buf[3],rx_buf[2];\r
+ \r
+ tx_buf[0] = opt;\r
+ tx_buf[1] = ((addr << 1) >> 8) & 0xff;\r
+ tx_buf[2] = ((addr << 1) & 0xff);\r
+\r
+ ret = spi_write_then_read(port->spi, tx_buf, sizeof(tx_buf), rx_buf, sizeof(rx_buf));\r
+ if(ret)\r
+ {\r
+ printk("%s:spi_write_then_read err!\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+ \r
+ ret = (rx_buf[0] << 8) | rx_buf[1];\r
+ \r
+ return (ret&0xffff);\r
+\r
+}\r
+\r
+\r
+int spi_dpram_write_mailbox(struct spi_dpram *dpram, unsigned int mailbox)\r
+{\r
+ int ret;\r
+ struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);\r
+ unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL) | ICE_SEL_DPRAM_WRITE);\r
+ unsigned char tx_buf[5];\r
+ \r
+ tx_buf[0] = opt;\r
+ tx_buf[1] = ((SPI_DPRAM_MAILBOX_APWRITE << 1) >> 8) & 0xff;\r
+ tx_buf[2] = ((SPI_DPRAM_MAILBOX_APWRITE << 1) & 0xff);\r
+ tx_buf[3] = mailbox>>8;\r
+ tx_buf[4] = mailbox&0xff;\r
+ \r
+ ret = spi_write(port->spi, tx_buf, sizeof(tx_buf));\r
+ if(ret)\r
+ {\r
+ printk("%s:spi_write err!\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+ \r
+ return 0;\r
+}\r
+\r
+\r
+int spi_dpram_read_mailbox(struct spi_dpram *dpram)\r
+{\r
+ int ret;\r
+ struct spi_fpga_port *port = container_of(dpram, struct spi_fpga_port, dpram);\r
+ unsigned char opt = ((ICE_SEL_DPRAM & ICE_SEL_DPRAM_NOMAL & ICE_SEL_DPRAM_READ));\r
+ unsigned char tx_buf[3],rx_buf[2];\r
+ \r
+ tx_buf[0] = opt;\r
+ tx_buf[1] = ((SPI_DPRAM_MAILBOX_BPWRITE << 1) >> 8) & 0xff;\r
+ tx_buf[2] = ((SPI_DPRAM_MAILBOX_BPWRITE << 1) & 0xff);\r
+\r
+ ret = spi_write_then_read(port->spi, tx_buf, sizeof(tx_buf), rx_buf, sizeof(rx_buf));\r
+ if(ret)\r
+ {\r
+ printk("%s:spi_write_then_read err!\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+ \r
+ return ((rx_buf[0]<<8) | rx_buf[1]);\r
+}\r
+\r
+\r
+static void spi_dpram_handle_busy(struct spi_device *spi)\r
+{ \r
+\r
+}\r
+\r
+\r
+static void spi_dpram_busy_work_handler(struct work_struct *work)\r
+{\r
+ struct spi_fpga_port *port =\r
+ container_of(work, struct spi_fpga_port, dpram.spi_dpram_busy_work);\r
+ spi_dpram_handle_busy(port->spi);\r
+}\r
+\r
+\r
+static irqreturn_t spi_dpram_busy_irq(int irq, void *dev_id)\r
+{\r
+ struct spi_fpga_port *port = dev_id;\r
+\r
+ DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+ /*\r
+ * Can't do anything in interrupt context because we need to\r
+ * block (spi_sync() is blocking) so fire of the interrupt\r
+ * handling workqueue.\r
+ * Remember that we access ICE65LXX registers through SPI bus\r
+ * via spi_sync() call.\r
+ */\r
+\r
+ queue_work(port->dpram.spi_dpram_busy_workqueue, &port->dpram.spi_dpram_busy_work);\r
+ \r
+ return IRQ_HANDLED;\r
+}\r
+\r
+#if SPI_DPRAM_TEST\r
+#define DPRAM_TEST_LEN 512 //8bit\r
+unsigned char buf_test_dpram[DPRAM_TEST_LEN];\r
+void spi_dpram_work_handler(struct work_struct *work)\r
+{\r
+ int i;\r
+ int ret;\r
+ struct spi_fpga_port *port =\r
+ container_of(work, struct spi_fpga_port, dpram.spi_dpram_work);\r
+ printk("*************test spi_dpram now***************\n");\r
+\r
+ for(i=0; i<(DPRAM_TEST_LEN>>1); i++)\r
+ {\r
+ buf_test_dpram[2*i] = (0xa000+i)>>8;\r
+ buf_test_dpram[2*i+1] = (0xa000+i)&0xff;\r
+ }\r
+#if 0\r
+ //RAM0\r
+ for(i=0;i<(SPI_DPRAM_BPWRITE_SIZE/(DPRAM_TEST_LEN>>1));i++)\r
+ {\r
+ spi_dpram_read_buf(&port->dpram, SPI_DPRAM_BPWRITE_START+(i*DPRAM_TEST_LEN>>1), port->dpram.prx, DPRAM_TEST_LEN);\r
+ }\r
+ \r
+ for(i=0;i<DPRAM_TEST_LEN;i++)\r
+ {\r
+ ret = (*(port->dpram.prx+2*i)<<8) | (*(port->dpram.prx+2*i+1));\r
+ if(ret != 0xa000+i)\r
+ printk("prx[%d]=0x%x ram[%d]=0x%x\n",i,ret&0xffff,i,0xa000+i);\r
+ }\r
+#endif\r
+\r
+ \r
+#if 0 \r
+ //RAM1\r
+ for(i=0;i<(SPI_DPRAM_APWRITE_SIZE/(DPRAM_TEST_LEN>>1));i++)\r
+ { \r
+ port->dpram.write_dpram(&port->dpram, ((DPRAM_TEST_LEN*i)>>1)+SPI_DPRAM_APWRITE_START, buf_test_dpram, sizeof(buf_test_dpram));\r
+ mdelay(1);\r
+ }\r
+\r
+ for(i=0;i<DPRAM_TEST_LEN;i++)\r
+ printk("buf_test_dpram[%d]=0x%x\n",i,buf_test_dpram[i]);\r
+ DBG("\n");\r
+#endif\r
+\r
+\r
+#if 0\r
+ //RAM2\r
+ for(i=0;i<(SPI_DPRAM_LOG_BPWRITE_SIZE/(DPRAM_TEST_LEN>>1));i++)\r
+ {\r
+ spi_dpram_read_buf(&port->dpram, SPI_DPRAM_LOG_BPWRITE_START+(i*DPRAM_TEST_LEN>>1), port->dpram.prx, DPRAM_TEST_LEN);\r
+ }\r
+ \r
+ for(i=0;i<DPRAM_TEST_LEN;i++)\r
+ { \r
+ ret = (*(port->dpram.prx+2*i)<<8) | (*(port->dpram.prx+2*i+1));\r
+ if(ret != 0xc000+i)\r
+ printk("prx[%d]=0x%x ram[%d]=0x%x\n",i,ret&0xffff,i,0xc000+i);\r
+ }\r
+#endif\r
+\r
+#if 0 \r
+ //RAM3\r
+ for(i=0;i<(SPI_DPRAM_LOG_APWRITE_SIZE/(DPRAM_TEST_LEN>>1));i++)\r
+ { \r
+ spi_dpram_write_buf(&port->dpram, ((DPRAM_TEST_LEN*i)>>1)+SPI_DPRAM_LOG_APWRITE_START, buf_test_dpram, sizeof(buf_test_dpram));\r
+ mdelay(1);\r
+ }\r
+ \r
+ for(i=0;i<DPRAM_TEST_LEN;i++)\r
+ printk("buf_test_dpram[%d]=0x%x\n",i,buf_test_dpram[i]);\r
+ DBG("\n");\r
+#endif\r
+\r
+#if 1\r
+ port->dpram.write_ptr(&port->dpram, SPI_DPRAM_PTR0_APWRITE_BPREAD, SPI_DPRAM_PTR0_APWRITE_BPREAD);\r
+ port->dpram.write_ptr(&port->dpram, SPI_DPRAM_PTR1_APWRITE_BPREAD, SPI_DPRAM_PTR1_APWRITE_BPREAD);\r
+ port->dpram.write_ptr(&port->dpram, SPI_DPRAM_PTR2_APWRITE_BPREAD, SPI_DPRAM_PTR2_APWRITE_BPREAD);\r
+ port->dpram.write_ptr(&port->dpram, SPI_DPRAM_PTR3_APWRITE_BPREAD, SPI_DPRAM_PTR3_APWRITE_BPREAD);\r
+ port->dpram.write_mailbox(&port->dpram, SPI_DPRAM_MAILBOX_APWRITE);\r
+\r
+ ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR0_BPWRITE_APREAD);\r
+ if(ret != SPI_DPRAM_PTR0_BPWRITE_APREAD)\r
+ {\r
+ //ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR0_BPWRITE_APREAD);\r
+ //if(ret != SPI_DPRAM_PTR0_BPWRITE_APREAD)\r
+ printk("SPI_DPRAM_PTR0_BPWRITE_APREAD(0x%x)=0x%x\n",SPI_DPRAM_PTR0_BPWRITE_APREAD,ret);\r
+ }\r
+ \r
+ ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR1_BPWRITE_APREAD);\r
+ if(ret != SPI_DPRAM_PTR1_BPWRITE_APREAD)\r
+ {\r
+ //ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR1_BPWRITE_APREAD);\r
+ //if(ret != SPI_DPRAM_PTR1_BPWRITE_APREAD)\r
+ printk("SPI_DPRAM_PTR1_BPWRITE_APREAD(0x%x)=0x%x\n",SPI_DPRAM_PTR1_BPWRITE_APREAD,ret);\r
+ }\r
+ \r
+ ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR2_BPWRITE_APREAD);\r
+ if(ret != SPI_DPRAM_PTR2_BPWRITE_APREAD)\r
+ {\r
+ //ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR2_BPWRITE_APREAD);\r
+ //if(ret != SPI_DPRAM_PTR2_BPWRITE_APREAD)\r
+ printk("SPI_DPRAM_PTR2_BPWRITE_APREAD(0x%x)=0x%x\n",SPI_DPRAM_PTR2_BPWRITE_APREAD,ret);\r
+ }\r
+\r
+\r
+ ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR3_BPWRITE_APREAD);\r
+ if(ret != SPI_DPRAM_PTR3_BPWRITE_APREAD)\r
+ {\r
+ //ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_PTR3_BPWRITE_APREAD);\r
+ //if(ret != SPI_DPRAM_PTR3_BPWRITE_APREAD) \r
+ printk("SPI_DPRAM_PTR3_BPWRITE_APREAD(0x%x)=0x%x\n",SPI_DPRAM_PTR3_BPWRITE_APREAD,ret);\r
+\r
+ }\r
+ mdelay(10);\r
+\r
+ ret = port->dpram.read_mailbox(&port->dpram);\r
+ if(ret != SPI_DPRAM_MAILBOX_BPWRITE)\r
+ {\r
+ //ret = port->dpram.read_ptr(&port->dpram, SPI_DPRAM_MAILBOX_BPWRITE);\r
+ //if(ret != SPI_DPRAM_MAILBOX_BPWRITE) \r
+ printk("SPI_DPRAM_MAILBOX_BPWRITE(0x%x)=0x%x\n",SPI_DPRAM_MAILBOX_BPWRITE,ret);\r
+ }\r
+\r
+#endif\r
+\r
+\r
+}\r
+\r
+static void spi_testdpram_timer(unsigned long data)\r
+{\r
+ struct spi_fpga_port *port = (struct spi_fpga_port *)data;\r
+ port->dpram.dpram_timer.expires = jiffies + msecs_to_jiffies(1000);\r
+ add_timer(&port->dpram.dpram_timer);\r
+ //schedule_work(&port->gpio.spi_gpio_work);\r
+ queue_work(port->dpram.spi_dpram_workqueue, &port->dpram.spi_dpram_work);\r
+}\r
+\r
+#endif\r
+\r
+\r
+int spi_dpram_handle_irq(struct spi_device *spi)\r
+{\r
+ struct spi_fpga_port *port = spi_get_drvdata(spi);\r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+#if 0\r
+ unsigned char mbox = port->dpram.read_mailbox(&port->dpram);\r
+ unsigned int len;\r
+ switch(mbox)\r
+ {\r
+ case MAILBOX_BPWRITE_DATA:\r
+ len = port->dpram.read_ptr(&port->dpram,SPI_DPRAM_PTR0_BPWRITE_APREAD);\r
+ port->dpram.read_dpram(&port->dpram, SPI_DPRAM_BPWRITE_START, port->dpram.prx, len);\r
+ port->dpram.rec_len += len;\r
+ break;\r
+ case MAILBOX_BPREAD_DATA:\r
+ port->dpram.apwrite_en = TRUE;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+#endif \r
+ return 0;\r
+}\r
+\r
+static int dpr_open(struct inode *inode, struct file *filp)\r
+{\r
+ struct spi_fpga_port *port = pFpgaPort;\r
+\r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ filp->private_data = port;\r
+ port->dpram.rec_len = 0;\r
+ port->dpram.send_len = 0;\r
+ port->dpram.apwrite_en = TRUE;\r
+\r
+ return nonseekable_open(inode, filp);\r
+}\r
+\r
+\r
+static int dpr_close(struct inode *inode, struct file *filp)\r
+{\r
+ struct spi_fpga_port *port = pFpgaPort;\r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ filp->private_data = NULL;\r
+ return 0;\r
+}\r
+\r
+\r
+static ssize_t dpr_read (struct file *filp, char __user *buffer, size_t count, loff_t *ppos)\r
+{\r
+ //int ret;\r
+ struct spi_fpga_port *port = filp->private_data;\r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ \r
+ while(port->dpram.rec_len == 0)\r
+ {\r
+ if( filp->f_flags&O_NONBLOCK )\r
+ return -EAGAIN;\r
+\r
+ if(wait_event_interruptible(port->dpram.recq, (port->dpram.rec_len != 0)))\r
+ { \r
+ printk("%s:NO data in dpram!\n",__FUNCTION__);\r
+ return -ERESTARTSYS; \r
+ }\r
+ }\r
+\r
+ /*read data from buffer*/\r
+ if(copy_to_user((char*)buffer, (char *)port->dpram.prx, port->dpram.rec_len))\r
+ {\r
+ printk("%s:copy_to_user err!\n",__FUNCTION__);\r
+ return -EFAULT;\r
+ }\r
+\r
+ count = port->dpram.rec_len;\r
+ port->dpram.rec_len = 0;\r
+ \r
+ return count;\r
+}\r
+\r
+\r
+static ssize_t dpr_write (struct file *filp, const char __user *buffer, size_t count, loff_t *ppos)\r
+{\r
+ struct spi_fpga_port *port = filp->private_data;\r
+ //int ret;\r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port); \r
+ \r
+ while(port->dpram.apwrite_en == FALSE)\r
+ {\r
+ if(filp->f_flags & O_NONBLOCK)\r
+ return -EAGAIN;\r
+ if(wait_event_interruptible(port->dpram.sendq, (port->dpram.apwrite_en == TRUE)))\r
+ return -ERESTARTSYS;\r
+ }\r
+\r
+ if(count > port->dpram.max_send_len)\r
+ {\r
+ count = port->dpram.max_send_len;\r
+ printk("%s:count is large than max_send_len(%d),and only %d's bytes is valid!\n",__FUNCTION__,count,count);\r
+ }\r
+ \r
+ if(copy_from_user((char *)port->dpram.ptx,buffer,count))\r
+ {\r
+ printk("%s:copy_from_user err!\n",__FUNCTION__);\r
+ return -EFAULT;\r
+ }\r
+\r
+ port->dpram.write_dpram(&port->dpram, SPI_DPRAM_APWRITE_START, port->dpram.ptx, count);\r
+ port->dpram.apwrite_en = FALSE; //clear apwrite_en after wirte data to dpram\r
+ port->dpram.write_mailbox(&port->dpram, MAILBOX_APSEND_IRQ); //send irq to bp after ap write data to dpram\r
+\r
+ return count;\r
+ \r
+}\r
+\r
+\r
+unsigned int dpr_poll(struct file *filp, struct poll_table_struct * wait)\r
+{\r
+ unsigned int mask = 0;\r
+ struct spi_fpga_port *port = filp->private_data;\r
+\r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+\r
+ return mask;\r
+}\r
+\r
+\r
+static struct file_operations dpr_fops={\r
+ .owner= THIS_MODULE,\r
+ .open= dpr_open,\r
+ .release= dpr_close,\r
+ .read= dpr_read,\r
+ .write= dpr_write,\r
+ .poll = dpr_poll,\r
+};\r
+\r
+int spi_dpram_register(struct spi_fpga_port *port)\r
+{\r
+ char b[28];\r
+ int ret;\r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ port->dpram.prx = (char *)kzalloc(sizeof(char)*((SPI_DPRAM_BPWRITE_SIZE<<1)+6), GFP_KERNEL);\r
+ if(port->dpram.prx == NULL)\r
+ {\r
+ printk("port->dpram.prx kzalloc err!!!\n");\r
+ return -ENOMEM;\r
+ }\r
+\r
+ port->dpram.ptx = (char *)kzalloc(sizeof(char)*((SPI_DPRAM_APWRITE_SIZE<<1)+6), GFP_KERNEL);\r
+ if(port->dpram.ptx == NULL)\r
+ {\r
+ printk("port->dpram.ptx kzalloc err!!!\n");\r
+ return -ENOMEM;\r
+ }\r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ sprintf(b, "spi_dpram_busy_workqueue");\r
+ port->dpram.spi_dpram_busy_workqueue = create_freezeable_workqueue(b);\r
+ if (!port->dpram.spi_dpram_busy_workqueue) {\r
+ printk("cannot create workqueue\n");\r
+ return -EBUSY;\r
+ } \r
+ INIT_WORK(&port->dpram.spi_dpram_busy_work, spi_dpram_busy_work_handler);\r
+ \r
+#if SPI_DPRAM_TEST\r
+ sprintf(b, "spi_dpram_workqueue");\r
+ port->dpram.spi_dpram_workqueue = create_freezeable_workqueue(b);\r
+ if (!port->dpram.spi_dpram_workqueue) {\r
+ printk("cannot create workqueue\n");\r
+ return -EBUSY;\r
+ }\r
+ INIT_WORK(&port->dpram.spi_dpram_work, spi_dpram_work_handler);\r
+\r
+ setup_timer(&port->dpram.dpram_timer, spi_testdpram_timer, (unsigned long)port);\r
+ port->dpram.dpram_timer.expires = jiffies+2000;//>1000ms\r
+ add_timer(&port->dpram.dpram_timer);\r
+#endif\r
+\r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+\r
+ //init the struct spi_dpram\r
+ init_waitqueue_head(&port->dpram.recq);\r
+ init_waitqueue_head(&port->dpram.sendq);\r
+ port->dpram.rec_len = 0;\r
+ port->dpram.send_len = 0;\r
+ port->dpram.apwrite_en = TRUE;\r
+ port->dpram.max_rec_len = SPI_DPRAM_BPWRITE_SIZE;\r
+ port->dpram.max_send_len = SPI_DPRAM_APWRITE_SIZE;\r
+ port->dpram.miscdev.minor = MISC_DYNAMIC_MINOR;\r
+ port->dpram.miscdev.name = "spi_dpram";//spi_fpga\r
+ port->dpram.miscdev.fops = &dpr_fops;\r
+\r
+ ret = misc_register(&port->dpram.miscdev);\r
+ if(ret)\r
+ {\r
+ printk("misc_register err!!!\n");\r
+ goto err0;\r
+ }\r
+\r
+ port->dpram.write_dpram = spi_dpram_write_buf;\r
+ port->dpram.read_dpram = spi_dpram_read_buf;\r
+ port->dpram.write_ptr = spi_dpram_write_ptr;\r
+ port->dpram.read_ptr = spi_dpram_read_ptr;\r
+ port->dpram.write_mailbox = spi_dpram_write_mailbox;\r
+ port->dpram.read_mailbox = spi_dpram_read_mailbox;\r
+ \r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+\r
+ ret = gpio_request(SPI_DPRAM_BUSY_PIN, NULL);\r
+ if (ret) {\r
+ printk("%s:failed to request fpga busy gpio\n",__FUNCTION__);\r
+ goto err1;\r
+ }\r
+\r
+ gpio_pull_updown(SPI_DPRAM_BUSY_PIN,GPIOPullUp);\r
+ ret = request_irq(gpio_to_irq(SPI_DPRAM_BUSY_PIN),spi_dpram_busy_irq,IRQF_TRIGGER_RISING,NULL,port);\r
+ if(ret)\r
+ {\r
+ printk("unable to request fpga busy_gpio irq\n");\r
+ goto err2;\r
+ } \r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ \r
+ return 0;\r
+ \r
+err2:\r
+ free_irq(gpio_to_irq(SPI_DPRAM_BUSY_PIN),NULL);\r
+err1: \r
+ gpio_free(SPI_DPRAM_BUSY_PIN);\r
+err0:\r
+ kfree(port->dpram.prx);\r
+ kfree(port->dpram.ptx);\r
+\r
+ return ret;\r
+ \r
+}\r
+\r
+int spi_dpram_unregister(struct spi_fpga_port *port)\r
+{\r
+\r
+ return 0;\r
+}\r
+\r
+\r
--- /dev/null
+/*\r
+defines of FPGA chip ICE65L08's register \r
+*/\r
+\r
+#ifndef SPI_UART_H\r
+#define SPI_UART_H\r
+\r
+#define SPI_FPGA_INT_PIN RK2818_PIN_PA4\r
+#define SPI_DPRAM_BUSY_PIN RK2818_PIN_PA2\r
+#define SPI_FPGA_STANDBY_PIN RK2818_PIN_PH7\r
+\r
+struct uart_icount {\r
+ __u32 cts;\r
+ __u32 dsr;\r
+ __u32 rng;\r
+ __u32 dcd;\r
+ __u32 rx;\r
+ __u32 tx;\r
+ __u32 frame;\r
+ __u32 overrun;\r
+ __u32 parity;\r
+ __u32 brk;\r
+};\r
+\r
+struct spi_uart\r
+{\r
+ struct workqueue_struct *spi_uart_workqueue;\r
+ struct work_struct spi_uart_work; \r
+ struct timer_list uart_timer;\r
+ struct tty_struct *tty;\r
+ struct kref kref;\r
+ struct mutex open_lock;\r
+ struct task_struct *in_spi_uart_irq; \r
+ struct circ_buf xmit;\r
+ struct uart_icount icount;\r
+ spinlock_t write_lock;\r
+ spinlock_t irq_lock;\r
+ unsigned int index;\r
+ unsigned int opened;\r
+ unsigned int regs_offset;\r
+ unsigned int uartclk;\r
+ unsigned int mctrl;\r
+ unsigned int read_status_mask;\r
+ unsigned int ignore_status_mask;\r
+ unsigned char x_char;\r
+ unsigned char ier;\r
+ unsigned char lcr;\r
+\r
+};\r
+\r
+struct spi_gpio\r
+{\r
+ struct workqueue_struct *spi_gpio_workqueue;\r
+ struct work_struct spi_gpio_work;\r
+ struct timer_list gpio_timer;\r
+\r
+};\r
+\r
+struct spi_i2c\r
+{\r
+ struct workqueue_struct *spi_i2c_workqueue;\r
+ struct work_struct spi_i2c_work;\r
+ struct timer_list i2c_timer;\r
+ struct i2c_adapter *adapter;\r
+ struct i2c_client *client;\r
+ spinlock_t i2c_lock ; \r
+ unsigned char interrupt;\r
+ unsigned char i2c_data_width[2];\r
+ unsigned int speed[2];\r
+};\r
+\r
+struct spi_dpram\r
+{\r
+ struct workqueue_struct *spi_dpram_workqueue;\r
+ struct work_struct spi_dpram_work; \r
+ struct workqueue_struct *spi_dpram_busy_workqueue;\r
+ struct work_struct spi_dpram_busy_work;\r
+ struct timer_list dpram_timer;\r
+ unsigned char *prx;\r
+ unsigned char *ptx;\r
+ unsigned int rec_len;\r
+ unsigned int send_len;\r
+ unsigned int max_rec_len;\r
+ unsigned int max_send_len;\r
+ volatile int apwrite_en;\r
+ unsigned short int dpram_addr;\r
+ struct semaphore rec_sem; \r
+ struct semaphore send_sem; \r
+ wait_queue_head_t recq, sendq;\r
+ struct miscdevice miscdev;\r
+\r
+ int (*write_dpram)(struct spi_dpram *, unsigned short int addr, unsigned char *buf, unsigned int len);\r
+ int (*read_dpram)(struct spi_dpram *, unsigned short int addr, unsigned char *buf, unsigned int len);\r
+ int (*write_ptr)(struct spi_dpram *, unsigned short int addr, unsigned int size);\r
+ int (*read_ptr)(struct spi_dpram *, unsigned short int addr);\r
+ int (*write_mailbox)(struct spi_dpram *, unsigned int mailbox);\r
+ int (*read_mailbox)(struct spi_dpram *);\r
+\r
+};\r
+\r
+struct spi_fpga_port {\r
+ const char *name;\r
+ struct spi_device *spi;\r
+ struct mutex spi_lock;\r
+ struct workqueue_struct *fpga_irq_workqueue;\r
+ struct work_struct fpga_irq_work; \r
+ struct timer_list fpga_timer;\r
+ /*spi2uart*/\r
+#ifdef CONFIG_SPI_UART\r
+ struct spi_uart uart;\r
+#endif\r
+ /*spi2gpio*/\r
+#ifdef CONFIG_SPI_GPIO\r
+ struct spi_gpio gpio;\r
+#endif\r
+ /*spi2i2c*/\r
+#ifdef CONFIG_SPI_I2C\r
+ struct spi_i2c i2c;\r
+#endif\r
+ /*spi2dpram*/\r
+#ifdef CONFIG_SPI_DPRAM\r
+ struct spi_dpram dpram;\r
+#endif\r
+\r
+};\r
+\r
+\r
+#define ICE_CC72 0\r
+#define ICE_CC196 1\r
+#define FPGA_TYPE ICE_CC196\r
+#define SEL_UART 0\r
+#define SEL_GPIO 1\r
+#define SEL_I2C 2\r
+#define SEL_DPRAM 3\r
+\r
+/* CMD */\r
+#define ICE_SEL_UART (SEL_UART<<6)\r
+#define ICE_SEL_GPIO (SEL_GPIO<<6)\r
+#define ICE_SEL_I2C (SEL_I2C<<6)\r
+#define ICE_SEL_DPRAM (SEL_DPRAM<<6)\r
+\r
+#define ICE_SEL_WRITE (~(1<<5))\r
+#define ICE_SEL_READ (1<<5)\r
+\r
+#define ICE_SEL_UART_CH(ch) ((ch&0x03)<<3)\r
+#define ICE_SEL_READ_INT_TYPE (3<<3)\r
+\r
+/*read int type*/\r
+#define ICE_INT_TYPE_UART0 (~(1<<0))\r
+#define ICE_INT_TYPE_UART1 (~(1<<1))\r
+#define ICE_INT_TYPE_UART2 (~(1<<2))\r
+#define ICE_INT_TYPE_I2C2 (~(1<<3))\r
+#define ICE_INT_TYPE_I2C3 (~(1<<4))\r
+#define ICE_INT_TYPE_GPIO (~(1<<5))\r
+#define ICE_INT_TYPE_DPRAM (~(1<<6))\r
+\r
+#define ICE_INT_I2C_ACK (~(1<<0))\r
+#define ICE_INT_I2C_READ (~(1<<1))\r
+#define ICE_INT_I2C_WRITE (~(1<<2))\r
+\r
+/*spi to uart*/\r
+#define ICE_RXFIFO_FULL (1<<8)\r
+#define ICE_RXFIFO_NOT_FULL (~(1<<8))\r
+#define ICE_RXFIFO_EMPTY (1<<9)\r
+#define ICE_RXFIFO_NOT_EMPTY (~(1<<9))\r
+#define ICE_TXFIFO_FULL (1<<10)\r
+#define ICE_TXFIFO_NOT_FULL (~(1<<10))\r
+#define ICE_TXFIFO_EMPTY (1<<11)\r
+#define ICE_TXFIFO_NOT_EMPTY (~(1<<11))\r
+\r
+\r
+/*spi to gpio*/\r
+#define ICE_SEL_GPIO0 (0X00<<3) //INT/GPIO0\r
+#define ICE_SEL_GPIO1 (0X02<<2) //GPIO1\r
+#define ICE_SEL_GPIO2 (0X03<<2)\r
+#define ICE_SEL_GPIO3 (0X04<<2)\r
+#define ICE_SEL_GPIO4 (0X05<<2)\r
+#define ICE_SEL_GPIO5 (0X06<<2)\r
+\r
+#define ICE_SEL_GPIO0_TYPE (0X00)\r
+#define ICE_SEL_GPIO0_DIR (0X01)\r
+#define ICE_SEL_GPIO0_DATA (0X02)\r
+#define ICE_SEL_GPIO0_INT_EN (0X03)\r
+#define ICE_SEL_GPIO0_INT_TRI (0X04)\r
+#define ICE_SEL_GPIO0_INT_STATE (0X05)\r
+\r
+#define ICE_SEL_GPIO_DIR (0X01)\r
+#define ICE_SEL_GPIO_DATA (0X02)\r
+\r
+/*spi to i2c*/\r
+\r
+typedef enum I2C_ch\r
+{\r
+ I2C_CH0,\r
+ I2C_CH1,\r
+ I2C_CH2,\r
+ I2C_CH3 \r
+}eI2C_ch_t;\r
+\r
+#define ICE_SEL_I2C_START (0<<0)\r
+#define ICE_SEL_I2C_STOP (1<<0)\r
+#define ICE_SEL_I2C_RESTART (2<<0)\r
+#define ICE_SEL_I2C_TRANS (3<<0)\r
+#define ICE_SEL_I2C_SMASK (~(3<<0))\r
+#define ICE_SEL_I2C_CH2 (0<<2)\r
+#define ICE_SEL_I2C_CH3 (1<<2)\r
+#define ICE_SEL_I2C_DEFMODE (0<<3)\r
+#define ICE_SEL_I2C_FIFO (1<<3)\r
+#define ICE_SEL_I2C_SPEED (2<<3)\r
+#define ICE_SEL_I2C_INT (3<<3)\r
+#define ICE_SEL_I2C_MMASK (~(3<<3))\r
+\r
+#define ICE_I2C_SLAVE_WRITE (0<<0)\r
+#define ICE_I2C_SLAVE_READ (1<<0)\r
+\r
+\r
+\r
+#define ICE_SEL_I2C_W8BIT (0<<2)\r
+#define ICE_SEL_I2C_W16BIT (1<<2)\r
+#define ICE_SEL_I2C_DWIDTH (2<<2)\r
+\r
+#define ICE_I2C_AD_ACK (~(1<<0))\r
+#define ICE_I2C_WRITE_ACK (~(1<<1))\r
+#define ICE_I2C_READ_ACK (~(1<<2))\r
+\r
+#define ICE_SEL_I2C_CH2_8BIT (0<<2)\r
+#define ICE_SEL_I2C_CH2_16BIT (1<<2)\r
+#define ICE_SEL_I2C_CH2_MIX (2<<2)\r
+\r
+#define ICE_SEL_I2C_CH3_8BIT (4<<2)\r
+#define ICE_SEL_I2C_CH3_16BIT (5<<2)\r
+#define ICE_SEL_I2C_CH3_MIX (6<<2)\r
+#define ICE_SEL_I2C_RD_A (7<<2)\r
+#define ICE_SEL_I2C_MASK (7<<2)\r
+#define ICE_SEL_I2C_ACK3 (1<<1)\r
+#define ICE_SEL_I2C_ACK2 (0<<1)\r
+\r
+#define INT_I2C_WRITE_ACK (2)\r
+#define INT_I2C_WRITE_NACK (3)\r
+#define INT_I2C_READ_ACK (4) \r
+#define INT_I2C_READ_NACK (5)\r
+#define INT_I2C_WRITE_MASK (~(1<<1))\r
+#define INT_I2C_READ_MASK (~(1<<2))\r
+\r
+#define ICE_SET_10K_I2C_SPEED (0x01)\r
+#define ICE_SET_100K_I2C_SPEED (0x02) \r
+#define ICE_SET_200K_I2C_SPEED (0x04)\r
+#define ICE_SET_300K_I2C_SPEED (0x08)\r
+#define ICE_SET_400K_I2C_SPEED (0x10)\r
+\r
+\r
+/*spi to dpram*/\r
+#define ICE_SEL_DPRAM_NOMAL (~(1<<5))\r
+#define ICE_SEL_DPRAM_SEM (1<<5)\r
+#define ICE_SEL_DPRAM_READ (~(1<<4))\r
+#define ICE_SEL_DPRAM_WRITE (1<<4)\r
+#define ICE_SEL_DPRAM_BL1 (0)\r
+#define ICE_SEL_DPRAM_BL32 (1)\r
+#define ICE_SEL_DPRAM_BL64 (2)\r
+#define ICE_SEL_DPRAM_BL128 (3)\r
+#define ICE_SEL_DPRAM_FULL (4)\r
+\r
+#define ICE_SEL_SEM_WRITE (0x7F)\r
+#define ICE_SEL_SEM_READ (0xBF)\r
+#define ICE_SEL_SEM_WRRD (0x3F)\r
+\r
+typedef void (*pSpiFunc)(void); //¶¨Ò庯ÊýÖ¸Õë, ÓÃÓÚµ÷Óþø¶ÔµØÖ·\r
+typedef void (*pSpiFuncIntr)(int,void *);\r
+typedef struct\r
+{\r
+ pSpiFuncIntr gpio_vector;\r
+ void *gpio_devid;\r
+}SPI_GPIO_PDATA;\r
+\r
+\r
+typedef enum eSpiGpioTypeSel\r
+{\r
+ SPI_GPIO0_IS_GPIO = 0,\r
+ SPI_GPIO0_IS_INT,\r
+}eSpiGpioTypeSel_t;\r
+\r
+\r
+\r
+typedef enum eSpiGpioPinInt\r
+{\r
+ SPI_GPIO_INT_DISABLE = 0,\r
+ SPI_GPIO_INT_ENABLE,\r
+}eSpiGpioPinInt_t;\r
+\r
+\r
+typedef enum eSpiGpioIntType \r
+{\r
+ SPI_GPIO_EDGE_FALLING = 0,\r
+ SPI_GPIO_EDGE_RISING,\r
+}eSpiGpioIntType_t;\r
+\r
+typedef enum eSpiGpioPinDirection\r
+{\r
+ SPI_GPIO_IN = 0,\r
+ SPI_GPIO_OUT,\r
+}eSpiGpioPinDirection_t;\r
+\r
+\r
+typedef enum eSpiGpioPinLevel\r
+{\r
+ SPI_GPIO_LOW = 0,\r
+ SPI_GPIO_HIGH,\r
+ SPI_GPIO_LEVEL_ERR,\r
+}eSpiGpioPinLevel_t;\r
+\r
+#if (FPGA_TYPE == ICE_CC72)\r
+typedef enum eSpiGpioPinNum\r
+{\r
+ SPI_GPIO_P0_00 = 0, //GPIO0[0]\r
+ SPI_GPIO_P0_01,\r
+ SPI_GPIO_P0_02,\r
+ SPI_GPIO_P0_03,\r
+ SPI_GPIO_P0_04,\r
+ SPI_GPIO_P0_05, \r
+ \r
+ SPI_GPIO_P2_00, \r
+ SPI_GPIO_P2_01,\r
+ SPI_GPIO_P2_02,\r
+ SPI_GPIO_P2_03,\r
+ SPI_GPIO_P2_04,\r
+ SPI_GPIO_P2_05,\r
+ SPI_GPIO_P2_06,\r
+ SPI_GPIO_P2_07,\r
+ SPI_GPIO_P2_08, \r
+ SPI_GPIO_P2_09 = 15, //GPIO0[15],the last interrupt/gpio pin \r
+ \r
+ SPI_GPIO_P3_00 = 16, //GPIO1[0]\r
+ SPI_GPIO_P3_01,\r
+ SPI_GPIO_P3_02,\r
+ SPI_GPIO_P3_03,\r
+ SPI_GPIO_P3_04,\r
+ SPI_GPIO_P3_05,\r
+ SPI_GPIO_P3_06,\r
+ SPI_GPIO_P3_07,\r
+ SPI_GPIO_P3_08,\r
+ SPI_GPIO_P3_09,\r
+ SPI_GPIO_P0_06 = 26, \r
+ SPI_GPIO_I2C3_SCL,\r
+ SPI_GPIO_I2C3_SDA,\r
+ SPI_GPIO_I2C4_SCL,\r
+ SPI_GPIO_I2C4_SDA,\r
+ \r
+}eSpiGpioPinNum_t;\r
+\r
+#elif (FPGA_TYPE == ICE_CC196)\r
+\r
+typedef enum eSpiGpioPinNum\r
+{\r
+ //GPIO0/INT\r
+ SPI_GPIO_P6_00 = 0, //HS_DET input \r
+ SPI_GPIO_P6_01,\r
+ SPI_GPIO_P6_02,\r
+ SPI_GPIO_P6_03,\r
+ SPI_GPIO_P6_04, //CM3605_POUT_L_INT input\r
+ SPI_GPIO_P6_05, \r
+ SPI_GPIO_P6_06, //CHG_OK input\r
+ SPI_GPIO_P6_07, //HP_HOOK input\r
+ SPI_GPIO_P6_08,\r
+ SPI_GPIO_P6_09,\r
+ SPI_GPIO_P6_10, //DEFSEL input \r
+ SPI_GPIO_P6_11, //FLASH_WP_INT input\r
+ SPI_GPIO_P6_12, //LOW_BATT_INT input\r
+ SPI_GPIO_P6_13, //DC_DET input\r
+ SPI_GPIO_P3_08, \r
+ SPI_GPIO_P3_09 = 15,\r
+\r
+ //GPIO1\r
+ SPI_GPIO_P1_00 = 16, //LCD_ON output\r
+ SPI_GPIO_P1_01, //LCD_PWR_CTRL output\r
+ SPI_GPIO_P1_02, //SD_POW_ON output\r
+ SPI_GPIO_P1_03, //WL_RST_N/WIFI_EN output\r
+ SPI_GPIO_P1_04, //HARDO,input\r
+ SPI_GPIO_P1_05, //SENSOR_PWDN output\r
+ SPI_GPIO_P1_06, //BT_PWR_EN output\r
+ SPI_GPIO_P1_07, //BT_RST output\r
+ SPI_GPIO_P1_08, //BT_WAKE_B output\r
+ SPI_GPIO_P1_09, //LCD_DISP_ON output\r
+ SPI_GPIO_P1_10, //WM_PWR_EN output\r
+ SPI_GPIO_P1_11, //HARD1,input\r
+ SPI_GPIO_P1_12, //VIB_MOTO output\r
+ SPI_GPIO_P1_13, //KEYLED_EN output\r
+ SPI_GPIO_P1_14, //CAM_RST output\r
+ SPI_GPIO_P1_15 = 31, //WL_WAKE_B output\r
+\r
+ //GPIO2\r
+ SPI_GPIO_P2_00 = 32, //Y+YD input\r
+ SPI_GPIO_P2_01, //Y-YU input\r
+ SPI_GPIO_P2_02, //AP_TD_UNDIFED input\r
+ SPI_GPIO_P2_03, //AP_PW_EN_TD output\r
+ SPI_GPIO_P2_04, //AP_RESET_TD output\r
+ SPI_GPIO_P2_05, //AP_SHUTDOWN_TD_PMU output\r
+ SPI_GPIO_P2_06, //AP_RESET_CMMB output\r
+ SPI_GPIO_P2_07, //AP_CHECK_TD_STATUS input\r
+ SPI_GPIO_P2_08, //CHARGE_CURRENT_SEL output\r
+ SPI_GPIO_P2_09, //AP_PWD_CMMB output\r
+ SPI_GPIO_P2_10, //X-XL input\r
+ SPI_GPIO_P2_11, //X+XR input\r
+ SPI_GPIO_P2_12, //LCD_RESET output\r
+ SPI_GPIO_P2_13, //USB_PWR_EN output\r
+ SPI_GPIO_P2_14, //WL_HOST_WAKE_B output\r
+ SPI_GPIO_P2_15 = 47, //TOUCH_SCREEN_RST output\r
+\r
+ //GPIO3\r
+ SPI_GPIO_P0_00 = 48, //\r
+ SPI_GPIO_P0_01,\r
+ SPI_GPIO_P0_02,\r
+ SPI_GPIO_P0_03,\r
+ SPI_GPIO_P0_04,\r
+ SPI_GPIO_P0_05,\r
+ SPI_GPIO_P0_06,\r
+ SPI_GPIO_P0_07,\r
+ SPI_GPIO_P0_08,\r
+ SPI_GPIO_P0_09, //FPGAС°å¸ÃÒý½ÅδÒý³ö C5\r
+ SPI_GPIO_P0_10,\r
+ SPI_GPIO_P0_11,\r
+ SPI_GPIO_P0_12,\r
+ SPI_GPIO_P0_13,\r
+ SPI_GPIO_P0_14,\r
+ SPI_GPIO_P0_15 = 63,\r
+\r
+ //GPIO4\r
+ SPI_GPIO_P4_00 = 64, \r
+ SPI_GPIO_P4_01, \r
+ SPI_GPIO_P4_02,\r
+ SPI_GPIO_P4_03,\r
+ SPI_GPIO_P4_04,\r
+ SPI_GPIO_P4_05,\r
+ SPI_GPIO_P4_06, //CHARGER_INT_END input\r
+ SPI_GPIO_P4_07, //CM3605_PWD output\r
+ SPI_GPIO_P3_00, \r
+ SPI_GPIO_P3_01,\r
+ SPI_GPIO_P3_02,\r
+ SPI_GPIO_P3_03,\r
+ SPI_GPIO_P3_04,\r
+ SPI_GPIO_P3_05,\r
+ SPI_GPIO_P3_06,\r
+ SPI_GPIO_P3_07 = 79, \r
+\r
+ //GPIO5\r
+ SPI_GPIO_P4_08 = 80, //CM3605_PS_SHUTDOWN\r
+ SPI_GPIO_P0_TXD2, //temp\r
+\r
+}eSpiGpioPinNum_t;\r
+\r
+#endif\r
+\r
+\r
+typedef enum eSpiGpioPinIntIsr\r
+{\r
+ SPI_GPIO_IS_INT = 0,\r
+ SPI_GPIO_NO_INT,\r
+}eSpiGpioPinIntIsr_t;\r
+\r
+extern struct spi_fpga_port *pFpgaPort;\r
+extern unsigned int spi_in(struct spi_fpga_port *port, int reg, int type);\r
+extern void spi_out(struct spi_fpga_port *port, int reg, int value, int type);\r
+\r
+#if defined(CONFIG_SPI_UART)\r
+extern void spi_uart_handle_irq(struct spi_device *spi);\r
+extern int spi_uart_register(struct spi_fpga_port *port);\r
+extern int spi_uart_unregister(struct spi_fpga_port *port);\r
+#endif\r
+#if defined(CONFIG_SPI_GPIO)\r
+extern int spi_gpio_int_sel(eSpiGpioPinNum_t PinNum,eSpiGpioTypeSel_t type);\r
+extern int spi_gpio_set_pindirection(eSpiGpioPinNum_t PinNum,eSpiGpioPinDirection_t direction);\r
+extern int spi_gpio_set_pinlevel(eSpiGpioPinNum_t PinNum, eSpiGpioPinLevel_t PinLevel);\r
+extern eSpiGpioPinLevel_t spi_gpio_get_pinlevel(eSpiGpioPinNum_t PinNum);\r
+extern int spi_gpio_enable_int(eSpiGpioPinNum_t PinNum);\r
+extern int spi_gpio_disable_int(eSpiGpioPinNum_t PinNum);\r
+extern int spi_gpio_set_int_trigger(eSpiGpioPinNum_t PinNum,eSpiGpioIntType_t IntType);\r
+extern int spi_gpio_read_iir(void);\r
+extern int spi_request_gpio_irq(eSpiGpioPinNum_t PinNum, pSpiFunc Routine, eSpiGpioIntType_t IntType,void *dev_id);\r
+extern int spi_free_gpio_irq(eSpiGpioPinNum_t PinNum);\r
+extern int spi_gpio_handle_irq(struct spi_device *spi);\r
+extern int spi_gpio_init(void);\r
+extern int spi_gpio_register(struct spi_fpga_port *port);\r
+extern int spi_gpio_unregister(struct spi_fpga_port *port);\r
+#endif\r
+#if defined(CONFIG_SPI_I2C)\r
+extern int spi_i2c_handle_irq(struct spi_fpga_port *port,unsigned char channel);\r
+extern int spi_i2c_register(struct spi_fpga_port *port);\r
+extern int spi_i2c_unregister(struct spi_fpga_port *port);\r
+#endif\r
+#if defined(CONFIG_SPI_DPRAM)\r
+extern int spi_dpram_handle_irq(struct spi_device *spi);\r
+extern int spi_dpram_register(struct spi_fpga_port *port);\r
+extern int spi_dpram_unregister(struct spi_fpga_port *port);\r
+#endif\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ * linux/drivers/fpga/spi_fpga_init.c - spi fpga init driver\r
+ *\r
+ * Copyright (C) 2010 ROCKCHIP, Inc.\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or (at\r
+ * your option) any later version.\r
+ */\r
+\r
+/*\r
+ * Note: fpga ice65l08xx is used for spi2uart,spi2gpio,spi2i2c and spi2dpram.\r
+ * this driver is the entry of all modules's drivers,should be run at first.\r
+ * the struct for fpga is build in the driver,and it is important.\r
+ */\r
+\r
+#include <linux/module.h>\r
+#include <linux/init.h>\r
+#include <linux/kernel.h>\r
+#include <linux/mutex.h>\r
+#include <linux/serial_reg.h>\r
+#include <linux/circ_buf.h>\r
+#include <linux/gfp.h>\r
+#include <linux/tty.h>\r
+#include <linux/tty_flip.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/spi/spi.h>\r
+#include <linux/delay.h>\r
+#include <linux/module.h>\r
+#include <linux/ioport.h>\r
+#include <linux/console.h>\r
+#include <linux/sysrq.h>\r
+#include <mach/gpio.h>\r
+#include <mach/iomux.h>\r
+#include <asm/io.h>\r
+#include <asm/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/poll.h>\r
+#include <linux/sched.h>\r
+#include <linux/kthread.h>\r
+#include <linux/jiffies.h>\r
+#include <linux/i2c.h>\r
+#include <mach/rk2818_iomap.h>\r
+\r
+#include "spi_fpga.h"\r
+\r
+#if defined(CONFIG_SPI_FPGA_INIT_DEBUG)\r
+#define DBG(x...) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+struct spi_fpga_port *pFpgaPort;\r
+\r
+/*------------------------spi¶ÁдµÄ»ù±¾º¯Êý-----------------------*/\r
+unsigned int spi_in(struct spi_fpga_port *port, int reg, int type)\r
+{\r
+ unsigned char index = 0;\r
+ unsigned char tx_buf[1], rx_buf[2], n_rx=2, stat=0;\r
+ unsigned int result=0;\r
+ //printk("index1=%d\n",index);\r
+\r
+ switch(type)\r
+ {\r
+#if defined(CONFIG_SPI_UART)\r
+ case SEL_UART:\r
+ index = port->uart.index;\r
+ reg = (((reg) | ICE_SEL_UART) | ICE_SEL_READ | ICE_SEL_UART_CH(index));\r
+ tx_buf[0] = reg & 0xff;\r
+ rx_buf[0] = 0;\r
+ rx_buf[1] = 0; \r
+ stat = spi_write_then_read(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf), rx_buf, n_rx);\r
+ result = rx_buf[1];\r
+ DBG("%s,SEL_UART reg=0x%x,result=0x%x\n",__FUNCTION__,reg&0xff,result&0xff);\r
+ break;\r
+#endif\r
+\r
+#if defined(CONFIG_SPI_GPIO)\r
+ case SEL_GPIO:\r
+ reg = (((reg) | ICE_SEL_GPIO) | ICE_SEL_READ );\r
+ tx_buf[0] = reg & 0xff;\r
+ rx_buf[0] = 0;\r
+ rx_buf[1] = 0; \r
+ stat = spi_write_then_read(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf), rx_buf, n_rx);\r
+ result = (rx_buf[0] << 8) | rx_buf[1];\r
+ DBG("%s,SEL_GPIO reg=0x%x,result=0x%x\n",__FUNCTION__,reg&0xff,result&0xffff);\r
+ break;\r
+#endif\r
+\r
+#if defined(CONFIG_SPI_I2C)\r
+ case SEL_I2C:\r
+ reg = (((reg) | ICE_SEL_I2C) & ICE_SEL_READ );\r
+ tx_buf[0] = reg & 0xff;\r
+ rx_buf[0] = 0;\r
+ rx_buf[1] = 0; \r
+ stat = spi_write_then_read(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf), rx_buf, n_rx);\r
+ result = (rx_buf[0] << 8) | rx_buf[1];\r
+ DBG("%s,SEL_I2C reg=0x%x,result=0x%x [0x%x] [0x%x]\n",__FUNCTION__,reg&0xff,result&0xffff,rx_buf[0],rx_buf[1]); \r
+ break;\r
+#endif\r
+\r
+#if defined(CONFIG_SPI_DPRAM)\r
+ case SEL_DPRAM:\r
+ reg = (((reg) | ICE_SEL_DPRAM) & ICE_SEL_DPRAM_READ );\r
+ tx_buf[0] = reg & 0xff;\r
+ rx_buf[0] = 0;\r
+ rx_buf[1] = 0; \r
+ stat = spi_write_then_read(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf), rx_buf, n_rx);\r
+ result = (rx_buf[0] << 8) | rx_buf[1];\r
+ DBG("%s,SEL_GPIO reg=0x%x,result=0x%x\n",__FUNCTION__,reg&0xff,result&0xffff); \r
+ break;\r
+#endif\r
+ default:\r
+ printk("Can not support this type!\n");\r
+ break;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+void spi_out(struct spi_fpga_port *port, int reg, int value, int type)\r
+{\r
+ unsigned char index = 0;\r
+ unsigned char tx_buf[3];\r
+ //printk("index2=%d,",index);\r
+ switch(type)\r
+ {\r
+#if defined(CONFIG_SPI_UART)\r
+ case SEL_UART:\r
+ index = port->uart.index;\r
+ reg = ((((reg) | ICE_SEL_UART) & ICE_SEL_WRITE) | ICE_SEL_UART_CH(index));\r
+ tx_buf[0] = reg & 0xff;\r
+ tx_buf[1] = (value>>8) & 0xff;\r
+ tx_buf[2] = value & 0xff;\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
+#endif\r
+\r
+#if defined(CONFIG_SPI_GPIO)\r
+ case SEL_GPIO:\r
+ reg = (((reg) | ICE_SEL_GPIO) & ICE_SEL_WRITE );\r
+ tx_buf[0] = reg & 0xff;\r
+ tx_buf[1] = (value>>8) & 0xff;\r
+ tx_buf[2] = value & 0xff;\r
+ spi_write(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));\r
+ DBG("%s,SEL_GPIO reg=0x%x,value=0x%x\n",__FUNCTION__,reg&0xff,value&0xffff);\r
+ break;\r
+#endif\r
+\r
+#if defined(CONFIG_SPI_I2C)\r
+\r
+ case SEL_I2C:\r
+ reg = (((reg) | ICE_SEL_I2C) & ICE_SEL_WRITE);\r
+ tx_buf[0] = reg & 0xff;\r
+ tx_buf[1] = (value>>8) & 0xff;\r
+ tx_buf[2] = value & 0xff;\r
+ spi_write(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));\r
+ DBG("%s,SEL_I2C reg=0x%x,value=0x%x\n",__FUNCTION__,reg&0xff,value&0xffff); \r
+ break;\r
+#endif\r
+ \r
+#if defined(CONFIG_SPI_DPRAM)\r
+ case SEL_DPRAM:\r
+ reg = (((reg) | ICE_SEL_DPRAM) | ICE_SEL_DPRAM_WRITE );\r
+ tx_buf[0] = reg & 0xff;\r
+ tx_buf[1] = (value>>8) & 0xff;\r
+ tx_buf[2] = value & 0xff;\r
+ spi_write(port->spi, (const u8 *)&tx_buf, sizeof(tx_buf));\r
+ DBG("%s,SEL_DPRAM reg=0x%x,value=0x%x\n",__FUNCTION__,reg&0xff,value&0xffff); \r
+ break;\r
+#endif\r
+\r
+ default:\r
+ printk("Can not support this type!\n");\r
+ break;\r
+ }\r
+\r
+}\r
+\r
+\r
+static void spi_fpga_irq_work_handler(struct work_struct *work)\r
+{\r
+ struct spi_fpga_port *port =\r
+ container_of(work, struct spi_fpga_port, fpga_irq_work);\r
+ struct spi_device *spi = port->spi;\r
+ int ret,uart_ch,gpio_ch;\r
+\r
+ DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+ \r
+ ret = spi_in(port, ICE_SEL_READ_INT_TYPE, SEL_UART);\r
+ if((ret | ICE_INT_TYPE_UART0) == ICE_INT_TYPE_UART0)\r
+ {\r
+#if defined(CONFIG_SPI_UART)\r
+ uart_ch = 0;\r
+ printk("Enter::%s,LINE=%d,uart_ch=%d,uart.index=%d\n",__FUNCTION__,__LINE__,uart_ch,port->uart.index);\r
+ port->uart.index = uart_ch;\r
+ spi_uart_handle_irq(spi);\r
+#endif\r
+ }\r
+ else if((ret | ICE_INT_TYPE_GPIO) == ICE_INT_TYPE_GPIO)\r
+ {\r
+ gpio_ch = 0;\r
+ printk("Enter::%s,LINE=%d,gpio_ch=%d\n",__FUNCTION__,__LINE__,gpio_ch);\r
+#if defined(CONFIG_SPI_GPIO)\r
+ spi_gpio_handle_irq(spi);\r
+#endif\r
+ }\r
+ else if((ret | ICE_INT_TYPE_I2C2) == ICE_INT_TYPE_I2C2)\r
+ {\r
+#if defined(CONFIG_SPI_I2C)\r
+ spi_i2c_handle_irq(port,0);\r
+#endif\r
+ }\r
+ else if((ret | ICE_INT_TYPE_I2C3) == ICE_INT_TYPE_I2C3)\r
+ {\r
+#if defined(CONFIG_SPI_I2C)\r
+ spi_i2c_handle_irq(port,1);\r
+#endif\r
+ }\r
+ else if((ret | ICE_INT_TYPE_DPRAM) == ICE_INT_TYPE_DPRAM)\r
+ {\r
+#if defined(CONFIG_SPI_DPRAM)\r
+ spi_dpram_handle_irq(spi);\r
+#endif\r
+ }\r
+ else\r
+ {\r
+ printk("%s:NO such INT TYPE\n",__FUNCTION__);\r
+ }\r
+\r
+ DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+}\r
+\r
+\r
+static irqreturn_t spi_fpga_irq(int irq, void *dev_id)\r
+{\r
+ struct spi_fpga_port *port = dev_id;\r
+ DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+ /*\r
+ * Can't do anything in interrupt context because we need to\r
+ * block (spi_sync() is blocking) so fire of the interrupt\r
+ * handling workqueue.\r
+ * Remember that we access ICE65LXX registers through SPI bus\r
+ * via spi_sync() call.\r
+ */\r
+ \r
+ //schedule_work(&port->fpga_irq_work);\r
+ queue_work(port->fpga_irq_workqueue, &port->fpga_irq_work);\r
+\r
+ return IRQ_HANDLED;\r
+}\r
+\r
+\r
+static int spi_open_sysclk(int set)\r
+{\r
+ int ret;\r
+ ret = gpio_request(SPI_FPGA_STANDBY_PIN, NULL);\r
+ if (ret) {\r
+ printk("%s:failed to request standby pin\n",__FUNCTION__);\r
+ return ret;\r
+ }\r
+ rk2818_mux_api_set(GPIOH7_HSADCCLK_SEL_NAME,IOMUXB_GPIO1_D7); \r
+ gpio_direction_output(SPI_FPGA_STANDBY_PIN,set);\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+static int __devinit spi_fpga_probe(struct spi_device * spi)\r
+{\r
+ struct spi_fpga_port *port;\r
+ int ret;\r
+ char b[12];\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ /*\r
+ * bits_per_word cannot be configured in platform data\r
+ */\r
+ spi->bits_per_word = 8;\r
+\r
+ ret = spi_setup(spi);\r
+ if (ret < 0)\r
+ return ret;\r
+ \r
+ port = kzalloc(sizeof(struct spi_fpga_port), GFP_KERNEL);\r
+ if (!port)\r
+ return -ENOMEM;\r
+ DBG("port=0x%x\n",(int)port);\r
+\r
+ mutex_init(&port->spi_lock);\r
+\r
+ spi_open_sysclk(GPIO_HIGH);\r
+\r
+ sprintf(b, "fpga_irq_workqueue");\r
+ port->fpga_irq_workqueue = create_freezeable_workqueue(b);\r
+ if (!port->fpga_irq_workqueue) {\r
+ printk("cannot create workqueue\n");\r
+ return -EBUSY;\r
+ }\r
+ INIT_WORK(&port->fpga_irq_work, spi_fpga_irq_work_handler);\r
+ \r
+#if defined(CONFIG_SPI_UART)\r
+ ret = spi_uart_register(port);\r
+ if(ret)\r
+ {\r
+ spi_uart_unregister(port);\r
+ printk("%s:ret=%d,fail to spi_uart_register\n",__FUNCTION__,ret);\r
+ return ret;\r
+ }\r
+#endif\r
+#if defined(CONFIG_SPI_GPIO)\r
+ ret = spi_gpio_register(port);\r
+ if(ret)\r
+ {\r
+ spi_gpio_unregister(port);\r
+ printk("%s:ret=%d,fail to spi_gpio_register\n",__FUNCTION__,ret);\r
+ return ret;\r
+ }\r
+#endif\r
+#if 0 //defined(CONFIG_SPI_I2C)\r
+\r
+ printk("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ ret = spi_i2c_register(port);\r
+ printk("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ if(ret)\r
+ {\r
+ spi_i2c_unregister(port);\r
+ printk("%s:ret=%d,fail to spi_i2c_register\n",__FUNCTION__,ret);\r
+ return ret;\r
+ }\r
+#endif\r
+#if defined(CONFIG_SPI_DPRAM)\r
+ ret = spi_dpram_register(port);\r
+ if(ret)\r
+ {\r
+ spi_dpram_unregister(port);\r
+ printk("%s:ret=%d,fail to spi_dpram_register\n",__FUNCTION__,ret);\r
+ return ret;\r
+ }\r
+#endif\r
+ port->spi = spi;\r
+ spi_set_drvdata(spi, port);\r
+ \r
+ ret = gpio_request(SPI_FPGA_INT_PIN, NULL);\r
+ if (ret) {\r
+ printk("%s:failed to request fpga intterupt gpio\n",__FUNCTION__);\r
+ goto err1;\r
+ }\r
+\r
+ gpio_pull_updown(SPI_FPGA_INT_PIN,GPIOPullUp);\r
+ ret = request_irq(gpio_to_irq(SPI_FPGA_INT_PIN),spi_fpga_irq,IRQF_TRIGGER_RISING,NULL,port);\r
+ if(ret)\r
+ {\r
+ printk("unable to request spi_uart irq\n");\r
+ goto err2;\r
+ } \r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ pFpgaPort = port;\r
+ \r
+#if defined(CONFIG_SPI_GPIO)\r
+ spi_gpio_init();\r
+#endif\r
+\r
+ return 0;\r
+\r
+err2:\r
+ free_irq(gpio_to_irq(SPI_FPGA_INT_PIN),NULL);\r
+err1: \r
+ gpio_free(SPI_FPGA_INT_PIN);\r
+\r
+ return ret;\r
+ \r
+\r
+}\r
+\r
+static int __devexit spi_fpga_remove(struct spi_device *spi)\r
+{\r
+ //struct spi_fpga_port *port = dev_get_drvdata(&spi->dev);\r
+\r
+ \r
+ return 0;\r
+}\r
+\r
+#ifdef CONFIG_PM\r
+\r
+static int spi_fpga_suspend(struct spi_device *spi, pm_message_t state)\r
+{\r
+ //struct spi_fpga_port *port = dev_get_drvdata(&spi->dev);\r
+\r
+ return 0;\r
+}\r
+\r
+static int spi_fpga_resume(struct spi_device *spi)\r
+{\r
+ //struct spi_fpga_port *port = dev_get_drvdata(&spi->dev);\r
+\r
+ return 0;\r
+}\r
+\r
+#else\r
+#define spi_fpga_suspend NULL\r
+#define spi_fpga_resume NULL\r
+#endif\r
+\r
+static struct spi_driver spi_fpga_driver = {\r
+ .driver = {\r
+ .name = "spi_fpga",\r
+ .bus = &spi_bus_type,\r
+ .owner = THIS_MODULE,\r
+ },\r
+\r
+ .probe = spi_fpga_probe,\r
+ .remove = __devexit_p(spi_fpga_remove),\r
+ .suspend = spi_fpga_suspend,\r
+ .resume = spi_fpga_resume,\r
+};\r
+\r
+static int __init spi_fpga_init(void)\r
+{\r
+ return spi_register_driver(&spi_fpga_driver);\r
+}\r
+\r
+static void __exit spi_fpga_exit(void)\r
+{\r
+ spi_unregister_driver(&spi_fpga_driver);\r
+}\r
+\r
+module_init(spi_fpga_init);\r
+module_exit(spi_fpga_exit);\r
+\r
+MODULE_DESCRIPTION("Driver for spi2uart,spi2gpio,spi2i2c.");\r
+MODULE_AUTHOR("luowei <lw@rock-chips.com>");\r
+MODULE_LICENSE("GPL");\r
--- /dev/null
+#include <linux/module.h>\r
+#include <linux/init.h>\r
+#include <linux/kernel.h>\r
+#include <linux/mutex.h>\r
+#include <linux/serial_reg.h>\r
+#include <linux/circ_buf.h>\r
+#include <linux/gfp.h>\r
+#include <linux/tty.h>\r
+#include <linux/tty_flip.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/spi/spi.h>\r
+#include <linux/delay.h>\r
+#include <linux/module.h>\r
+#include <linux/ioport.h>\r
+#include <linux/console.h>\r
+#include <linux/sysrq.h>\r
+#include <mach/gpio.h>\r
+#include <mach/iomux.h>\r
+#include <asm/io.h>\r
+#include <asm/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/poll.h>\r
+#include <linux/sched.h>\r
+#include <linux/kthread.h>\r
+#include <linux/jiffies.h>\r
+#include <linux/i2c.h>\r
+#include <mach/rk2818_iomap.h>\r
+\r
+#include "spi_fpga.h"\r
+\r
+#if defined(CONFIG_SPI_GPIO_DEBUG)\r
+#define DBG(x...) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define SPI_GPIO_TEST 0\r
+#define HIGH_SPI_TEST 1\r
+spinlock_t gpio_lock;\r
+spinlock_t gpio_state_lock;\r
+spinlock_t gpio_irq_lock;\r
+static unsigned short int gGpio0State = 0; \r
+#define SPI_GPIO_IRQ_NUM 16\r
+static SPI_GPIO_PDATA g_spiGpioVectorTable[SPI_GPIO_IRQ_NUM] = \\r
+{{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}; \r
+\r
+\r
+static void spi_gpio_write_reg(int reg, int PinNum, int set)\r
+{\r
+ unsigned int old_set;\r
+ unsigned int new_set;\r
+ struct spi_fpga_port *port = pFpgaPort;\r
+ PinNum = PinNum % 16;\r
+ //mutex_lock(&port->spi_lock);\r
+ old_set= spi_in(port, reg, SEL_GPIO);\r
+ if(1 == set)\r
+ new_set = old_set | (1 << PinNum ); \r
+ else\r
+ new_set = old_set & (~(1 << PinNum ));\r
+ spi_out(port, reg, new_set, SEL_GPIO);\r
+ //mutex_unlock(&port->spi_lock);\r
+ \r
+}\r
+\r
+static int spi_gpio_read_reg(int reg)\r
+{\r
+ int ret = 0;\r
+ struct spi_fpga_port *port = pFpgaPort;\r
+ \r
+ //mutex_lock(&port->spi_lock);\r
+ ret = spi_in(port, reg, SEL_GPIO);\r
+ //mutex_unlock(&port->spi_lock);\r
+\r
+ return ret; \r
+}\r
+\r
+\r
+static int get_gpio_addr(eSpiGpioPinNum_t PinNum)\r
+{\r
+ int gpio = PinNum / 16;\r
+ int reg = -1;\r
+ switch(gpio)\r
+ {\r
+ case 0:\r
+ reg = ICE_SEL_GPIO0;\r
+ break;\r
+ case 1:\r
+ reg = ICE_SEL_GPIO1;\r
+ break;\r
+ case 2:\r
+ reg = ICE_SEL_GPIO2;\r
+ break;\r
+ case 3:\r
+ reg = ICE_SEL_GPIO3;\r
+ break;\r
+ case 4:\r
+ reg = ICE_SEL_GPIO4;\r
+ break;\r
+ case 5:\r
+ reg = ICE_SEL_GPIO5;\r
+ break;\r
+ default:\r
+ break;\r
+\r
+ }\r
+\r
+ return reg;\r
+\r
+}\r
+\r
+\r
+int spi_gpio_int_sel(eSpiGpioPinNum_t PinNum,eSpiGpioTypeSel_t type)\r
+{\r
+ int reg = get_gpio_addr(PinNum);\r
+ //struct spi_fpga_port *port = pFpgaPort;\r
+ \r
+ if(ICE_SEL_GPIO0 == reg)\r
+ {\r
+ reg |= ICE_SEL_GPIO0_TYPE;\r
+ spin_lock(&gpio_state_lock);\r
+ if(SPI_GPIO0_IS_INT == type)\r
+ gGpio0State |= (1 << PinNum );\r
+ else\r
+ gGpio0State &= (~(1 << PinNum ));\r
+ spin_unlock(&gpio_state_lock);\r
+ DBG("%s,PinNum=%d,GPIO[%d]:type=%d\n",__FUNCTION__,PinNum,PinNum/16,type);\r
+ //mutex_lock(&port->spi_lock);\r
+ spi_gpio_write_reg(reg, PinNum, type);\r
+ //mutex_unlock(&port->spi_lock);\r
+ \r
+ return 0;\r
+ }\r
+ else\r
+ {\r
+ printk("%s:error\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+ \r
+}\r
+\r
+ \r
+int spi_gpio_set_pindirection(eSpiGpioPinNum_t PinNum,eSpiGpioPinDirection_t direction)\r
+{\r
+ int reg = get_gpio_addr(PinNum);\r
+ //struct spi_fpga_port *port = pFpgaPort;\r
+ \r
+ if(reg == -1)\r
+ {\r
+ printk("%s:error\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+\r
+ if(ICE_SEL_GPIO0 == reg)\r
+ {\r
+ reg |= ICE_SEL_GPIO0_DIR;\r
+ spin_lock(&gpio_state_lock);\r
+ if((gGpio0State & (1 << PinNum )) != 0)\r
+ {\r
+ printk("Fail to set direction because it is int pin!\n");\r
+ return -1;\r
+ }\r
+ spin_unlock(&gpio_state_lock); \r
+ DBG("%s,PinNum=%d,direction=%d,GPIO[%d]:PinNum/16=%d\n",__FUNCTION__,PinNum,direction,PinNum/16,PinNum%16);\r
+ //mutex_lock(&port->spi_lock);\r
+ spi_gpio_write_reg(reg, PinNum, direction);\r
+ //mutex_unlock(&port->spi_lock);\r
+ }\r
+ else\r
+ {\r
+ reg |= ICE_SEL_GPIO_DIR;\r
+ DBG("%s,PinNum=%d,direction=%d,GPIO[%d]:PinNum/16=%d\n",__FUNCTION__,PinNum,direction,PinNum/16,PinNum%16);\r
+ //mutex_lock(&port->spi_lock);\r
+ spi_gpio_write_reg(reg, PinNum, direction);\r
+ //mutex_unlock(&port->spi_lock);\r
+ }\r
+ return 0;\r
+}\r
+\r
+\r
+int spi_gpio_set_pinlevel(eSpiGpioPinNum_t PinNum, eSpiGpioPinLevel_t PinLevel)\r
+{\r
+ int reg = get_gpio_addr(PinNum);\r
+ //struct spi_fpga_port *port = pFpgaPort;\r
+ \r
+ if(reg == -1)\r
+ {\r
+ printk("%s:error\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+ \r
+ if(ICE_SEL_GPIO0 == reg)\r
+ {\r
+ reg |= ICE_SEL_GPIO0_DATA;\r
+ spin_lock(&gpio_state_lock);\r
+ if((gGpio0State & (1 << PinNum )) != 0)\r
+ {\r
+ printk("Fail to set PinLevel because PinNum=%d is int pin!\n",PinNum);\r
+ return -1;\r
+ }\r
+ spin_unlock(&gpio_state_lock); \r
+ DBG("%s,PinNum=%d,GPIO[%d]:PinNum/16=%d,PinLevel=%d\n",__FUNCTION__,PinNum,PinNum/16,PinNum%16,PinLevel);\r
+ //mutex_lock(&port->spi_lock);\r
+ spi_gpio_write_reg(reg, PinNum, PinLevel);\r
+ //mutex_unlock(&port->spi_lock);\r
+ \r
+ }\r
+ else\r
+ {\r
+ reg |= ICE_SEL_GPIO_DATA;\r
+ DBG("%s,PinNum=%d,GPIO[%d]:PinNum/16=%d,PinLevel=%d\n",__FUNCTION__,PinNum,PinNum/16,PinNum%16,PinLevel);\r
+ //mutex_lock(&port->spi_lock);\r
+ spi_gpio_write_reg(reg, PinNum, PinLevel);\r
+ //mutex_unlock(&port->spi_lock);\r
+ }\r
+\r
+ return 0;\r
+ \r
+}\r
+\r
+\r
+eSpiGpioPinLevel_t spi_gpio_get_pinlevel(eSpiGpioPinNum_t PinNum)\r
+{\r
+ int ret = 0;\r
+ int reg = get_gpio_addr(PinNum);\r
+ int level = 0;\r
+ //struct spi_fpga_port *port = pFpgaPort;\r
+ \r
+ if(reg == -1)\r
+ {\r
+ printk("%s:error\n",__FUNCTION__);\r
+ return SPI_GPIO_LEVEL_ERR;\r
+ }\r
+\r
+ if(ICE_SEL_GPIO0 == reg)\r
+ {\r
+ reg |= ICE_SEL_GPIO0_DATA;\r
+ spin_lock(&gpio_state_lock);\r
+ if((gGpio0State & (1 << PinNum )) != 0)\r
+ {\r
+ printk("Fail to get PinLevel because it is int pin!\n");\r
+ return SPI_GPIO_LEVEL_ERR;\r
+ }\r
+ spin_unlock(&gpio_state_lock); \r
+ //mutex_lock(&port->spi_lock);\r
+ ret = spi_gpio_read_reg(reg);\r
+ //mutex_unlock(&port->spi_lock);\r
+ }\r
+ else\r
+ {\r
+ reg |= ICE_SEL_GPIO_DATA;\r
+ //mutex_lock(&port->spi_lock);\r
+ ret = spi_gpio_read_reg(reg);\r
+ //mutex_unlock(&port->spi_lock);\r
+ }\r
+\r
+ if((ret & (1 << (PinNum%16) )) == 0)\r
+ level = SPI_GPIO_LOW;\r
+ else\r
+ level = SPI_GPIO_HIGH;\r
+\r
+ DBG("%s,PinNum=%d,ret=0x%x,GPIO[%d]:PinNum/16=%d,PinLevel=%d\n\n",__FUNCTION__,PinNum,ret,PinNum/16,PinNum%16,level);\r
+\r
+ return level;\r
+ \r
+}\r
+\r
+\r
+int spi_gpio_enable_int(eSpiGpioPinNum_t PinNum)\r
+{\r
+ int reg = get_gpio_addr(PinNum);\r
+ //struct spi_fpga_port *port = pFpgaPort;\r
+ \r
+ if(ICE_SEL_GPIO0 == reg)\r
+ {\r
+ reg |= ICE_SEL_GPIO0_INT_EN;\r
+ spin_lock(&gpio_state_lock);\r
+ if((gGpio0State & (1 << PinNum )) == 0)\r
+ {\r
+ printk("Fail to enable int because it is gpio pin!\n");\r
+ return -1;\r
+ }\r
+ spin_unlock(&gpio_state_lock);\r
+ DBG("%s,PinNum=%d,IntEn=%d\n",__FUNCTION__,PinNum,SPI_GPIO_INT_ENABLE); \r
+ //mutex_lock(&port->spi_lock);\r
+ spi_gpio_write_reg(reg, PinNum, SPI_GPIO_INT_ENABLE);\r
+ //mutex_unlock(&port->spi_lock); \r
+ }\r
+ else\r
+ {\r
+ printk("%s:error\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+int spi_gpio_disable_int(eSpiGpioPinNum_t PinNum)\r
+{\r
+ int reg = get_gpio_addr(PinNum);\r
+ //struct spi_fpga_port *port = pFpgaPort;\r
+ \r
+ if(ICE_SEL_GPIO0 == reg)\r
+ {\r
+ reg |= ICE_SEL_GPIO0_INT_EN;\r
+ spin_lock(&gpio_state_lock);\r
+ if((gGpio0State & (1 << PinNum )) == 0)\r
+ {\r
+ printk("Fail to enable int because it is gpio pin!\n");\r
+ return -1;\r
+ }\r
+ spin_unlock(&gpio_state_lock); \r
+ DBG("%s,PinNum=%d,IntEn=%d\n",__FUNCTION__,PinNum,SPI_GPIO_INT_DISABLE);\r
+ //mutex_lock(&port->spi_lock);\r
+ spi_gpio_write_reg(reg, PinNum, SPI_GPIO_INT_DISABLE);\r
+ //mutex_unlock(&port->spi_lock); \r
+ }\r
+ else\r
+ {\r
+ printk("%s:error\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+int spi_gpio_set_int_trigger(eSpiGpioPinNum_t PinNum,eSpiGpioIntType_t IntType)\r
+{\r
+ int reg = get_gpio_addr(PinNum);\r
+ //struct spi_fpga_port *port = pFpgaPort;\r
+ \r
+ if(ICE_SEL_GPIO0 == reg)\r
+ {\r
+ reg |= ICE_SEL_GPIO0_INT_TRI;\r
+ spin_lock(&gpio_state_lock);\r
+ if((gGpio0State & (1 << PinNum )) == 0)\r
+ {\r
+ printk("Fail to enable int because it is gpio pin!\n");\r
+ return -1;\r
+ }\r
+ spin_unlock(&gpio_state_lock); \r
+ DBG("%s,PinNum=%d,IntType=%d\n",__FUNCTION__,PinNum,IntType); \r
+ //mutex_lock(&port->spi_lock);\r
+ spi_gpio_write_reg(reg, PinNum, IntType);\r
+ //mutex_unlock(&port->spi_lock);\r
+ }\r
+ else\r
+ {\r
+ printk("%s:error\n",__FUNCTION__);\r
+ return -1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+int spi_gpio_read_iir(void)\r
+{\r
+ int reg = ICE_SEL_GPIO0 | ICE_SEL_GPIO0_INT_STATE;\r
+ int ret = 0;\r
+\r
+ ret = spi_gpio_read_reg(reg);\r
+ DBG("%s,IntState=%d\n",__FUNCTION__,ret);\r
+ return ret;\r
+}\r
+\r
+int spi_request_gpio_irq(eSpiGpioPinNum_t PinNum, pSpiFunc Routine, eSpiGpioIntType_t IntType,void *dev_id)\r
+{ \r
+ if(PinNum >= SPI_GPIO_IRQ_NUM)\r
+ return -1;\r
+ DBG("Enter::%s,LINE=%d,PinNum=%d\n",__FUNCTION__,__LINE__,PinNum);\r
+ if(spi_gpio_int_sel(PinNum,SPI_GPIO0_IS_INT))\r
+ return -1;\r
+ if(spi_gpio_set_int_trigger(PinNum,IntType))\r
+ return -1;\r
+ spin_lock(&gpio_irq_lock);\r
+ if(g_spiGpioVectorTable[PinNum].gpio_vector) \r
+ return -1;\r
+ g_spiGpioVectorTable[PinNum].gpio_vector = (pSpiFuncIntr)Routine;\r
+ g_spiGpioVectorTable[PinNum].gpio_devid= dev_id;\r
+ spin_unlock(&gpio_irq_lock);\r
+ if(spi_gpio_enable_int(PinNum))\r
+ return -1;\r
+ \r
+ return 0;\r
+}\r
+\r
+int spi_free_gpio_irq(eSpiGpioPinNum_t PinNum)\r
+{ \r
+ spi_gpio_disable_int(PinNum);\r
+ spin_lock(&gpio_irq_lock);\r
+ g_spiGpioVectorTable[PinNum].gpio_vector = NULL;\r
+ g_spiGpioVectorTable[PinNum].gpio_devid= NULL;\r
+ spin_unlock(&gpio_irq_lock);\r
+\r
+ return 0;\r
+}\r
+ \r
+\r
+int spi_gpio_handle_irq(struct spi_device *spi)\r
+{\r
+ int gpio_iir, i;\r
+\r
+#if 1\r
+ gpio_iir = spi_gpio_read_iir() & 0xffff; \r
+ if(gpio_iir == 0xffff)\r
+ return -1;\r
+ //spin_lock(&gpio_state_lock);\r
+ DBG("gpio_iir=0x%x\n",gpio_iir);\r
+ for(i=0; i<SPI_GPIO_IRQ_NUM; i++)\r
+ {\r
+ if(((gpio_iir & (1 << i)) == 0) && ((gGpio0State & (1 << i)) != 0))\r
+ {\r
+ if(g_spiGpioVectorTable[i].gpio_vector)\r
+ {\r
+ g_spiGpioVectorTable[i].gpio_vector(i,g_spiGpioVectorTable[i].gpio_devid);\r
+ DBG("spi_gpio_irq=%d\n",i);\r
+ }\r
+ } \r
+ } \r
+ //spin_unlock(&gpio_state_lock);\r
+#endif\r
+\r
+ return 0;\r
+\r
+}\r
+\r
+int spi_gpio_init(void)\r
+{\r
+ int i,ret;\r
+ struct spi_fpga_port *port = pFpgaPort;\r
+#if HIGH_SPI_TEST \r
+ printk("*************test spi communication now***************\n");\r
+ printk("%s:LINE=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ for(i=0;i<0xff;i++)\r
+ {\r
+ spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), i, SEL_GPIO);//all gpio is input\r
+ ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;\r
+ if(i != ret)\r
+ printk("err:i=0x%x but ret=0x%x\n",i,ret);\r
+ }\r
+\r
+#endif\r
+#if (FPGA_TYPE == ICE_CC72)\r
+ for(i=0; i<16; i++)\r
+ {\r
+ DBG("i=%d\n\n",i);\r
+ spi_gpio_int_sel(i,SPI_GPIO0_IS_GPIO);\r
+ spi_gpio_set_pinlevel(i, SPI_GPIO_LOW);\r
+ spi_gpio_set_pindirection(i, SPI_GPIO_OUT); \r
+ }\r
+/* \r
+ for(i=6; i<16; i++)\r
+ {\r
+ DBG("i=%d\n\n",i);\r
+ spi_gpio_int_sel(i,SPI_GPIO0_IS_INT);\r
+ spi_gpio_set_int_trigger(i,SPI_GPIO_EDGE_FALLING);\r
+ spi_gpio_disable_int(i); \r
+ } \r
+*/ \r
+ for(i=16; i<32; i++)\r
+ {\r
+ spi_gpio_set_pinlevel(i, SPI_GPIO_LOW);\r
+ spi_gpio_set_pindirection(i, SPI_GPIO_OUT);\r
+ }\r
+ \r
+ //spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DATA), 0, SEL_GPIO);//all gpio is zero\r
+ //spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), 0, SEL_GPIO);//all gpio is input\r
+ \r
+#elif (FPGA_TYPE == ICE_CC196)\r
+\r
+#if 0\r
+ for(i=0;i<82;i++)\r
+ {\r
+ if(i<16)\r
+ spi_gpio_int_sel(i,SPI_GPIO0_IS_GPIO); \r
+ spi_gpio_set_pindirection(i, SPI_GPIO_OUT); \r
+ }\r
+ \r
+ while(1)\r
+ {\r
+ if(TestGpioPinLevel == 0)\r
+ TestGpioPinLevel = 1;\r
+ else\r
+ TestGpioPinLevel = 0;\r
+ for(i=0;i<82;i++)\r
+ {\r
+ spi_gpio_set_pinlevel(i, TestGpioPinLevel);\r
+ ret = spi_gpio_get_pinlevel(i);\r
+ if(ret != TestGpioPinLevel)\r
+ DBG("PinNum=%d,set_pinlevel=%d,get_pinlevel=%d\n\n",i,TestGpioPinLevel,ret); \r
+ }\r
+ mdelay(10);\r
+\r
+ DBG("%s:LINE=%d\n",__FUNCTION__,__LINE__);\r
+ }\r
+\r
+#endif\r
+ \r
+#if 0\r
+ DBG("%s:LINE=%d\n",__FUNCTION__,__LINE__);\r
+ spi_out(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO0_TYPE), 0x0000, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO0_TYPE), SEL_GPIO) & 0xffff;\r
+ if(ret != 0x0000)\r
+ DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+ \r
+ spi_out(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;\r
+ if(ret != 0x0000)\r
+ DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+ \r
+ spi_out(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DIR), 0xffff, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;\r
+ if(ret != 0xffff)\r
+ DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+\r
+ spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DATA), 0x0224, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;\r
+ if(ret != 0x0224)\r
+ DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+ \r
+ spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), 0xf7ef, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;\r
+ if(ret != 0xf7ef)\r
+ DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+ \r
+ spi_out(port, (ICE_SEL_GPIO2 | ICE_SEL_GPIO_DATA), 0x2008, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO2 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;\r
+ if(ret != 0x2008)\r
+ DBG("%s:Line=%d,set=0x2008,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+ \r
+ spi_out(port, (ICE_SEL_GPIO2 | ICE_SEL_GPIO_DIR), 0xf378, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;\r
+ if(ret != 0xf378)\r
+ DBG("%s:Line=%d,set=0xf378,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+\r
+ spi_out(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;\r
+ if(ret != 0x0000)\r
+ DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+ \r
+ spi_out(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DIR), 0xffff, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;\r
+ if(ret != 0xffff)\r
+ DBG("%s:Line=%d,set=0xffff,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+\r
+ spi_out(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;\r
+ if(ret != 0x0000)\r
+ DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+ \r
+ spi_out(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DIR), 0xffbf, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;\r
+ if(ret != 0xffbf)\r
+ DBG("%s:Line=%d,set=0xffbf,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+ \r
+ spi_out(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff;\r
+ if(ret != 0x0000)\r
+ DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+ \r
+ spi_out(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DIR), 0xffff, SEL_GPIO);\r
+ ret = spi_in(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff;\r
+ if(ret != 0xffff)\r
+ DBG("%s:Line=%d,set=0xffff,ret=0x%x\n",__FUNCTION__,__LINE__,ret);\r
+ \r
+ \r
+#else\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_00, SPI_GPIO_LOW); //LCD_ON output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_00, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_01, SPI_GPIO_LOW); //LCD_PWR_CTRL output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_01, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_02, SPI_GPIO_HIGH); //SD_POW_ON output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_02, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_03, SPI_GPIO_LOW); //WL_RST_N/WIFI_EN output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_03, SPI_GPIO_OUT);\r
+ \r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_04, SPI_GPIO_IN); //HARDO,input\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_05, SPI_GPIO_HIGH); //SENSOR_PWDN output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_05, SPI_GPIO_OUT); \r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_06, SPI_GPIO_LOW); //BT_PWR_EN output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_06, SPI_GPIO_OUT); \r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_07, SPI_GPIO_LOW); //BT_RST output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_07, SPI_GPIO_OUT);\r
+ \r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_08, SPI_GPIO_LOW); //BT_WAKE_B output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_08, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_09, SPI_GPIO_HIGH); //LCD_DISP_ON output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_09, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_10, SPI_GPIO_LOW); //WM_PWR_EN output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_10, SPI_GPIO_OUT);\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_11, SPI_GPIO_IN); //HARD1,input\r
+ \r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_12, SPI_GPIO_LOW); //VIB_MOTO output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_12, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_13, SPI_GPIO_HIGH); //KEYLED_EN output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_13, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_14, SPI_GPIO_LOW); //CAM_RST output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_14, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P1_15, SPI_GPIO_LOW); //WL_WAKE_B output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P1_15, SPI_GPIO_OUT);\r
+\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_00, SPI_GPIO_IN); //Y+YD input\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_01, SPI_GPIO_IN); //Y-YU input\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_02, SPI_GPIO_IN); //AP_TD_UNDIFED input \r
+ spi_gpio_set_pinlevel(SPI_GPIO_P2_03, SPI_GPIO_HIGH); //AP_PW_EN_TD output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_03, SPI_GPIO_OUT);\r
+ \r
+ spi_gpio_set_pinlevel(SPI_GPIO_P2_04, SPI_GPIO_LOW); //AP_RESET_TD output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_04, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P2_05, SPI_GPIO_LOW); //AP_SHUTDOWN_TD_PMU output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_05, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P2_06, SPI_GPIO_LOW); //AP_RESET_CMMB output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_06, SPI_GPIO_OUT);\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_07, SPI_GPIO_IN); //AP_CHECK_TD_STATUS input\r
+ \r
+ spi_gpio_set_pinlevel(SPI_GPIO_P2_08, SPI_GPIO_LOW); //CHARGE_CURRENT_SEL output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_08, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P2_09, SPI_GPIO_LOW); //AP_PWD_CMMB output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_09, SPI_GPIO_OUT);\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_10, SPI_GPIO_IN); //X-XL input\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_11, SPI_GPIO_IN); //X+XR input\r
+ \r
+ spi_gpio_set_pinlevel(SPI_GPIO_P2_12, SPI_GPIO_LOW); //LCD_RESET output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_12, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P2_13, SPI_GPIO_HIGH); //USB_PWR_EN output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_13, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P2_14, SPI_GPIO_LOW); //WL_HOST_WAKE_B output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_14, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P2_15, SPI_GPIO_LOW); //TOUCH_SCREEN_RST output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P2_15, SPI_GPIO_OUT);\r
+\r
+ spi_gpio_set_pindirection(SPI_GPIO_P4_06, SPI_GPIO_IN); //CHARGER_INT_END input\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P4_07, SPI_GPIO_LOW); //TOUCH_SCREEN_RST output\r
+ spi_gpio_set_pindirection(SPI_GPIO_P4_07, SPI_GPIO_OUT);\r
+ spi_gpio_set_pinlevel(SPI_GPIO_P4_08, SPI_GPIO_LOW); //CM3605_PS_SHUTDOWN\r
+ spi_gpio_set_pindirection(SPI_GPIO_P4_08, SPI_GPIO_OUT);\r
+ \r
+#endif\r
+\r
+#endif\r
+ return 0;\r
+\r
+}\r
+\r
+\r
+#if SPI_GPIO_TEST\r
+volatile int TestGpioPinLevel = 0;\r
+void spi_gpio_work_handler(struct work_struct *work)\r
+{\r
+ struct spi_fpga_port *port =\r
+ container_of(work, struct spi_fpga_port, gpio.spi_gpio_work);\r
+ int i,ret;\r
+ printk("*************test spi_gpio now***************\n");\r
+ \r
+ if(TestGpioPinLevel == 0)\r
+ TestGpioPinLevel = 1;\r
+ else\r
+ TestGpioPinLevel = 0;\r
+\r
+#if (FPGA_TYPE == ICE_CC72)\r
+ for(i=0;i<32;i++)\r
+ {\r
+ spi_gpio_set_pinlevel(i, TestGpioPinLevel);\r
+ ret = spi_gpio_get_pinlevel(i);\r
+ if(ret != TestGpioPinLevel)\r
+ DBG("PinNum=%d,set_pinlevel=%d,get_pinlevel=%d\n",i,TestGpioPinLevel,ret);\r
+ //spi_gpio_set_pindirection(i, SPI_GPIO_OUT); \r
+ }\r
+\r
+#elif (FPGA_TYPE == ICE_CC196)\r
+ for(i=0;i<16;i++)\r
+ {\r
+ if(i<16)\r
+ spi_gpio_int_sel(i,SPI_GPIO0_IS_GPIO); \r
+ spi_gpio_set_pindirection(i, SPI_GPIO_OUT); \r
+ }\r
+ \r
+ for(i=0;i<81;i++)\r
+ {\r
+ spi_gpio_set_pinlevel(i, TestGpioPinLevel);\r
+ ret = spi_gpio_get_pinlevel(i);\r
+ if(ret != TestGpioPinLevel)\r
+ printk("err:PinNum=%d,set_pinlevel=%d but get_pinlevel=%d\n\n",i,TestGpioPinLevel,ret); \r
+ }\r
+\r
+ DBG("%s:LINE=%d\n",__FUNCTION__,__LINE__);\r
+\r
+#endif\r
+\r
+}\r
+\r
+static void spi_testgpio_timer(unsigned long data)\r
+{\r
+ struct spi_fpga_port *port = (struct spi_fpga_port *)data;\r
+ port->gpio.gpio_timer.expires = jiffies + msecs_to_jiffies(1000);\r
+ add_timer(&port->gpio.gpio_timer);\r
+ //schedule_work(&port->gpio.spi_gpio_work);\r
+ queue_work(port->gpio.spi_gpio_workqueue, &port->gpio.spi_gpio_work);\r
+}\r
+\r
+#endif\r
+\r
+\r
+\r
+int spi_gpio_register(struct spi_fpga_port *port)\r
+{\r
+#if SPI_GPIO_TEST\r
+ char b[20];\r
+ sprintf(b, "spi_gpio_workqueue");\r
+ port->gpio.spi_gpio_workqueue = create_freezeable_workqueue(b);\r
+ if (!port->gpio.spi_gpio_workqueue) {\r
+ printk("cannot create spi_gpio workqueue\n");\r
+ return -EBUSY;\r
+ }\r
+ INIT_WORK(&port->gpio.spi_gpio_work, spi_gpio_work_handler);\r
+ setup_timer(&port->gpio.gpio_timer, spi_testgpio_timer, (unsigned long)port);\r
+ port->gpio.gpio_timer.expires = jiffies+2000;//>1000ms\r
+ add_timer(&port->gpio.gpio_timer);\r
+\r
+#endif \r
+\r
+ spin_lock_init(&gpio_lock);\r
+ spin_lock_init(&gpio_state_lock);\r
+ spin_lock_init(&gpio_irq_lock);\r
+ DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port);\r
+ return 0;\r
+}\r
+int spi_gpio_unregister(struct spi_fpga_port *port)\r
+{ \r
+ return 0;\r
+}\r
+\r
+MODULE_DESCRIPTION("Driver for spi2gpio.");\r
+MODULE_AUTHOR("luowei <lw@rock-chips.com>");\r
+MODULE_LICENSE("GPL");\r
+\r
+\r
--- /dev/null
+#include <linux/module.h>\r
+#include <linux/init.h>\r
+#include <linux/kernel.h>\r
+#include <linux/mutex.h>\r
+#include <linux/serial_reg.h>\r
+#include <linux/circ_buf.h>\r
+#include <linux/gfp.h>\r
+#include <linux/tty.h>\r
+#include <linux/tty_flip.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/spi/spi.h>\r
+#include <linux/delay.h>\r
+#include <linux/ioport.h>\r
+#include <linux/console.h>\r
+#include <linux/sysrq.h>\r
+#include <mach/gpio.h>\r
+#include <mach/iomux.h>\r
+#include <asm/io.h>\r
+#include <asm/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/poll.h>\r
+#include <linux/sched.h>\r
+#include <linux/kthread.h>\r
+#include <linux/jiffies.h>\r
+#include <linux/i2c.h>\r
+#include <mach/board.h>\r
+#include <mach/rk2818_iomap.h>\r
+\r
+#include "spi_fpga.h"\r
+\r
+#if defined(CONFIG_SPI_I2C_DEBUG)\r
+#define DBG(x...) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define SPI_I2C_TEST 0\r
+\r
+#define MAXMSGLEN 16\r
+#define DRV_NAME "fpga_i2c"\r
+\r
+\r
+struct spi_i2c_data {\r
+ struct device *dev;\r
+ struct i2c_adapter adapter;\r
+ unsigned long scl_rate;\r
+ spinlock_t i2c_lock; \r
+};\r
+\r
+\r
+int spi_i2c_handle_irq(struct spi_fpga_port *port,unsigned char channel)\r
+{\r
+ int reg;\r
+ int ret;\r
+\r
+ if(channel == 0)\r
+ reg = ICE_SEL_I2C_INT|ICE_SEL_I2C_CH2;\r
+ else\r
+ reg = ICE_SEL_I2C_INT|ICE_SEL_I2C_CH3;\r
+ \r
+ port->i2c.interrupt = 0;\r
+ ret = spi_in(port,reg,SEL_I2C);\r
+ if(ret == INT_I2C_READ_ACK)\r
+ port->i2c.interrupt = INT_I2C_READ_ACK; \r
+ else if(ret == INT_I2C_READ_NACK)\r
+ {\r
+ printk("Error::read no ack!!check the I2C slave device \n");\r
+ }\r
+ else if(ret == INT_I2C_WRITE_ACK)\r
+ port->i2c.interrupt = INT_I2C_WRITE_ACK;\r
+ else if(ret == INT_I2C_WRITE_NACK)\r
+ {\r
+ printk("Error::write no ack!!check the I2C slave device \n");\r
+ }\r
+ else\r
+ printk("Error:ack value error!!check the I2C slave device \n");\r
+ return port->i2c.interrupt;\r
+}\r
+\r
+int spi_i2c_select_speed(int speed)\r
+{\r
+ int result = 0; \r
+ switch(speed)\r
+ {\r
+ case 10:\r
+ result = ICE_SET_10K_I2C_SPEED; \r
+ break; \r
+ case 100:\r
+ result = ICE_SET_100K_I2C_SPEED; \r
+ break; \r
+ case 200:\r
+ result = ICE_SET_200K_I2C_SPEED; \r
+ break; \r
+ case 300: \r
+ result = ICE_SET_300K_I2C_SPEED; \r
+ break; \r
+ case 400: \r
+ result = ICE_SET_400K_I2C_SPEED; \r
+ break; \r
+ default: \r
+ break; \r
+ }\r
+ return result;\r
+}\r
+\r
+int spi_i2c_readbuf(struct spi_fpga_port *port ,struct i2c_msg *pmsg)\r
+{\r
+ \r
+ unsigned int reg ;\r
+ unsigned int len,i;\r
+ unsigned int slaveaddr;\r
+ unsigned int speed;\r
+ unsigned int channel = 0 ;\r
+ unsigned int result;\r
+ \r
+ slaveaddr = pmsg->addr;\r
+ len = pmsg->len; \r
+ speed = spi_i2c_select_speed(pmsg->scl_rate);\r
+ \r
+ if(pmsg->channel == I2C_CH2)\r
+ channel = ICE_SEL_I2C_CH2;\r
+ else if(pmsg->channel == I2C_CH3)\r
+ channel = ICE_SEL_I2C_CH3;\r
+ else\r
+ {\r
+ printk("Error:try to read form error i2c channel\n");\r
+ return 0;\r
+ }\r
+ \r
+ if(pmsg->read_type == 0)\r
+ {\r
+ //slaveaddr ;\r
+ slaveaddr = slaveaddr<<1;\r
+ reg = channel |ICE_SEL_I2C_START;\r
+ spi_out(port,reg,slaveaddr,SEL_I2C);\r
+ //speed;\r
+ reg = channel |ICE_SEL_I2C_SPEED|ICE_SEL_I2C_TRANS;\r
+ spi_out(port,reg,speed,SEL_I2C);\r
+ //len;\r
+ reg = channel |ICE_SEL_I2C_FIFO |ICE_SEL_I2C_TRANS;\r
+ spi_out(port,reg,len,SEL_I2C);\r
+ reg = channel |ICE_SEL_I2C_TRANS;\r
+ //data;\r
+ for(i = 0 ;i < len;i++)\r
+ {\r
+ if(i == len-1)\r
+ reg = channel |ICE_SEL_I2C_STOP;\r
+ spi_out(port,reg,pmsg->buf[i],SEL_I2C);\r
+ } \r
+ \r
+ }\r
+ //slaveaddr\r
+ slaveaddr = slaveaddr|ICE_I2C_SLAVE_READ;\r
+ if(pmsg->read_type == 0)\r
+ reg = channel |ICE_SEL_I2C_RESTART;\r
+ else\r
+ reg = channel |ICE_SEL_I2C_START;\r
+ spi_out(port,reg,slaveaddr,SEL_I2C);\r
+ //speed;\r
+ reg = channel |ICE_SEL_I2C_SPEED|ICE_SEL_I2C_TRANS;\r
+ spi_out(port,reg,speed,SEL_I2C);\r
+ //len;\r
+ reg = channel |ICE_SEL_I2C_FIFO |ICE_SEL_I2C_TRANS;\r
+ spi_out(port,reg,len,SEL_I2C);\r
+ \r
+ i=50;\r
+ while(i--)\r
+ { \r
+ if(port->i2c.interrupt == INT_I2C_READ_ACK)\r
+ { \r
+ for(i = 0;i<len;i++)\r
+ {\r
+ result = spi_in(port,reg,SEL_I2C);\r
+ pmsg->buf[i] = result & 0xFF; \r
+ }\r
+ spin_lock(&port->i2c.i2c_lock);\r
+ port->i2c.interrupt &= INT_I2C_READ_MASK;\r
+ spin_unlock(&port->i2c.i2c_lock);\r
+ break;\r
+ } \r
+ }\r
+ for(i = 0;i<len;i++)\r
+ DBG("pmsg->buf[%d] = 0x%x \n",i,pmsg->buf[i]); \r
+ return pmsg->len;\r
+}\r
+int spi_i2c_writebuf(struct spi_fpga_port *port ,struct i2c_msg *pmsg)\r
+{\r
+ \r
+ unsigned int reg ;\r
+ unsigned int len,i;\r
+ unsigned int slaveaddr;\r
+ unsigned int speed;\r
+ unsigned int channel = 0;\r
+ \r
+ slaveaddr = pmsg->addr;\r
+ len = pmsg->len; \r
+ speed = spi_i2c_select_speed(pmsg->scl_rate);\r
+ \r
+ if(pmsg->channel == I2C_CH2)\r
+ channel = ICE_SEL_I2C_CH2;\r
+ else if(pmsg->channel == I2C_CH3)\r
+ channel = ICE_SEL_I2C_CH3;\r
+ else\r
+ {\r
+ printk("Error: try to write the error i2c channel\n");\r
+ return 0;\r
+ }\r
+\r
+ //slaveaddr ;\r
+ slaveaddr = slaveaddr<<1;\r
+ reg = channel |ICE_SEL_I2C_START;\r
+ spi_out(port,reg,slaveaddr,SEL_I2C);\r
+ //speed;\r
+ reg = channel |ICE_SEL_I2C_SPEED|ICE_SEL_I2C_TRANS;\r
+ spi_out(port,reg,speed,SEL_I2C);\r
+ //len;\r
+ reg = channel |ICE_SEL_I2C_FIFO |ICE_SEL_I2C_TRANS;\r
+ spi_out(port,reg,len,SEL_I2C);\r
+ reg = channel |ICE_SEL_I2C_TRANS;\r
+ //data;\r
+ for(i = 0 ;i < len;i++)\r
+ {\r
+ if(i == len-1)\r
+ reg = channel|ICE_SEL_I2C_STOP;\r
+ spi_out(port,reg,pmsg->buf[i],SEL_I2C);\r
+ }\r
+ \r
+ i = 50;\r
+ while(i--)\r
+ { \r
+ if(port->i2c.interrupt == INT_I2C_WRITE_ACK)\r
+ { \r
+ spin_lock(&port->i2c.i2c_lock);\r
+ port->i2c.interrupt &= INT_I2C_WRITE_MASK;\r
+ spin_unlock(&port->i2c.i2c_lock);\r
+ break;\r
+ } \r
+ }\r
+ DBG("wait num= %d,port->i2c.interrupt = 0x%x\n",i,port->i2c.interrupt);\r
+ return pmsg->len;\r
+ \r
+ \r
+}\r
+#if defined(CONFIG_SPI_I2C_DEBUG)\r
+unsigned short rda5400[][2] = \r
+{\r
+{0x3f,0x0000},//page 0\r
+{0x0B,0x3200},// pll_cal_eachtime\r
+{0x0E,0x5200},// rxfilter_op_cal_bit_dr rxfilter_sys_cal_bit_dr\r
+{0x13,0x016D},// fts_cap=01, for high nak rate at high temperature¡£\r
+{0x16,0x9C23},// Load8.5pf crystal,2.2pf cap\r
+{0x17,0xBB12},// xtal_cpuclk_en,*\r
+{0x19,0xEE18},// rxfilter_bp_mode rxfilter_tuning_cap_for die\r
+{0x1A,0x59EE},// rmx_lo_reg=1011, tmx_iqswap\r
+{0x1C,0x008F},//\r
+{0x30,0x002B},//\r
+{0x3B,0x33EA},// rxfilter_imgrej_lo\r
+{0x3E,0x0040},// tmx_lo_reg set to1\r
+{0x3f,0x0001},//page 1\r
+{0x02,0x0001},// rxfilter_sys_cal_polarity\r
+{0x04,0xE41E},// ldo_ictrl<5bit> set to 1\r
+{0x05,0xBC00},// ldo_ictrl<5bit> set to 1\r
+{0x06,0x262D},// \r
+{0x0B,0x001F},// vco_bit=111\r
+{0x10,0x0100},// thermo power setting\r
+{0x13,0x001C},// pre_sca=1100\r
+{0x19,0x001C},// lo_buff=1100, improve RF per formance at high temp\r
+{0x1a,0x1404},\r
+{0x1E,0x2A48},// resetn_ex_selfgen_enable=0, for 32K is no need when poweron\r
+{0x27,0x0070},// power table setting, maxpower\r
+{0x26,0x3254},// power table setting\r
+{0x25,0x2180},// power table settings\r
+{0x24,0x0000},// power table setting\r
+{0x23,0x0000},// power table setting\r
+{0x22,0x0000},// power table setting\r
+{0x21,0x0000},// power table setting\r
+{0x20,0x0000},// power table setting\r
+{0x37,0x0600},// padrv_cal_bypass\r
+{0x3A,0x06E0},// dcdc setting\r
+{0x3f,0x0000},//page 0\r
+};\r
+\r
+int spi_i2c_16bit_test(struct spi_fpga_port *port)\r
+{\r
+ u8 i2c_buf[8];\r
+ int len = 2;\r
+ int i ;\r
+ struct i2c_msg msg[1] = \r
+ {\r
+ {0x16,0,len+2,i2c_buf,200,3,0}\r
+ };\r
+ \r
+ for(i = 0;i < (sizeof(rda5400)/sizeof(rda5400[0]));i++)\r
+ { \r
+ i2c_buf[0] = 0x22;\r
+ i2c_buf[1] = rda5400[i][0];\r
+ i2c_buf[1] = rda5400[i][1]>>8;\r
+ i2c_buf[2] = rda5400[i][1]&0xFF;\r
+ spi_i2c_writebuf(port, msg);\r
+ msg[0].len = 2;\r
+ spi_i2c_readbuf(port, msg);\r
+ }\r
+ return 0;\r
+ \r
+}\r
+\r
+int spi_i2c_8bit_test(struct spi_fpga_port *port)\r
+{\r
+ u8 i2c_buf[8];\r
+ int len = 2;\r
+ int i ;\r
+ struct i2c_msg msg[1] = \r
+ {\r
+ {0x16,0,len+1,i2c_buf,200,2,0}\r
+ };\r
+ \r
+ for(i = 0;i < (sizeof(rda5400)/sizeof(rda5400[0]));i++)\r
+ { \r
+ i2c_buf[0] = rda5400[i][0];\r
+ i2c_buf[1] = rda5400[i][1]>>8;\r
+ i2c_buf[2] = rda5400[i][1]&0xFF;\r
+ spi_i2c_writebuf(port, msg);\r
+ msg[0].len = 1;\r
+ spi_i2c_readbuf(port, msg);\r
+ }\r
+ return 0;\r
+ \r
+}\r
+ int spi_i2c_test(void )\r
+{\r
+ struct spi_fpga_port *port = pFpgaPort;\r
+ printk("IN::************spi_i2c_test********\r\n"); \r
+ spi_i2c_8bit_test(port);\r
+ spi_i2c_16bit_test(port);\r
+ \r
+ printk("OUT::************spi_i2c_test********\r\n");\r
+ return 0;\r
+ \r
+}\r
+\r
+#endif\r
+\r
+\r
+ int spi_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *pmsg, int num)\r
+{\r
+ \r
+ struct spi_fpga_port *port = pFpgaPort;\r
+ \r
+ printk("%s:line=%d,channel = %d\n",__FUNCTION__,__LINE__,adapter->nr);\r
+ if(pmsg->len > MAXMSGLEN)\r
+ return 0;\r
+ if(pmsg->flags) \r
+ spi_i2c_readbuf(port,pmsg);\r
+ else\r
+ spi_i2c_writebuf(port,pmsg);\r
+\r
+ return pmsg->len; \r
+\r
+ return 0;\r
+}\r
+\r
+static unsigned int spi_i2c_func(struct i2c_adapter *adapter)\r
+{\r
+ return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL);\r
+}\r
+ \r
+static const struct i2c_algorithm spi_i2c_algorithm = {\r
+ .master_xfer = spi_i2c_xfer,\r
+ .functionality = spi_i2c_func,\r
+};\r
+\r
+static int spi_i2c_probe(struct platform_device *pdev)\r
+{\r
+ int ret;\r
+ struct spi_i2c_data *i2c;\r
+ struct rk2818_i2c_platform_data *pdata;\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ pdata = pdev->dev.platform_data;\r
+ if(!pdata)\r
+ {\r
+ dev_err(&pdev->dev,"no platform data\n");\r
+ return -EINVAL; \r
+ }\r
+ i2c = kzalloc(sizeof(struct spi_i2c_data),GFP_KERNEL);\r
+ if(!i2c)\r
+ {\r
+ dev_err(&pdev->dev,"no memory for state\n");\r
+ return -ENOMEM; \r
+ }\r
+ strlcpy(i2c->adapter.name,DRV_NAME,sizeof(i2c->adapter.name));\r
+ i2c->adapter.owner = THIS_MODULE;\r
+ i2c->adapter.algo = &spi_i2c_algorithm;\r
+ i2c->adapter.class = I2C_CLASS_HWMON; \r
+ \r
+ i2c->dev = &pdev->dev;\r
+ i2c->adapter.algo_data = i2c;\r
+ i2c->adapter.dev.parent = &pdev->dev;\r
+ i2c->adapter.nr = pdata->bus_num;\r
+ ret = i2c_add_numbered_adapter(&i2c->adapter);\r
+ if(ret < 0){\r
+ dev_err(&pdev->dev,"fail to add bus to i2c core fpga\n");\r
+ kfree(i2c);\r
+ return ret;\r
+ }\r
+ platform_set_drvdata(pdev,i2c);\r
+ printk("Enter::%s,LINE=%d i2c->adap.nr = %d ************************\n",__FUNCTION__,__LINE__,i2c->adapter.nr);\r
+ #if defined(CONFIG_SPI_I2C_DEBUG)\r
+ \r
+ #endif\r
+ return 0; \r
+}\r
+\r
+static int spi_i2c_remove(struct platform_device *pdev)\r
+{\r
+ return 0; \r
+}\r
+\r
+static struct platform_driver spi_i2c_driver = {\r
+ .probe = spi_i2c_probe,\r
+ .remove = spi_i2c_remove, \r
+ .driver = {\r
+ .owner = THIS_MODULE,\r
+ .name = DRV_NAME,\r
+ },\r
+};\r
+\r
+static int __init spi_i2c_adap_init(void)\r
+{\r
+ printk(" *************Enter::%s,LINE=%d ************\n",__FUNCTION__,__LINE__);\r
+ return platform_driver_register(&spi_i2c_driver); \r
+}\r
+static void __exit spi_i2c_adap_exit(void)\r
+{\r
+ platform_driver_unregister(&spi_i2c_driver); \r
+}\r
+\r
+subsys_initcall(spi_i2c_adap_init);\r
+module_exit(spi_i2c_adap_exit);\r
+\r
+MODULE_DESCRIPTION("Driver for spi2i2c.");\r
+MODULE_AUTHOR("swj <swj@rock-chips.com>");\r
+MODULE_LICENSE("GPL");\r
+\r
+\r
--- /dev/null
+#include <linux/module.h>\r
+#include <linux/init.h>\r
+#include <linux/kernel.h>\r
+#include <linux/mutex.h>\r
+#include <linux/serial_reg.h>\r
+#include <linux/circ_buf.h>\r
+#include <linux/gfp.h>\r
+#include <linux/tty.h>\r
+#include <linux/tty_flip.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/spi/spi.h>\r
+#include <linux/delay.h>\r
+#include <linux/module.h>\r
+#include <linux/ioport.h>\r
+#include <linux/console.h>\r
+#include <linux/sysrq.h>\r
+#include <mach/gpio.h>\r
+#include <mach/iomux.h>\r
+#include <asm/io.h>\r
+#include <asm/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/poll.h>\r
+#include <linux/sched.h>\r
+#include <linux/kthread.h>\r
+#include <linux/jiffies.h>\r
+#include <linux/i2c.h>\r
+#include <mach/rk2818_iomap.h>\r
+\r
+#include "spi_fpga.h"\r
+\r
+#if defined(CONFIG_SPI_UART_DEBUG)\r
+#define DBG(x...) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define SPI_UART_TEST 0\r
+\r
+static struct tty_driver *spi_uart_tty_driver;\r
+/*------------------------ÒÔÏÂÊÇspi2uart±äÁ¿-----------------------*/\r
+\r
+#define UART_NR 1 /* Number of UARTs this driver can handle */\r
+\r
+#define UART_XMIT_SIZE PAGE_SIZE\r
+#define WAKEUP_CHARS 1024\r
+\r
+#define circ_empty(circ) ((circ)->head == (circ)->tail)\r
+#define circ_clear(circ) ((circ)->head = (circ)->tail = 0)\r
+\r
+#define circ_chars_pending(circ) \\r
+ (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))\r
+\r
+#define circ_chars_free(circ) \\r
+ (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))\r
+\r
+\r
+\r
+\r
+static struct spi_uart *spi_uart_table[UART_NR];\r
+static DEFINE_SPINLOCK(spi_uart_table_lock);\r
+\r
+\r
+static int spi_uart_add_port(struct spi_uart *uart)\r
+{\r
+ int index, ret = -EBUSY;\r
+\r
+ kref_init(&uart->kref);\r
+ mutex_init(&uart->open_lock);\r
+ spin_lock_init(&uart->write_lock);\r
+ spin_lock_init(&uart->irq_lock);\r
+ \r
+ spin_lock(&spi_uart_table_lock);\r
+ for (index = 0; index < UART_NR; index++) \r
+ {\r
+ if (!spi_uart_table[index]) {\r
+ uart->index = index;\r
+ //printk("index=%d\n\n",index);\r
+ spi_uart_table[index] = uart;\r
+ ret = 0;\r
+ break;\r
+ }\r
+ }\r
+ spin_unlock(&spi_uart_table_lock);\r
+\r
+ return ret;\r
+}\r
+\r
+static struct spi_uart *spi_uart_port_get(unsigned index)\r
+{\r
+ struct spi_uart *uart;\r
+\r
+ if (index >= UART_NR)\r
+ return NULL;\r
+\r
+ spin_lock(&spi_uart_table_lock);\r
+ uart = spi_uart_table[index];\r
+ uart->index = index;\r
+ printk("uart->index=%d\n",uart->index);\r
+ if (uart)\r
+ kref_get(&uart->kref);\r
+ spin_unlock(&spi_uart_table_lock);\r
+\r
+ return uart;\r
+}\r
+\r
+static void spi_uart_port_destroy(struct kref *kref)\r
+{\r
+ struct spi_uart *uart =\r
+ container_of(kref, struct spi_uart, kref);\r
+ kfree(uart);\r
+}\r
+\r
+static void spi_uart_port_put(struct spi_uart *uart)\r
+{\r
+ kref_put(&uart->kref, spi_uart_port_destroy);\r
+}\r
+\r
+static void spi_uart_port_remove(struct spi_uart *uart)\r
+{\r
+ struct spi_device *spi;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ \r
+ BUG_ON(spi_uart_table[uart->index] != uart);\r
+\r
+ spin_lock(&spi_uart_table_lock);\r
+ spi_uart_table[uart->index] = NULL;\r
+ spin_unlock(&spi_uart_table_lock);\r
+\r
+ /*\r
+ * We're killing a port that potentially still is in use by\r
+ * the tty layer. Be careful to arrange for the tty layer to\r
+ * give up on that port ASAP.\r
+ * Beware: the lock ordering is critical.\r
+ */\r
+ mutex_lock(&uart->open_lock);\r
+ //mutex_lock(&port->spi_lock);\r
+ spi = port->spi;\r
+\r
+ port->spi = NULL;\r
+ //mutex_unlock(&port->spi_lock);\r
+ if (uart->opened)\r
+ tty_hangup(uart->tty);\r
+ mutex_unlock(&uart->open_lock);\r
+\r
+ spi_uart_port_put(uart);\r
+}\r
+\r
+static unsigned int spi_uart_get_mctrl(struct spi_uart *uart)\r
+{\r
+ unsigned char status;\r
+ unsigned int ret;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ \r
+ status = spi_in(port, UART_MSR, SEL_UART);//\r
+ ret = 0;\r
+#if 0\r
+ if (status & UART_MSR_DCD)\r
+ ret |= TIOCM_CAR;\r
+ if (status & UART_MSR_RI)\r
+ ret |= TIOCM_RNG;\r
+ if (status & UART_MSR_DSR)\r
+ ret |= TIOCM_DSR; \r
+ if (status & UART_MSR_CTS)\r
+ ret |= TIOCM_CTS;\r
+#endif\r
+ if (status & UART_MSR_CTS)\r
+ ret = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;\r
+ DBG("Enter::%s,LINE=%d,ret=0x%x************************\n",__FUNCTION__,__LINE__,ret);\r
+ return ret;\r
+}\r
+\r
+static void spi_uart_write_mctrl(struct spi_uart *uart, unsigned int mctrl)\r
+{\r
+ unsigned char mcr = 0;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+#if 1\r
+ if (mctrl & TIOCM_RTS)\r
+ {\r
+ mcr |= UART_MCR_RTS;\r
+ mcr |= UART_MCR_AFE;\r
+ }\r
+ //if (mctrl & TIOCM_DTR)\r
+ // mcr |= UART_MCR_DTR;\r
+ //if (mctrl & TIOCM_OUT1)\r
+ // mcr |= UART_MCR_OUT1;\r
+ //if (mctrl & TIOCM_OUT2)\r
+ // mcr |= UART_MCR_OUT2;\r
+ //if (mctrl & TIOCM_LOOP)\r
+ // mcr |= UART_MCR_LOOP;\r
+ \r
+#endif\r
+ \r
+ DBG("Enter::%s,LINE=%d,mcr=0x%x\n",__FUNCTION__,__LINE__,mcr);\r
+ spi_out(port, UART_MCR, mcr, SEL_UART);\r
+}\r
+\r
+static inline void spi_uart_update_mctrl(struct spi_uart *uart,\r
+ unsigned int set, unsigned int clear)\r
+{\r
+ unsigned int old;\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ old = uart->mctrl;\r
+ uart->mctrl = (old & ~clear) | set;\r
+ if (old != uart->mctrl)\r
+ spi_uart_write_mctrl(uart, uart->mctrl);\r
+}\r
+\r
+#define spi_uart_set_mctrl(uart, x) spi_uart_update_mctrl(uart, x, 0)\r
+#define spi_uart_clear_mctrl(uart, x) spi_uart_update_mctrl(uart, 0, x)\r
+\r
+static void spi_uart_change_speed(struct spi_uart *uart,\r
+ struct ktermios *termios,\r
+ struct ktermios *old)\r
+{\r
+ unsigned char cval, fcr = 0;\r
+ unsigned int baud, quot;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ \r
+ switch (termios->c_cflag & CSIZE) {\r
+ case CS5:\r
+ cval = UART_LCR_WLEN5;\r
+ break;\r
+ case CS6:\r
+ cval = UART_LCR_WLEN6;\r
+ break;\r
+ case CS7:\r
+ cval = UART_LCR_WLEN7;\r
+ break;\r
+ default:\r
+ case CS8:\r
+ cval = UART_LCR_WLEN8;\r
+ break;\r
+ }\r
+\r
+ if (termios->c_cflag & CSTOPB)\r
+ cval |= UART_LCR_STOP;\r
+ if (termios->c_cflag & PARENB)\r
+ cval |= UART_LCR_PARITY;\r
+ if (!(termios->c_cflag & PARODD))\r
+ cval |= UART_LCR_EPAR;\r
+\r
+ for (;;) {\r
+ baud = tty_termios_baud_rate(termios);\r
+ if (baud == 0)\r
+ baud = 115200; /* Special case: B0 rate. */\r
+ if (baud <= uart->uartclk)\r
+ break;\r
+ /*\r
+ * Oops, the quotient was zero. Try again with the old\r
+ * baud rate if possible, otherwise default to 115200.\r
+ */\r
+ termios->c_cflag &= ~CBAUD;\r
+ if (old) {\r
+ termios->c_cflag |= old->c_cflag & CBAUD;\r
+ old = NULL;\r
+ } else\r
+ termios->c_cflag |= B115200;\r
+ }\r
+ //quot = (2 * uart->uartclk + baud) / (2 * baud);\r
+ quot = (uart->uartclk / 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
+ else\r
+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;\r
+\r
+ uart->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;\r
+ if (termios->c_iflag & INPCK)\r
+ uart->read_status_mask |= UART_LSR_FE | UART_LSR_PE;\r
+ if (termios->c_iflag & (BRKINT | PARMRK))\r
+ uart->read_status_mask |= UART_LSR_BI;\r
+\r
+ /*\r
+ * Characters to ignore\r
+ */\r
+ uart->ignore_status_mask = 0;\r
+ if (termios->c_iflag & IGNPAR)\r
+ uart->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;\r
+ if (termios->c_iflag & IGNBRK) {\r
+ uart->ignore_status_mask |= UART_LSR_BI;\r
+ /*\r
+ * If we're ignoring parity and break indicators,\r
+ * ignore overruns too (for real raw support).\r
+ */\r
+ if (termios->c_iflag & IGNPAR)\r
+ uart->ignore_status_mask |= UART_LSR_OE;\r
+ }\r
+\r
+ /*\r
+ * ignore all characters if CREAD is not set\r
+ */\r
+ if ((termios->c_cflag & CREAD) == 0)\r
+ uart->ignore_status_mask |= UART_LSR_DR;\r
+\r
+ /*\r
+ * CTS flow control flag and modem status interrupts\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
+\r
+ uart->lcr = cval;\r
+\r
+ spi_out(port, UART_IER, uart->ier, SEL_UART);\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
+ DBG("Enter::%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
+}\r
+\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("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
+#endif\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("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
+}\r
+\r
+static void spi_uart_stop_rx(struct spi_uart *uart)\r
+{\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ uart->ier &= ~UART_IER_RLSI;\r
+ uart->read_status_mask &= ~UART_LSR_DR;\r
+ spi_out(port, UART_IER, uart->ier, SEL_UART);\r
+}\r
+\r
+static void spi_uart_receive_chars(struct spi_uart *uart, unsigned int *status)\r
+{\r
+ struct tty_struct *tty = uart->tty;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ \r
+ unsigned int ch, flag;\r
+ int max_count = 1024; \r
+ //printk("rx:");\r
+ while (--max_count >0 )\r
+ {\r
+ ch = spi_in(port, UART_RX, SEL_UART);//\r
+ //printk("0x%x,",ch&0xff);\r
+ flag = TTY_NORMAL;\r
+ uart->icount.rx++;\r
+ //--max_count;\r
+#if 1\r
+ if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |\r
+ UART_LSR_FE | UART_LSR_OE))) {\r
+ /*\r
+ * For statistics only\r
+ */\r
+ if (*status & UART_LSR_BI) {\r
+ *status &= ~(UART_LSR_FE | UART_LSR_PE);\r
+ uart->icount.brk++;\r
+ } else if (*status & UART_LSR_PE)\r
+ uart->icount.parity++;\r
+ else if (*status & UART_LSR_FE)\r
+ uart->icount.frame++;\r
+ if (*status & UART_LSR_OE)\r
+ uart->icount.overrun++;\r
+\r
+ /*\r
+ * Mask off conditions which should be ignored.\r
+ */\r
+ *status &= uart->read_status_mask;\r
+ if (*status & UART_LSR_BI) {\r
+ flag = TTY_BREAK;\r
+ } else if (*status & UART_LSR_PE)\r
+ flag = TTY_PARITY;\r
+ else if (*status & UART_LSR_FE)\r
+ flag = TTY_FRAME;\r
+ }\r
+#endif\r
+ if ((*status & uart->ignore_status_mask & ~UART_LSR_OE) == 0)\r
+ tty_insert_flip_char(tty, ch, flag);\r
+\r
+ /*\r
+ * Overrun is special. Since it's reported immediately,\r
+ * it doesn't affect the current character.\r
+ */\r
+ if (*status & ~uart->ignore_status_mask & UART_LSR_OE)\r
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);\r
+ *status = spi_in(port, UART_LSR, SEL_UART);\r
+ if(!(*status & UART_LSR_DR))\r
+ break;\r
+ } \r
+ //printk("\n");\r
+ DBG("Enter::%s,LINE=%d,rx_count=%d********\n",__FUNCTION__,__LINE__,(1024-max_count));\r
+ printk("r%d\n",1024-max_count);\r
+ tty_flip_buffer_push(tty);\r
+ \r
+}\r
+\r
+static void spi_uart_transmit_chars(struct spi_uart *uart)\r
+{\r
+ struct circ_buf *xmit = &uart->xmit;\r
+ int count;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ \r
+ if (uart->x_char) {\r
+ spi_out(port, UART_TX, uart->x_char, SEL_UART);\r
+ uart->icount.tx++;\r
+ uart->x_char = 0;\r
+ printk("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+ return;\r
+ }\r
+ if (circ_empty(xmit) || uart->tty->stopped || uart->tty->hw_stopped) {\r
+ spi_uart_stop_tx(uart);\r
+ DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+ //printk("circ_empty()\n");\r
+ return;\r
+ }\r
+ //printk("tx:");\r
+ count = 32;//\r
+ while(count > 0)\r
+ {\r
+ spi_out(port, UART_TX, xmit->buf[xmit->tail], SEL_UART);\r
+ //printk("0x%x,",xmit->buf[xmit->tail]);\r
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);\r
+ uart->icount.tx++;\r
+ --count;\r
+ if (circ_empty(xmit))\r
+ break; \r
+ }\r
+\r
+ //printk("\n");\r
+ DBG("Enter::%s,LINE=%d,tx_count=%d\n",__FUNCTION__,__LINE__,(32-count));\r
+ if (circ_chars_pending(xmit) < WAKEUP_CHARS)\r
+ { \r
+ tty_wakeup(uart->tty);\r
+ printk("k,");\r
+ }\r
+ DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+ if (circ_empty(xmit))\r
+ {\r
+ DBG("circ_empty(xmit)\n");\r
+ spi_uart_stop_tx(uart);\r
+ printk("e,");\r
+ }\r
+ \r
+ printk("t%d\n",32-count);\r
+\r
+ DBG("uart->tty->hw_stopped = %d\n",uart->tty->hw_stopped);\r
+}\r
+\r
+#if 0\r
+static void spi_uart_check_modem_status(struct spi_uart *uart)\r
+{\r
+ int status;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ \r
+ status = spi_in(port, UART_MSR, SEL_UART);//\r
+ DBG("Enter::%s,LINE=%d,status=0x%x*******\n",__FUNCTION__,__LINE__,status);\r
+ if ((status & UART_MSR_ANY_DELTA) == 0)\r
+ return;\r
+\r
+ if (status & UART_MSR_TERI)\r
+ uart->icount.rng++;\r
+ if (status & UART_MSR_DDSR)\r
+ uart->icount.dsr++;\r
+ if (status & UART_MSR_DDCD)\r
+ uart->icount.dcd++;\r
+ if (status & UART_MSR_DCTS) {\r
+ uart->icount.cts++;\r
+ if (uart->tty->termios->c_cflag & CRTSCTS) {\r
+ int cts = (status & UART_MSR_CTS);\r
+ if (uart->tty->hw_stopped) {\r
+ if (cts) {\r
+ uart->tty->hw_stopped = 0;\r
+ spi_uart_start_tx(uart);\r
+ DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
+ tty_wakeup(uart->tty);\r
+ }\r
+ } else {\r
+ if (!cts) {\r
+ uart->tty->hw_stopped = 1;\r
+ DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
+ spi_uart_stop_tx(uart);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ DBG("Enter::%s,LINE=%d,status=0x%x*******\n",__FUNCTION__,__LINE__,status);\r
+}\r
+#endif\r
+\r
+\r
+#if SPI_UART_TEST\r
+#define UART_TEST_LEN 16 //8bit\r
+unsigned char buf_test_uart[UART_TEST_LEN];\r
+unsigned int ice65l08_init_para[]=\r
+{\r
+ 0x030083, \r
+ 0x010000,\r
+ 0x000034, // (0100XYH) ÉèÖ÷ÖƵϵÊý£ºXY = MCLK / (4*²¨ÌØÂÊ)£»\r
+ 0x030003, // ÉèÖÃ×Ö½ÚÓÐЧ³¤¶È£º 8 bits£»\r
+ 0x01000f, // TX RX ÖжÏ\r
+ 0x020080, // ÉèÖô¥·¢µÈ¼¶ ½ÓÊÜFIFOΪ 16bytes ²úÉúÖжϣ»\r
+};\r
+\r
+void spi_uart_work_handler(struct work_struct *work)\r
+{\r
+ int i;\r
+ int ret,count;\r
+ int offset,value;\r
+ struct spi_fpga_port *port =\r
+ container_of(work, struct spi_fpga_port, uart.spi_uart_work);\r
+ printk("*************test spi_uart now***************\n");\r
+\r
+ for(i=0;i<UART_TEST_LEN;i++)\r
+ buf_test_uart[i] = '0'+i; \r
+\r
+ for(i =0; i<sizeof(ice65l08_init_para)/sizeof(ice65l08_init_para[0]); i++)\r
+ {\r
+ offset = (ice65l08_init_para[i] >> 16) & 0xff;\r
+ value = ice65l08_init_para[i] & 0xffff;\r
+ spi_out(port, offset, value, SEL_UART);\r
+ } \r
+ \r
+ count = UART_TEST_LEN;\r
+ while(count > 0)\r
+ {\r
+ spi_out(port, UART_TX, buf_test_uart[UART_TEST_LEN-count], SEL_UART);\r
+ --count;\r
+ }\r
+}\r
+\r
+static void spi_testuart_timer(unsigned long data)\r
+{\r
+ struct spi_fpga_port *port = (struct spi_fpga_port *)data;\r
+ port->uart.uart_timer.expires = jiffies + msecs_to_jiffies(1000);\r
+ add_timer(&port->uart.uart_timer);\r
+ //schedule_work(&port->gpio.spi_gpio_work);\r
+ queue_work(port->uart.spi_uart_workqueue, &port->uart.spi_uart_work);\r
+}\r
+\r
+#endif\r
+\r
+\r
+\r
+\r
+/*\r
+ * This handles the interrupt from one port.\r
+ */\r
+void spi_uart_handle_irq(struct spi_device *spi)\r
+{\r
+ struct spi_fpga_port *port = spi_get_drvdata(spi);\r
+ struct spi_uart *uart = &port->uart;\r
+ unsigned int uart_iir, lsr;\r
+\r
+ if (unlikely(uart->in_spi_uart_irq == current))\r
+ return;\r
+ DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+\r
+ /*\r
+ * In a few places spi_uart_handle_irq() is called directly instead of\r
+ * waiting for the actual interrupt to be raised and the SPI IRQ\r
+ * thread scheduled in order to reduce latency. However, some\r
+ * interaction with the tty core may end up calling us back\r
+ * (serial echo, flow control, etc.) through those same places\r
+ * causing undesirable effects. Let's stop the recursion here.\r
+ */\r
+ \r
+ uart_iir = spi_in(port, UART_IIR, SEL_UART);// \r
+ if (uart_iir & UART_IIR_NO_INT)\r
+ return;\r
+ \r
+ DBG("iir=0x%x\n",uart_iir);\r
+ \r
+ uart->in_spi_uart_irq = current;\r
+ lsr = spi_in(port, UART_LSR, SEL_UART);//\r
+ DBG("lsr=0x%x\n",lsr);\r
+\r
+ if (lsr & UART_LSR_DR)\r
+ //if (((uart_iir & UART_IIR_RDI) | (uart_iir & UART_IIR_RLSI)) && (lsr & UART_LSR_DR))\r
+ {\r
+ DBG("Enter::%s,LINE=%d,lsr & UART_LSR_DR************\n",__FUNCTION__,__LINE__);\r
+ spi_uart_receive_chars(uart, &lsr); \r
+ }\r
+\r
+ //spi_uart_check_modem_status(uart);\r
+ \r
+ \r
+ if (lsr & UART_LSR_THRE)\r
+ //if ((uart_iir & UART_IIR_THRI)&&(lsr & UART_LSR_THRE))\r
+ {\r
+ DBG("Enter::%s,LINE=%d,ICE_STATUS_TXF == 0************\n",__FUNCTION__,__LINE__);\r
+ spi_uart_transmit_chars(uart);\r
+ }\r
+\r
+ uart->in_spi_uart_irq = NULL;\r
+\r
+ DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+ \r
+}\r
+\r
+static int spi_uart_startup(struct spi_uart *uart)\r
+{\r
+ unsigned long page;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ \r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ /*\r
+ * Set the TTY IO error marker - we will only clear this\r
+ * once we have successfully opened the port.\r
+ */\r
+ set_bit(TTY_IO_ERROR, &uart->tty->flags);\r
+\r
+ /* Initialise and allocate the transmit buffer. */\r
+ page = __get_free_page(GFP_KERNEL);\r
+ if (!page)\r
+ return -ENOMEM;\r
+\r
+ uart->xmit.buf = (unsigned char *)page;\r
+ circ_clear(&uart->xmit);\r
+\r
+ //mutex_lock(&port->spi_lock);\r
+\r
+ /*\r
+ * Clear the FIFO buffers and disable them.\r
+ * (they will be reenabled in spi_change_speed())\r
+ */\r
+ spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO, SEL_UART);\r
+ spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |\r
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, SEL_UART);\r
+ spi_out(port, UART_FCR, 0, SEL_UART);\r
+\r
+ /*\r
+ * Clear the interrupt registers.\r
+ */\r
+ (void) spi_in(port, UART_LSR, SEL_UART);//\r
+ (void) spi_in(port, UART_RX, SEL_UART);//\r
+ (void) spi_in(port, UART_IIR, SEL_UART);//\r
+ (void) spi_in(port, UART_MSR, SEL_UART);//\r
+\r
+ /*\r
+ * Now, initialize the UART\r
+ */\r
+ spi_out(port, UART_LCR, UART_LCR_WLEN8, SEL_UART);\r
+\r
+ uart->ier = UART_IER_RLSI | UART_IER_RDI;\r
+ //uart->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;\r
+ uart->mctrl = TIOCM_OUT2;\r
+\r
+ spi_uart_change_speed(uart, uart->tty->termios, NULL);\r
+\r
+ if (uart->tty->termios->c_cflag & CBAUD)\r
+ spi_uart_set_mctrl(uart, TIOCM_RTS | TIOCM_DTR);\r
+\r
+ if (uart->tty->termios->c_cflag & CRTSCTS)\r
+ if (!(spi_uart_get_mctrl(uart) & TIOCM_CTS))\r
+ uart->tty->hw_stopped = 1;\r
+\r
+ clear_bit(TTY_IO_ERROR, &uart->tty->flags);\r
+ DBG("Enter::%s,LINE=%d,uart->ier=0x%x\n",__FUNCTION__,__LINE__,uart->ier);\r
+ /* Kick the IRQ handler once while we're still holding the host lock */\r
+ //spi_uart_handle_irq(port->spi);\r
+ //mutex_unlock(&port->spi_lock);\r
+ return 0;\r
+\r
+//err1:\r
+ //free_page((unsigned long)uart->xmit.buf);\r
+ //return ret;\r
+}\r
+\r
+static void spi_uart_shutdown(struct spi_uart *uart)\r
+{\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ //mutex_lock(&port->spi_lock);\r
+ spi_uart_stop_rx(uart);\r
+\r
+ /* TODO: wait here for TX FIFO to drain */\r
+\r
+ /* Turn off DTR and RTS early. */\r
+ if (uart->tty->termios->c_cflag & HUPCL)\r
+ spi_uart_clear_mctrl(uart, TIOCM_DTR | TIOCM_RTS);\r
+\r
+ /* Disable interrupts from this port */\r
+\r
+ uart->ier = 0;\r
+ spi_out(port, UART_IER, 0, SEL_UART);\r
+\r
+ spi_uart_clear_mctrl(uart, TIOCM_OUT2);\r
+\r
+ /* Disable break condition and FIFOs. */\r
+ uart->lcr &= ~UART_LCR_SBC;\r
+ spi_out(port, UART_LCR, uart->lcr, SEL_UART);\r
+ spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |\r
+ UART_FCR_CLEAR_RCVR |\r
+ UART_FCR_CLEAR_XMIT, SEL_UART);\r
+ spi_out(port, UART_FCR, 0, SEL_UART);\r
+\r
+ //mutex_unlock(&port->spi_lock);\r
+\r
+//skip:\r
+ /* Free the transmit buffer page. */\r
+ free_page((unsigned long)uart->xmit.buf);\r
+}\r
+\r
+static int spi_uart_open (struct tty_struct *tty, struct file * filp)\r
+{\r
+ struct spi_uart *uart;\r
+ int ret;\r
+ \r
+ uart = spi_uart_port_get(tty->index);\r
+ if (!uart)\r
+ {\r
+ DBG("Enter::%s,LINE=%d,!port\n",__FUNCTION__,__LINE__);\r
+ return -ENODEV;\r
+ }\r
+ DBG("Enter::%s,LINE=%d,tty->index=%d\n",__FUNCTION__,__LINE__,tty->index);\r
+ mutex_lock(&uart->open_lock);\r
+\r
+ /*\r
+ * Make sure not to mess up with a dead port\r
+ * which has not been closed yet.\r
+ */\r
+ if (tty->driver_data && tty->driver_data != uart) {\r
+ mutex_unlock(&uart->open_lock);\r
+ spi_uart_port_put(uart);\r
+ DBG("Enter::%s,LINE=%d,!= uart\n",__FUNCTION__,__LINE__);\r
+ return -EBUSY;\r
+ }\r
+\r
+ if (!uart->opened) {\r
+ tty->driver_data = uart;\r
+ uart->tty = tty;\r
+ ret = spi_uart_startup(uart);\r
+ if (ret) {\r
+ tty->driver_data = NULL;\r
+ uart->tty = NULL;\r
+ mutex_unlock(&uart->open_lock);\r
+ spi_uart_port_put(uart);\r
+ DBG("Enter::%s,LINE=%d,ret=%d\n",__FUNCTION__,__LINE__,ret);\r
+ return ret;\r
+ }\r
+ }\r
+ uart->opened++;\r
+ DBG("Enter::%s,uart->opened++=%d\n",__FUNCTION__,uart->opened);\r
+ mutex_unlock(&uart->open_lock);\r
+ return 0;\r
+}\r
+\r
+static void spi_uart_close(struct tty_struct *tty, struct file * filp)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ printk("Enter::%s,LINE=%d,tty->hw_stopped=%d\n",__FUNCTION__,__LINE__,tty->hw_stopped);\r
+ if (!uart)\r
+ return;\r
+\r
+ mutex_lock(&uart->open_lock);\r
+ BUG_ON(!uart->opened);\r
+\r
+ /*\r
+ * This is messy. The tty layer calls us even when open()\r
+ * returned an error. Ignore this close request if tty->count\r
+ * is larger than uart->count.\r
+ */\r
+ if (tty->count > uart->opened) {\r
+ mutex_unlock(&uart->open_lock);\r
+ return;\r
+ }\r
+\r
+ if (--uart->opened == 0) {\r
+ DBG("Enter::%s,opened=%d\n",__FUNCTION__,uart->opened);\r
+ tty->closing = 1;\r
+ spi_uart_shutdown(uart);\r
+ tty_ldisc_flush(tty);\r
+ uart->tty = NULL;\r
+ tty->driver_data = NULL;\r
+ tty->closing = 0;\r
+ }\r
+ spi_uart_port_put(uart);\r
+ mutex_unlock(&uart->open_lock);\r
+\r
+}\r
+\r
+static int spi_uart_write(struct tty_struct * tty, const unsigned char *buf,\r
+ int count)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ struct circ_buf *circ = &uart->xmit;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ int c, ret = 0;\r
+\r
+ if (!port->spi)\r
+ {\r
+ printk("spi error!!!!\n");\r
+ return -ENODEV;\r
+ }\r
+\r
+ \r
+ DBG("spi_uart_write 1 circ->head=%d,circ->tail=%d\n",circ->head,circ->tail);\r
+\r
+ spin_lock(&uart->write_lock);\r
+ while (1) {\r
+ c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);\r
+ if (count < c)\r
+ c = count;\r
+ if (c <= 0)\r
+ break;\r
+ memcpy(circ->buf + circ->head, buf, c);\r
+ circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);\r
+ buf += c;\r
+ count -= c;\r
+ ret += c;\r
+ }\r
+ spin_unlock(&uart->write_lock);\r
+ \r
+#if 1\r
+ if ( !(uart->ier & UART_IER_THRI)) {\r
+ //mutex_lock(&port->spi_lock);\r
+ DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+ /*Note:ICE65L08 output a 'Transmitter holding register interrupt' after 1us*/\r
+ //printk("s,");\r
+ spi_uart_start_tx(uart);\r
+ spi_uart_handle_irq(port->spi);\r
+ //mutex_unlock(&port->spi_lock); \r
+ } \r
+#endif \r
+\r
+ //printk("w%d\n",ret);\r
+ return ret;\r
+}\r
+\r
+static int spi_uart_write_room(struct tty_struct *tty)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
+ return uart ? circ_chars_free(&uart->xmit) : 0;\r
+}\r
+\r
+static int spi_uart_chars_in_buffer(struct tty_struct *tty)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ printk("Enter::%s,LINE=%d,circ=%ld****\n",__FUNCTION__,__LINE__,circ_chars_pending(&uart->xmit)); \r
+ return uart ? circ_chars_pending(&uart->xmit) : 0;\r
+}\r
+\r
+static void spi_uart_send_xchar(struct tty_struct *tty, char ch)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ uart->x_char = ch;\r
+ if (ch && !(uart->ier & UART_IER_THRI)) {\r
+ //mutex_lock(&port->spi_lock);\r
+ spi_uart_start_tx(uart);\r
+ printk("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
+ spi_uart_handle_irq(port->spi);\r
+ //mutex_unlock(&port->spi_lock); \r
+ }\r
+}\r
+\r
+static void spi_uart_throttle(struct tty_struct *tty)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS))\r
+ return;\r
+ printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ //mutex_lock(&port->spi_lock);\r
+ if (I_IXOFF(tty)) {\r
+ uart->x_char = STOP_CHAR(tty);\r
+ spi_uart_start_tx(uart);\r
+ DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
+ }\r
+\r
+ if (tty->termios->c_cflag & CRTSCTS)\r
+ spi_uart_clear_mctrl(uart, TIOCM_RTS);\r
+\r
+ spi_uart_handle_irq(port->spi);\r
+ //mutex_unlock(&port->spi_lock);\r
+}\r
+\r
+static void spi_uart_unthrottle(struct tty_struct *tty)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
+ printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS))\r
+ return;\r
+ //mutex_lock(&port->spi_lock);\r
+ if (I_IXOFF(tty)) {\r
+ if (uart->x_char) {\r
+ uart->x_char = 0;\r
+ } else {\r
+ uart->x_char = START_CHAR(tty);\r
+ spi_uart_start_tx(uart);\r
+ DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
+ }\r
+ }\r
+\r
+ if (tty->termios->c_cflag & CRTSCTS)\r
+ spi_uart_set_mctrl(uart, TIOCM_RTS);\r
+\r
+ spi_uart_handle_irq(port->spi);\r
+ //mutex_unlock(&port->spi_lock);\r
+}\r
+\r
+static void spi_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ unsigned int cflag = tty->termios->c_cflag;\r
+ unsigned int mask = TIOCM_DTR;\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ \r
+#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))\r
+\r
+ if ((cflag ^ old_termios->c_cflag) == 0 &&\r
+ RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)\r
+ return;\r
+\r
+ //mutex_lock(&port->spi_lock);\r
+ spi_uart_change_speed(uart, tty->termios, old_termios);\r
+\r
+ /* Handle transition to B0 status */\r
+ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)){\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ spi_uart_clear_mctrl(uart, TIOCM_RTS | TIOCM_DTR);\r
+ //spi_uart_clear_mctrl(uart, TIOCM_RTS);\r
+ }\r
+ \r
+ /* Handle transition away from B0 status */\r
+ if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ if (!(cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags))\r
+ mask |= TIOCM_RTS;\r
+ spi_uart_set_mctrl(uart, mask);\r
+ }\r
+\r
+ /* Handle turning off CRTSCTS */\r
+ if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ tty->hw_stopped = 0;\r
+ spi_uart_start_tx(uart);\r
+ DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
+ }\r
+\r
+ /* Handle turning on CRTSCTS */\r
+ if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {\r
+ DBG("Enter::%s,LINE=%d,status=0x%x,Handle turning on CRTSCTS*****************\n",__FUNCTION__,__LINE__,spi_uart_get_mctrl(uart));\r
+ //spi_uart_set_mctrl(uart, TIOCM_RTS);\r
+ if (!(spi_uart_get_mctrl(uart) & TIOCM_CTS)) {\r
+ DBG("Enter::%s,LINE=%d,tty->hw_stopped = 1********\n",__FUNCTION__,__LINE__);\r
+ tty->hw_stopped = 1;\r
+ spi_uart_stop_tx(uart);\r
+ }\r
+ }\r
+ //mutex_unlock(&port->spi_lock);\r
+\r
+}\r
+\r
+static int spi_uart_break_ctl(struct tty_struct *tty, int break_state)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart); \r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ //mutex_lock(&port->spi_lock);\r
+ if (break_state == -1)\r
+ uart->lcr |= UART_LCR_SBC;\r
+ else\r
+ uart->lcr &= ~UART_LCR_SBC;\r
+ spi_out(port, UART_LCR, uart->lcr, SEL_UART);\r
+ //mutex_unlock(&port->spi_lock);\r
+ return 0;\r
+}\r
+\r
+static int spi_uart_tiocmget(struct tty_struct *tty, struct file *file)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ int result;\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ //mutex_lock(&port->spi_lock);\r
+ result = uart->mctrl | spi_uart_get_mctrl(uart);\r
+ //mutex_unlock(&port->spi_lock);\r
+ return result;\r
+}\r
+\r
+static int spi_uart_tiocmset(struct tty_struct *tty, struct file *file,\r
+ unsigned int set, unsigned int clear)\r
+{\r
+ struct spi_uart *uart = tty->driver_data;\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ //mutex_lock(&port->spi_lock);\r
+ spi_uart_update_mctrl(uart, set, clear);\r
+ //mutex_unlock(&port->spi_lock);\r
+\r
+ return 0;\r
+}\r
+\r
+#if 0\r
+static int spi_uart_read_proc(char *page, char **start, off_t off,\r
+ int count, int *eof, void *data)\r
+{\r
+ int i, len = 0;\r
+ off_t begin = 0;\r
+ DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
+ len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n",\r
+ "", "", "");\r
+ for (i = 0; i < UART_NR && len < PAGE_SIZE - 96; i++) {\r
+ struct spi_uart *uart = spi_uart_port_get(i);\r
+ if (uart) {\r
+ len += sprintf(page+len, "%d: uart:SPI", i);\r
+ if(capable(CAP_SYS_ADMIN)) {\r
+ len += sprintf(page + len, " tx:%d rx:%d",\r
+ uart->icount.tx, uart->icount.rx);\r
+ if (uart->icount.frame)\r
+ len += sprintf(page + len, " fe:%d",\r
+ uart->icount.frame);\r
+ if (uart->icount.parity)\r
+ len += sprintf(page + len, " pe:%d",\r
+ uart->icount.parity);\r
+ if (uart->icount.brk)\r
+ len += sprintf(page + len, " brk:%d",\r
+ uart->icount.brk);\r
+ if (uart->icount.overrun)\r
+ len += sprintf(page + len, " oe:%d",\r
+ uart->icount.overrun);\r
+ if (uart->icount.cts)\r
+ len += sprintf(page + len, " cts:%d",\r
+ uart->icount.cts);\r
+ if (uart->icount.dsr)\r
+ len += sprintf(page + len, " dsr:%d",\r
+ uart->icount.dsr);\r
+ if (uart->icount.rng)\r
+ len += sprintf(page + len, " rng:%d",\r
+ uart->icount.rng);\r
+ if (uart->icount.dcd)\r
+ len += sprintf(page + len, " dcd:%d",\r
+ uart->icount.dcd);\r
+ }\r
+ strcat(page, "\n");\r
+ len++;\r
+ spi_uart_port_put(uart);\r
+ }\r
+\r
+ if (len + begin > off + count)\r
+ goto done;\r
+ if (len + begin < off) {\r
+ begin += len;\r
+ len = 0;\r
+ }\r
+ }\r
+ *eof = 1;\r
+\r
+done:\r
+ if (off >= len + begin)\r
+ return 0;\r
+ *start = page + (off - begin);\r
+ return (count < begin + len - off) ? count : (begin + len - off);\r
+}\r
+#endif\r
+\r
+static const struct tty_operations spi_uart_ops = {\r
+ .open = spi_uart_open,\r
+ .close = spi_uart_close,\r
+ .write = spi_uart_write,\r
+ .write_room = spi_uart_write_room,\r
+ .chars_in_buffer = spi_uart_chars_in_buffer,\r
+ .send_xchar = spi_uart_send_xchar,\r
+ .throttle = spi_uart_throttle,\r
+ .unthrottle = spi_uart_unthrottle,\r
+ .set_termios = spi_uart_set_termios,\r
+ .break_ctl = spi_uart_break_ctl,\r
+ .tiocmget = spi_uart_tiocmget,\r
+ .tiocmset = spi_uart_tiocmset,\r
+ //.read_proc = spi_uart_read_proc,\r
+};\r
+\r
+\r
+static struct tty_driver *spi_uart_tty_driver;\r
+\r
+int spi_uart_register(struct spi_fpga_port *port)\r
+{\r
+ int i,ret;\r
+ struct tty_driver *tty_drv;\r
+ spi_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR);\r
+ if (!tty_drv)\r
+ return -ENOMEM;\r
+ tty_drv->owner = THIS_MODULE;\r
+ tty_drv->driver_name = "spi_uart";\r
+ tty_drv->name = "ttySPI";\r
+ tty_drv->major = 0; /* dynamically allocated */\r
+ tty_drv->minor_start = 0;\r
+ //tty_drv->num = UART_NR;\r
+ tty_drv->type = TTY_DRIVER_TYPE_SERIAL;\r
+ tty_drv->subtype = SERIAL_TYPE_NORMAL;\r
+ tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;\r
+ tty_drv->init_termios = tty_std_termios;\r
+ tty_drv->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;\r
+ tty_drv->init_termios.c_ispeed = 115200;\r
+ tty_drv->init_termios.c_ospeed = 115200;\r
+ tty_set_operations(tty_drv, &spi_uart_ops);\r
+\r
+ ret = tty_register_driver(tty_drv);\r
+ if (ret)\r
+ goto err1;\r
+\r
+ //port->uart.uartclk = 64*115200; //MCLK/4\r
+ port->uart.uartclk = 60*100000; //MCLK/4\r
+\r
+ for(i=0; i<UART_NR; i++)\r
+ {\r
+ ret = spi_uart_add_port(&port->uart);\r
+ if (ret) {\r
+ goto err2;\r
+ } else {\r
+ struct device *dev;\r
+ dev = tty_register_device(spi_uart_tty_driver, port->uart.index, &port->spi->dev);\r
+ if (IS_ERR(dev)) {\r
+ spi_uart_port_remove(&port->uart);\r
+ ret = PTR_ERR(dev);\r
+ goto err2;\r
+ }\r
+ }\r
+ }\r
+\r
+#if SPI_UART_TEST\r
+ char b[20];\r
+ sprintf(b, "spi_uart_workqueue");\r
+ port->uart.spi_uart_workqueue = create_freezeable_workqueue(b);\r
+ if (!port->uart.spi_uart_workqueue) {\r
+ printk("cannot create workqueue\n");\r
+ return -EBUSY;\r
+ }\r
+ INIT_WORK(&port->uart.spi_uart_work, spi_uart_work_handler);\r
+\r
+ setup_timer(&port->uart.uart_timer, spi_testuart_timer, (unsigned long)port);\r
+ port->uart.uart_timer.expires = jiffies+2000;\r
+ add_timer(&port->uart.uart_timer);\r
+\r
+#endif\r
+\r
+\r
+ return 0;\r
+\r
+err2:\r
+ tty_unregister_driver(tty_drv);\r
+err1:\r
+ put_tty_driver(tty_drv);\r
+ \r
+ return ret;\r
+ \r
+ \r
+}\r
+int spi_uart_unregister(struct spi_fpga_port *port)\r
+{\r
+\r
+ return 0;\r
+}\r
+\r
+MODULE_DESCRIPTION("Driver for spi2uart.");\r
+MODULE_AUTHOR("luowei <lw@rock-chips.com>");\r
+MODULE_LICENSE("GPL");\r
__u16 len; /* msg length */
__u8 *buf; /* pointer to msg data */
__u32 scl_rate;
+ __u16 channel;
+ __u16 read_type;
};
/* To determine what functionality is present */