i2c: mvtwsi: Fix mvtwsi not working on sun6i and newer sunxi SoCs
Subsystems (3)
PATCH 1/2 i2c: mvtwsi: Fix mvtwsi not working on sun6i and newer sunxi SoCs
On sun6i and newer IFLG is a write-clear bit which is cleared by writing 1, rather then a normal r/w bit which is cleared by writing 0.
--- drivers/i2c/mvtwsi.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
drivers/i2c/mvtwsi.c +15 -4
@@ -73,6 +73,17 @@ struct mvtwsi_registers {#define MVTWSI_CONTROL_INTEN 0x00000080/* +* On sun6i and newer IFLG is a write-clear bit which is cleared by writing 1, +* on other platforms it is a normal r/w bit which is cleared by writing 0. +*/ + +#ifdef CONFIG_SUNXI_GEN_SUN6I +#define MVTWSI_CONTROL_CLEAR_IFLG 0x00000008 +#else +#define MVTWSI_CONTROL_CLEAR_IFLG 0x00000000 +#endif + +/* * Status register values -- only those expected in normal master * operation on non-10-bit-address devices; whatever status we don't * expect in nominal conditions (bus errors, arbitration losses,
@@ -189,7 +200,7 @@ static int twsi_start(struct i2c_adapter *adap, int expected_status)/* globally set TWSIEN in case it was not */ twsi_control_flags |=MVTWSI_CONTROL_TWSIEN ;/* assert START */ -writel (twsi_control_flags |MVTWSI_CONTROL_START , &twsi->control); +writel (twsi_control_flags |MVTWSI_CONTROL_START |MVTWSI_CONTROL_CLEAR_IFLG , &twsi->control);/* wait for controller to process START */ return twsi_wait (adap, expected_status); }
@@ -204,7 +215,7 @@ static int twsi_send(struct i2c_adapter *adap, u8 byte, int expected_status)/* put byte in data register for sending */ writel (byte, &twsi->data);/* clear any pending interrupt -- that'll cause sending */ -writel (twsi_control_flags, &twsi->control); +writel (twsi_control_flags |MVTWSI_CONTROL_CLEAR_IFLG , &twsi->control);/* wait for controller to receive byte and check ACK */ return twsi_wait (adap, expected_status); }
@@ -224,7 +235,7 @@ static int twsi_recv(struct i2c_adapter *adap, u8 *byte)else expected_status =MVTWSI_STATUS_DATA_R_NAK ;/* acknowledge *previous state* and launch receive */ -writel (twsi_control_flags, &twsi->control); +writel (twsi_control_flags |MVTWSI_CONTROL_CLEAR_IFLG , &twsi->control);/* wait for controller to receive byte and assert ACK or NAK */ status =twsi_wait (adap, expected_status);/* if we did receive expected byte then store it */
@@ -246,7 +257,7 @@ static int twsi_stop(struct i2c_adapter *adap, int status)/* assert STOP */ control =MVTWSI_CONTROL_TWSIEN |MVTWSI_CONTROL_STOP ; -writel (control, &twsi->control); +writel (control |MVTWSI_CONTROL_CLEAR_IFLG , &twsi->control);/* wait for IDLE; IFLG won't rise so twsi_wait() is no use. */ do { stop_status = readl(&twsi->status);
Signature · 1 line
2.5.0
PATCH 2/2 sunxi: Add support for the I2C controller which is part of the PRCM
From: Jelle van der Waa <[email protected]>
--- arch/arm/cpu/armv7/sunxi/clock_sun6i.c | 10 ++++++++++ arch/arm/cpu/armv7/sunxi/prcm.c | 12 ++++++++++++ arch/arm/include/asm/arch-sunxi/cpu_sun4i.h | 1 + arch/arm/include/asm/arch-sunxi/gpio.h | 2 ++ arch/arm/include/asm/arch-sunxi/i2c.h | 3 +++ arch/arm/include/asm/arch-sunxi/prcm.h | 2 ++ board/sunxi/Kconfig | 6 ++++++ board/sunxi/board.c | 6 ++++++ configs/orangepi_pc_defconfig | 1 + drivers/i2c/mvtwsi.c | 11 +++++++++++ include/configs/sunxi-common.h | 2 +- 11 files changed, 55 insertions(+), 1 deletion(-)
arch/arm/cpu/armv7/sunxi/clock_sun6i.c +10 -0
@@ -77,6 +77,16 @@ int clock_twi_onoff(int port, int state)struct sunxi_ccm_reg *const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE ; +if (port ==5 ) { +if (state) +prcm_apb0_enable ( +PRCM_APB0_GATE_PIO |PRCM_APB0_GATE_I2C ); +else +prcm_apb0_disable ( +PRCM_APB0_GATE_PIO |PRCM_APB0_GATE_I2C ); +return 0 ; + } +/* set the apb clock gate for twi */ if (state) setbits_le32(&ccm->apb2_gate,
arch/arm/cpu/armv7/sunxi/prcm.c +12 -0
@@ -33,3 +33,15 @@ void prcm_apb0_enable(u32 flags)/* deassert reset for module */ setbits_le32 (&prcm->apb0_reset, flags); } + +void prcm_apb0_disable (u32 flags) +{ +struct sunxi_prcm_reg *prcm = + (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE ; + +/* assert reset for module */ +clrbits_le32 (&prcm->apb0_reset, flags); + +/* close the clock for module */ +clrbits_le32 (&prcm->apb0_gate, flags); +}
arch/arm/include/asm/arch-sunxi/cpu_sun4i.h +1 -0
@@ -134,6 +134,7 @@#define SUNXI_RTC_BASE 0x01f00000#define SUNXI_PRCM_BASE 0x01f01400#define SUN6I_CPUCFG_BASE 0x01f01c00 +#define SUNXI_R_TWI_BASE 0x01f02400#define SUNXI_R_UART_BASE 0x01f02800#define SUNXI_R_PIO_BASE 0x01f02c00#define SUN6I_P2WI_BASE 0x01f03400
arch/arm/include/asm/arch-sunxi/gpio.h +2 -0
@@ -199,6 +199,8 @@ enum sunxi_gpio_number {#define SUN6I_GPL1_R_P2WI_SDA 3#define SUN8I_GPL_R_RSB 2 +#define SUN8I_H3_GPL_R_TWI 2 +#define SUN8I_A23_GPL_R_TWI 3#define SUN8I_GPL_R_UART 2#define SUN9I_GPN_R_RSB 3
arch/arm/include/asm/arch-sunxi/i2c.h +3 -0
@@ -23,6 +23,9 @@#ifdef CONFIG_I2C4_ENABLE #define CONFIG_I2C_MVTWSI_BASE4 SUNXI_TWI4_BASE#endif +#ifdef CONFIG_R_I2C_ENABLE +#define CONFIG_I2C_MVTWSI_BASE5 SUNXI_R_TWI_BASE +#endif /* This is abp0-clk on sun4i/5i/7i / abp1-clk on sun6i/sun8i which is 24MHz */ #define CONFIG_SYS_TCLK 24000000
arch/arm/include/asm/arch-sunxi/prcm.h +2 -0
@@ -236,5 +236,7 @@ struct sunxi_prcm_reg { };void prcm_apb0_enable (u32 flags); +void prcm_apb0_disable (u32 flags); +#endif /* __ASSEMBLY__ */ #endif /* _PRCM_H */
board/sunxi/Kconfig +6 -0
@@ -363,6 +363,12 @@ config I2C3_ENABLE See I2C0_ENABLE help text. endif +config R_I2C_ENABLE + bool "Enable the PRCM I2C/TWI controller" + default n + ---help--- + Set this to y to enable the I2C controller which is part of the PRCM. + if MACH_SUN7I config I2C4_ENABLE bool "Enable I2C/TWI controller 4"
board/sunxi/board.c +6 -0
@@ -422,6 +422,12 @@ void i2c_init_board(void)clock_twi_onoff (4 ,1 );#endif #endif + +#ifdef CONFIG_R_I2C_ENABLE +clock_twi_onoff (5 ,1 ); +sunxi_gpio_set_cfgpin (SUNXI_GPL (0 ),SUN8I_H3_GPL_R_TWI ); +sunxi_gpio_set_cfgpin (SUNXI_GPL (1 ),SUN8I_H3_GPL_R_TWI ); +#endif }#ifdef CONFIG_SPL_BUILD
configs/orangepi_pc_defconfig +1 -0
@@ -12,3 +12,4 @@ CONFIG_SPL=y # CONFIG_CMD_FLASH is not set # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y +CONFIG_R_I2C_ENABLE=y
drivers/i2c/mvtwsi.c +11 -0
@@ -128,6 +128,10 @@ static struct mvtwsi_registers *twsi_get_base(struct i2c_adapter *adap)case 4 :return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE4 ;#endif +#ifdef CONFIG_I2C_MVTWSI_BASE5 +case 5 : +return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE5 ; +#endif default :printf ("Missing mvtwsi controller %d base\n" , adap->hwadapnr);break ;
@@ -486,3 +490,10 @@ U_BOOT_I2C_ADAP_COMPLETE(twsi4, twsi_i2c_init, twsi_i2c_probe, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 4)#endif +#ifdef CONFIG_I2C_MVTWSI_BASE5 +U_BOOT_I2C_ADAP_COMPLETE (twsi5, twsi_i2c_init, twsi_i2c_probe, + twsi_i2c_read, twsi_i2c_write, + twsi_i2c_set_bus_speed, + CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 5) + +#endif
include/configs/sunxi-common.h +1 -1
@@ -212,7 +212,7 @@#if definedCONFIG_I2C0_ENABLE || definedCONFIG_I2C1_ENABLE || \ definedCONFIG_I2C2_ENABLE || definedCONFIG_I2C3_ENABLE || \ - definedCONFIG_I2C4_ENABLE + definedCONFIG_I2C4_ENABLE || definedCONFIG_R_I2C_ENABLE #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MVTWSI #define CONFIG_SYS_I2C_SPEED 400000
Signature · 1 line
2.5.0
PATCH 2/2 sunxi: Add support for the I2C controller which is part of the PRCM
Hello Hans,
Am 14.01.2016 um 14:06 schrieb Hans de Goede:
Quoted 5 lines
From: Jelle van der Waa <[email protected]>
Signed-off-by Jelle van der Waa <[email protected]>[hdegoede at redhat.com: Minor cleanups]Signed-off-by Hans de Goede <[email protected]>
Quoted 13 lines
--- arch/arm/cpu/armv7/sunxi/clock_sun6i.c | 10 ++++++++++ arch/arm/cpu/armv7/sunxi/prcm.c | 12 ++++++++++++ arch/arm/include/asm/arch-sunxi/cpu_sun4i.h | 1 + arch/arm/include/asm/arch-sunxi/gpio.h | 2 ++ arch/arm/include/asm/arch-sunxi/i2c.h | 3 +++ arch/arm/include/asm/arch-sunxi/prcm.h | 2 ++ board/sunxi/Kconfig | 6 ++++++ board/sunxi/board.c | 6 ++++++ configs/orangepi_pc_defconfig | 1 + drivers/i2c/mvtwsi.c | 11 +++++++++++ include/configs/sunxi-common.h | 2 +- 11 files changed, 55 insertions(+), 1 deletion(-)
Thanks!
Applied to u-boot-i2c.git with fixing 2 checkpatch warnigns.
bye,
Heiko
Quoted 176 lines
arch/arm/cpu/armv7/sunxi/clock_sun6i.c +10
-0@@ -77,6 +77,16 @@ int clock_twi_onoff(int port, int state)struct sunxi_ccm_reg *const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE ; +if (port ==5 ) { +if (state) +prcm_apb0_enable ( +PRCM_APB0_GATE_PIO |PRCM_APB0_GATE_I2C ); +else +prcm_apb0_disable ( +PRCM_APB0_GATE_PIO |PRCM_APB0_GATE_I2C ); +return 0 ; + } +/* set the apb clock gate for twi */ if (state) setbits_le32(&ccm->apb2_gate,arch/arm/cpu/armv7/sunxi/prcm.c +12
-0@@ -33,3 +33,15 @@ void prcm_apb0_enable(u32 flags)/* deassert reset for module */ setbits_le32 (&prcm->apb0_reset, flags); } + +void prcm_apb0_disable (u32 flags) +{ +struct sunxi_prcm_reg *prcm = + (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE ; + +/* assert reset for module */ +clrbits_le32 (&prcm->apb0_reset, flags); + +/* close the clock for module */ +clrbits_le32 (&prcm->apb0_gate, flags); +}arch/arm/include/asm/arch-sunxi/cpu_sun4i.h +1
-0@@ -134,6 +134,7 @@#define SUNXI_RTC_BASE 0x01f00000#define SUNXI_PRCM_BASE 0x01f01400#define SUN6I_CPUCFG_BASE 0x01f01c00 +#define SUNXI_R_TWI_BASE 0x01f02400#define SUNXI_R_UART_BASE 0x01f02800#define SUNXI_R_PIO_BASE 0x01f02c00#define SUN6I_P2WI_BASE 0x01f03400arch/arm/include/asm/arch-sunxi/gpio.h +2
-0@@ -199,6 +199,8 @@ enum sunxi_gpio_number {#define SUN6I_GPL1_R_P2WI_SDA 3#define SUN8I_GPL_R_RSB 2 +#define SUN8I_H3_GPL_R_TWI 2 +#define SUN8I_A23_GPL_R_TWI 3#define SUN8I_GPL_R_UART 2#define SUN9I_GPN_R_RSB 3arch/arm/include/asm/arch-sunxi/i2c.h +3
-0@@ -23,6 +23,9 @@#ifdef CONFIG_I2C4_ENABLE #define CONFIG_I2C_MVTWSI_BASE4 SUNXI_TWI4_BASE#endif +#ifdef CONFIG_R_I2C_ENABLE +#define CONFIG_I2C_MVTWSI_BASE5 SUNXI_R_TWI_BASE +#endif /* This is abp0-clk on sun4i/5i/7i / abp1-clk on sun6i/sun8i which is 24MHz */ #define CONFIG_SYS_TCLK 24000000arch/arm/include/asm/arch-sunxi/prcm.h +2
-0@@ -236,5 +236,7 @@ struct sunxi_prcm_reg { };void prcm_apb0_enable (u32 flags); +void prcm_apb0_disable (u32 flags); +#endif /* __ASSEMBLY__ */ #endif /* _PRCM_H */ board/sunxi/Kconfig +6
-0@@ -363,6 +363,12 @@ config I2C3_ENABLE See I2C0_ENABLE help text. endif +config R_I2C_ENABLE + bool "Enable the PRCM I2C/TWI controller" + default n + ---help--- + Set this to y to enable the I2C controller which is part of the PRCM. + if MACH_SUN7I config I2C4_ENABLE bool "Enable I2C/TWI controller 4"board/sunxi/board.c +6
-0@@ -422,6 +422,12 @@ void i2c_init_board(void)clock_twi_onoff (4 ,1 );#endif #endif + +#ifdef CONFIG_R_I2C_ENABLE +clock_twi_onoff (5 ,1 ); +sunxi_gpio_set_cfgpin (SUNXI_GPL (0 ),SUN8I_H3_GPL_R_TWI ); +sunxi_gpio_set_cfgpin (SUNXI_GPL (1 ),SUN8I_H3_GPL_R_TWI ); +#endif }#ifdef CONFIG_SPL_BUILD configs/orangepi_pc_defconfig +1
-0@@ -12,3 +12,4 @@ CONFIG_SPL=y # CONFIG_CMD_FLASH is not set # CONFIG_CMD_FPGA is not set CONFIG_CMD_GPIO=y +CONFIG_R_I2C_ENABLE=ydrivers/i2c/mvtwsi.c +11
-0@@ -128,6 +128,10 @@ static struct mvtwsi_registers *twsi_get_base(struct i2c_adapter *adap)case 4 :return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE4 ;#endif +#ifdef CONFIG_I2C_MVTWSI_BASE5 +case 5 : +return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE5 ; +#endif default :printf ("Missing mvtwsi controller %d base\n" , adap->hwadapnr);break ;@@ -486,3 +490,10 @@ U_BOOT_I2C_ADAP_COMPLETE(twsi4, twsi_i2c_init, twsi_i2c_probe, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 4)#endif +#ifdef CONFIG_I2C_MVTWSI_BASE5 +U_BOOT_I2C_ADAP_COMPLETE (twsi5, twsi_i2c_init, twsi_i2c_probe, + twsi_i2c_read, twsi_i2c_write, + twsi_i2c_set_bus_speed, + CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 5) + +#endif include/configs/sunxi-common.h +1
-1@@ -212,7 +212,7 @@#if definedCONFIG_I2C0_ENABLE || definedCONFIG_I2C1_ENABLE || \ definedCONFIG_I2C2_ENABLE || definedCONFIG_I2C3_ENABLE || \ - definedCONFIG_I2C4_ENABLE + definedCONFIG_I2C4_ENABLE || definedCONFIG_R_I2C_ENABLE #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MVTWSI #define CONFIG_SYS_I2C_SPEED 400000
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH 1/2 i2c: mvtwsi: Fix mvtwsi not working on sun6i and newer sunxi SoCs
In reply to Hans de GoedeHello Hans,
Am 14.01.2016 um 14:06 schrieb Hans de Goede:
Quoted 7 lines
On sun6i and newer IFLG is a write-clear bit which is cleared by writing 1, rather then a normal r/w bit which is cleared by writing 0.
Signed-off-by Hans de Goede <[email protected]>--- drivers/i2c/mvtwsi.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
Thanks!
Applied to u-boot-i2c.git with fixing 3 checkpatch errors/warnings.
bye,
Heiko
Quoted 60 lines
drivers/i2c/mvtwsi.c +15
-4@@ -73,6 +73,17 @@ struct mvtwsi_registers {#define MVTWSI_CONTROL_INTEN 0x00000080/* +* On sun6i and newer IFLG is a write-clear bit which is cleared by writing 1, +* on other platforms it is a normal r/w bit which is cleared by writing 0. +*/ + +#ifdef CONFIG_SUNXI_GEN_SUN6I +#define MVTWSI_CONTROL_CLEAR_IFLG 0x00000008 +#else +#define MVTWSI_CONTROL_CLEAR_IFLG 0x00000000 +#endif + +/* * Status register values -- only those expected in normal master * operation on non-10-bit-address devices; whatever status we don't * expect in nominal conditions (bus errors, arbitration losses, @@ -189,7 +200,7 @@ static int twsi_start(struct i2c_adapter *adap, int expected_status)/* globally set TWSIEN in case it was not */ twsi_control_flags |=MVTWSI_CONTROL_TWSIEN ;/* assert START */ -writel (twsi_control_flags |MVTWSI_CONTROL_START , &twsi->control); +writel (twsi_control_flags |MVTWSI_CONTROL_START |MVTWSI_CONTROL_CLEAR_IFLG , &twsi->control);/* wait for controller to process START */ return twsi_wait (adap, expected_status); }@@ -204,7 +215,7 @@ static int twsi_send(struct i2c_adapter *adap, u8 byte, int expected_status)/* put byte in data register for sending */ writel (byte, &twsi->data);/* clear any pending interrupt -- that'll cause sending */ -writel (twsi_control_flags, &twsi->control); +writel (twsi_control_flags |MVTWSI_CONTROL_CLEAR_IFLG , &twsi->control);/* wait for controller to receive byte and check ACK */ return twsi_wait (adap, expected_status); }@@ -224,7 +235,7 @@ static int twsi_recv(struct i2c_adapter *adap, u8 *byte)else expected_status =MVTWSI_STATUS_DATA_R_NAK ;/* acknowledge *previous state* and launch receive */ -writel (twsi_control_flags, &twsi->control); +writel (twsi_control_flags |MVTWSI_CONTROL_CLEAR_IFLG , &twsi->control);/* wait for controller to receive byte and assert ACK or NAK */ status =twsi_wait (adap, expected_status);/* if we did receive expected byte then store it */ @@ -246,7 +257,7 @@ static int twsi_stop(struct i2c_adapter *adap, int status)/* assert STOP */ control =MVTWSI_CONTROL_TWSIEN |MVTWSI_CONTROL_STOP ; -writel (control, &twsi->control); +writel (control |MVTWSI_CONTROL_CLEAR_IFLG , &twsi->control);/* wait for IDLE; IFLG won't rise so twsi_wait() is no use. */ do { stop_status = readl(&twsi->status);
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany