From: root Date: Tue, 17 Aug 2010 07:32:02 +0000 (-0700) Subject: 添加tca6424的代码,需要注意的是由于此芯片中断响应必须在I2C的读完成之后操作SDA和SCL脚,在i2c-rk2818.c中添加了一个函数。如果有影响其他器件的工作... X-Git-Tag: firefly_0821_release~11259 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=742cf307846969779053384b0e50a7904f3d4df9;p=firefly-linux-kernel-4.4.55.git 添加tca6424的代码,需要注意的是由于此芯片中断响应必须在I2C的读完成之后操作SDA和SCL脚,在i2c-rk2818.c中添加了一个函数。如果有影响其他器件的工作,请提出。使用之前需要make menuconfig先配置中断引脚数和支持的中断数,都为24,并配置扩展IOtca6424。 --- diff --git a/arch/arm/mach-rk2818/board-infosdk.c b/arch/arm/mach-rk2818/board-infosdk.c index 74c9a237a3cc..4841277db402 100755 --- a/arch/arm/mach-rk2818/board-infosdk.c +++ b/arch/arm/mach-rk2818/board-infosdk.c @@ -254,6 +254,75 @@ struct pca9554_platform_data rk2818_pca9554_data={ }; #endif +#if defined (CONFIG_IOEXTEND_TCA6424) +struct rk2818_gpio_expander_info extgpio_tca6424_settinginfo[] = { + + { + .gpio_num = TCA6424_P01, + .pin_type = GPIO_OUT, + .pin_value = GPIO_LOW, + }, + + { + .gpio_num = TCA6424_P02,// tp3 + .pin_type = GPIO_OUT, + .pin_value = GPIO_LOW, + }, + { + .gpio_num = TCA6424_P03, + .pin_type = GPIO_OUT, + .pin_value = GPIO_LOW, + }, + + { + .gpio_num = TCA6424_P04,// tp3 + .pin_type = GPIO_OUT, + .pin_value = GPIO_LOW, + }, + { + .gpio_num = TCA6424_P05, + .pin_type = GPIO_OUT, + .pin_value = GPIO_LOW, + }, + { + .gpio_num = TCA6424_P12, + .pin_type = GPIO_IN, + //.pin_value =GPIO_HIGH, + }, + + { + .gpio_num = TCA6424_P13,// tp3 + .pin_type = GPIO_IN, + //.pin_value =GPIO_HIGH, + }, + { + .gpio_num = TCA6424_P14, + .pin_type = GPIO_IN, + //.pin_value =GPIO_HIGH, + }, + + { + .gpio_num = TCA6424_P15,// tp3 + .pin_type = GPIO_IN, + //.pin_value =GPIO_HIGH, + }, + +}; + +struct tca6424_platform_data rk2818_tca6424_data={ + .gpio_base=GPIO_EXPANDER_BASE, + .gpio_pin_num=CONFIG_EXPANDED_GPIO_NUM, + .gpio_irq_start=NR_AIC_IRQS + 2*NUM_GROUP + CONFIG_SPI_FPGA_GPIO_IRQ_NUM, + .irq_pin_num=CONFIG_EXPANDED_GPIO_IRQ_NUM, + .tca6424_irq_pin=RK2818_PIN_PA1, + .settinginfo=extgpio_tca6424_settinginfo, + .settinginfolen=ARRAY_SIZE(extgpio_tca6424_settinginfo), + .names="extend_gpio_tca6424", +}; +#endif + + + /***************************************************************************************** * i2c devices * author: kfx@rock-chips.com @@ -357,6 +426,15 @@ static struct i2c_board_info __initdata board_i2c1_devices[] = { .platform_data=&rk2818_pca9554_data.gpio_base, }, #endif +#if defined (CONFIG_IOEXTEND_TCA6424) + { + .type = "extend_gpio_tca6424", + .addr = 0x23, + .flags = 0, + .platform_data=&rk2818_tca6424_data.gpio_base, + }, +#endif + #if defined (CONFIG_PMIC_LP8725) { .type = "lp8725", diff --git a/arch/arm/mach-rk2818/include/mach/board.h b/arch/arm/mach-rk2818/include/mach/board.h index cb6d44f60239..2cb4ecd64f62 100755 --- a/arch/arm/mach-rk2818/include/mach/board.h +++ b/arch/arm/mach-rk2818/include/mach/board.h @@ -117,6 +117,27 @@ struct pca9554_platform_data { char **names; }; +struct tca6424_platform_data { + /* the first extern gpio number in all of gpio groups */ + unsigned gpio_base; + unsigned gpio_pin_num; + /* the first gpio irq number in all of irq source */ + + unsigned gpio_irq_start; + unsigned irq_pin_num; //ÖжϵĸöÊý + unsigned tca6424_irq_pin; //À©Õ¹IOµÄÖжϹÒÔÚÄĸögpio + /* initial polarity inversion setting */ + uint16_t invert; + struct rk2818_gpio_expander_info *settinginfo; + int settinginfolen; + void *context; /* param to setup/teardown */ + + int (*setup)(struct i2c_client *client,unsigned gpio, unsigned ngpio,void *context); + int (*teardown)(struct i2c_client *client,unsigned gpio, unsigned ngpio,void *context); + char **names; +}; + + /*lcd*/ struct lcd_td043mgea1_data{ u32 pin_txd; diff --git a/arch/arm/mach-rk2818/include/mach/gpio.h b/arch/arm/mach-rk2818/include/mach/gpio.h old mode 100755 new mode 100644 index cb46e3c8fa67..ee892286b28c --- a/arch/arm/mach-rk2818/include/mach/gpio.h +++ b/arch/arm/mach-rk2818/include/mach/gpio.h @@ -20,12 +20,19 @@ #include #include -#define PIN_BASE 0//¶¨ÒåRK2818ÄÚ²¿GPIOµÄµÚÒ»¸öPIN¿Ú(¼´GPIO0_A0)ÔÚgpio_descÊý×éµÄµØÖ· +#define PIN_BASE 0//¶¨ÒåRK2818ÄÚ²¿GPIOµÄµÚÒ»¸öPIN¿Ú(¼´GPIO0_A0)ÔÚgpio_descÊý×éµÄµØÖ· #define NUM_GROUP 8// ¶¨ÒåRK2818ÄÚ²¿GPIOÿһ×é×î´óµÄPINÊýÄ¿£¬ÏÖÔÚ¶¨Îª8¸ö£¬¼´GPIOX_Y0~ GPIOX_Y7(ÆäÖÐX=0/1;Y=A/B/C/D) #define MAX_GPIO_BANKS 8//¶¨ÒåRK2818ÄÚ²¿GPIO×ܹ²Óм¸×飬ÏÖÔÚ¶¨Îª8×飬¼´GPIO0_A~ GPIO0_D£¬GPIO1_A~ GPIO1_D¡£ -#define GPIOS_EXPANDER_BASE (PIN_BASE+NUM_GROUP*MAX_GPIO_BANKS) -//¶¨ÒåGPIOµÄPIN¿Ú×î´óÊýÄ¿¡£(NUM_GROUP*MAX_GPIO_BANKS)±íʾRK2818µÄÄÚ²¿GPIOµÄPIN¿Ú×î´óÊýÄ¿£»CONFIG_ARCH_EXTEND_GPIOS±íʾÀ©Õ¹IOµÄ×î´óÊýÄ¿¡£ -#define ARCH_NR_GPIOS (NUM_GROUP*MAX_GPIO_BANKS) + CONFIG_EXPANDED_GPIO_NUM +#define SPI_FPGA_EXPANDER_BASE (PIN_BASE+NUM_GROUP*MAX_GPIO_BANKS) + +#if defined (CONFIG_SPI_GPIO) +#define GPIO_EXPANDER_BASE (PIN_BASE+NUM_GROUP*MAX_GPIO_BANKS+CONFIG_SPI_FPGA_GPIO_NUM) +#else +#define GPIO_EXPANDER_BASE (PIN_BASE+NUM_GROUP*MAX_GPIO_BANKS) +#endif + +//¶¨ÒåGPIOµÄPIN¿Ú×î´óÊýÄ¿¡£(NUM_GROUP*MAX_GPIO_BANKS)±íʾRK2818µÄÄÚ²¿GPIOµÄPIN¿Ú×î´óÊýÄ¿£»CONFIG_ARCH_EXTEND_GPIOS±íʾÀ©Õ¹IOµÄ×î´óÊýÄ¿,CONFIG_SPI_FPGA_GPIO_NUM±íʾFPGAµÄPIN½ÅÊý¡£ +#define ARCH_NR_GPIOS ((NUM_GROUP*MAX_GPIO_BANKS)+CONFIG_EXPANDED_GPIO_NUM+CONFIG_SPI_FPGA_GPIO_NUM) typedef enum eGPIOPinLevel { GPIO_LOW=0, @@ -122,14 +129,14 @@ struct rk2818_gpio_bank { #define RK2818_PIN_PC6 (PIN_BASE + 2*NUM_GROUP + 6) #define RK2818_PIN_PC7 (PIN_BASE + 2*NUM_GROUP + 7) -#define RK2818_PIN_PD0 (PIN_BASE + 3*NUM_GROUP + 0) -#define RK2818_PIN_PD1 (PIN_BASE + 3*NUM_GROUP + 1) -#define RK2818_PIN_PD2 (PIN_BASE + 3*NUM_GROUP + 2) -#define RK2818_PIN_PD3 (PIN_BASE + 3*NUM_GROUP + 3) -#define RK2818_PIN_PD4 (PIN_BASE + 3*NUM_GROUP + 4) -#define RK2818_PIN_PD5 (PIN_BASE + 3*NUM_GROUP + 5) -#define RK2818_PIN_PD6 (PIN_BASE + 3*NUM_GROUP + 6) -#define RK2818_PIN_PD7 (PIN_BASE + 3*NUM_GROUP + 7) +#define RK2818_PIN_PD0 (PIN_BASE + 3*NUM_GROUP + 0) +#define RK2818_PIN_PD1 (PIN_BASE + 3*NUM_GROUP + 1) +#define RK2818_PIN_PD2 (PIN_BASE + 3*NUM_GROUP + 2) +#define RK2818_PIN_PD3 (PIN_BASE + 3*NUM_GROUP + 3) +#define RK2818_PIN_PD4 (PIN_BASE + 3*NUM_GROUP + 4) +#define RK2818_PIN_PD5 (PIN_BASE + 3*NUM_GROUP + 5) +#define RK2818_PIN_PD6 (PIN_BASE + 3*NUM_GROUP + 6) +#define RK2818_PIN_PD7 (PIN_BASE + 3*NUM_GROUP + 7) #define RK2818_PIN_PE0 (PIN_BASE + 4*NUM_GROUP + 0) #define RK2818_PIN_PE1 (PIN_BASE + 4*NUM_GROUP + 1) @@ -168,117 +175,149 @@ struct rk2818_gpio_bank { #define RK2818_PIN_PH6 (PIN_BASE + 7*NUM_GROUP + 6) #define RK2818_PIN_PH7 (PIN_BASE + 7*NUM_GROUP + 7) /***********************define extern gpio pin num******************************/ + #if defined(CONFIG_SPI_GPIO) -#define FPGA_PIO0_00 (GPIOS_EXPANDER_BASE + 0*NUM_GROUP + 0) -#define FPGA_PIO0_01 (GPIOS_EXPANDER_BASE + 0*NUM_GROUP + 1) -#define FPGA_PIO0_02 (GPIOS_EXPANDER_BASE + 0*NUM_GROUP + 2) -#define FPGA_PIO0_03 (GPIOS_EXPANDER_BASE + 0*NUM_GROUP + 3) -#define FPGA_PIO0_04 (GPIOS_EXPANDER_BASE + 0*NUM_GROUP + 4) -#define FPGA_PIO0_05 (GPIOS_EXPANDER_BASE + 0*NUM_GROUP + 5) -#define FPGA_PIO0_06 (GPIOS_EXPANDER_BASE + 0*NUM_GROUP + 6) -#define FPGA_PIO0_07 (GPIOS_EXPANDER_BASE + 0*NUM_GROUP + 7) - -#define FPGA_PIO0_08 (GPIOS_EXPANDER_BASE + 1*NUM_GROUP + 0) -#define FPGA_PIO0_09 (GPIOS_EXPANDER_BASE + 1*NUM_GROUP + 1) -#define FPGA_PIO0_10 (GPIOS_EXPANDER_BASE + 1*NUM_GROUP + 2) -#define FPGA_PIO0_11 (GPIOS_EXPANDER_BASE + 1*NUM_GROUP + 3) -#define FPGA_PIO0_12 (GPIOS_EXPANDER_BASE + 1*NUM_GROUP + 4) -#define FPGA_PIO0_13 (GPIOS_EXPANDER_BASE + 1*NUM_GROUP + 5) -#define FPGA_PIO0_14 (GPIOS_EXPANDER_BASE + 1*NUM_GROUP + 6) -#define FPGA_PIO0_15 (GPIOS_EXPANDER_BASE + 1*NUM_GROUP + 7) - -#define FPGA_PIO1_00 (GPIOS_EXPANDER_BASE + 2*NUM_GROUP + 0) -#define FPGA_PIO1_01 (GPIOS_EXPANDER_BASE + 2*NUM_GROUP + 1) -#define FPGA_PIO1_02 (GPIOS_EXPANDER_BASE + 2*NUM_GROUP + 2) -#define FPGA_PIO1_03 (GPIOS_EXPANDER_BASE + 2*NUM_GROUP + 3) -#define FPGA_PIO1_04 (GPIOS_EXPANDER_BASE + 2*NUM_GROUP + 4) -#define FPGA_PIO1_05 (GPIOS_EXPANDER_BASE + 2*NUM_GROUP + 5) -#define FPGA_PIO1_06 (GPIOS_EXPANDER_BASE + 2*NUM_GROUP + 6) -#define FPGA_PIO1_07 (GPIOS_EXPANDER_BASE + 2*NUM_GROUP + 7) - -#define FPGA_PIO1_08 (GPIOS_EXPANDER_BASE + 3*NUM_GROUP + 0) -#define FPGA_PIO1_09 (GPIOS_EXPANDER_BASE + 3*NUM_GROUP + 1) -#define FPGA_PIO1_10 (GPIOS_EXPANDER_BASE + 3*NUM_GROUP + 2) -#define FPGA_PIO1_11 (GPIOS_EXPANDER_BASE + 3*NUM_GROUP + 3) -#define FPGA_PIO1_12 (GPIOS_EXPANDER_BASE + 3*NUM_GROUP + 4) -#define FPGA_PIO1_13 (GPIOS_EXPANDER_BASE + 3*NUM_GROUP + 5) -#define FPGA_PIO1_14 (GPIOS_EXPANDER_BASE + 3*NUM_GROUP + 6) -#define FPGA_PIO1_15 (GPIOS_EXPANDER_BASE + 3*NUM_GROUP + 7) - -#define FPGA_PIO2_00 (GPIOS_EXPANDER_BASE + 4*NUM_GROUP + 0) -#define FPGA_PIO2_01 (GPIOS_EXPANDER_BASE + 4*NUM_GROUP + 1) -#define FPGA_PIO2_02 (GPIOS_EXPANDER_BASE + 4*NUM_GROUP + 2) -#define FPGA_PIO2_03 (GPIOS_EXPANDER_BASE + 4*NUM_GROUP + 3) -#define FPGA_PIO2_04 (GPIOS_EXPANDER_BASE + 4*NUM_GROUP + 4) -#define FPGA_PIO2_05 (GPIOS_EXPANDER_BASE + 4*NUM_GROUP + 5) -#define FPGA_PIO2_06 (GPIOS_EXPANDER_BASE + 4*NUM_GROUP + 6) -#define FPGA_PIO2_07 (GPIOS_EXPANDER_BASE + 4*NUM_GROUP + 7) - -#define FPGA_PIO2_08 (GPIOS_EXPANDER_BASE + 5*NUM_GROUP + 0) -#define FPGA_PIO2_09 (GPIOS_EXPANDER_BASE + 5*NUM_GROUP + 1) -#define FPGA_PIO2_10 (GPIOS_EXPANDER_BASE + 5*NUM_GROUP + 2) -#define FPGA_PIO2_11 (GPIOS_EXPANDER_BASE + 5*NUM_GROUP + 3) -#define FPGA_PIO2_12 (GPIOS_EXPANDER_BASE + 5*NUM_GROUP + 4) -#define FPGA_PIO2_13 (GPIOS_EXPANDER_BASE + 5*NUM_GROUP + 5) -#define FPGA_PIO2_14 (GPIOS_EXPANDER_BASE + 5*NUM_GROUP + 6) -#define FPGA_PIO2_15 (GPIOS_EXPANDER_BASE + 5*NUM_GROUP + 7) - -#define FPGA_PIO3_00 (GPIOS_EXPANDER_BASE + 6*NUM_GROUP + 0) -#define FPGA_PIO3_01 (GPIOS_EXPANDER_BASE + 6*NUM_GROUP + 1) -#define FPGA_PIO3_02 (GPIOS_EXPANDER_BASE + 6*NUM_GROUP + 2) -#define FPGA_PIO3_03 (GPIOS_EXPANDER_BASE + 6*NUM_GROUP + 3) -#define FPGA_PIO3_04 (GPIOS_EXPANDER_BASE + 6*NUM_GROUP + 4) -#define FPGA_PIO3_05 (GPIOS_EXPANDER_BASE + 6*NUM_GROUP + 5) -#define FPGA_PIO3_06 (GPIOS_EXPANDER_BASE + 6*NUM_GROUP + 6) -#define FPGA_PIO3_07 (GPIOS_EXPANDER_BASE + 6*NUM_GROUP + 7) - -#define FPGA_PIO3_08 (GPIOS_EXPANDER_BASE + 7*NUM_GROUP + 0) -#define FPGA_PIO3_09 (GPIOS_EXPANDER_BASE + 7*NUM_GROUP + 1) -#define FPGA_PIO3_10 (GPIOS_EXPANDER_BASE + 7*NUM_GROUP + 2) -#define FPGA_PIO3_11 (GPIOS_EXPANDER_BASE + 7*NUM_GROUP + 3) -#define FPGA_PIO3_12 (GPIOS_EXPANDER_BASE + 7*NUM_GROUP + 4) -#define FPGA_PIO3_13 (GPIOS_EXPANDER_BASE + 7*NUM_GROUP + 5) -#define FPGA_PIO3_14 (GPIOS_EXPANDER_BASE + 7*NUM_GROUP + 6) -#define FPGA_PIO3_15 (GPIOS_EXPANDER_BASE + 7*NUM_GROUP + 7) - -#define FPGA_PIO4_00 (GPIOS_EXPANDER_BASE + 8*NUM_GROUP + 0) -#define FPGA_PIO4_01 (GPIOS_EXPANDER_BASE + 8*NUM_GROUP + 1) -#define FPGA_PIO4_02 (GPIOS_EXPANDER_BASE + 8*NUM_GROUP + 2) -#define FPGA_PIO4_03 (GPIOS_EXPANDER_BASE + 8*NUM_GROUP + 3) -#define FPGA_PIO4_04 (GPIOS_EXPANDER_BASE + 8*NUM_GROUP + 4) -#define FPGA_PIO4_05 (GPIOS_EXPANDER_BASE + 8*NUM_GROUP + 5) -#define FPGA_PIO4_06 (GPIOS_EXPANDER_BASE + 8*NUM_GROUP + 6) -#define FPGA_PIO4_07 (GPIOS_EXPANDER_BASE + 8*NUM_GROUP + 7) - -#define FPGA_PIO4_08 (GPIOS_EXPANDER_BASE + 9*NUM_GROUP + 0) -#define FPGA_PIO4_09 (GPIOS_EXPANDER_BASE + 9*NUM_GROUP + 1) -#define FPGA_PIO4_10 (GPIOS_EXPANDER_BASE + 9*NUM_GROUP + 2) -#define FPGA_PIO4_11 (GPIOS_EXPANDER_BASE + 9*NUM_GROUP + 3) -#define FPGA_PIO4_12 (GPIOS_EXPANDER_BASE + 9*NUM_GROUP + 4) -#define FPGA_PIO4_13 (GPIOS_EXPANDER_BASE + 9*NUM_GROUP + 5) -#define FPGA_PIO4_14 (GPIOS_EXPANDER_BASE + 9*NUM_GROUP + 6) -#define FPGA_PIO4_15 (GPIOS_EXPANDER_BASE + 9*NUM_GROUP + 7) - -#define FPGA_PIO5_00 (GPIOS_EXPANDER_BASE + 10*NUM_GROUP + 0) -#define FPGA_PIO5_01 (GPIOS_EXPANDER_BASE + 10*NUM_GROUP + 1) -#define FPGA_PIO5_02 (GPIOS_EXPANDER_BASE + 10*NUM_GROUP + 2) -#define FPGA_PIO5_03 (GPIOS_EXPANDER_BASE + 10*NUM_GROUP + 3) -#define FPGA_PIO5_04 (GPIOS_EXPANDER_BASE + 10*NUM_GROUP + 4) -#define FPGA_PIO5_05 (GPIOS_EXPANDER_BASE + 10*NUM_GROUP + 5) -#define FPGA_PIO5_06 (GPIOS_EXPANDER_BASE + 10*NUM_GROUP + 6) -#define FPGA_PIO5_07 (GPIOS_EXPANDER_BASE + 10*NUM_GROUP + 7) - -#define FPGA_PIO5_08 (GPIOS_EXPANDER_BASE + 11*NUM_GROUP + 0) -#define FPGA_PIO5_09 (GPIOS_EXPANDER_BASE + 11*NUM_GROUP + 1) -#define FPGA_PIO5_10 (GPIOS_EXPANDER_BASE + 11*NUM_GROUP + 2) -#define FPGA_PIO5_11 (GPIOS_EXPANDER_BASE + 11*NUM_GROUP + 3) -#define FPGA_PIO5_12 (GPIOS_EXPANDER_BASE + 11*NUM_GROUP + 4) -#define FPGA_PIO5_13 (GPIOS_EXPANDER_BASE + 11*NUM_GROUP + 5) -#define FPGA_PIO5_14 (GPIOS_EXPANDER_BASE + 11*NUM_GROUP + 6) -#define FPGA_PIO5_15 (GPIOS_EXPANDER_BASE + 11*NUM_GROUP + 7) +#define FPGA_PIO0_00 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 0) +#define FPGA_PIO0_01 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 1) +#define FPGA_PIO0_02 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 2) +#define FPGA_PIO0_03 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 3) +#define FPGA_PIO0_04 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 4) +#define FPGA_PIO0_05 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 5) +#define FPGA_PIO0_06 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 6) +#define FPGA_PIO0_07 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 7) + +#define FPGA_PIO0_08 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 0) +#define FPGA_PIO0_09 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 1) +#define FPGA_PIO0_10 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 2) +#define FPGA_PIO0_11 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 3) +#define FPGA_PIO0_12 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 4) +#define FPGA_PIO0_13 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 5) +#define FPGA_PIO0_14 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 6) +#define FPGA_PIO0_15 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 7) + +#define FPGA_PIO1_00 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 0) +#define FPGA_PIO1_01 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 1) +#define FPGA_PIO1_02 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 2) +#define FPGA_PIO1_03 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 3) +#define FPGA_PIO1_04 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 4) +#define FPGA_PIO1_05 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 5) +#define FPGA_PIO1_06 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 6) +#define FPGA_PIO1_07 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 7) + +#define FPGA_PIO1_08 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 0) +#define FPGA_PIO1_09 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 1) +#define FPGA_PIO1_10 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 2) +#define FPGA_PIO1_11 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 3) +#define FPGA_PIO1_12 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 4) +#define FPGA_PIO1_13 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 5) +#define FPGA_PIO1_14 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 6) +#define FPGA_PIO1_15 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 7) + +#define FPGA_PIO2_00 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 0) +#define FPGA_PIO2_01 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 1) +#define FPGA_PIO2_02 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 2) +#define FPGA_PIO2_03 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 3) +#define FPGA_PIO2_04 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 4) +#define FPGA_PIO2_05 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 5) +#define FPGA_PIO2_06 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 6) +#define FPGA_PIO2_07 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 7) + +#define FPGA_PIO2_08 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 0) +#define FPGA_PIO2_09 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 1) +#define FPGA_PIO2_10 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 2) +#define FPGA_PIO2_11 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 3) +#define FPGA_PIO2_12 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 4) +#define FPGA_PIO2_13 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 5) +#define FPGA_PIO2_14 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 6) +#define FPGA_PIO2_15 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 7) + +#define FPGA_PIO3_00 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 0) +#define FPGA_PIO3_01 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 1) +#define FPGA_PIO3_02 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 2) +#define FPGA_PIO3_03 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 3) +#define FPGA_PIO3_04 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 4) +#define FPGA_PIO3_05 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 5) +#define FPGA_PIO3_06 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 6) +#define FPGA_PIO3_07 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 7) + +#define FPGA_PIO3_08 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 0) +#define FPGA_PIO3_09 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 1) +#define FPGA_PIO3_10 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 2) +#define FPGA_PIO3_11 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 3) +#define FPGA_PIO3_12 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 4) +#define FPGA_PIO3_13 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 5) +#define FPGA_PIO3_14 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 6) +#define FPGA_PIO3_15 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 7) + +#define FPGA_PIO4_00 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 0) +#define FPGA_PIO4_01 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 1) +#define FPGA_PIO4_02 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 2) +#define FPGA_PIO4_03 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 3) +#define FPGA_PIO4_04 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 4) +#define FPGA_PIO4_05 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 5) +#define FPGA_PIO4_06 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 6) +#define FPGA_PIO4_07 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 7) + +#define FPGA_PIO4_08 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 0) +#define FPGA_PIO4_09 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 1) +#define FPGA_PIO4_10 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 2) +#define FPGA_PIO4_11 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 3) +#define FPGA_PIO4_12 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 4) +#define FPGA_PIO4_13 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 5) +#define FPGA_PIO4_14 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 6) +#define FPGA_PIO4_15 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 7) + +#define FPGA_PIO5_00 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 0) +#define FPGA_PIO5_01 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 1) +#define FPGA_PIO5_02 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 2) +#define FPGA_PIO5_03 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 3) +#define FPGA_PIO5_04 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 4) +#define FPGA_PIO5_05 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 5) +#define FPGA_PIO5_06 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 6) +#define FPGA_PIO5_07 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 7) + +#define FPGA_PIO5_08 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 0) +#define FPGA_PIO5_09 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 1) +#define FPGA_PIO5_10 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 2) +#define FPGA_PIO5_11 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 3) +#define FPGA_PIO5_12 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 4) +#define FPGA_PIO5_13 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 5) +#define FPGA_PIO5_14 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 6) +#define FPGA_PIO5_15 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 7) #endif +#if defined(CONFIG_IOEXTEND_TCA6424) +#define TCA6424_P00 (GPIO_EXPANDER_BASE + 0*NUM_GROUP + 0) +#define TCA6424_P01 (GPIO_EXPANDER_BASE + 0*NUM_GROUP + 1) +#define TCA6424_P02 (GPIO_EXPANDER_BASE + 0*NUM_GROUP + 2) +#define TCA6424_P03 (GPIO_EXPANDER_BASE + 0*NUM_GROUP + 3) +#define TCA6424_P04 (GPIO_EXPANDER_BASE + 0*NUM_GROUP + 4) +#define TCA6424_P05 (GPIO_EXPANDER_BASE + 0*NUM_GROUP + 5) +#define TCA6424_P06 (GPIO_EXPANDER_BASE + 0*NUM_GROUP + 6) +#define TCA6424_P07 (GPIO_EXPANDER_BASE + 0*NUM_GROUP + 7) + +#define TCA6424_P10 (GPIO_EXPANDER_BASE + 1*NUM_GROUP + 0) +#define TCA6424_P11 (GPIO_EXPANDER_BASE + 1*NUM_GROUP + 1) +#define TCA6424_P12 (GPIO_EXPANDER_BASE + 1*NUM_GROUP + 2) +#define TCA6424_P13 (GPIO_EXPANDER_BASE + 1*NUM_GROUP + 3) +#define TCA6424_P14 (GPIO_EXPANDER_BASE + 1*NUM_GROUP + 4) +#define TCA6424_P15 (GPIO_EXPANDER_BASE + 1*NUM_GROUP + 5) +#define TCA6424_P16 (GPIO_EXPANDER_BASE + 1*NUM_GROUP + 6) +#define TCA6424_P17 (GPIO_EXPANDER_BASE + 1*NUM_GROUP + 7) + +#define TCA6424_P20 (GPIO_EXPANDER_BASE + 2*NUM_GROUP + 0) +#define TCA6424_P21 (GPIO_EXPANDER_BASE + 2*NUM_GROUP + 1) +#define TCA6424_P22 (GPIO_EXPANDER_BASE + 2*NUM_GROUP + 2) +#define TCA6424_P23 (GPIO_EXPANDER_BASE + 2*NUM_GROUP + 3) +#define TCA6424_P24 (GPIO_EXPANDER_BASE + 2*NUM_GROUP + 4) +#define TCA6424_P25 (GPIO_EXPANDER_BASE + 2*NUM_GROUP + 5) +#define TCA6424_P26 (GPIO_EXPANDER_BASE + 2*NUM_GROUP + 6) +#define TCA6424_P27 (GPIO_EXPANDER_BASE + 2*NUM_GROUP + 7) + +#endif + + #ifndef __ASSEMBLY__ extern void __init rk2818_gpio_init(struct rk2818_gpio_bank *data, int nr_banks); extern void __init rk2818_gpio_irq_setup(void); @@ -320,6 +359,13 @@ static inline int irq_to_gpio(unsigned irq) return (FPGA_PIO0_00 + (irq - __gpio_to_irq(FPGA_PIO0_00))); } #endif +#if defined(CONFIG_IOEXTEND_TCA6424) + else if((irq - __gpio_to_irq(TCA6424_P00)) <3*NUM_GROUP) + { + return (TCA6424_P00 + (irq - __gpio_to_irq(TCA6424_P00))); + } +#endif + else { return -ENXIO; diff --git a/arch/arm/mach-rk2818/include/mach/irqs.h b/arch/arm/mach-rk2818/include/mach/irqs.h index f2f80a29bf10..ce57f74d3cd8 100644 --- a/arch/arm/mach-rk2818/include/mach/irqs.h +++ b/arch/arm/mach-rk2818/include/mach/irqs.h @@ -46,7 +46,7 @@ CONFIG_RK28_GPIO_IRQ±íʾRK2818µÄGPIO¸´ÓõÄ×î´óÖжÏÊýÄ¿£¬CONFIG_EXTEND_GPIO_IRQ±íʾRK2818µÄ À©Õ¹IO¸´ÓõÄ×î´óÖжÏÊýÄ¿¡£*/ #define NR_AIC_IRQS 48 -#define NR_IRQS (NR_AIC_IRQS + CONFIG_RK28_GPIO_IRQ + CONFIG_EXPANDED_GPIO_IRQ_NUM) +#define NR_IRQS (NR_AIC_IRQS + CONFIG_RK28_GPIO_IRQ+CONFIG_EXPANDED_GPIO_IRQ_NUM+CONFIG_SPI_FPGA_GPIO_IRQ_NUM) /*irq number*/ diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig old mode 100644 new mode 100755 index 91baae369d7c..c474b7b6c1d7 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -236,13 +236,32 @@ config GPIO_PCA9554 help Say yes here to access the PCA9554 GPIO EXPANDER +config IOEXTEND_TCA6424 + bool "ROCKCHIP TCA6424 CONTROL" + depends on I2C + help + Say yes here to access the TCA6424 GPIO EXPANDER + + config EXPANDED_GPIO_NUM int "setting the amount of expanded gpios" - default 8 if GPIO_PCA9554 - default 0 + help + for tca6424, set 24 config EXPANDED_GPIO_IRQ_NUM int "setting the amount of expanded gpio irqs" - default 8 if GPIO_PCA9554 - default 0 + help + for tca6424, set 24 + +config SPI_FPGA_GPIO_NUM + default 96 + int "setting the amount of fpga gpios" + help + for fpga, set 96,no used ,set 0 + +config SPI_FPGA_GPIO_IRQ_NUM + default 16 + int "setting the amount of fpga gpio irqs" + help + for fpga, set 16,no used ,set 0 endif diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile old mode 100644 new mode 100755 index 8fef4c219b7b..e8500c2d9d7e --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o obj-$(CONFIG_GPIO_PCA9554) += pca9554.o +obj-$(CONFIG_IOEXTEND_TCA6424) += tca6424.o diff --git a/drivers/gpio/tca6424.c b/drivers/gpio/tca6424.c new file mode 100755 index 000000000000..ec7010708aa2 --- /dev/null +++ b/drivers/gpio/tca6424.c @@ -0,0 +1,972 @@ +/* + * Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +/*******************************************************************/ +/* COPYRIGHT (C) ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED. */ +/******************************************************************* +FILE : tca6424.c +MODIFY : sxj +DATE : 2010-8-11 +NOTES : +********************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define TCA6424DEB +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +#if 1 +#define DBGERR(x...) printk(KERN_INFO x) +#else +#define DBGERR(x...) +#endif + +struct tca6424_chip { + /* the first extern gpio number in all of gpio groups */ + unsigned gpio_start; + unsigned gpio_pin_num; + /* the first gpio irq number in all of irq source */ + unsigned gpio_irq_start; + unsigned irq_pin_num; //ÖжϵĸöÊý + unsigned irq_gpiopin; //¸¸ÖжϵÄÖжϺŠ+ unsigned irq_chain; //¸¸ÖжϵÄÖжϺŠ+ uint8_t reg_input[TCA6424_PortNum]; + uint8_t reg_output[TCA6424_PortNum]; + uint8_t reg_direction[TCA6424_PortNum]; + uint8_t interrupt_en[TCA6424_PortNum]; // 0 dis + uint8_t interrupt_mask[TCA6424_PortNum];// 0 unmask + uint8_t inttype_set[TCA6424_PortNum]; // Inttype enable + uint8_t inttype[TCA6424_PortNum]; + uint8_t inttype1[TCA6424_PortNum]; + + #ifdef TCA6424_OUTREGLOCK + struct mutex outreglock; + #endif + #ifdef TCA6424_INPUTREGLOCK + struct mutex inputreglock; + #endif + #ifdef TCA6424_CONFIGREGLOCK + struct mutex configreglock; + #endif + struct i2c_client *client; + //struct extgpio_data_s *p; + struct tca6424_platform_data *dyn_pdata; + struct work_struct tca6424_work; + struct gpio_chip gpio_chip; + char **names; +}; + +static const struct i2c_device_id tca6424_id[] = +{ + {"extend_gpio_tca6424",8,}, + { } +}; +MODULE_DEVICE_TABLE(i2c, tca6424_id); + +static short int portnum[TCA6424_PortNum]={ TCA6424_Port0PinNum, + TCA6424_Port1PinNum,TCA6424_Port2PinNum}; +typedef struct _tca6424_access_{ +u8 portreg[TCA6424_PortNum]; +u8 accessflag[TCA6424_PortNum];//0 ²»½øÐвÙ×÷ +} tca6424_access; + +extern inline struct gpio_chip *gpio_to_chip(unsigned gpio); +extern struct lock_class_key gpio_lock_class; +struct workqueue_struct *tca6424workqueue; + +static int tca6424_write_reg(struct i2c_client *client, uint8_t reg, uint8_t val) +{ + int ret=-1; + struct i2c_adapter *adap; + struct i2c_msg msg; + char tx_buf[2]; + if(!client) + return ret; + adap = client->adapter; + tx_buf[0] = reg; + tx_buf[1]= val; + + msg.addr = client->addr; + msg.buf = tx_buf; + msg.len = 1 +1; + msg.flags = client->flags; + msg.scl_rate = TCA6424_I2C_RATE; + + ret = i2c_transfer(adap, &msg, 1); + return ret; +} + +static int tca6424_read_reg(struct i2c_client *client, uint8_t reg, uint8_t *val) +{ + int ret=-1; + struct i2c_adapter *adap; + struct i2c_msg msgs[2]; + + if(!client) + return ret; + adap = client->adapter; + //·¢ËͼĴæÆ÷µØÖ· + msgs[0].addr = client->addr; + msgs[0].buf = ® + msgs[0].flags = client->flags; + msgs[0].len = 1; + msgs[0].scl_rate = TCA6424_I2C_RATE; + //½ÓÊÕÊý¾Ý + msgs[1].buf = val; + msgs[1].addr = client->addr; + msgs[1].flags = client->flags | I2C_M_RD; + msgs[1].len = 1; + msgs[1].scl_rate = TCA6424_I2C_RATE; + + ret = i2c_transfer(adap, msgs, 2); + return ret; + +} + +static int tca6424_gpio_direction_input(struct gpio_chip *gc, uint8_t pin_num) +{ + struct tca6424_chip *chip; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t reg_val; + uint8_t Regaddr; + int ret = -1; + + chip = container_of(gc, struct tca6424_chip, gpio_chip); + gpioPortNum = pin_num/8; + gpioPortPinNum= pin_num%8; + if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum])) + return ret; + Regaddr = TCA6424_Config_Reg+gpioPortNum; + + #ifdef TCA6424_CONFIGREGLOCK + if (!mutex_trylock(&chip->configreglock)) + { + DBGERR("**%s[%d]Did not get the configreglock**\n",__FUNCTION__,__LINE__); + return ret; + } + #endif + + reg_val = tca6424setbit(chip->reg_direction[gpioPortNum], gpioPortPinNum); + ret = tca6424_write_reg(chip->client, Regaddr, reg_val); + if(ret<0) + goto err; + + chip->reg_direction[gpioPortNum] = reg_val; +err: + + DBG("**%s[%d],config_reg=%2x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret); + + #ifdef TCA6424_CONFIGREGLOCK + mutex_unlock(&chip->configreglock); + #endif + + return (ret<0)?-1:0; +} + +static int tca6424_gpio_direction_output(struct gpio_chip *gc,uint8_t pin_num, int val) +{ + struct tca6424_chip *chip; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t reg_val; + uint8_t Regaddr; + int ret = -1; + + chip = container_of(gc, struct tca6424_chip, gpio_chip); + gpioPortNum = pin_num/8; + gpioPortPinNum = pin_num%8; + if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum])) + return ret; + Regaddr = TCA6424_Config_Reg+gpioPortNum; + + #ifdef TCA6424_CONFIGREGLOCK + if (!mutex_trylock(&chip->configreglock)) + { + DBGERR("**%s[%d]Did not get the configreglock**\n",__FUNCTION__,__LINE__); + return -1; + } + #endif + /* then direction */ + reg_val = tca6424clearbit(chip->reg_direction[gpioPortNum], gpioPortPinNum); + DBG("**%s[%d],reg_val=%2x, Regaddr=%2x,**\n",__FUNCTION__,__LINE__,reg_val,Regaddr); + ret = tca6424_write_reg(chip->client, Regaddr, reg_val); + if(ret<0) + { + #ifdef TCA6424_CONFIGREGLOCK + mutex_unlock(&chip->configreglock); + #endif + DBGERR("**%s[%d] set direction reg is error,reg_val=%x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret); + return ret; + } + chip->reg_direction[gpioPortNum] = reg_val; + #ifdef TCA6424_CONFIGREGLOCK + mutex_unlock(&chip->configreglock); + #endif + ret=-1; + #ifdef TCA6424_OUTREGLOCK + if (!mutex_trylock(&chip->outreglock)) + { + DBGERR("**%s[%d] Did not get the outreglock**\n",__FUNCTION__,__LINE__); + return ret; + } + #endif + /* set output level */ + if (val) + reg_val = tca6424setbit(chip->reg_output[gpioPortNum], gpioPortPinNum); + else + reg_val = tca6424clearbit(chip->reg_output[gpioPortNum], gpioPortPinNum); + + Regaddr = TCA6424_OutputLevel_Reg+gpioPortNum; + ret = tca6424_write_reg(chip->client, Regaddr, reg_val); + if (ret<0) + { + #ifdef TCA6424_OUTREGLOCK + mutex_unlock(&chip->outreglock); + #endif + DBGERR("**%s[%d] set out reg is error,reg_val=%x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret); + return ret; + } + chip->reg_output[gpioPortNum] = reg_val; + + #ifdef TCA6424_OUTREGLOCK + mutex_unlock(&chip->outreglock); + #endif + + DBG("**%s[%d],output_reg=%2x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret); + return (ret<0)?-1:0; +} + +static int tca6424_gpio_get_value(struct gpio_chip *gc, uint8_t pin_num) +{ + struct tca6424_chip *chip; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t reg_val; + uint8_t Regaddr; + int ret=-1; + + chip = container_of(gc, struct tca6424_chip, gpio_chip); + gpioPortNum = pin_num/8; + gpioPortPinNum= pin_num%8; + + if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum])) + return -1; + + Regaddr = TCA6424_InputLevel_Reg+gpioPortNum; + + if(!tca6424getbit(chip->reg_direction[gpioPortNum],gpioPortPinNum)) //ÅжϸÃpinÊÇ·ñÉèÖóÉÊä³ö + { + DBG("**it is a output pin**\n"); + return -1; + } + #ifdef TCA6424_INPUTREGLOCK + if (!mutex_trylock(&chip->inputreglock)) + { + DBGERR("**%s[%d]Did not get the inputreglock**\n",__FUNCTION__,__LINE__); + return -1; + } + #endif + + ret = tca6424_read_reg(chip->client, Regaddr, ®_val); + if (ret < 0) + goto err; + chip->reg_input[gpioPortNum] = reg_val; + +err: + #ifdef TCA6424_CONFIGREGLOCK + mutex_unlock(&chip->inputreglock); + #endif + DBGERR("**%s[%d] input_reg=%2x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret); + + return (ret < 0)?-1:((chip->reg_input[gpioPortNum] >> gpioPortPinNum) & 0x01); +} + +static void tca6424_gpio_set_value(struct gpio_chip *gc, uint8_t pin_num, int val) +{ + struct tca6424_chip *chip; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t reg_val; + uint8_t Regaddr; + int ret=-1; + DBG("**run in the %s**\n",__FUNCTION__); + + chip = container_of(gc, struct tca6424_chip, gpio_chip); + + gpioPortNum = pin_num/8; + gpioPortPinNum= pin_num%8; + + if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum])) + return;// -1; + + Regaddr = TCA6424_OutputLevel_Reg+gpioPortNum; + + if(tca6424getbit(chip->reg_direction[gpioPortNum],gpioPortPinNum)) // input state + return;// -1; + +#ifdef TCA6424_OUTREGLOCK + if (!mutex_trylock(&chip->outreglock)) + { + DBGERR("**%s[%d] Did not get the outreglock**\n",__FUNCTION__,__LINE__); + return;// -1; + } +#endif + if (val) + reg_val = tca6424setbit(chip->reg_output[gpioPortNum], gpioPortPinNum); + else + reg_val = tca6424clearbit(chip->reg_output[gpioPortNum], gpioPortPinNum); + + ret = tca6424_write_reg(chip->client, Regaddr, reg_val); + if (ret<0) + goto err; + chip->reg_output[gpioPortNum] = reg_val; + +err: + #ifdef TCA6424_OUTREGLOCK + mutex_unlock(&chip->outreglock); + #endif + + DBG("**%s[%d],output_reg=%2x,ret=%d**\n",__FUNCTION__,__LINE__,reg_val,ret); + return;// (ret<0)?-1:0; + +} +static int tca6424_gpio_to_irq(struct gpio_chip *chip,unsigned offset) +{ + struct tca6424_chip *pca_chip = container_of(chip, struct tca6424_chip, gpio_chip); + if(((pca_chip->gpio_start+offset)>=chip->base)&&((pca_chip->gpio_start+offset)<(chip->base+chip->ngpio))) + { + //DBG("**%s,offset=%d,gpio_irq_start=%d,base=%d,ngpio=%d,gpio_irq_start=%d**\n", + // __FUNCTION__,offset,pca_chip->gpio_irq_start,chip->base,chip->ngpio,pca_chip->gpio_irq_start); + return (offset+pca_chip->gpio_irq_start); + } + else + { + return -1; + } +} + +int tca6424_checkrange(int start,int num,int val) +{ + + if((val<(start+num))&&(val>=start)) + return 0; + else return -1; + +} + +static void tca6424_gpio_irq_enable(unsigned irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + //int gpiopinnum; + struct tca6424_chip *pchip=(struct tca6424_chip *)desc->chip_data; + //struct gpio_chip *chip_gpio; + uint8_t gpio_num; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t tca6424pinnum; + + + if(!tca6424_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq)) + { + tca6424pinnum = irq-pchip->gpio_irq_start; + } + else + { + return; + } + gpioPortNum = tca6424pinnum/8; + gpioPortPinNum= tca6424pinnum%8; + gpio_num=pchip->gpio_start+tca6424pinnum; + if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum])) + return; + DBG("**%s**\n",__FUNCTION__); + pchip->interrupt_en[gpioPortNum]=tca6424setbit(pchip->interrupt_en[gpioPortNum],gpioPortPinNum); +} +static void tca6424_gpio_irq_disable(unsigned irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + struct tca6424_chip *pchip=(struct tca6424_chip *)desc->chip_data; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t tca6424pinnum; + + if(!tca6424_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq)) + { + tca6424pinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq) + } + else + { + return; + } + gpioPortNum = tca6424pinnum/8; + gpioPortPinNum= tca6424pinnum%8; + + if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum])) + return; + DBG("**%s**\n",__FUNCTION__); + + pchip->interrupt_en[gpioPortNum]=tca6424clearbit(pchip->interrupt_en[gpioPortNum],gpioPortPinNum); + +} + + +static void tca6424_gpio_irq_mask(unsigned irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + struct tca6424_chip *pchip=(struct tca6424_chip *)desc->chip_data; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t tca6424pinnum; + + if(!tca6424_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq)) + { + tca6424pinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq) + } + else + { + return; + } + gpioPortNum = tca6424pinnum/8; + gpioPortPinNum= tca6424pinnum%8; + + if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum])) + return; + + DBG("**%s**\n",__FUNCTION__); + + pchip->interrupt_mask[gpioPortNum]=tca6424setbit(pchip->interrupt_mask[gpioPortNum],gpioPortPinNum); + +} + +static void tca6424_gpio_irq_unmask(unsigned irq) +{ + struct irq_desc *desc = irq_to_desc(irq); + //int gpiopinnum;//=irq_to_gpio(irq); + struct tca6424_chip *pchip=(struct tca6424_chip *)desc->chip_data; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t tca6424pinnum; + + DBG("**%s**\n",__FUNCTION__); + + if(!tca6424_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq)) + { + tca6424pinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq) + } + else + { + return; + } + gpioPortNum = tca6424pinnum/8; + gpioPortPinNum= tca6424pinnum%8; + + if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum])) + return; + pchip->interrupt_mask[gpioPortNum]=tca6424clearbit(pchip->interrupt_mask[gpioPortNum],gpioPortPinNum); +} + +static int tca6424_gpio_irq_type(unsigned int irq, unsigned int type) +{ + struct irq_desc *desc_irq=irq_to_desc(irq); + struct tca6424_chip *pchip=(struct tca6424_chip *)desc_irq->chip_data; + //struct gpio_chip *chip_gpio; + int gpio_num; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum; + uint8_t tca6424pinnum; + if(!tca6424_checkrange(pchip->gpio_irq_start,pchip->irq_pin_num,irq)) + { + tca6424pinnum=irq-pchip->gpio_irq_start;//irq_to_gpio(irq) + gpio_num=pchip->gpio_start+tca6424pinnum; + } + else + return -1; + + gpioPortNum = tca6424pinnum/8; + gpioPortPinNum= tca6424pinnum%8; + //DBG("**%s %d gpio_num=%d,PortNum=%d,PortPinNum=%d**\n",__FUNCTION__,__LINE__,gpio_num,gpioPortNum,gpioPortPinNum); + switch (type) { + case IRQ_TYPE_NONE: + pchip->inttype_set[gpioPortNum]=tca6424clearbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum); + DBG("**%s IRQ_TYPE_NONE**\n",__FUNCTION__); + break; + case IRQ_TYPE_EDGE_RISING: + pchip->inttype_set[gpioPortNum]=tca6424setbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum); + pchip->inttype[gpioPortNum]=tca6424setbit(pchip->inttype[gpioPortNum],gpioPortPinNum); + pchip->inttype1[gpioPortNum]=tca6424clearbit(pchip->inttype1[gpioPortNum],gpioPortPinNum); + DBG("**%s IRQ_TYPE_EDGE_RISING,inttype=%x,inttype1=%x**\n",__FUNCTION__,pchip->inttype[gpioPortNum],pchip->inttype1[gpioPortNum]); + + break; + case IRQ_TYPE_EDGE_FALLING: + pchip->inttype_set[gpioPortNum]=tca6424setbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum); + pchip->inttype[gpioPortNum]=tca6424clearbit(pchip->inttype[gpioPortNum],gpioPortPinNum); + pchip->inttype1[gpioPortNum]=tca6424clearbit(pchip->inttype1[gpioPortNum],gpioPortPinNum); + DBG("**%s IRQ_TYPE_EDGE_RISING,inttype=%x,inttype1=%x**\n",__FUNCTION__,pchip->inttype[gpioPortNum],pchip->inttype1[gpioPortNum]); + + break; + case IRQ_TYPE_EDGE_BOTH: + pchip->inttype_set[gpioPortNum]=tca6424setbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum); + pchip->inttype1[gpioPortNum]=tca6424setbit(pchip->inttype1[gpioPortNum],gpioPortPinNum); + DBG("**%s IRQ_TYPE_EDGE_RISING,inttype=%x,inttype1=%x**\n",__FUNCTION__,pchip->inttype[gpioPortNum],pchip->inttype1[gpioPortNum]); + break; + case IRQ_TYPE_LEVEL_HIGH: + pchip->inttype_set[gpioPortNum]=tca6424clearbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum); + DBG("extern gpios does not support IRQ_TYPE_LEVEL_HIGH irq typ"); + break; + case IRQ_TYPE_LEVEL_LOW: + pchip->inttype_set[gpioPortNum]=tca6424clearbit(pchip->inttype_set[gpioPortNum],gpioPortPinNum); + DBG("extern gpios does not support IRQ_TYPE_LEVEL_LOW irq typ"); + break; + default: + return -EINVAL; + } +return 0; +} + +static int tca6424_gpio_irq_set_wake(unsigned irq, unsigned state) +{ + //no irq wake + return 0; + +} +static struct irq_chip tca6424_gpio_irqchip = { + .name = "extend_gpio_tca6424", + .enable = tca6424_gpio_irq_enable, + .disable = tca6424_gpio_irq_disable, + .mask = tca6424_gpio_irq_mask, + .unmask = tca6424_gpio_irq_unmask, + .set_type = tca6424_gpio_irq_type, + .set_wake = tca6424_gpio_irq_set_wake, +}; + + +static void tca6424_extend_gpio_irq_handler(struct work_struct *work) +{ + struct tca6424_chip *pchip = container_of(work, struct tca6424_chip,tca6424_work); + u8 tempintputreg[TCA6424_PortNum]={0,0,0}; + u8 tempallowint=0; + u8 levelchg=0; + u8 intbit=0; + u8 tempinttype=0; + int i,j; + struct irq_desc *gpio_irq_desc; + unsigned int irq; + if(tca6424_read_reg(pchip->client,TCA6424_InputLevel_Reg,&tempintputreg[0])<0) + { + + DBG("**%s[%d] reading reg is error\n",__FUNCTION__,__LINE__); + enable_irq(pchip->irq_chain); + return; + } + if(tca6424_read_reg(pchip->client,(TCA6424_InputLevel_Reg+1),&tempintputreg[1])<0) + { + + DBG("**%s[%d] reading reg is error\n",__FUNCTION__,__LINE__); + enable_irq(pchip->irq_chain); + return; + } + if(tca6424_read_reg(pchip->client,(TCA6424_InputLevel_Reg+2),&tempintputreg[2])<0) + { + + DBG("**%s[%d] reading reg is error\n",__FUNCTION__,__LINE__); + enable_irq(pchip->irq_chain); + return; + } + DBG("**has run at %s**,tempintreg[0] = %x,tempintreg[1] = %x,tempintreg[2] = %x\n",__FUNCTION__,tempintputreg[0],tempintputreg[1],tempintputreg[2]); + if((pchip->interrupt_en[0]==0)&&(pchip->interrupt_en[1]==0)&&(pchip->interrupt_en[2]==0)) + { + memcpy(&pchip->reg_input[0],&tempintputreg[0],sizeof(tempintputreg)); + DBGERR("there are no pin reg irq\n"); + enable_irq(pchip->irq_chain); + return; + } + + for(i=0;iinterrupt_en[i]&pchip->reg_direction[i]&(~pchip->interrupt_mask[i]);// Âú×ãÖжÏÌõ¼þ + levelchg=pchip->reg_input[i]^tempintputreg[i];// ÕÒ³öÇ°ºó״̬²»Ò»ÑùµÄpin + tempinttype=~(tempintputreg[i]^pchip->inttype[i]);// ÕÒ³ö´¥·¢×´Ì¬ºÍµ±Ç°pin״̬һÑùµÄpin£¬×¢ÒâÖ»Ö§³Ölow highÁ½ÖÖpin´¥·¢ + + tempinttype=(~pchip->inttype1[i])&tempinttype;// inttype1 ΪÕæµÄλ¶ÔÓ¦µÄtempinttypeλÇåÁ㣬ÒòΪ¸ÃλֻÊÜinttype1¿ØÖÆ + tempinttype|=pchip->inttype1[i];//µçƽֻҪÊDZ仯¾Í²úÉúÖÐ¶Ï + tempinttype&=pchip->inttype_set[i];//ÒѾ­ÉèÖÃÁËtypeÀàÐÍ + + intbit=tempallowint&levelchg&tempinttype; + DBG(" tempallowint=%x,levelchg=%x,tempinttype=%x,intbit=%d\n",tempallowint,levelchg,tempinttype,intbit); + + if(intbit) + for(j=0;jgpio_irq_start+TCA6424_PortPinNum*i+j; + gpio_irq_desc = irq_to_desc(irq); + gpio_irq_desc->chip->mask(irq); + generic_handle_irq(irq); + gpio_irq_desc->chip->unmask(irq); + DBG("tca6424_i2c_irq_handler port=%d,pin=%d,pinlevel=%d\n",i,j,tca6424getbit(tempintputreg[i],j)); + } + } + + pchip->reg_input[i]=tempintputreg[i]; + + } + enable_irq(pchip->irq_chain); + return; +} + +static irqreturn_t tca6424_gpio_irq_handler(int irq, void * dev_id) +{ + + struct irq_desc *gpio_irq_desc = irq_to_desc(irq); + struct tca6424_chip *pchip=(struct tca6424_chip *)gpio_irq_desc->chip_data; + + DBG("******************%s*******************\n",__FUNCTION__); + disable_irq_nosync(pchip->irq_chain); + queue_work(tca6424workqueue,&pchip->tca6424_work); + return IRQ_HANDLED; +} + +static irqreturn_t test_handler(int irq, void * dev_id) +{ + + DBG("******************%s*******************\n",__FUNCTION__); + return IRQ_HANDLED; +} + +static void tca6424_setup_gpio(struct tca6424_chip *chip, int gpios) +{ + struct gpio_chip *gc; + + gc = &chip->gpio_chip; + + gc->direction_input = tca6424_gpio_direction_input; + gc->direction_output = tca6424_gpio_direction_output; + gc->get = tca6424_gpio_get_value; + gc->set = tca6424_gpio_set_value; + gc->to_irq = tca6424_gpio_to_irq; + + gc->can_sleep = 1; + + gc->base = chip->gpio_start; + gc->ngpio = chip->gpio_pin_num; + gc->label = chip->client->name; + gc->dev = &chip->client->dev; + gc->owner = THIS_MODULE; + gc->names = chip->names; +} + +static void tca6424_gpio_irq_setup(struct tca6424_chip *pchip) +{ + unsigned pioc, irq_num; + int ret; + int testprint1 = 0; + int testprint2 = 0; + struct irq_desc *desc; + irq_num = pchip->gpio_irq_start; //ÖжϺţ¬À©Õ¹ioµÄÖжϺÅÓ¦¸Ã½ô¸úÔÚÄÚ²¿ioÖжϺŵĺóÃæ¡£ÈçrkÄÚ²¿ÖжÏ48¸ö£¬¼ÓÉÏÄÚ²¿gpio 16¸öÐéÄâÖжϣ¬ÕâÀïpinÓ¦¸Ã´Ó48+16¿ªÊ¼ + + for (pioc = 0; pioc < pchip->irq_pin_num; pioc++,irq_num++) + { + lockdep_set_class(&irq_desc[irq_num].lock, &gpio_lock_class); + /* + * Can use the "simple" and not "edge" handler since it's + * shorter, and the AIC handles interrupts sanely. + */ + testprint1 = set_irq_chip(irq_num, &tca6424_gpio_irqchip); + set_irq_handler(irq_num, handle_simple_irq); + testprint2 = set_irq_chip_data(irq_num,(void *)pchip); + desc = irq_to_desc(irq_num); + DBG("**%s line=%d,test1=%d,test2=%d,desc=%x,chipdate=%x,pchip=%x,irq_num=%d**\n",__FUNCTION__,__LINE__,testprint1,testprint2,desc,desc->chip_data,pchip,irq_num); + set_irq_flags(irq_num, IRQF_VALID); + } + ret = gpio_request(pchip->irq_gpiopin,NULL); + if(ret!=0) + { + gpio_free(pchip->irq_gpiopin); + DBG("tca6424_gpio_irq_setup request gpio is err\n"); + } + + gpio_pull_updown(pchip->irq_gpiopin, GPIOPullUp); //gpio ÐèÒªÀ­¸ßirq_to_gpio(pchip->irq_chain) + +#if 0 + + set_irq_chip_data(pchip->irq_chain, pchip); + set_irq_chained_handler(pchip->irq_chain, gpio_irq_handlerxxx); + set_irq_type(pchip->irq_chain,IRQ_TYPE_LEVEL_LOW); + enable_irq(pchip->irq_chain); + +#else + tca6424workqueue=create_workqueue("tca6424 workqueue"); + INIT_WORK(&pchip->tca6424_work,tca6424_extend_gpio_irq_handler); + + set_irq_chip_data(pchip->irq_chain, pchip); + if(request_irq(pchip->irq_chain,tca6424_gpio_irq_handler, IRQF_TRIGGER_LOW, "tca6424", pchip)!=0) + { + DBG("**%s line=%d is err**\n",__FUNCTION__,__LINE__); + } + +#endif +} + +int tca6424_init_pintype(struct tca6424_chip *chip,struct i2c_client *client) +{ + int i; + struct tca6424_platform_data *platform_data=(struct tca6424_platform_data *)client->dev.platform_data; + struct rk2818_gpio_expander_info *tca6424_gpio_settinginfo; + uint8_t reg_output[TCA6424_PortNum]={0,0,0}; + uint8_t reg_direction[TCA6424_PortNum]={0,0,0}; + uint8_t tca6424_pin_num; + uint8_t gpioPortNum; + uint8_t gpioPortPinNum,tca6424_settingpin_num=0; + + if(platform_data) + { + tca6424_gpio_settinginfo=platform_data->settinginfo; + if(tca6424_gpio_settinginfo) + { + tca6424_settingpin_num=platform_data->settinginfolen; + for(i=0;igpio_start,chip->gpio_pin_num,tca6424_gpio_settinginfo[i].gpio_num)) + { + tca6424_pin_num=tca6424_gpio_settinginfo[i].gpio_num-chip->gpio_start; + gpioPortNum = tca6424_pin_num/ TCA6424_PortPinNum; + gpioPortPinNum= tca6424_pin_num% TCA6424_PortPinNum; + //DBG("gpioPortNum=%d,gpioPortNum=%d,tca6424_pin_num=%d,reg_direction=%x,reg_output=%x,reg_input=%x\n",gpioPortNum,gpioPortPinNum,tca6424_pin_num,reg_direction[i],reg_output[i]); + if((gpioPortNum>=TCA6424_PortNum)||(gpioPortPinNum>=portnum[gpioPortNum])) + continue; + if(tca6424_gpio_settinginfo[i].pin_type==GPIO_IN) + { + reg_direction[gpioPortNum]=tca6424setbit(reg_direction[gpioPortNum],gpioPortPinNum); + } + else + { + reg_direction[gpioPortNum]=tca6424clearbit(reg_direction[gpioPortNum],gpioPortPinNum); + if(tca6424_gpio_settinginfo[i].pin_value==GPIO_HIGH) + { + reg_output[gpioPortNum]=tca6424setbit(reg_output[gpioPortNum],gpioPortPinNum); + } + else + { + reg_output[gpioPortNum]=tca6424clearbit(reg_output[gpioPortNum],gpioPortPinNum); + } + } + + } + } + } + } + #ifdef TCA6424_OUTREGLOCK + mutex_init(&chip->outreglock); + #endif + #ifdef TCA6424_INPUTREGLOCK + mutex_init(&chip->inputreglock); + #endif + #ifdef TCA6424_OUTREGLOCK + mutex_init(&chip->configreglock); + #endif + + for(i=0; ireg_direction[i]=reg_direction[i]; + if (tca6424_write_reg(client, (TCA6424_OutputLevel_Reg+i), reg_output[i])<0) + { + DBGERR("*%s %d write reg err*\n",__FUNCTION__,__LINE__); + return -1; + } + chip->reg_output[i]=reg_output[i]; + + if (tca6424_write_reg(client, (TCA6424_Invert_Reg+i), 0)<0) //make sure this reg be 0 + { + DBGERR("*%s %d* write reg err\n",__FUNCTION__,__LINE__); + return -1; + } + + if(tca6424_read_reg(client, (TCA6424_InputLevel_Reg+i), &chip->reg_input[i])<0) + { + DBGERR("*%s %d read reg err*\n",__FUNCTION__,__LINE__); + return -1; + } + //DBG("reg_direction=%x,reg_output=%x,reg_input=%x\n",chip->reg_direction[i],chip->reg_output[i],chip->reg_input[i]); + + } + + return 0; +} +void tca6424_reset_itr(void) +{ + gpio_request(RK2818_PIN_PE6,NULL); + gpio_request(RK2818_PIN_PE7,NULL); + + rk2818_mux_api_set(GPIOE_U1IR_I2C1_NAME, IOMUXA_GPIO1_A67); + gpio_direction_output(RK2818_PIN_PE6,GPIO_HIGH); + gpio_direction_output(RK2818_PIN_PE7,GPIO_LOW); + udelay(3); + gpio_set_value(RK2818_PIN_PE7,GPIO_HIGH); + udelay(1); + rk2818_mux_api_set(GPIOE_U1IR_I2C1_NAME, IOMUXA_I2C1); + + gpio_free(RK2818_PIN_PE6); + gpio_free(RK2818_PIN_PE7); +} + +static int __devinit tca6424_probe(struct i2c_client *client,const struct i2c_device_id *id) +{ + struct tca6424_chip *chip; + struct tca6424_platform_data *pdata; + int ret; + uint8_t val; + + DBG(KERN_ALERT"*******gpio %s in %d line,dev adr is %x**\n",__FUNCTION__,__LINE__,client->addr); + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EIO; + + chip = kzalloc(sizeof(struct tca6424_chip), GFP_KERNEL); + if (chip == NULL) + return -ENOMEM; + pdata = client->dev.platform_data; + if (pdata == NULL) { + DBGERR(" %s no platform data\n",__FUNCTION__); + ret = -EINVAL; + goto out_failed; + } + + chip->gpio_start = pdata->gpio_base; + chip->gpio_irq_start =pdata->gpio_irq_start; + chip->gpio_pin_num=pdata->gpio_pin_num; + chip->irq_pin_num = pdata->irq_pin_num; + chip->irq_gpiopin=pdata->tca6424_irq_pin; + chip->irq_chain = gpio_to_irq(pdata->tca6424_irq_pin); + chip->names =pdata->names; + + //DBG("**%s in %d start=%d,irq_start=%d,pin_num=%d,irq_pin_num=%d,irq_gpiopin=%d,irq_chain=%d,**\n", + // __FUNCTION__,__LINE__,chip->gpio_start,chip->gpio_irq_start,chip->gpio_pin_num,chip->irq_pin_num,chip->irq_gpiopin + // ,chip->irq_chain); + + /* initialize cached registers from their original values. + * we can't share this chip with another i2c master. + */ + tca6424_setup_gpio(chip, id->driver_data); + ret = gpiochip_add(&chip->gpio_chip); + if (ret) + goto out_failed; + + if(tca6424_init_pintype(chip,client)) + goto out_failed; + + if (pdata->setup) { + ret = pdata->setup(client, chip->gpio_chip.base, + chip->gpio_chip.ngpio, pdata->context); + if (ret < 0) + DBGERR(" %s setup failed, %d\n",__FUNCTION__,ret); + } + + tca6424_gpio_irq_setup(chip); + i2c_set_clientdata(client, chip); + chip->client = client; + return 0; + +out_failed: + + kfree(chip); + return 0; +} + +static int tca6424_remove(struct i2c_client *client) +{ + struct tca6424_platform_data *pdata = client->dev.platform_data; + struct tca6424_chip *chip = i2c_get_clientdata(client); + int ret = 0; + + if (pdata->teardown) { + ret = pdata->teardown(client, chip->gpio_chip.base, + chip->gpio_chip.ngpio, pdata->context); + if (ret < 0) { + DBGERR(" %s failed, %d\n",__FUNCTION__,ret); + return ret; + } + } + + ret = gpiochip_remove(&chip->gpio_chip); + if (ret) { + dev_err(&client->dev, "%s failed, %d\n", + "gpiochip_remove()", ret); + return ret; + } + kfree(chip); + return 0; +} + + +static struct i2c_driver tca6424_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "extend_gpio_tca6424", + }, + .probe = tca6424_probe, + .remove = tca6424_remove, + .id_table = tca6424_id, +}; + + +static int __init tca6424_init(void) +{ + int tmp; + DBG(KERN_ALERT"**********tca6424_init**********\n"); + tmp=i2c_add_driver(&tca6424_driver); + return 0; +} +static void __exit tca6424_exit(void) +{ + DBG(KERN_ALERT"**********tca6424_exit**********\n"); + i2c_del_driver(&tca6424_driver); +} + +module_init(tca6424_init); +module_exit(tca6424_exit); + +MODULE_AUTHOR(" XXX XXX@rock-chips.com"); +MODULE_DESCRIPTION("Driver for rk2818 tca6424 device"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/i2c/busses/i2c-rk2818.c b/drivers/i2c/busses/i2c-rk2818.c index 24e6a20bb0bc..fde5cbe1ade0 100755 --- a/drivers/i2c/busses/i2c-rk2818.c +++ b/drivers/i2c/busses/i2c-rk2818.c @@ -35,6 +35,10 @@ #define RK2818_I2C_TIMEOUT (msecs_to_jiffies(500)) #define RK2818_DELAY_TIME 2 +#if defined (CONFIG_IOEXTEND_TCA6424) + void tca6424_reset_itr(void); +#endif + #if 0 #define i2c_dbg(dev, format, arg...) \ dev_printk(KERN_INFO , dev , format , ## arg) @@ -458,6 +462,14 @@ exit: { dev_err(i2c->dev, "rk2818_i2c_stop timeout\n"); } + + //not I2C code,add by sxj,used for extend gpio intrrupt,set SCL and SDA pin. + if(msg->flags & I2C_M_RD) + { + #if defined (CONFIG_IOEXTEND_TCA6424) + tca6424_reset_itr( ); + #endif + } } return ret; diff --git a/include/linux/i2c/tca6424.h b/include/linux/i2c/tca6424.h new file mode 100755 index 000000000000..6cb23359a9c6 --- /dev/null +++ b/include/linux/i2c/tca6424.h @@ -0,0 +1,45 @@ +/******************************************************************/ +/* Copyright (C) 2008 ROCK-CHIPS FUZHOU . All Rights Reserved. */ +/******************************************************************* +File : gpio.h +Desc : ¶¨ÒågpioµÄ¼Ä´æÆ÷½á¹¹Ìå\¼Ä´æÆ÷λµÄºê¶¨Òå\½Ó¿Úº¯Êý + +Author : +Date : 2008-11-20 +Modified: +Revision: 1.00 +$Log: gpio.h,v $ +*********************************************************************/ +#ifndef _DRIVER_TCA6424_GPIO_H_ +#define _DRIVER_TCA6424_GPIO_H_ + +#define TCA6424_PortNum 3 +#define TCA6424_PortPinNum 8 +#define TCA6424_Port0PinNum 8 +#define TCA6424_Port1PinNum 8 +#define TCA6424_Port2PinNum 8 + +#define TCA6424_TotalPortPinNum (TCA6424_Port0PinNum+TCA6424_Port1PinNum+TCA6424_Port2PinNum) + +#define TCA6424_InputLevel_Reg 0x0 //r only +#define TCA6424_OutputLevel_Reg 0x4 // r/w default ffff +#define TCA6424_Invert_Reg 0x8 // r/w default 0 +#define TCA6424_Config_Reg 0x0c // r/w default ffff + + +#define TCA6424_Auto_InputLevel_Reg 0x80 +#define TCA6424_Auto_OutputLevel_Reg 0x84 +#define TCA6424_Auto_Invert_Reg 0x88 +#define TCA6424_Auto_Config_Reg 0x8c + +#define TCA6424_OUTREGLOCK +#define TCA6424_INPUTREGLOCK +#define TCA6424_CONFIGREGLOCK + +#define tca6424getbit(a,num) (((a)>>(num))&0x01) +#define tca6424setbit(a,num) ((a)|(0x01<<(num))) +#define tca6424clearbit(a,num) ((a)&(~(0x01<<(num)))) + +#define TCA6424_I2C_RATE 300*1000 + +#endif