From 2d4da31b22fee269118e00e018db1cdbaa79ef3f Mon Sep 17 00:00:00 2001 From: root Date: Tue, 10 Aug 2010 14:42:39 +0800 Subject: [PATCH] =?utf8?q?=E7=BD=97=E4=BC=9F=E6=8F=90=E4=BA=A4fpga=20gpio?= =?utf8?q?=E6=8E=A5=E5=8F=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- arch/arm/mach-rk2818/include/mach/spi_fpga.h | 5 + drivers/fpga/spi_gpio.c | 392 +++++++++---------- 2 files changed, 194 insertions(+), 203 deletions(-) diff --git a/arch/arm/mach-rk2818/include/mach/spi_fpga.h b/arch/arm/mach-rk2818/include/mach/spi_fpga.h index bb58ed2ff63f..1b7c4a057074 100755 --- a/arch/arm/mach-rk2818/include/mach/spi_fpga.h +++ b/arch/arm/mach-rk2818/include/mach/spi_fpga.h @@ -4,12 +4,14 @@ defines of FPGA chip ICE65L08's register #ifndef SPI_UART_H #define SPI_UART_H + #include #include #define SPI_FPGA_INT_PIN RK2818_PIN_PA4 #define SPI_DPRAM_BUSY_PIN RK2818_PIN_PA2 #define SPI_FPGA_STANDBY_PIN RK2818_PIN_PH7 +#define SPI_FPGA_RST_PIN RK2818_PIN_PH6 #define SPI_FPGA_TEST_DEBUG 0 #if SPI_FPGA_TEST_DEBUG @@ -60,7 +62,10 @@ struct spi_gpio { struct workqueue_struct *spi_gpio_workqueue; struct work_struct spi_gpio_work; + struct workqueue_struct *spi_gpio_irq_workqueue; + struct work_struct spi_gpio_irq_work; struct timer_list gpio_timer; + struct list_head msg_queue; }; struct spi_i2c_data diff --git a/drivers/fpga/spi_gpio.c b/drivers/fpga/spi_gpio.c index 3df06448b538..c7306456b5f4 100755 --- a/drivers/fpga/spi_gpio.c +++ b/drivers/fpga/spi_gpio.c @@ -38,7 +38,6 @@ #define SPI_GPIO_TEST 0 #define HIGH_SPI_TEST 1 -#define USE_SYS_INT 0 spinlock_t gpio_lock; spinlock_t gpio_state_lock; @@ -278,11 +277,11 @@ eSpiGpioPinLevel_t spi_gpio_get_pinlevel(eSpiGpioPinNum_t PinNum) if(ICE_SEL_GPIO0 == reg) { reg |= ICE_SEL_GPIO0_DATA; - if((state & (1 << PinNum )) != 0) - { - printk("Fail to get PinLevel because it is int pin!\n"); - return SPI_GPIO_LEVEL_ERR; - } + //if((state & (1 << PinNum )) != 0) + //{ + // printk("Fail to get PinLevel because it is int pin!\n"); + // return SPI_GPIO_LEVEL_ERR; + //} ret = spi_gpio_read_reg(reg); } else @@ -411,6 +410,7 @@ int spi_gpio_read_iir(void) int spi_request_gpio_irq(eSpiGpioPinNum_t PinNum, pSpiFunc Routine, eSpiGpioIntType_t IntType,void *dev_id) { +#if 0 if(PinNum >= SPI_GPIO_IRQ_NUM) return -1; DBG("Enter::%s,LINE=%d,PinNum=%d\n",__FUNCTION__,__LINE__,PinNum); @@ -439,7 +439,7 @@ int spi_request_gpio_irq(eSpiGpioPinNum_t PinNum, pSpiFunc Routine, eSpiGpioIntT printk("%s err:fail to enable gpio intterupt when PinNum=%d\n",__FUNCTION__,PinNum); return -1; } - +#endif return 0; } @@ -454,38 +454,7 @@ int spi_free_gpio_irq(eSpiGpioPinNum_t PinNum) return 0; } -#if (USE_SYS_INT ==0) -int spi_gpio_handle_irq(struct spi_device *spi) -{ - int gpio_iir, i; - int state; - spin_lock(&gpio_state_lock); - state = gGpio0State; - spin_unlock(&gpio_state_lock); - - gpio_iir = spi_gpio_read_iir() & 0xffff; - if(gpio_iir == 0xffff) - return -1; - - DBG("gpio_iir=0x%x\n",gpio_iir); - for(i=0; igpio.gpio_timer.expires = jiffies + msecs_to_jiffies(1000); add_timer(&port->gpio.gpio_timer); - //schedule_work(&port->gpio.spi_gpio_work); queue_work(port->gpio.spi_gpio_workqueue, &port->gpio.spi_gpio_work); } @@ -658,74 +604,6 @@ int spi_gpio_init_first(void) #elif (FPGA_TYPE == ICE_CC196) -#if 0 - DBG("%s:LINE=%d\n",__FUNCTION__,__LINE__); - spi_out(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO0_TYPE), 0x0000, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO0_TYPE), SEL_GPIO) & 0xffff; - if(ret != 0x0000) - DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff; - if(ret != 0x0000) - DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DIR), 0xffff, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO0 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff; - if(ret != 0xffff) - DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DATA), 0x0224, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff; - if(ret != 0x0224) - DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), 0xf7ef, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff; - if(ret != 0xf7ef) - DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO2 | ICE_SEL_GPIO_DATA), 0x2008, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO2 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff; - if(ret != 0x2008) - DBG("%s:Line=%d,set=0x2008,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO2 | ICE_SEL_GPIO_DIR), 0xf378, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO1 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff; - if(ret != 0xf378) - DBG("%s:Line=%d,set=0xf378,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff; - if(ret != 0x0000) - DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DIR), 0xffff, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO3 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff; - if(ret != 0xffff) - DBG("%s:Line=%d,set=0xffff,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff; - if(ret != 0x0000) - DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DIR), 0xffbf, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO4 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff; - if(ret != 0xffbf) - DBG("%s:Line=%d,set=0xffbf,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DATA), 0x0000, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DATA), SEL_GPIO) & 0xffff; - if(ret != 0x0000) - DBG("%s:Line=%d,set=0x0000,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - - spi_out(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DIR), 0xffff, SEL_GPIO); - ret = spi_in(port, (ICE_SEL_GPIO5 | ICE_SEL_GPIO_DIR), SEL_GPIO) & 0xffff; - if(ret != 0xffff) - DBG("%s:Line=%d,set=0xffff,ret=0x%x\n",__FUNCTION__,__LINE__,ret); - -#else spi_gpio_set_pinlevel(SPI_GPIO_P1_00, SPI_GPIO_HIGH); //LCD_ON output// spi_gpio_set_pindirection(SPI_GPIO_P1_00, SPI_GPIO_OUT); spi_gpio_set_pinlevel(SPI_GPIO_P1_01, SPI_GPIO_HIGH); //LCD_PWR_CTRL output @@ -766,9 +644,9 @@ int spi_gpio_init_first(void) spi_gpio_set_pinlevel(SPI_GPIO_P2_03, SPI_GPIO_HIGH); //AP_PW_EN_TD output spi_gpio_set_pindirection(SPI_GPIO_P2_03, SPI_GPIO_OUT); - spi_gpio_set_pinlevel(SPI_GPIO_P2_04, SPI_GPIO_LOW); //AP_RESET_TD output + spi_gpio_set_pinlevel(SPI_GPIO_P2_04, SPI_GPIO_HIGH); //AP_RESET_TD output spi_gpio_set_pindirection(SPI_GPIO_P2_04, SPI_GPIO_OUT); - spi_gpio_set_pinlevel(SPI_GPIO_P2_05, SPI_GPIO_LOW); //AP_SHUTDOWN_TD_PMU output + spi_gpio_set_pinlevel(SPI_GPIO_P2_05, SPI_GPIO_HIGH); //AP_SHUTDOWN_TD_PMU output spi_gpio_set_pindirection(SPI_GPIO_P2_05, SPI_GPIO_OUT); spi_gpio_set_pinlevel(SPI_GPIO_P2_06, SPI_GPIO_LOW); //AP_RESET_CMMB output spi_gpio_set_pindirection(SPI_GPIO_P2_06, SPI_GPIO_OUT); @@ -796,57 +674,14 @@ int spi_gpio_init_first(void) spi_gpio_set_pinlevel(SPI_GPIO_P4_08, SPI_GPIO_LOW); //CM3605_PS_SHUTDOWN spi_gpio_set_pindirection(SPI_GPIO_P4_08, SPI_GPIO_OUT); -#endif -#if SPI_GPIO_TEST -#if (USE_SYS_INT == 0) - for(i=0;i<81;i++) - { - if(i<4) - { - switch(i) - { - case 0: - spi_request_gpio_irq(i, (pSpiFunc)spi_gpio_int_test_0, SPI_GPIO_EDGE_FALLING, port); - break; - case 1: - spi_request_gpio_irq(i, (pSpiFunc)spi_gpio_int_test_1, SPI_GPIO_EDGE_FALLING, port); - break; - case 2: - spi_request_gpio_irq(i, (pSpiFunc)spi_gpio_int_test_2, SPI_GPIO_EDGE_FALLING, port); - break; - case 3: - spi_request_gpio_irq(i, (pSpiFunc)spi_gpio_int_test_3, SPI_GPIO_EDGE_FALLING, port); - break; - - default: - break; - } - - } - else - { - //if(i<16) - //spi_gpio_int_sel(i,SPI_GPIO0_IS_GPIO); - spi_gpio_set_pindirection(i, SPI_GPIO_OUT); - ret = spi_gpio_get_pindirection(i); - if(ret != SPI_GPIO_OUT) - { - #if SPI_FPGA_TEST_DEBUG - spi_test_wrong_handle(); - #endif - printk("err:PinNum=%d,set_pindirection=%d but get_pindirection=%d\n",i,SPI_GPIO_OUT,ret); - } - } - - } -#endif -#endif #endif return 0; } +void spi_gpio_irq_work_handler(struct work_struct *work); + int spi_gpio_register(struct spi_fpga_port *port) { #if SPI_GPIO_TEST @@ -867,6 +702,15 @@ int spi_gpio_register(struct spi_fpga_port *port) spin_lock_init(&gpio_lock); spin_lock_init(&gpio_state_lock); spin_lock_init(&gpio_irq_lock); + + port->gpio.spi_gpio_irq_workqueue = create_freezeable_workqueue("spi_gpio_irq_workqueue"); + if (!port->gpio.spi_gpio_irq_workqueue) { + printk("cannot create spi_gpio_irq workqueue\n"); + return -EBUSY; + } + INIT_WORK(&port->gpio.spi_gpio_irq_work, spi_gpio_irq_work_handler); + INIT_LIST_HEAD(&port->gpio.msg_queue); + DBG("%s:line=%d,port=0x%x\n",__FUNCTION__,__LINE__,(int)port); return 0; } @@ -975,10 +819,24 @@ static struct fpga_gpio_chip spi_gpio_chip[] = { }; -static void spi_gpio_irq_enable(unsigned irq) +#define ID_SPI_GPIO_IRQ_ENABLE 1 +#define ID_SPI_GPIO_IRQ_DISABLE 2 +#define ID_SPI_GPIO_IRQ_SET_TYPE 3 +#define ID_SPI_GPIO_IRQ_SET_WAKE 4 + +struct spi_gpio_irq_transfer +{ + unsigned int irq; + unsigned int type; + unsigned int state; + unsigned int id; + struct list_head queue; +}; + +static void _spi_gpio_irq_enable(unsigned irq) { int gpio = irq_to_gpio(irq) - GPIOS_EXPANDER_BASE; - printk("%s:line=%d,irq=%d,gpio=%d\n",__FUNCTION__,__LINE__,irq,gpio); + DBG("%s:line=%d,irq=%d,gpio=%d\n",__FUNCTION__,__LINE__,irq,gpio); if(gpio < 16) spi_gpio_int_sel(gpio,SPI_GPIO0_IS_INT); else @@ -989,10 +847,10 @@ static void spi_gpio_irq_enable(unsigned irq) spi_gpio_enable_int(gpio); } -static void spi_gpio_irq_disable(unsigned irq) +static void _spi_gpio_irq_disable(unsigned irq) { int gpio = irq_to_gpio(irq) - GPIOS_EXPANDER_BASE; - printk("%s:line=%d,irq=%d,gpio=%d\n",__FUNCTION__,__LINE__,irq,gpio); + DBG("%s:line=%d,irq=%d,gpio=%d\n",__FUNCTION__,__LINE__,irq,gpio); if(gpio < 16) spi_gpio_int_sel(gpio,SPI_GPIO0_IS_INT); else @@ -1004,22 +862,11 @@ static void spi_gpio_irq_disable(unsigned irq) } - -static void spi_gpio_irq_mask(unsigned int irq) -{ - //FPGA do not support irq mask -} - -static void spi_gpio_irq_unmask(unsigned int irq) -{ - //FPGA do not support irq unmask -} - -static int spi_gpio_irq_set_type(unsigned int irq, unsigned int type) +static int _spi_gpio_irq_set_type(unsigned int irq, unsigned int type) { int gpio = irq_to_gpio(irq) - GPIOS_EXPANDER_BASE; int int_type = 0; - printk("%s:line=%d,irq=%d,type=%d,gpio=%d\n",__FUNCTION__,__LINE__,irq,type,gpio); + DBG("%s:line=%d,irq=%d,type=%d,gpio=%d\n",__FUNCTION__,__LINE__,irq,type,gpio); if(gpio < 16) spi_gpio_int_sel(gpio,SPI_GPIO0_IS_INT); else @@ -1043,13 +890,156 @@ static int spi_gpio_irq_set_type(unsigned int irq, unsigned int type) return 0; } -static int spi_gpio_irq_set_wake(unsigned irq, unsigned state) +static int _spi_gpio_irq_set_wake(unsigned irq, unsigned state) { //unsigned int pin = irq_to_gpio(irq); set_irq_wake(irq, state); return 0; } +void spi_gpio_irq_work_handler(struct work_struct *work) +{ + unsigned int irq; + unsigned int type; + unsigned int state; + unsigned int id; + struct spi_fpga_port *port = + container_of(work, struct spi_fpga_port, gpio.spi_gpio_irq_work); + + while (!list_empty(&port->gpio.msg_queue)) + { + struct spi_gpio_irq_transfer *t = NULL; + list_for_each_entry(t, &port->gpio.msg_queue, queue) + { + irq = t->irq; + type = t->type; + state = t->state; + id = t->id; + if ((irq == 0) || (id == 0)) + break; + printk("%s:irq=%d,type=%d,state=%d,id=%d\n",__FUNCTION__,irq,type,state,id); + switch(id) + { + case ID_SPI_GPIO_IRQ_ENABLE: + _spi_gpio_irq_enable(irq); + break; + case ID_SPI_GPIO_IRQ_DISABLE: + _spi_gpio_irq_disable(irq); + break; + case ID_SPI_GPIO_IRQ_SET_TYPE: + _spi_gpio_irq_set_type(irq,type); + break; + case ID_SPI_GPIO_IRQ_SET_WAKE: + _spi_gpio_irq_set_wake(irq,state); + break; + default: + break; + + } + kfree(t); + } + list_del_init(&port->gpio.msg_queue); + } +} + + +static void spi_gpio_irq_enable(unsigned irq) +{ + struct spi_fpga_port *port = pFpgaPort; + struct spi_gpio_irq_transfer *t; + unsigned long flags; + t = kzalloc(sizeof(struct spi_gpio_irq_transfer), GFP_KERNEL); + if (!t) + { + printk("err:%s:ENOMEM\n",__FUNCTION__); + return ; + } + t->irq = irq; + t->id = ID_SPI_GPIO_IRQ_ENABLE; + + spin_lock_irqsave(&port->spi_lock, flags); + list_add_tail(&t->queue, &port->gpio.msg_queue); + queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work); + spin_unlock_irqrestore(&port->spi_lock, flags); +} + +static void spi_gpio_irq_disable(unsigned irq) +{ + struct spi_fpga_port *port = pFpgaPort; + struct spi_gpio_irq_transfer *t; + unsigned long flags; + t = kzalloc(sizeof(struct spi_gpio_irq_transfer), GFP_KERNEL); + if (!t) + { + printk("err:%s:ENOMEM\n",__FUNCTION__); + return ; + } + t->irq = irq; + t->id = ID_SPI_GPIO_IRQ_DISABLE; + + spin_lock_irqsave(&port->spi_lock, flags); + list_add_tail(&t->queue, &port->gpio.msg_queue); + queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work); + spin_unlock_irqrestore(&port->spi_lock, flags); + + +} + +static void spi_gpio_irq_mask(unsigned int irq) +{ + //FPGA do not support irq mask +} + +static void spi_gpio_irq_unmask(unsigned int irq) +{ + //FPGA do not support irq unmask +} + +static int spi_gpio_irq_set_type(unsigned int irq, unsigned int type) +{ + struct spi_fpga_port *port = pFpgaPort; + struct spi_gpio_irq_transfer *t; + unsigned long flags; + t = kzalloc(sizeof(struct spi_gpio_irq_transfer), GFP_KERNEL); + if (!t) + { + printk("err:%s:ENOMEM\n",__FUNCTION__); + return -ENOMEM; + } + t->irq = irq; + t->id = ID_SPI_GPIO_IRQ_SET_TYPE; + t->type = type; + + spin_lock_irqsave(&port->spi_lock, flags); + list_add_tail(&t->queue, &port->gpio.msg_queue); + queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work); + spin_unlock_irqrestore(&port->spi_lock, flags); + return 0; +} + +static int spi_gpio_irq_set_wake(unsigned irq, unsigned state) +{ + struct spi_fpga_port *port = pFpgaPort; + struct spi_gpio_irq_transfer *t; + unsigned long flags; + t = kzalloc(sizeof(struct spi_gpio_irq_transfer), GFP_KERNEL); + if (!t) + { + printk("err:%s:ENOMEM\n",__FUNCTION__); + return -ENOMEM; + } + t->irq = irq; + t->id = ID_SPI_GPIO_IRQ_SET_WAKE; + t->state = state; + + spin_lock_irqsave(&port->spi_lock, flags); + list_add_tail(&t->queue, &port->gpio.msg_queue); + queue_work(port->gpio.spi_gpio_irq_workqueue, &port->gpio.spi_gpio_irq_work); + spin_unlock_irqrestore(&port->spi_lock, flags); + return 0; +} + + static struct irq_chip spi_gpio_irq_chip = { .name = "SPI_GPIO_IRQ", .enable = spi_gpio_irq_enable, @@ -1074,7 +1064,7 @@ void spi_gpio_test_gpio_irq_init(void) printk("%s:failed to request GPIO[%d]\n",__FUNCTION__,gpio); } } -#if USE_SYS_INT + for(i=0;i<4;i++) { gpio = GPIOS_EXPANDER_BASE+i; @@ -1109,7 +1099,7 @@ void spi_gpio_test_gpio_irq_init(void) } break; - case 9: + case 3: ret = request_irq(irq ,spi_gpio_int_test_3,IRQF_TRIGGER_FALLING,NULL,port); if(ret) { @@ -1123,7 +1113,6 @@ void spi_gpio_test_gpio_irq_init(void) } } -#endif #endif @@ -1155,13 +1144,10 @@ void spi_gpio_irq_setup(void) set_irq_flags(pin+j, IRQF_VALID); } - //set_irq_chip_data(pin+j, this); - //set_irq_chained_handler(pin+j, spi_fpga_irq); + printk("%s: %d gpio irqs in %d banks\n", __FUNCTION__, pin+j-GPIOS_EXPANDER_BASE, spi_gpio_banks); - printk("%s: %d gpio irqs in %d banks\n", __FUNCTION__, pin-GPIOS_EXPANDER_BASE, spi_gpio_banks); -#if SPI_GPIO_TEST spi_gpio_test_gpio_irq_init(); -#endif + } -- 2.34.1