From 21d314a6612564ee202d8a8189ed37d5c6abf0dd Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 12 Sep 2021 11:48:43 -0500 Subject: clk: sunxi: Move header out of arch directory The CCU header is only used by the DM drivers, not any platform code. Its current location adds an artificial dependency on CONFIG_ARM and ARCH_SUNXI, which will be problematic when adding the CCU driver for a RISC-V sunxi platform. Signed-off-by: Samuel Holland Reviewed-by: Bin Meng Signed-off-by: Andre Przywara --- arch/arm/include/asm/arch-sunxi/ccu.h | 100 ---------------------------------- 1 file changed, 100 deletions(-) delete mode 100644 arch/arm/include/asm/arch-sunxi/ccu.h (limited to 'arch') diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h deleted file mode 100644 index cac5c5faf05..00000000000 --- a/arch/arm/include/asm/arch-sunxi/ccu.h +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2018 Amarula Solutions. - * Author: Jagan Teki - */ - -#ifndef _ASM_ARCH_CCU_H -#define _ASM_ARCH_CCU_H - -#ifndef __ASSEMBLY__ -#include -#endif - -/** - * enum ccu_flags - ccu clock/reset flags - * - * @CCU_CLK_F_IS_VALID: is given clock gate is valid? - * @CCU_RST_F_IS_VALID: is given reset control is valid? - */ -enum ccu_flags { - CCU_CLK_F_IS_VALID = BIT(0), - CCU_RST_F_IS_VALID = BIT(1), -}; - -/** - * struct ccu_clk_gate - ccu clock gate - * @off: gate offset - * @bit: gate bit - * @flags: ccu clock gate flags - */ -struct ccu_clk_gate { - u16 off; - u32 bit; - enum ccu_flags flags; -}; - -#define GATE(_off, _bit) { \ - .off = _off, \ - .bit = _bit, \ - .flags = CCU_CLK_F_IS_VALID, \ -} - -/** - * struct ccu_reset - ccu reset - * @off: reset offset - * @bit: reset bit - * @flags: ccu reset control flags - */ -struct ccu_reset { - u16 off; - u32 bit; - enum ccu_flags flags; -}; - -#define RESET(_off, _bit) { \ - .off = _off, \ - .bit = _bit, \ - .flags = CCU_RST_F_IS_VALID, \ -} - -/** - * struct ccu_desc - clock control unit descriptor - * - * @gates: clock gates - * @resets: reset unit - */ -struct ccu_desc { - const struct ccu_clk_gate *gates; - const struct ccu_reset *resets; -}; - -/** - * struct ccu_priv - sunxi clock control unit - * - * @base: base address - * @desc: ccu descriptor - */ -struct ccu_priv { - void *base; - const struct ccu_desc *desc; -}; - -/** - * sunxi_clk_probe - common sunxi clock probe - * @dev: clock device - */ -int sunxi_clk_probe(struct udevice *dev); - -extern struct clk_ops sunxi_clk_ops; - -/** - * sunxi_reset_bind() - reset binding - * - * @dev: reset device - * @count: reset count - * @return 0 success, or error value - */ -int sunxi_reset_bind(struct udevice *dev, ulong count); - -#endif /* _ASM_ARCH_CCU_H */ -- cgit v1.3.1 From dda9fa734f813c0d0c29aa03bfe200950b40cfea Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 12 Sep 2021 10:28:35 -0500 Subject: sunxi: Simplify MMC pinmux selection Only one board, Yones Toptech BD1078, actually uses a non-default MMC pinmux. All other uses of these symbols select the default value or an invalid value. To simplify things, remove support for the unused pinmux options, and convert the remaining option to a Boolean. This allows the pinmux to be chosen by the preprocessor, instead of having the code parse a string at runtime (for a build-time option!). Not only does this reduce code size, but it also allows this Kconfig option to be used in a table-driven DM pinctrl driver. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/include/asm/arch-sunxi/gpio.h | 4 -- arch/arm/mach-sunxi/Kconfig | 21 ++----- board/sunxi/board.c | 101 ++++++++++----------------------- configs/A20-Olimex-SOM-EVB_defconfig | 1 - configs/Sinlinx_SinA31s_defconfig | 1 - configs/Yones_Toptech_BD1078_defconfig | 2 +- configs/parrot_r16_defconfig | 1 - 7 files changed, 34 insertions(+), 97 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 2969a530ae1..43b1b97391a 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -148,8 +148,6 @@ enum sunxi_gpio_number { #define SUNXI_GPA_EMAC 2 #define SUN6I_GPA_GMAC 2 #define SUN7I_GPA_GMAC 5 -#define SUN6I_GPA_SDC2 5 -#define SUN6I_GPA_SDC3 4 #define SUN8I_H3_GPA_UART0 2 #define SUN4I_GPB_PWM 2 @@ -173,12 +171,10 @@ enum sunxi_gpio_number { #define SUN6I_GPC_SDC3 4 #define SUN50I_GPC_SPI0 4 -#define SUN8I_GPD_SDC1 3 #define SUNXI_GPD_LCD0 2 #define SUNXI_GPD_LVDS0 3 #define SUNXI_GPD_PWM 2 -#define SUN5I_GPE_SDC2 3 #define SUN8I_GPE_TWI2 3 #define SUN50I_GPE_TWI2 3 diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 1d4a4fdd0c5..7308f977a59 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -677,24 +677,11 @@ config MMC3_CD_PIN ---help--- See MMC0_CD_PIN help text. -config MMC1_PINS - string "Pins for mmc1" - default "" - ---help--- - Set the pins used for mmc1, when applicable. This takes a string in the - format understood by sunxi_name_to_gpio_bank, e.g. PH for port H. - -config MMC2_PINS - string "Pins for mmc2" - default "" - ---help--- - See MMC1_PINS help text. - -config MMC3_PINS - string "Pins for mmc3" - default "" +config MMC1_PINS_PH + bool "Pins for mmc1 are on Port H" + depends on MACH_SUN4I || MACH_SUN7I || MACH_SUN8I_R40 ---help--- - See MMC1_PINS help text. + Select this option for boards where mmc1 uses the Port H pinmux. config MMC_SUNXI_SLOT_EXTRA int "mmc extra slot number" diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 2b7d655678d..418dc0ce756 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -413,7 +413,6 @@ void board_nand_init(void) static void mmc_pinmux_setup(int sdc) { unsigned int pin; - __maybe_unused int pins; switch (sdc) { case 0: @@ -426,11 +425,9 @@ static void mmc_pinmux_setup(int sdc) break; case 1: - pins = sunxi_name_to_gpio_bank(CONFIG_MMC1_PINS); - #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) || \ defined(CONFIG_MACH_SUN8I_R40) - if (pins == SUNXI_GPIO_H) { + if (IS_ENABLED(CONFIG_MMC1_PINS_PH)) { /* SDC1: PH22-PH-27 */ for (pin = SUNXI_GPH(22); pin <= SUNXI_GPH(27); pin++) { sunxi_gpio_set_cfgpin(pin, SUN4I_GPH_SDC1); @@ -460,27 +457,16 @@ static void mmc_pinmux_setup(int sdc) sunxi_gpio_set_drv(pin, 2); } #elif defined(CONFIG_MACH_SUN8I) - if (pins == SUNXI_GPIO_D) { - /* SDC1: PD2-PD7 */ - for (pin = SUNXI_GPD(2); pin <= SUNXI_GPD(7); pin++) { - sunxi_gpio_set_cfgpin(pin, SUN8I_GPD_SDC1); - sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); - sunxi_gpio_set_drv(pin, 2); - } - } else { - /* SDC1: PG0-PG5 */ - for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) { - sunxi_gpio_set_cfgpin(pin, SUN8I_GPG_SDC1); - sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); - sunxi_gpio_set_drv(pin, 2); - } + /* SDC1: PG0-PG5 */ + for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) { + sunxi_gpio_set_cfgpin(pin, SUN8I_GPG_SDC1); + sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); + sunxi_gpio_set_drv(pin, 2); } #endif break; case 2: - pins = sunxi_name_to_gpio_bank(CONFIG_MMC2_PINS); - #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) /* SDC2: PC6-PC11 */ for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(11); pin++) { @@ -489,41 +475,23 @@ static void mmc_pinmux_setup(int sdc) sunxi_gpio_set_drv(pin, 2); } #elif defined(CONFIG_MACH_SUN5I) - if (pins == SUNXI_GPIO_E) { - /* SDC2: PE4-PE9 */ - for (pin = SUNXI_GPE(4); pin <= SUNXI_GPD(9); pin++) { - sunxi_gpio_set_cfgpin(pin, SUN5I_GPE_SDC2); - sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); - sunxi_gpio_set_drv(pin, 2); - } - } else { - /* SDC2: PC6-PC15 */ - for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) { - sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2); - sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); - sunxi_gpio_set_drv(pin, 2); - } + /* SDC2: PC6-PC15 */ + for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) { + sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2); + sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); + sunxi_gpio_set_drv(pin, 2); } #elif defined(CONFIG_MACH_SUN6I) - if (pins == SUNXI_GPIO_A) { - /* SDC2: PA9-PA14 */ - for (pin = SUNXI_GPA(9); pin <= SUNXI_GPA(14); pin++) { - sunxi_gpio_set_cfgpin(pin, SUN6I_GPA_SDC2); - sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); - sunxi_gpio_set_drv(pin, 2); - } - } else { - /* SDC2: PC6-PC15, PC24 */ - for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) { - sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2); - sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); - sunxi_gpio_set_drv(pin, 2); - } - - sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2); - sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP); - sunxi_gpio_set_drv(SUNXI_GPC(24), 2); + /* SDC2: PC6-PC15, PC24 */ + for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) { + sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2); + sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); + sunxi_gpio_set_drv(pin, 2); } + + sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2); + sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP); + sunxi_gpio_set_drv(SUNXI_GPC(24), 2); #elif defined(CONFIG_MACH_SUN8I_R40) /* SDC2: PC6-PC15, PC24 */ for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) { @@ -579,8 +547,6 @@ static void mmc_pinmux_setup(int sdc) break; case 3: - pins = sunxi_name_to_gpio_bank(CONFIG_MMC3_PINS); - #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) || \ defined(CONFIG_MACH_SUN8I_R40) /* SDC3: PI4-PI9 */ @@ -590,25 +556,16 @@ static void mmc_pinmux_setup(int sdc) sunxi_gpio_set_drv(pin, 2); } #elif defined(CONFIG_MACH_SUN6I) - if (pins == SUNXI_GPIO_A) { - /* SDC3: PA9-PA14 */ - for (pin = SUNXI_GPA(9); pin <= SUNXI_GPA(14); pin++) { - sunxi_gpio_set_cfgpin(pin, SUN6I_GPA_SDC3); - sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); - sunxi_gpio_set_drv(pin, 2); - } - } else { - /* SDC3: PC6-PC15, PC24 */ - for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) { - sunxi_gpio_set_cfgpin(pin, SUN6I_GPC_SDC3); - sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); - sunxi_gpio_set_drv(pin, 2); - } - - sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUN6I_GPC_SDC3); - sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP); - sunxi_gpio_set_drv(SUNXI_GPC(24), 2); + /* SDC3: PC6-PC15, PC24 */ + for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) { + sunxi_gpio_set_cfgpin(pin, SUN6I_GPC_SDC3); + sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP); + sunxi_gpio_set_drv(pin, 2); } + + sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUN6I_GPC_SDC3); + sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP); + sunxi_gpio_set_drv(SUNXI_GPC(24), 2); #endif break; diff --git a/configs/A20-Olimex-SOM-EVB_defconfig b/configs/A20-Olimex-SOM-EVB_defconfig index ececdaca150..075d999e1c9 100644 --- a/configs/A20-Olimex-SOM-EVB_defconfig +++ b/configs/A20-Olimex-SOM-EVB_defconfig @@ -6,7 +6,6 @@ CONFIG_MACH_SUN7I=y CONFIG_DRAM_CLK=384 CONFIG_MMC0_CD_PIN="PH1" CONFIG_MMC3_CD_PIN="PH0" -CONFIG_MMC3_PINS="PH" CONFIG_MMC_SUNXI_SLOT_EXTRA=3 CONFIG_USB0_VBUS_PIN="PB9" CONFIG_USB0_VBUS_DET="PH5" diff --git a/configs/Sinlinx_SinA31s_defconfig b/configs/Sinlinx_SinA31s_defconfig index 8fa8246344c..238b0073e79 100644 --- a/configs/Sinlinx_SinA31s_defconfig +++ b/configs/Sinlinx_SinA31s_defconfig @@ -6,7 +6,6 @@ CONFIG_MACH_SUN6I=y CONFIG_DRAM_CLK=432 CONFIG_DRAM_ZQ=251 CONFIG_MMC0_CD_PIN="PA4" -CONFIG_MMC3_PINS="PC" CONFIG_MMC_SUNXI_SLOT_EXTRA=3 CONFIG_USB1_VBUS_PIN="" CONFIG_USB2_VBUS_PIN="" diff --git a/configs/Yones_Toptech_BD1078_defconfig b/configs/Yones_Toptech_BD1078_defconfig index 1b88cfabf04..f1ceb8b5527 100644 --- a/configs/Yones_Toptech_BD1078_defconfig +++ b/configs/Yones_Toptech_BD1078_defconfig @@ -6,7 +6,7 @@ CONFIG_MACH_SUN7I=y CONFIG_DRAM_CLK=408 CONFIG_MMC0_CD_PIN="PH1" CONFIG_MMC1_CD_PIN="PH2" -CONFIG_MMC1_PINS="PH" +CONFIG_MMC1_PINS_PH=y CONFIG_MMC_SUNXI_SLOT_EXTRA=1 CONFIG_USB0_VBUS_PIN="PB9" CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT" diff --git a/configs/parrot_r16_defconfig b/configs/parrot_r16_defconfig index de340e230f2..d56c4504b6a 100644 --- a/configs/parrot_r16_defconfig +++ b/configs/parrot_r16_defconfig @@ -6,7 +6,6 @@ CONFIG_MACH_SUN8I_A33=y CONFIG_DRAM_CLK=600 CONFIG_DRAM_ZQ=15291 CONFIG_MMC0_CD_PIN="PD14" -CONFIG_MMC2_PINS="PC" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_USB0_ID_DET="PD10" CONFIG_USB1_VBUS_PIN="PD12" -- cgit v1.3.1 From 14c8c631e986d350ce468ae5d627f547e5a4e1aa Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 12 Sep 2021 10:28:36 -0500 Subject: gpio: sunxi: Remove the sunxi_name_to_gpio_bank function The only caller of this function was the MMC pinmux code, which used it to parse a string given from a Kconfig symbol. As the Kconfig symbol has been converted to a Boolean, this function is no longer needed. Signed-off-by: Samuel Holland Reviewed-by: Simon Glass Signed-off-by: Andre Przywara --- arch/arm/include/asm/arch-sunxi/gpio.h | 1 - drivers/gpio/sunxi_gpio.c | 14 -------------- 2 files changed, 15 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 43b1b97391a..c595dcc6351 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -238,7 +238,6 @@ int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset); int sunxi_gpio_get_cfgpin(u32 pin); int sunxi_gpio_set_drv(u32 pin, u32 val); int sunxi_gpio_set_pull(u32 pin, u32 val); -int sunxi_name_to_gpio_bank(const char *name); int sunxi_name_to_gpio(const char *name); #define name_to_gpio(name) sunxi_name_to_gpio(name) diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index 24cb604e3e3..c5d73d0a049 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -118,20 +118,6 @@ int sunxi_name_to_gpio(const char *name) } #endif /* DM_GPIO */ -int sunxi_name_to_gpio_bank(const char *name) -{ - int group = 0; - - if (*name == 'P' || *name == 'p') - name++; - if (*name >= 'A') { - group = *name - (*name > 'a' ? 'a' : 'A'); - return group; - } - - return -1; -} - #if CONFIG_IS_ENABLED(DM_GPIO) /* TODO(sjg@chromium.org): Remove this function and use device tree */ int sunxi_name_to_gpio(const char *name) -- cgit v1.3.1 From 425084610e08e344d43e0d142e72e65c9602379f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 11 Sep 2021 16:50:47 -0500 Subject: sunxi: Clean up inclusions of asm/arch/gpio.h As part of migrating to DM_GPIO and DM_PINCTRL, eventually we will remove the asm/arch/gpio.h header. In preparation, clean up the various files that include it. Some files did not contain any GPIO code at all, so this header was completely unused. A few files contained only legacy platform-specific GPIO code for setting up pin muxes. They were left unchanged, as that code will be completely removed by the DM_PINCTRL migration. The remaining files contain some combination of DM_GPIO and legacy GPIO code. For those, switch to including asm/gpio.h (if it wasn't included already). Right now, this header provides both sets of functions, because ARCH_SUNXI selects GPIO_EXTRA_HEADER. This will still be the right header to include once the DM_GPIO migration is complete and GPIO_EXTRA_HEADER is no longer needed. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/mach-sunxi/board.c | 1 - arch/arm/mach-sunxi/clock.c | 1 - arch/arm/mach-sunxi/clock_sun4i.c | 1 - board/sunxi/board.c | 1 - board/sunxi/gmac.c | 1 - drivers/gpio/axp_gpio.c | 1 - drivers/gpio/sunxi_gpio.c | 1 - drivers/mmc/sunxi_mmc.c | 3 +-- drivers/net/sun8i_emac.c | 5 +---- drivers/power/axp809.c | 1 - drivers/power/axp818.c | 1 - drivers/usb/musb-new/sunxi.c | 2 -- drivers/video/sunxi/sunxi_display.c | 1 - drivers/video/sunxi/sunxi_lcd.c | 1 - 14 files changed, 2 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index d9b04f75fc4..373cb56db49 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-sunxi/clock.c b/arch/arm/mach-sunxi/clock.c index f591affebf7..de7e8752988 100644 --- a/arch/arm/mach-sunxi/clock.c +++ b/arch/arm/mach-sunxi/clock.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-sunxi/clock_sun4i.c b/arch/arm/mach-sunxi/clock_sun4i.c index 57ee018eaa2..471609764d2 100644 --- a/arch/arm/mach-sunxi/clock_sun4i.c +++ b/arch/arm/mach-sunxi/clock_sun4i.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #ifdef CONFIG_SPL_BUILD diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 6ba7bf523a6..65cb3a6fe31 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/board/sunxi/gmac.c b/board/sunxi/gmac.c index d8fdf7728e0..1fa54ed72de 100644 --- a/board/sunxi/gmac.c +++ b/board/sunxi/gmac.c @@ -4,7 +4,6 @@ #include #include #include -#include void eth_init_board(void) { diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c index 73058cf40b4..35585dc8ac9 100644 --- a/drivers/gpio/axp_gpio.c +++ b/drivers/gpio/axp_gpio.c @@ -6,7 +6,6 @@ */ #include -#include #include #include #include diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index c5d73d0a049..bf7d82fbf50 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index aaab0cf8668..c170c16d5ab 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -15,12 +15,11 @@ #include #include #include +#include #include #include #include -#include #include -#include #include #ifndef CCM_MMC_CTRL_MODE_SEL_NEW diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c index a6eb82bd166..2e24d122141 100644 --- a/drivers/net/sun8i_emac.c +++ b/drivers/net/sun8i_emac.c @@ -14,9 +14,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -31,9 +31,6 @@ #include #include #include -#if CONFIG_IS_ENABLED(DM_GPIO) -#include -#endif #define MDIO_CMD_MII_BUSY BIT(0) #define MDIO_CMD_MII_WRITE BIT(1) diff --git a/drivers/power/axp809.c b/drivers/power/axp809.c index 6323492b66d..0396502cdb5 100644 --- a/drivers/power/axp809.c +++ b/drivers/power/axp809.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/drivers/power/axp818.c b/drivers/power/axp818.c index 0531707c8aa..2dc736467bb 100644 --- a/drivers/power/axp818.c +++ b/drivers/power/axp818.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index fea4105f3d1..7e62e3fe6ea 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -25,8 +25,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index 4361a58cd7e..128888f7af1 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include diff --git a/drivers/video/sunxi/sunxi_lcd.c b/drivers/video/sunxi/sunxi_lcd.c index 7a9eba1ed42..8b9c3b2bfa9 100644 --- a/drivers/video/sunxi/sunxi_lcd.c +++ b/drivers/video/sunxi/sunxi_lcd.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include -- cgit v1.3.1 From 4d9958b6424b370555fa9fda7a0dd97b353b9797 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 11 Sep 2021 16:50:48 -0500 Subject: sunxi: gpio: Remove name_to_gpio macro This clarifies which callers must be updated to complete the DM_GPIO conversion. The only remaining caller of name_to_gpio in generic code is inside the !DM_GPIO block in cmd/gpio.c. DM_GPIO is always selected on sunxi, so that code cannot be reached. And after this commit, there are only two remaining implementations of name_to_gpio. Signed-off-by: Samuel Holland Acked-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/include/asm/arch-sunxi/gpio.h | 1 - drivers/spi/spi-sunxi.c | 2 +- drivers/video/Kconfig | 10 +++++----- drivers/video/hitachi_tx18d42vm_lcd.c | 6 +++--- drivers/video/sunxi/sunxi_display.c | 10 +++++----- 5 files changed, 14 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index c595dcc6351..59e3915c379 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -239,7 +239,6 @@ int sunxi_gpio_get_cfgpin(u32 pin); int sunxi_gpio_set_drv(u32 pin, u32 val); int sunxi_gpio_set_pull(u32 pin, u32 val); int sunxi_name_to_gpio(const char *name); -#define name_to_gpio(name) sunxi_name_to_gpio(name) #if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO int axp_gpio_init(void); diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index 4ca5d3a93ac..bc2f544e863 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -245,7 +245,7 @@ static int sun4i_spi_parse_pins(struct udevice *dev) break; } - pin = name_to_gpio(pin_name); + pin = sunxi_name_to_gpio(pin_name); if (pin < 0) break; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 9f789a6a58a..2f4650f8309 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -452,7 +452,7 @@ config VIDEO_LCD_SSD2828_RESET default "" ---help--- The reset pin of SSD2828 chip. This takes a string in the format - understood by 'name_to_gpio' function, e.g. PH1 for pin 1 of port H. + understood by 'sunxi_name_to_gpio' function, e.g. PH1 for pin 1 of port H. config VIDEO_LCD_TDO_TL070WSH30 bool "TDO TL070WSH30 DSI LCD panel support" @@ -477,7 +477,7 @@ config VIDEO_LCD_SPI_CS This is one of the SPI communication pins, involved in setting up a working LCD configuration. The exact role of SPI may differ for different hardware setups. The option takes a string in the format - understood by 'name_to_gpio' function, e.g. PH1 for pin 1 of port H. + understood by 'sunxi_name_to_gpio' function, e.g. PH1 for pin 1 of port H. config VIDEO_LCD_SPI_SCLK string "SPI SCLK pin for LCD related config job" @@ -487,7 +487,7 @@ config VIDEO_LCD_SPI_SCLK This is one of the SPI communication pins, involved in setting up a working LCD configuration. The exact role of SPI may differ for different hardware setups. The option takes a string in the format - understood by 'name_to_gpio' function, e.g. PH1 for pin 1 of port H. + understood by 'sunxi_name_to_gpio' function, e.g. PH1 for pin 1 of port H. config VIDEO_LCD_SPI_MOSI string "SPI MOSI pin for LCD related config job" @@ -497,7 +497,7 @@ config VIDEO_LCD_SPI_MOSI This is one of the SPI communication pins, involved in setting up a working LCD configuration. The exact role of SPI may differ for different hardware setups. The option takes a string in the format - understood by 'name_to_gpio' function, e.g. PH1 for pin 1 of port H. + understood by 'sunxi_name_to_gpio' function, e.g. PH1 for pin 1 of port H. config VIDEO_LCD_SPI_MISO string "SPI MISO pin for LCD related config job (optional)" @@ -509,7 +509,7 @@ config VIDEO_LCD_SPI_MISO different hardware setups. If wired up, this pin may provide additional useful functionality. Such as bi-directional communication with the hardware and LCD panel id retrieval (if the panel can report it). The - option takes a string in the format understood by 'name_to_gpio' + option takes a string in the format understood by 'sunxi_name_to_gpio' function, e.g. PH1 for pin 1 of port H. source "drivers/video/meson/Kconfig" diff --git a/drivers/video/hitachi_tx18d42vm_lcd.c b/drivers/video/hitachi_tx18d42vm_lcd.c index c6c8df6a96e..87c4d27438a 100644 --- a/drivers/video/hitachi_tx18d42vm_lcd.c +++ b/drivers/video/hitachi_tx18d42vm_lcd.c @@ -49,9 +49,9 @@ int hitachi_tx18d42vm_init(void) }; int i, cs, clk, mosi, ret = 0; - cs = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS); - clk = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK); - mosi = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI); + cs = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS); + clk = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK); + mosi = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI); if (cs == -1 || clk == -1 || mosi == 1) { printf("Error tx18d42vm spi gpio config is invalid\n"); diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index 128888f7af1..da3e8988296 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -871,11 +871,11 @@ static void sunxi_vga_external_dac_enable(void) static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode) { struct ssd2828_config cfg = { - .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS), - .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK), - .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI), - .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO), - .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET), + .csx_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS), + .sck_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK), + .sdi_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI), + .sdo_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO), + .reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET), .ssd2828_tx_clk_khz = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000, .ssd2828_color_depth = 24, #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828 -- cgit v1.3.1 From 8fe8ff34110792f8a4ed4ab7a4f4e14c82feb452 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 11 Sep 2021 16:50:49 -0500 Subject: sunxi: gpio: Remove bank-specific size macros Since the beginning, all banks have had space for 32 pins, even when not all pins were implemented. Let's use a single constant for the GPIO bank size here, like the GPIO driver is already doing. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/include/asm/arch-sunxi/gpio.h | 14 ++------------ drivers/gpio/sunxi_gpio.c | 2 -- 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 59e3915c379..f3ab1aea0ef 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -93,20 +93,10 @@ struct sunxi_gpio_reg { #define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1) /* GPIO bank sizes */ -#define SUNXI_GPIO_A_NR 32 -#define SUNXI_GPIO_B_NR 32 -#define SUNXI_GPIO_C_NR 32 -#define SUNXI_GPIO_D_NR 32 -#define SUNXI_GPIO_E_NR 32 -#define SUNXI_GPIO_F_NR 32 -#define SUNXI_GPIO_G_NR 32 -#define SUNXI_GPIO_H_NR 32 -#define SUNXI_GPIO_I_NR 32 -#define SUNXI_GPIO_L_NR 32 -#define SUNXI_GPIO_M_NR 32 +#define SUNXI_GPIOS_PER_BANK 32 #define SUNXI_GPIO_NEXT(__gpio) \ - ((__gpio##_START) + (__gpio##_NR) + 0) + ((__gpio##_START) + SUNXI_GPIOS_PER_BANK) enum sunxi_gpio_number { SUNXI_GPIO_A_START = 0, diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index bf7d82fbf50..cdbc40d48fd 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -19,8 +19,6 @@ #include #include -#define SUNXI_GPIOS_PER_BANK SUNXI_GPIO_A_NR - struct sunxi_gpio_plat { struct sunxi_gpio *regs; const char *bank_name; /* Name of bank, e.g. "B" */ -- cgit v1.3.1 From e7510d24cab4741f72489b9d67c2d42b18fe5374 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Sun, 10 Oct 2021 21:36:57 +0800 Subject: sunxi: Add support for FriendlyARM NanoPi R1S H5 This adds support for the NanoPi R1S H5 board. Allwinner H5 SoC 512MB DDR3 RAM 10/100/1000M Ethernet x 2 RTL8189ETV WiFi 802.11b/g/n USB 2.0 host port (A) MicroSD Slot Reset button Serial Debug Port WAN - LAN - SYS LED The dts file is taken from Linux 5.14 tag. Signed-off-by: Chukun Pan Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/dts/Makefile | 1 + arch/arm/dts/sun50i-h5-nanopi-r1s-h5.dts | 195 +++++++++++++++++++++++++++++++ board/sunxi/MAINTAINERS | 5 + configs/nanopi_r1s_h5_defconfig | 14 +++ 4 files changed, 215 insertions(+) create mode 100644 arch/arm/dts/sun50i-h5-nanopi-r1s-h5.dts create mode 100644 configs/nanopi_r1s_h5_defconfig (limited to 'arch') diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index b8a382d1539..ed3d360bb10 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -638,6 +638,7 @@ dtb-$(CONFIG_MACH_SUN50I_H5) += \ sun50i-h5-libretech-all-h5-cc.dtb \ sun50i-h5-nanopi-neo2.dtb \ sun50i-h5-nanopi-neo-plus2.dtb \ + sun50i-h5-nanopi-r1s-h5.dtb \ sun50i-h5-orangepi-zero-plus.dtb \ sun50i-h5-orangepi-pc2.dtb \ sun50i-h5-orangepi-prime.dtb \ diff --git a/arch/arm/dts/sun50i-h5-nanopi-r1s-h5.dts b/arch/arm/dts/sun50i-h5-nanopi-r1s-h5.dts new file mode 100644 index 00000000000..55bcdf8d1a0 --- /dev/null +++ b/arch/arm/dts/sun50i-h5-nanopi-r1s-h5.dts @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2021 Chukun Pan + * + * Based on sun50i-h5-nanopi-neo-plus2.dts, which is: + * Copyright (C) 2017 Antony Antony + * Copyright (C) 2016 ARM Ltd. + */ + +/dts-v1/; +#include "sun50i-h5.dtsi" +#include "sun50i-h5-cpu-opp.dtsi" + +#include +#include +#include + +/ { + model = "FriendlyARM NanoPi R1S H5"; + compatible = "friendlyarm,nanopi-r1s-h5", "allwinner,sun50i-h5"; + + aliases { + ethernet0 = &emac; + ethernet1 = &rtl8189etv; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + function = LED_FUNCTION_LAN; + color = ; + gpios = <&pio 0 9 GPIO_ACTIVE_HIGH>; + }; + + led-1 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + + led-2 { + function = LED_FUNCTION_WAN; + color = ; + gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>; + }; + }; + + r-gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; + }; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; + }; + + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_usb0_vbus: usb0-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb0-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&r_pio 0 2 GPIO_ACTIVE_HIGH>; /* PL2 */ + status = "okay"; + }; + + vdd_cpux: gpio-regulator { + compatible = "regulator-gpio"; + regulator-name = "vdd-cpux"; + regulator-type = "voltage"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1300000>; + regulator-ramp-delay = <50>; /* 4ms */ + gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; + gpios-states = <0x1>; + states = <1100000 0x0>, <1300000 0x1>; + }; + + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */ + post-power-on-delay-ms = <200>; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_cpux>; +}; + +&ehci1 { + status = "okay"; +}; + +&ehci2 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_rgmii_pins>; + phy-supply = <®_gmac_3v3>; + phy-handle = <&ext_rgmii_phy>; + phy-mode = "rgmii-id"; + status = "okay"; +}; + +&external_mdio { + ext_rgmii_phy: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + }; +}; + +&i2c0 { + status = "okay"; + + eeprom@51 { + compatible = "microchip,24c02"; + reg = <0x51>; + pagesize = <16>; + }; +}; + +&mmc0 { + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ + status = "okay"; +}; + +&mmc1 { + vmmc-supply = <®_vcc3v3>; + vqmmc-supply = <®_vcc3v3>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; + + rtl8189etv: sdio_wifi@1 { + reg = <1>; + }; +}; + +&ohci1 { + status = "okay"; +}; + +&ohci2 { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pa_pins>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "peripheral"; + status = "okay"; +}; + +&usbphy { + /* USB Type-A port's VBUS is always on */ + usb0_id_det-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */ + usb0_vbus-supply = <®_usb0_vbus>; + status = "okay"; +}; diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS index 2543c94de79..56a0ee3689b 100644 --- a/board/sunxi/MAINTAINERS +++ b/board/sunxi/MAINTAINERS @@ -358,6 +358,11 @@ M: Jelle van der Waa S: Maintained F: configs/nanopi_neo_air_defconfig +NANOPI-R1S-H5 BOARD +M: Chukun Pan +S: Maintained +F: configs/nanopi_r1s_h5_defconfig + NANOPI-A64 BOARD M: Jagan Teki S: Maintained diff --git a/configs/nanopi_r1s_h5_defconfig b/configs/nanopi_r1s_h5_defconfig new file mode 100644 index 00000000000..27cf172d72a --- /dev/null +++ b/configs/nanopi_r1s_h5_defconfig @@ -0,0 +1,14 @@ +CONFIG_ARM=y +CONFIG_ARCH_SUNXI=y +CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-nanopi-r1s-h5" +CONFIG_SPL=y +CONFIG_MACH_SUN50I_H5=y +CONFIG_DRAM_CLK=672 +CONFIG_DRAM_ZQ=3881977 +# CONFIG_DRAM_ODT_EN is not set +CONFIG_MACPWR="PD6" +CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SUN8I_EMAC=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y -- cgit v1.3.1 From ea261fdeb23d54ee17a5e5a95cf35f97180deb76 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 8 Oct 2021 00:17:17 -0500 Subject: sunxi: Only initialize legacy I2C when enabled CONFIG_SPL_I2C is the wrong symbol to use here. It is the top-level Kconfig symbol (not specific to either legacy or DM I2C), whereas the i2c_init() function is specific to legacy I2C. This change fixes a build failure when enabling SPL_I2C but not SPL_SYS_I2C_LEGACY. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-by: Andre Przywara --- arch/arm/mach-sunxi/board.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 373cb56db49..b4ba2a72c42 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -338,7 +338,7 @@ void board_init_f(ulong dummy) spl_init(); preloader_console_init(); -#ifdef CONFIG_SPL_I2C +#if CONFIG_IS_ENABLED(I2C) && CONFIG_IS_ENABLED(SYS_I2C_LEGACY) /* Needed early by sunxi_board_init if PMU is enabled */ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); #endif -- cgit v1.3.1 From abd2e783f15ce372e275eb66f732c4edbaf0c0b6 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 8 Oct 2021 00:17:18 -0500 Subject: sunxi: Select SUN8I_RSB more carefully SUN8I_RSB should not be selected by MACH_SUN8I, because the hardware is not present in half of those SoCs (H3/H5, R40, and V3s). Move the selection to the SoCs where the hardware actually exists. As it currently stands, selecting that option also requires using it in some way, which is not the case for one A80 board. Since we have only three A80 boards in total, we select it their via their defconfigs. Reviewed-by: Andre Przywara Signed-off-by: Samuel Holland [Andre: fixing up Sunchip_CX-A99 build] Signed-off-by: Andre Przywara --- arch/arm/mach-sunxi/Kconfig | 5 +++-- configs/Cubieboard4_defconfig | 1 + configs/Merrii_A80_Optimus_defconfig | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 7308f977a59..03054a331aa 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -260,6 +260,7 @@ config MACH_SUN8I_A23 select ARCH_SUPPORT_PSCI select DRAM_SUN8I_A23 select PHY_SUN4I_USB + select SUN8I_RSB select SUNXI_GEN_SUN6I select SUPPORT_SPL select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT @@ -273,6 +274,7 @@ config MACH_SUN8I_A33 select ARCH_SUPPORT_PSCI select DRAM_SUN8I_A33 select PHY_SUN4I_USB + select SUN8I_RSB select SUNXI_GEN_SUN6I select SUPPORT_SPL select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT @@ -283,6 +285,7 @@ config MACH_SUN8I_A83T select CPU_V7A select DRAM_SUN8I_A83T select PHY_SUN4I_USB + select SUN8I_RSB select SUNXI_GEN_SUN6I select MMC_SUNXI_HAS_NEW_MODE select MMC_SUNXI_HAS_MODE_SWITCH @@ -329,7 +332,6 @@ config MACH_SUN9I select DRAM_SUN9I select SUN6I_PRCM select SUNXI_GEN_SUN6I - select SUN8I_RSB select SUPPORT_SPL config MACH_SUN50I @@ -377,7 +379,6 @@ endchoice # The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 || A33" config MACH_SUN8I bool - select SUN8I_RSB select SUN6I_PRCM default y if MACH_SUN8I_A23 default y if MACH_SUN8I_A33 diff --git a/configs/Cubieboard4_defconfig b/configs/Cubieboard4_defconfig index c66f29e5da2..0377bb83da1 100644 --- a/configs/Cubieboard4_defconfig +++ b/configs/Cubieboard4_defconfig @@ -11,5 +11,6 @@ CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT" CONFIG_USB0_ID_DET="PH16" CONFIG_USB1_VBUS_PIN="PH14" CONFIG_USB3_VBUS_PIN="PH15" +CONFIG_SUN8I_RSB=y CONFIG_AXP_GPIO=y CONFIG_AXP809_POWER=y diff --git a/configs/Merrii_A80_Optimus_defconfig b/configs/Merrii_A80_Optimus_defconfig index 0944e649578..8fb65042099 100644 --- a/configs/Merrii_A80_Optimus_defconfig +++ b/configs/Merrii_A80_Optimus_defconfig @@ -11,5 +11,6 @@ CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT" CONFIG_USB0_ID_DET="PH3" CONFIG_USB1_VBUS_PIN="PH4" CONFIG_USB3_VBUS_PIN="PH5" +CONFIG_SUN8I_RSB=y CONFIG_AXP_GPIO=y CONFIG_AXP809_POWER=y -- cgit v1.3.1 From 4ab39e74b640799748dfdef49f099b416a5ae497 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 8 Oct 2021 00:17:19 -0500 Subject: sunxi: pmic_bus: Fix Kconfig dependencies AXP_PMIC_BUS enables communication with a specific AXP PMIC at a PMIC-dependent I2C/P2WI/RSB bus address. It is automatically selected as a dependency of the PMIC driver. It should not be selectable by the user when no PMIC is chosen. AXP_GPIO uses the pmic_bus functions, and also depends on a specific PMIC header to pick up register definitions. Both of these changes have no impact on any existing configs, since the code does not compile if the dependencies are not met. Reviewed-by: Jaehoon Chung Signed-off-by: Samuel Holland Signed-off-by: Andre Przywara --- arch/arm/mach-sunxi/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 03054a331aa..da35cc87e85 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -106,7 +106,7 @@ config SUN6I_PRCM in A31 SoC. config AXP_PMIC_BUS - bool "Sunxi AXP PMIC bus access helpers" + bool help Select this PMIC bus access helpers for Sunxi platform PRCM or other AXP family PMIC devices. @@ -795,6 +795,7 @@ endif config AXP_GPIO bool "Enable support for gpio-s on axp PMICs" + depends on AXP_PMIC_BUS ---help--- Say Y here to enable support for the gpio pins of the axp PMIC ICs. -- cgit v1.3.1 From 104950a7feae7926e40676f27cfbd279a43b4bc3 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 8 Oct 2021 00:17:20 -0500 Subject: i2c: Add a DM_I2C driver for the sun6i P2WI controller This bus controller is used to communicate with an X-Powers AXP PMIC. Currently, various drivers access PMIC registers through a platform- specific non-DM "pmic_bus" interface, which depends on the legacy I2C framework. In order to convert those drivers to use DM_PMIC, this bus needs a DM_I2C driver. Refactor the p2wi functions to take the base address as a parameter, and implement both the existing interface (which is still needed in SPL) and the DM_I2C interface on top of them. The register for switching between I2C/P2WI/RSB mode is the same across all PMIC variants. Move that to the common header, so it can be used by both interface implementations. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/mach-sunxi/Kconfig | 14 +-- arch/arm/mach-sunxi/Makefile | 1 - arch/arm/mach-sunxi/p2wi.c | 117 ---------------------- arch/arm/mach-sunxi/pmic_bus.c | 7 +- drivers/i2c/Kconfig | 8 ++ drivers/i2c/Makefile | 1 + drivers/i2c/sun6i_p2wi.c | 220 +++++++++++++++++++++++++++++++++++++++++ include/axp_pmic.h | 6 ++ 8 files changed, 240 insertions(+), 134 deletions(-) delete mode 100644 arch/arm/mach-sunxi/p2wi.c create mode 100644 drivers/i2c/sun6i_p2wi.c (limited to 'arch') diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index da35cc87e85..f4a45284bdc 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -88,17 +88,6 @@ config DRAM_SUN50I_H616_UNKNOWN_FEATURE feature. endif -config SUN6I_P2WI - bool "Allwinner sun6i internal P2WI controller" - help - If you say yes to this option, support will be included for the - P2WI (Push/Pull 2 Wire Interface) controller embedded in some sunxi - SOCs. - The P2WI looks like an SMBus controller (which supports only byte - accesses), except that it only supports one slave device. - This interface is used to connect to specific PMIC devices (like the - AXP221). - config SUN6I_PRCM bool help @@ -232,10 +221,11 @@ config MACH_SUN6I select ARCH_SUPPORT_PSCI select DRAM_SUN6I select PHY_SUN4I_USB - select SUN6I_P2WI + select SPL_I2C select SUN6I_PRCM select SUNXI_GEN_SUN6I select SUPPORT_SPL + select SYS_I2C_SUN6I_P2WI select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT config MACH_SUN7I diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile index 3f081d92f37..c9312bb3934 100644 --- a/arch/arm/mach-sunxi/Makefile +++ b/arch/arm/mach-sunxi/Makefile @@ -11,7 +11,6 @@ obj-y += clock.o obj-y += cpu_info.o obj-y += dram_helpers.o obj-y += pinmux.o -obj-$(CONFIG_SUN6I_P2WI) += p2wi.o obj-$(CONFIG_SUN6I_PRCM) += prcm.o obj-$(CONFIG_AXP_PMIC_BUS) += pmic_bus.o obj-$(CONFIG_SUN8I_RSB) += rsb.o diff --git a/arch/arm/mach-sunxi/p2wi.c b/arch/arm/mach-sunxi/p2wi.c deleted file mode 100644 index 7c5c12254ea..00000000000 --- a/arch/arm/mach-sunxi/p2wi.c +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Sunxi A31 Power Management Unit - * - * (C) Copyright 2013 Oliver Schinagl - * http://linux-sunxi.org - * - * Based on sun6i sources and earlier U-Boot Allwinner A10 SPL work - * - * (C) Copyright 2006-2013 - * Allwinner Technology Co., Ltd. - * Berg Xing - * Tom Cubie - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void p2wi_init(void) -{ - struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; - - /* Enable p2wi and PIO clk, and de-assert their resets */ - prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_P2WI); - - sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN6I_GPL0_R_P2WI_SCK); - sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN6I_GPL1_R_P2WI_SDA); - - /* Reset p2wi controller and set clock to CLKIN(12)/8 = 1.5 MHz */ - writel(P2WI_CTRL_RESET, &p2wi->ctrl); - sdelay(0x100); - writel(P2WI_CC_SDA_OUT_DELAY(1) | P2WI_CC_CLK_DIV(8), - &p2wi->cc); -} - -int p2wi_change_to_p2wi_mode(u8 slave_addr, u8 ctrl_reg, u8 init_data) -{ - struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; - unsigned long tmo = timer_get_us() + 1000000; - - writel(P2WI_PM_DEV_ADDR(slave_addr) | - P2WI_PM_CTRL_ADDR(ctrl_reg) | - P2WI_PM_INIT_DATA(init_data) | - P2WI_PM_INIT_SEND, - &p2wi->pm); - - while ((readl(&p2wi->pm) & P2WI_PM_INIT_SEND)) { - if (timer_get_us() > tmo) - return -ETIME; - } - - return 0; -} - -static int p2wi_await_trans(void) -{ - struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; - unsigned long tmo = timer_get_us() + 1000000; - int ret; - u8 reg; - - while (1) { - reg = readl(&p2wi->status); - if (reg & P2WI_STAT_TRANS_ERR) { - ret = -EIO; - break; - } - if (reg & P2WI_STAT_TRANS_DONE) { - ret = 0; - break; - } - if (timer_get_us() > tmo) { - ret = -ETIME; - break; - } - } - writel(reg, &p2wi->status); /* Clear status bits */ - return ret; -} - -int p2wi_read(const u8 addr, u8 *data) -{ - struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; - int ret; - - writel(P2WI_DATADDR_BYTE_1(addr), &p2wi->dataddr0); - writel(P2WI_DATA_NUM_BYTES(1) | - P2WI_DATA_NUM_BYTES_READ, &p2wi->numbytes); - writel(P2WI_STAT_TRANS_DONE, &p2wi->status); - writel(P2WI_CTRL_TRANS_START, &p2wi->ctrl); - - ret = p2wi_await_trans(); - - *data = readl(&p2wi->data0) & P2WI_DATA_BYTE_1_MASK; - return ret; -} - -int p2wi_write(const u8 addr, u8 data) -{ - struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; - - writel(P2WI_DATADDR_BYTE_1(addr), &p2wi->dataddr0); - writel(P2WI_DATA_BYTE_1(data), &p2wi->data0); - writel(P2WI_DATA_NUM_BYTES(1), &p2wi->numbytes); - writel(P2WI_STAT_TRANS_DONE, &p2wi->status); - writel(P2WI_CTRL_TRANS_START, &p2wi->ctrl); - - return p2wi_await_trans(); -} diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c index 0394ce85644..673a05fdd16 100644 --- a/arch/arm/mach-sunxi/pmic_bus.c +++ b/arch/arm/mach-sunxi/pmic_bus.c @@ -8,6 +8,7 @@ * axp223 uses the rsb bus, these functions abstract this. */ +#include #include #include #include @@ -21,8 +22,6 @@ #define AXP305_I2C_ADDR 0x36 #define AXP221_CHIP_ADDR 0x68 -#define AXP221_CTRL_ADDR 0x3e -#define AXP221_INIT_DATA 0x3e /* AXP818 device and runtime addresses are same as AXP223 */ #define AXP223_DEVICE_ADDR 0x3a3 @@ -40,8 +39,8 @@ int pmic_bus_init(void) #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER # ifdef CONFIG_MACH_SUN6I p2wi_init(); - ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR, - AXP221_INIT_DATA); + ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP_PMIC_MODE_REG, + AXP_PMIC_MODE_P2WI); # elif defined CONFIG_MACH_SUN8I_R40 /* Nothing. R40 uses the AXP221s in I2C mode */ ret = 0; diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 57cac4483f0..0adf143abfd 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -575,6 +575,14 @@ config SYS_I2C_STM32F7 _ Optional clock stretching _ Software reset +config SYS_I2C_SUN6I_P2WI + bool "Allwinner sun6i P2WI controller" + depends on ARCH_SUNXI + help + Support for the P2WI (Push/Pull 2 Wire Interface) controller embedded + in the Allwinner A31 and A31s SOCs. This interface is used to connect + to specific devices like the X-Powers AXP221 PMIC. + config SYS_I2C_SYNQUACER bool "Socionext SynQuacer I2C controller" depends on ARCH_SYNQUACER && DM_I2C diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 67841bf3e02..0a2cc641930 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o +obj-$(CONFIG_SYS_I2C_SUN6I_P2WI) += sun6i_p2wi.o obj-$(CONFIG_SYS_I2C_SYNQUACER) += synquacer_i2c.o obj-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o obj-$(CONFIG_SYS_I2C_UNIPHIER) += i2c-uniphier.o diff --git a/drivers/i2c/sun6i_p2wi.c b/drivers/i2c/sun6i_p2wi.c new file mode 100644 index 00000000000..c9e1b3fcd5f --- /dev/null +++ b/drivers/i2c/sun6i_p2wi.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Sunxi A31 Power Management Unit + * + * (C) Copyright 2013 Oliver Schinagl + * http://linux-sunxi.org + * + * Based on sun6i sources and earlier U-Boot Allwinner A10 SPL work + * + * (C) Copyright 2006-2013 + * Allwinner Technology Co., Ltd. + * Berg Xing + * Tom Cubie + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int sun6i_p2wi_await_trans(struct sunxi_p2wi_reg *base) +{ + unsigned long tmo = timer_get_us() + 1000000; + int ret; + u8 reg; + + while (1) { + reg = readl(&base->status); + if (reg & P2WI_STAT_TRANS_ERR) { + ret = -EIO; + break; + } + if (reg & P2WI_STAT_TRANS_DONE) { + ret = 0; + break; + } + if (timer_get_us() > tmo) { + ret = -ETIME; + break; + } + } + writel(reg, &base->status); /* Clear status bits */ + + return ret; +} + +static int sun6i_p2wi_read(struct sunxi_p2wi_reg *base, const u8 addr, u8 *data) +{ + int ret; + + writel(P2WI_DATADDR_BYTE_1(addr), &base->dataddr0); + writel(P2WI_DATA_NUM_BYTES(1) | + P2WI_DATA_NUM_BYTES_READ, &base->numbytes); + writel(P2WI_STAT_TRANS_DONE, &base->status); + writel(P2WI_CTRL_TRANS_START, &base->ctrl); + + ret = sun6i_p2wi_await_trans(base); + + *data = readl(&base->data0) & P2WI_DATA_BYTE_1_MASK; + + return ret; +} + +static int sun6i_p2wi_write(struct sunxi_p2wi_reg *base, const u8 addr, u8 data) +{ + writel(P2WI_DATADDR_BYTE_1(addr), &base->dataddr0); + writel(P2WI_DATA_BYTE_1(data), &base->data0); + writel(P2WI_DATA_NUM_BYTES(1), &base->numbytes); + writel(P2WI_STAT_TRANS_DONE, &base->status); + writel(P2WI_CTRL_TRANS_START, &base->ctrl); + + return sun6i_p2wi_await_trans(base); +} + +static int sun6i_p2wi_change_to_p2wi_mode(struct sunxi_p2wi_reg *base, + u8 slave_addr, u8 ctrl_reg, + u8 init_data) +{ + unsigned long tmo = timer_get_us() + 1000000; + + writel(P2WI_PM_DEV_ADDR(slave_addr) | + P2WI_PM_CTRL_ADDR(ctrl_reg) | + P2WI_PM_INIT_DATA(init_data) | + P2WI_PM_INIT_SEND, + &base->pm); + + while ((readl(&base->pm) & P2WI_PM_INIT_SEND)) { + if (timer_get_us() > tmo) + return -ETIME; + } + + return 0; +} + +static void sun6i_p2wi_init(struct sunxi_p2wi_reg *base) +{ + /* Enable p2wi and PIO clk, and de-assert their resets */ + prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_P2WI); + + sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN6I_GPL0_R_P2WI_SCK); + sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN6I_GPL1_R_P2WI_SDA); + + /* Reset p2wi controller and set clock to CLKIN(12)/8 = 1.5 MHz */ + writel(P2WI_CTRL_RESET, &base->ctrl); + sdelay(0x100); + writel(P2WI_CC_SDA_OUT_DELAY(1) | P2WI_CC_CLK_DIV(8), + &base->cc); +} + +#if IS_ENABLED(CONFIG_AXP_PMIC_BUS) +int p2wi_read(const u8 addr, u8 *data) +{ + struct sunxi_p2wi_reg *base = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; + + return sun6i_p2wi_read(base, addr, data); +} + +int p2wi_write(const u8 addr, u8 data) +{ + struct sunxi_p2wi_reg *base = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; + + return sun6i_p2wi_write(base, addr, data); +} + +int p2wi_change_to_p2wi_mode(u8 slave_addr, u8 ctrl_reg, u8 init_data) +{ + struct sunxi_p2wi_reg *base = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; + + return sun6i_p2wi_change_to_p2wi_mode(base, slave_addr, ctrl_reg, + init_data); +} + +void p2wi_init(void) +{ + struct sunxi_p2wi_reg *base = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; + + sun6i_p2wi_init(base); +} +#endif + +#if CONFIG_IS_ENABLED(DM_I2C) +struct sun6i_p2wi_priv { + struct sunxi_p2wi_reg *base; +}; + +static int sun6i_p2wi_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) +{ + struct sun6i_p2wi_priv *priv = dev_get_priv(bus); + + /* The hardware only supports SMBus-style transfers. */ + if (nmsgs == 2 && msg[1].flags == I2C_M_RD && msg[1].len == 1) + return sun6i_p2wi_read(priv->base, + msg[0].buf[0], &msg[1].buf[0]); + + if (nmsgs == 1 && msg[0].len == 2) + return sun6i_p2wi_write(priv->base, + msg[0].buf[0], msg[0].buf[1]); + + return -EINVAL; +} + +static int sun6i_p2wi_probe_chip(struct udevice *bus, uint chip_addr, + uint chip_flags) +{ + struct sun6i_p2wi_priv *priv = dev_get_priv(bus); + + return sun6i_p2wi_change_to_p2wi_mode(priv->base, chip_addr, + AXP_PMIC_MODE_REG, + AXP_PMIC_MODE_P2WI); +} + +static int sun6i_p2wi_probe(struct udevice *bus) +{ + struct sun6i_p2wi_priv *priv = dev_get_priv(bus); + + priv->base = dev_read_addr_ptr(bus); + + sun6i_p2wi_init(priv->base); + + return 0; +} + +static int sun6i_p2wi_child_pre_probe(struct udevice *child) +{ + struct dm_i2c_chip *chip = dev_get_parent_plat(child); + + /* Ensure each transfer is for a single register. */ + chip->flags |= DM_I2C_CHIP_RD_ADDRESS | DM_I2C_CHIP_WR_ADDRESS; + + return 0; +} + +static const struct dm_i2c_ops sun6i_p2wi_ops = { + .xfer = sun6i_p2wi_xfer, + .probe_chip = sun6i_p2wi_probe_chip, +}; + +static const struct udevice_id sun6i_p2wi_ids[] = { + { .compatible = "allwinner,sun6i-a31-p2wi" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sun6i_p2wi) = { + .name = "sun6i_p2wi", + .id = UCLASS_I2C, + .of_match = sun6i_p2wi_ids, + .probe = sun6i_p2wi_probe, + .child_pre_probe = sun6i_p2wi_child_pre_probe, + .priv_auto = sizeof(struct sun6i_p2wi_priv), + .ops = &sun6i_p2wi_ops, +}; +#endif /* CONFIG_IS_ENABLED(DM_I2C) */ diff --git a/include/axp_pmic.h b/include/axp_pmic.h index 405044c3a32..0db3e143eda 100644 --- a/include/axp_pmic.h +++ b/include/axp_pmic.h @@ -6,6 +6,8 @@ */ #ifndef _AXP_PMIC_H_ +#include + #ifdef CONFIG_AXP152_POWER #include #endif @@ -25,6 +27,10 @@ #include #endif +#define AXP_PMIC_MODE_REG 0x3e +#define AXP_PMIC_MODE_I2C 0x00 +#define AXP_PMIC_MODE_P2WI 0x3e + int axp_set_dcdc1(unsigned int mvolt); int axp_set_dcdc2(unsigned int mvolt); int axp_set_dcdc3(unsigned int mvolt); -- cgit v1.3.1 From 3227c85fe76312290c3ec15a02dcba3f9c6bc399 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 8 Oct 2021 00:17:21 -0500 Subject: i2c: Add a DM_I2C driver for the sun8i RSB controller This bus controller is used to communicate with an X-Powers AXP PMIC. Currently, various drivers access PMIC registers through a platform- specific non-DM "pmic_bus" interface, which depends on the legacy I2C framework. In order to convert those drivers to use DM_PMIC, this bus needs a DM_I2C driver. Refactor the rsb functions to take the base address as a parameter, and implement both the existing interface (which is still needed in SPL) and the DM_I2C interface on top of them. The register for switching between I2C/P2WI/RSB mode is the same across all PMIC variants, so move that to the common header. There are only a couple of pairs of hardware/runtime addresses used across all PMIC variants. So far the code expected only the "primary" pair, but some PMICs like the AXP305 and AXP805 use the secondary pair, so add support for that to the DM driver as well. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/mach-sunxi/Kconfig | 18 +-- arch/arm/mach-sunxi/Makefile | 1 - arch/arm/mach-sunxi/pmic_bus.c | 11 +- arch/arm/mach-sunxi/rsb.c | 175 ---------------------- configs/Cubieboard4_defconfig | 2 +- configs/Merrii_A80_Optimus_defconfig | 2 +- drivers/i2c/Kconfig | 8 + drivers/i2c/Makefile | 1 + drivers/i2c/sun8i_rsb.c | 281 +++++++++++++++++++++++++++++++++++ include/axp_pmic.h | 6 + 10 files changed, 309 insertions(+), 196 deletions(-) delete mode 100644 arch/arm/mach-sunxi/rsb.c create mode 100644 drivers/i2c/sun8i_rsb.c (limited to 'arch') diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index f4a45284bdc..10401d3249a 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -100,14 +100,6 @@ config AXP_PMIC_BUS Select this PMIC bus access helpers for Sunxi platform PRCM or other AXP family PMIC devices. -config SUN8I_RSB - bool "Allwinner sunXi Reduced Serial Bus Driver" - help - Say y here to enable support for Allwinner's Reduced Serial Bus - (RSB) support. This controller is responsible for communicating - with various RSB based devices, such as AXP223, AXP8XX PMICs, - and AC100/AC200 ICs. - config SUNXI_SRAM_ADDRESS hex default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5 @@ -250,9 +242,10 @@ config MACH_SUN8I_A23 select ARCH_SUPPORT_PSCI select DRAM_SUN8I_A23 select PHY_SUN4I_USB - select SUN8I_RSB + select SPL_I2C select SUNXI_GEN_SUN6I select SUPPORT_SPL + select SYS_I2C_SUN8I_RSB select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT imply CONS_INDEX_5 if !DM_SERIAL @@ -264,9 +257,10 @@ config MACH_SUN8I_A33 select ARCH_SUPPORT_PSCI select DRAM_SUN8I_A33 select PHY_SUN4I_USB - select SUN8I_RSB + select SPL_I2C select SUNXI_GEN_SUN6I select SUPPORT_SPL + select SYS_I2C_SUN8I_RSB select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT imply CONS_INDEX_5 if !DM_SERIAL @@ -275,11 +269,12 @@ config MACH_SUN8I_A83T select CPU_V7A select DRAM_SUN8I_A83T select PHY_SUN4I_USB - select SUN8I_RSB + select SPL_I2C select SUNXI_GEN_SUN6I select MMC_SUNXI_HAS_NEW_MODE select MMC_SUNXI_HAS_MODE_SWITCH select SUPPORT_SPL + select SYS_I2C_SUN8I_RSB config MACH_SUN8I_H3 bool "sun8i (Allwinner H3)" @@ -320,6 +315,7 @@ config MACH_SUN9I bool "sun9i (Allwinner A80)" select CPU_V7A select DRAM_SUN9I + select SPL_I2C select SUN6I_PRCM select SUNXI_GEN_SUN6I select SUPPORT_SPL diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile index c9312bb3934..5d3fd70f749 100644 --- a/arch/arm/mach-sunxi/Makefile +++ b/arch/arm/mach-sunxi/Makefile @@ -13,7 +13,6 @@ obj-y += dram_helpers.o obj-y += pinmux.o obj-$(CONFIG_SUN6I_PRCM) += prcm.o obj-$(CONFIG_AXP_PMIC_BUS) += pmic_bus.o -obj-$(CONFIG_SUN8I_RSB) += rsb.o obj-$(CONFIG_MACH_SUN4I) += clock_sun4i.o obj-$(CONFIG_MACH_SUN5I) += clock_sun4i.o obj-$(CONFIG_MACH_SUN6I) += clock_sun6i.o diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c index 673a05fdd16..827797249ea 100644 --- a/arch/arm/mach-sunxi/pmic_bus.c +++ b/arch/arm/mach-sunxi/pmic_bus.c @@ -23,10 +23,6 @@ #define AXP221_CHIP_ADDR 0x68 -/* AXP818 device and runtime addresses are same as AXP223 */ -#define AXP223_DEVICE_ADDR 0x3a3 -#define AXP223_RUNTIME_ADDR 0x2d - int pmic_bus_init(void) { /* This cannot be 0 because it is used in SPL before BSS is ready */ @@ -49,7 +45,8 @@ int pmic_bus_init(void) if (ret) return ret; - ret = rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR); + ret = rsb_set_device_address(AXP_PMIC_PRI_DEVICE_ADDR, + AXP_PMIC_PRI_RUNTIME_ADDR); # endif if (ret) return ret; @@ -73,7 +70,7 @@ int pmic_bus_read(u8 reg, u8 *data) # elif defined CONFIG_MACH_SUN8I_R40 return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1); # else - return rsb_read(AXP223_RUNTIME_ADDR, reg, data); + return rsb_read(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data); # endif #endif } @@ -92,7 +89,7 @@ int pmic_bus_write(u8 reg, u8 data) # elif defined CONFIG_MACH_SUN8I_R40 return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1); # else - return rsb_write(AXP223_RUNTIME_ADDR, reg, data); + return rsb_write(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data); # endif #endif } diff --git a/arch/arm/mach-sunxi/rsb.c b/arch/arm/mach-sunxi/rsb.c deleted file mode 100644 index 01bb09b7478..00000000000 --- a/arch/arm/mach-sunxi/rsb.c +++ /dev/null @@ -1,175 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2014 Hans de Goede - * - * Based on allwinner u-boot sources rsb code which is: - * (C) Copyright 2007-2013 - * Allwinner Technology Co., Ltd. - * lixiang - */ - -#include -#include -#include -#include -#include -#include -#include - -static int rsb_set_device_mode(void); - -static void rsb_cfg_io(void) -{ -#ifdef CONFIG_MACH_SUN8I - sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL_R_RSB); - sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL_R_RSB); - sunxi_gpio_set_pull(SUNXI_GPL(0), 1); - sunxi_gpio_set_pull(SUNXI_GPL(1), 1); - sunxi_gpio_set_drv(SUNXI_GPL(0), 2); - sunxi_gpio_set_drv(SUNXI_GPL(1), 2); -#elif defined CONFIG_MACH_SUN9I - sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN_R_RSB); - sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN_R_RSB); - sunxi_gpio_set_pull(SUNXI_GPN(0), 1); - sunxi_gpio_set_pull(SUNXI_GPN(1), 1); - sunxi_gpio_set_drv(SUNXI_GPN(0), 2); - sunxi_gpio_set_drv(SUNXI_GPN(1), 2); -#else -#error unsupported MACH_SUNXI -#endif -} - -static void rsb_set_clk(void) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - u32 div = 0; - u32 cd_odly = 0; - - /* Source is Hosc24M, set RSB clk to 3Mhz */ - div = 24000000 / 3000000 / 2 - 1; - cd_odly = div >> 1; - if (!cd_odly) - cd_odly = 1; - - writel((cd_odly << 8) | div, &rsb->ccr); -} - -int rsb_init(void) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - - /* Enable RSB and PIO clk, and de-assert their resets */ - prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB); - - /* Setup external pins */ - rsb_cfg_io(); - - writel(RSB_CTRL_SOFT_RST, &rsb->ctrl); - rsb_set_clk(); - - return rsb_set_device_mode(); -} - -static int rsb_await_trans(void) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - unsigned long tmo = timer_get_us() + 1000000; - u32 stat; - int ret; - - while (1) { - stat = readl(&rsb->stat); - if (stat & RSB_STAT_LBSY_INT) { - ret = -EBUSY; - break; - } - if (stat & RSB_STAT_TERR_INT) { - ret = -EIO; - break; - } - if (stat & RSB_STAT_TOVER_INT) { - ret = 0; - break; - } - if (timer_get_us() > tmo) { - ret = -ETIME; - break; - } - } - writel(stat, &rsb->stat); /* Clear status bits */ - - return ret; -} - -static int rsb_set_device_mode(void) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - unsigned long tmo = timer_get_us() + 1000000; - - writel(RSB_DMCR_DEVICE_MODE_START | RSB_DMCR_DEVICE_MODE_DATA, - &rsb->dmcr); - - while (readl(&rsb->dmcr) & RSB_DMCR_DEVICE_MODE_START) { - if (timer_get_us() > tmo) - return -ETIME; - } - - return rsb_await_trans(); -} - -static int rsb_do_trans(void) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - - setbits_le32(&rsb->ctrl, RSB_CTRL_START_TRANS); - return rsb_await_trans(); -} - -int rsb_set_device_address(u16 device_addr, u16 runtime_addr) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - - writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr) | - RSB_DEVADDR_DEVICE_ADDR(device_addr), &rsb->devaddr); - writel(RSB_CMD_SET_RTSADDR, &rsb->cmd); - - return rsb_do_trans(); -} - -int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - - writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr); - writel(reg_addr, &rsb->addr); - writel(data, &rsb->data); - writel(RSB_CMD_BYTE_WRITE, &rsb->cmd); - - return rsb_do_trans(); -} - -int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - int ret; - - writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr); - writel(reg_addr, &rsb->addr); - writel(RSB_CMD_BYTE_READ, &rsb->cmd); - - ret = rsb_do_trans(); - if (ret) - return ret; - - *data = readl(&rsb->data) & 0xff; - - return 0; -} diff --git a/configs/Cubieboard4_defconfig b/configs/Cubieboard4_defconfig index 0377bb83da1..3848cab4b68 100644 --- a/configs/Cubieboard4_defconfig +++ b/configs/Cubieboard4_defconfig @@ -11,6 +11,6 @@ CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT" CONFIG_USB0_ID_DET="PH16" CONFIG_USB1_VBUS_PIN="PH14" CONFIG_USB3_VBUS_PIN="PH15" -CONFIG_SUN8I_RSB=y +CONFIG_SYS_I2C_SUN8I_RSB=y CONFIG_AXP_GPIO=y CONFIG_AXP809_POWER=y diff --git a/configs/Merrii_A80_Optimus_defconfig b/configs/Merrii_A80_Optimus_defconfig index 8fb65042099..35e575327f4 100644 --- a/configs/Merrii_A80_Optimus_defconfig +++ b/configs/Merrii_A80_Optimus_defconfig @@ -11,6 +11,6 @@ CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT" CONFIG_USB0_ID_DET="PH3" CONFIG_USB1_VBUS_PIN="PH4" CONFIG_USB3_VBUS_PIN="PH5" -CONFIG_SUN8I_RSB=y +CONFIG_SYS_I2C_SUN8I_RSB=y CONFIG_AXP_GPIO=y CONFIG_AXP809_POWER=y diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 0adf143abfd..66bd6fe2f34 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -583,6 +583,14 @@ config SYS_I2C_SUN6I_P2WI in the Allwinner A31 and A31s SOCs. This interface is used to connect to specific devices like the X-Powers AXP221 PMIC. +config SYS_I2C_SUN8I_RSB + bool "Allwinner sun8i Reduced Serial Bus controller" + depends on ARCH_SUNXI + help + Support for Allwinner's Reduced Serial Bus (RSB) controller. This + controller is responsible for communicating with various RSB based + devices, such as X-Powers AXPxxx PMICs and AC100/AC200 CODEC ICs. + config SYS_I2C_SYNQUACER bool "Socionext SynQuacer I2C controller" depends on ARCH_SYNQUACER && DM_I2C diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 0a2cc641930..916427452a5 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o obj-$(CONFIG_SYS_I2C_SUN6I_P2WI) += sun6i_p2wi.o +obj-$(CONFIG_SYS_I2C_SUN8I_RSB) += sun8i_rsb.o obj-$(CONFIG_SYS_I2C_SYNQUACER) += synquacer_i2c.o obj-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o obj-$(CONFIG_SYS_I2C_UNIPHIER) += i2c-uniphier.o diff --git a/drivers/i2c/sun8i_rsb.c b/drivers/i2c/sun8i_rsb.c new file mode 100644 index 00000000000..716b245a003 --- /dev/null +++ b/drivers/i2c/sun8i_rsb.c @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2014 Hans de Goede + * + * Based on allwinner u-boot sources rsb code which is: + * (C) Copyright 2007-2013 + * Allwinner Technology Co., Ltd. + * lixiang + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int sun8i_rsb_await_trans(struct sunxi_rsb_reg *base) +{ + unsigned long tmo = timer_get_us() + 1000000; + u32 stat; + int ret; + + while (1) { + stat = readl(&base->stat); + if (stat & RSB_STAT_LBSY_INT) { + ret = -EBUSY; + break; + } + if (stat & RSB_STAT_TERR_INT) { + ret = -EIO; + break; + } + if (stat & RSB_STAT_TOVER_INT) { + ret = 0; + break; + } + if (timer_get_us() > tmo) { + ret = -ETIME; + break; + } + } + writel(stat, &base->stat); /* Clear status bits */ + + return ret; +} + +static int sun8i_rsb_do_trans(struct sunxi_rsb_reg *base) +{ + setbits_le32(&base->ctrl, RSB_CTRL_START_TRANS); + + return sun8i_rsb_await_trans(base); +} + +static int sun8i_rsb_read(struct sunxi_rsb_reg *base, u16 runtime_addr, + u8 reg_addr, u8 *data) +{ + int ret; + + writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr), &base->devaddr); + writel(reg_addr, &base->addr); + writel(RSB_CMD_BYTE_READ, &base->cmd); + + ret = sun8i_rsb_do_trans(base); + if (ret) + return ret; + + *data = readl(&base->data) & 0xff; + + return 0; +} + +static int sun8i_rsb_write(struct sunxi_rsb_reg *base, u16 runtime_addr, + u8 reg_addr, u8 data) +{ + writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr), &base->devaddr); + writel(reg_addr, &base->addr); + writel(data, &base->data); + writel(RSB_CMD_BYTE_WRITE, &base->cmd); + + return sun8i_rsb_do_trans(base); +} + +static int sun8i_rsb_set_device_address(struct sunxi_rsb_reg *base, + u16 device_addr, u16 runtime_addr) +{ + writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr) | + RSB_DEVADDR_DEVICE_ADDR(device_addr), &base->devaddr); + writel(RSB_CMD_SET_RTSADDR, &base->cmd); + + return sun8i_rsb_do_trans(base); +} + +static void sun8i_rsb_cfg_io(void) +{ +#ifdef CONFIG_MACH_SUN8I + sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL_R_RSB); + sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL_R_RSB); + sunxi_gpio_set_pull(SUNXI_GPL(0), 1); + sunxi_gpio_set_pull(SUNXI_GPL(1), 1); + sunxi_gpio_set_drv(SUNXI_GPL(0), 2); + sunxi_gpio_set_drv(SUNXI_GPL(1), 2); +#elif defined CONFIG_MACH_SUN9I + sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN_R_RSB); + sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN_R_RSB); + sunxi_gpio_set_pull(SUNXI_GPN(0), 1); + sunxi_gpio_set_pull(SUNXI_GPN(1), 1); + sunxi_gpio_set_drv(SUNXI_GPN(0), 2); + sunxi_gpio_set_drv(SUNXI_GPN(1), 2); +#else +#error unsupported MACH_SUNXI +#endif +} + +static void sun8i_rsb_set_clk(struct sunxi_rsb_reg *base) +{ + u32 div = 0; + u32 cd_odly = 0; + + /* Source is Hosc24M, set RSB clk to 3Mhz */ + div = 24000000 / 3000000 / 2 - 1; + cd_odly = div >> 1; + if (!cd_odly) + cd_odly = 1; + + writel((cd_odly << 8) | div, &base->ccr); +} + +static int sun8i_rsb_set_device_mode(struct sunxi_rsb_reg *base) +{ + unsigned long tmo = timer_get_us() + 1000000; + + writel(RSB_DMCR_DEVICE_MODE_START | RSB_DMCR_DEVICE_MODE_DATA, + &base->dmcr); + + while (readl(&base->dmcr) & RSB_DMCR_DEVICE_MODE_START) { + if (timer_get_us() > tmo) + return -ETIME; + } + + return sun8i_rsb_await_trans(base); +} + +static int sun8i_rsb_init(struct sunxi_rsb_reg *base) +{ + /* Enable RSB and PIO clk, and de-assert their resets */ + prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB); + + /* Setup external pins */ + sun8i_rsb_cfg_io(); + + writel(RSB_CTRL_SOFT_RST, &base->ctrl); + sun8i_rsb_set_clk(base); + + return sun8i_rsb_set_device_mode(base); +} + +#if IS_ENABLED(CONFIG_AXP_PMIC_BUS) +int rsb_read(const u16 runtime_addr, const u8 reg_addr, u8 *data) +{ + struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; + + return sun8i_rsb_read(base, runtime_addr, reg_addr, data); +} + +int rsb_write(const u16 runtime_addr, const u8 reg_addr, u8 data) +{ + struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; + + return sun8i_rsb_write(base, runtime_addr, reg_addr, data); +} + +int rsb_set_device_address(u16 device_addr, u16 runtime_addr) +{ + struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; + + return sun8i_rsb_set_device_address(base, device_addr, runtime_addr); +} + +int rsb_init(void) +{ + struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; + + return sun8i_rsb_init(base); +} +#endif + +#if CONFIG_IS_ENABLED(DM_I2C) +struct sun8i_rsb_priv { + struct sunxi_rsb_reg *base; +}; + +/* + * The mapping from hardware address to runtime address is fixed, and shared + * among all RSB drivers. See the comment in drivers/bus/sunxi-rsb.c in Linux. + */ +static int sun8i_rsb_get_runtime_address(u16 device_addr) +{ + if (device_addr == AXP_PMIC_PRI_DEVICE_ADDR) + return AXP_PMIC_PRI_RUNTIME_ADDR; + if (device_addr == AXP_PMIC_SEC_DEVICE_ADDR) + return AXP_PMIC_SEC_RUNTIME_ADDR; + + return -ENXIO; +} + +static int sun8i_rsb_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) +{ + int runtime_addr = sun8i_rsb_get_runtime_address(msg->addr); + struct sun8i_rsb_priv *priv = dev_get_priv(bus); + + if (runtime_addr < 0) + return runtime_addr; + + /* The hardware only supports SMBus-style transfers. */ + if (nmsgs == 2 && msg[1].flags == I2C_M_RD && msg[1].len == 1) + return sun8i_rsb_read(priv->base, runtime_addr, + msg[0].buf[0], &msg[1].buf[0]); + + if (nmsgs == 1 && msg[0].len == 2) + return sun8i_rsb_write(priv->base, runtime_addr, + msg[0].buf[0], msg[0].buf[1]); + + return -EINVAL; +} + +static int sun8i_rsb_probe_chip(struct udevice *bus, uint chip_addr, + uint chip_flags) +{ + int runtime_addr = sun8i_rsb_get_runtime_address(chip_addr); + struct sun8i_rsb_priv *priv = dev_get_priv(bus); + + if (runtime_addr < 0) + return runtime_addr; + + return sun8i_rsb_set_device_address(priv->base, chip_addr, runtime_addr); +} + +static int sun8i_rsb_probe(struct udevice *bus) +{ + struct sun8i_rsb_priv *priv = dev_get_priv(bus); + + priv->base = dev_read_addr_ptr(bus); + + return sun8i_rsb_init(priv->base); +} + +static int sun8i_rsb_child_pre_probe(struct udevice *child) +{ + struct dm_i2c_chip *chip = dev_get_parent_plat(child); + + /* Ensure each transfer is for a single register. */ + chip->flags |= DM_I2C_CHIP_RD_ADDRESS | DM_I2C_CHIP_WR_ADDRESS; + + return 0; +} + +static const struct dm_i2c_ops sun8i_rsb_ops = { + .xfer = sun8i_rsb_xfer, + .probe_chip = sun8i_rsb_probe_chip, +}; + +static const struct udevice_id sun8i_rsb_ids[] = { + { .compatible = "allwinner,sun8i-a23-rsb" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sun8i_rsb) = { + .name = "sun8i_rsb", + .id = UCLASS_I2C, + .of_match = sun8i_rsb_ids, + .probe = sun8i_rsb_probe, + .child_pre_probe = sun8i_rsb_child_pre_probe, + .priv_auto = sizeof(struct sun8i_rsb_priv), + .ops = &sun8i_rsb_ops, +}; +#endif /* CONFIG_IS_ENABLED(DM_I2C) */ diff --git a/include/axp_pmic.h b/include/axp_pmic.h index 0db3e143eda..46a017d2efa 100644 --- a/include/axp_pmic.h +++ b/include/axp_pmic.h @@ -30,6 +30,12 @@ #define AXP_PMIC_MODE_REG 0x3e #define AXP_PMIC_MODE_I2C 0x00 #define AXP_PMIC_MODE_P2WI 0x3e +#define AXP_PMIC_MODE_RSB 0x7c + +#define AXP_PMIC_PRI_DEVICE_ADDR 0x3a3 +#define AXP_PMIC_PRI_RUNTIME_ADDR 0x2d +#define AXP_PMIC_SEC_DEVICE_ADDR 0x745 +#define AXP_PMIC_SEC_RUNTIME_ADDR 0x3a int axp_set_dcdc1(unsigned int mvolt); int axp_set_dcdc2(unsigned int mvolt); -- cgit v1.3.1 From d3b02987cb6126650ff5077ccaba1e4e1ba76d6c Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 8 Oct 2021 00:17:22 -0500 Subject: sunxi: pmic_bus: Clean up preprocessor conditions Instead of using the SoC symbols to decide the bus type, use whichever bus driver is actually enabled. This allows collapsing all of the AXP2xx and AXP8xx variants into one "else" case. It also has the advantage of falling back to I2C when the other bus drivers are disabled; this works because all of the PMICs support I2C in addition to other interfaces. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/mach-sunxi/pmic_bus.c | 90 ++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 51 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c index 827797249ea..20ded436cd2 100644 --- a/arch/arm/mach-sunxi/pmic_bus.c +++ b/arch/arm/mach-sunxi/pmic_bus.c @@ -23,75 +23,63 @@ #define AXP221_CHIP_ADDR 0x68 +static int pmic_i2c_address(void) +{ + if (IS_ENABLED(CONFIG_AXP152_POWER)) + return AXP152_I2C_ADDR; + if (IS_ENABLED(CONFIG_AXP305_POWER)) + return AXP305_I2C_ADDR; + + /* Other AXP2xx and AXP8xx variants */ + return AXP209_I2C_ADDR; +} + int pmic_bus_init(void) { /* This cannot be 0 because it is used in SPL before BSS is ready */ static int needs_init = 1; - __maybe_unused int ret; + int ret = 0; if (!needs_init) return 0; -#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER -# ifdef CONFIG_MACH_SUN6I - p2wi_init(); - ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP_PMIC_MODE_REG, - AXP_PMIC_MODE_P2WI); -# elif defined CONFIG_MACH_SUN8I_R40 - /* Nothing. R40 uses the AXP221s in I2C mode */ - ret = 0; -# else - ret = rsb_init(); - if (ret) - return ret; + if (IS_ENABLED(CONFIG_SYS_I2C_SUN6I_P2WI)) { + p2wi_init(); + ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, + AXP_PMIC_MODE_REG, + AXP_PMIC_MODE_P2WI); + } else if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB)) { + ret = rsb_init(); + if (ret) + return ret; - ret = rsb_set_device_address(AXP_PMIC_PRI_DEVICE_ADDR, - AXP_PMIC_PRI_RUNTIME_ADDR); -# endif - if (ret) - return ret; -#endif + ret = rsb_set_device_address(AXP_PMIC_PRI_DEVICE_ADDR, + AXP_PMIC_PRI_RUNTIME_ADDR); + } + + needs_init = ret; - needs_init = 0; - return 0; + return ret; } int pmic_bus_read(u8 reg, u8 *data) { -#ifdef CONFIG_AXP152_POWER - return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1); -#elif defined CONFIG_AXP209_POWER - return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1); -#elif defined CONFIG_AXP305_POWER - return i2c_read(AXP305_I2C_ADDR, reg, 1, data, 1); -#elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER -# ifdef CONFIG_MACH_SUN6I - return p2wi_read(reg, data); -# elif defined CONFIG_MACH_SUN8I_R40 - return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1); -# else - return rsb_read(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data); -# endif -#endif + if (IS_ENABLED(CONFIG_SYS_I2C_SUN6I_P2WI)) + return p2wi_read(reg, data); + if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB)) + return rsb_read(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data); + + return i2c_read(pmic_i2c_address(), reg, 1, data, 1); } int pmic_bus_write(u8 reg, u8 data) { -#ifdef CONFIG_AXP152_POWER - return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1); -#elif defined CONFIG_AXP209_POWER - return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1); -#elif defined CONFIG_AXP305_POWER - return i2c_write(AXP305_I2C_ADDR, reg, 1, &data, 1); -#elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER -# ifdef CONFIG_MACH_SUN6I - return p2wi_write(reg, data); -# elif defined CONFIG_MACH_SUN8I_R40 - return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1); -# else - return rsb_write(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data); -# endif -#endif + if (IS_ENABLED(CONFIG_SYS_I2C_SUN6I_P2WI)) + return p2wi_write(reg, data); + if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB)) + return rsb_write(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data); + + return i2c_write(pmic_i2c_address(), reg, 1, &data, 1); } int pmic_bus_setbits(u8 reg, u8 bits) -- cgit v1.3.1 From 8b0eacdf2b0d472d991c3af4a236ad02759fc59e Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 8 Oct 2021 00:17:23 -0500 Subject: sunxi: pmic_bus: Use the DM PMIC interface when possible The pmic_bus functions are used in both SPL (for regulator setup) and U-Boot proper (for regulator setup, SID access, GPIO, and poweroff). Currently, pmic_bus conflicts with DM_I2C because it uses the legacy I2C interface. This commit makes pmic_bus dual-compatible with either the legacy I2C functions or the newly-added PMIC_AXP driver (which uses DM_I2C). In turn, this allows platforms to start transitioning to DM_I2C in U-Boot proper, without breaking boards that still depend on the legacy I2C interface for other reasons. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/mach-sunxi/Kconfig | 2 ++ arch/arm/mach-sunxi/pmic_bus.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 10401d3249a..83f8f9513f6 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -96,6 +96,8 @@ config SUN6I_PRCM config AXP_PMIC_BUS bool + select DM_PMIC if DM_I2C + select PMIC_AXP if DM_I2C help Select this PMIC bus access helpers for Sunxi platform PRCM or other AXP family PMIC devices. diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c index 20ded436cd2..c0908406370 100644 --- a/arch/arm/mach-sunxi/pmic_bus.c +++ b/arch/arm/mach-sunxi/pmic_bus.c @@ -10,9 +10,11 @@ #include #include +#include #include #include #include +#include #include #define AXP152_I2C_ADDR 0x30 @@ -23,6 +25,9 @@ #define AXP221_CHIP_ADDR 0x68 +#if CONFIG_IS_ENABLED(PMIC_AXP) +static struct udevice *pmic; +#else static int pmic_i2c_address(void) { if (IS_ENABLED(CONFIG_AXP152_POWER)) @@ -33,6 +38,7 @@ static int pmic_i2c_address(void) /* Other AXP2xx and AXP8xx variants */ return AXP209_I2C_ADDR; } +#endif int pmic_bus_init(void) { @@ -43,6 +49,10 @@ int pmic_bus_init(void) if (!needs_init) return 0; +#if CONFIG_IS_ENABLED(PMIC_AXP) + ret = uclass_get_device_by_driver(UCLASS_PMIC, DM_DRIVER_GET(axp_pmic), + &pmic); +#else if (IS_ENABLED(CONFIG_SYS_I2C_SUN6I_P2WI)) { p2wi_init(); ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, @@ -56,6 +66,7 @@ int pmic_bus_init(void) ret = rsb_set_device_address(AXP_PMIC_PRI_DEVICE_ADDR, AXP_PMIC_PRI_RUNTIME_ADDR); } +#endif needs_init = ret; @@ -64,22 +75,30 @@ int pmic_bus_init(void) int pmic_bus_read(u8 reg, u8 *data) { +#if CONFIG_IS_ENABLED(PMIC_AXP) + return pmic_read(pmic, reg, data, 1); +#else if (IS_ENABLED(CONFIG_SYS_I2C_SUN6I_P2WI)) return p2wi_read(reg, data); if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB)) return rsb_read(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data); return i2c_read(pmic_i2c_address(), reg, 1, data, 1); +#endif } int pmic_bus_write(u8 reg, u8 data) { +#if CONFIG_IS_ENABLED(PMIC_AXP) + return pmic_write(pmic, reg, &data, 1); +#else if (IS_ENABLED(CONFIG_SYS_I2C_SUN6I_P2WI)) return p2wi_write(reg, data); if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB)) return rsb_write(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data); return i2c_write(pmic_i2c_address(), reg, 1, &data, 1); +#endif } int pmic_bus_setbits(u8 reg, u8 bits) -- cgit v1.3.1 From 2421497cb78b7647ff7592acda3d444caa120f01 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 8 Oct 2021 00:17:24 -0500 Subject: sunxi: video: Convert panel I2C to use DM_I2C Two displays supported by the sunxi display driver (each one used by a single board) require initialization over I2C. Both previously used i2c_soft; replace this with the i2c-gpio instance that already exists in those boards' device trees (sun5i-a13-utoo-p66 and sun6i-a31-colombus). Since the i2c-gpio nodes are not referenced by any other node in the device trees (the device trees have no panel node), the I2C bus is selected by its node name. This panel initialization code was the only i2c_soft user, so the i2c_soft GPIO setup code can be removed now as well. Reviewed-by: Heiko Schocher Signed-off-by: Samuel Holland Signed-off-by: Andre Przywara --- arch/arm/mach-sunxi/Kconfig | 21 +++----- board/sunxi/board.c | 44 +-------------- configs/Colombus_defconfig | 6 --- configs/UTOO_P66_defconfig | 3 -- drivers/video/anx9804.c | 103 ++++++++++++++++++------------------ drivers/video/anx9804.h | 5 +- drivers/video/sunxi/sunxi_display.c | 55 +++++++++++++------ include/configs/sunxi-common.h | 17 ------ 8 files changed, 100 insertions(+), 154 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 83f8f9513f6..c1e762a5184 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -909,27 +909,18 @@ config VIDEO_LCD_BL_PWM_ACTIVE_LOW config VIDEO_LCD_PANEL_I2C bool "LCD panel needs to be configured via i2c" depends on VIDEO_SUNXI - select CMD_I2C + select DM_I2C + select DM_I2C_GPIO ---help--- Say y here if the LCD panel needs to be configured via i2c. This will add a bitbang i2c controller using gpios to talk to the LCD. -config VIDEO_LCD_PANEL_I2C_SDA - string "LCD panel i2c interface SDA pin" - depends on VIDEO_LCD_PANEL_I2C - default "PG12" - ---help--- - Set the SDA pin for the LCD i2c interface. This takes a string in the - format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H. - -config VIDEO_LCD_PANEL_I2C_SCL - string "LCD panel i2c interface SCL pin" +config VIDEO_LCD_PANEL_I2C_NAME + string "LCD panel i2c interface node name" depends on VIDEO_LCD_PANEL_I2C - default "PG10" + default "i2c@0" ---help--- - Set the SCL pin for the LCD i2c interface. This takes a string in the - format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H. - + Set the device tree node name for the LCD i2c interface. # Note only one of these may be selected at a time! But hidden choices are # not supported by Kconfig diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 65cb3a6fe31..4f5747c34a9 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -47,47 +47,6 @@ #include #include -#if defined(CONFIG_VIDEO_LCD_PANEL_I2C) -/* So that we can use pin names in Kconfig and sunxi_name_to_gpio() */ -int soft_i2c_gpio_sda; -int soft_i2c_gpio_scl; - -static int soft_i2c_board_init(void) -{ - int ret; - - soft_i2c_gpio_sda = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_PANEL_I2C_SDA); - if (soft_i2c_gpio_sda < 0) { - printf("Error invalid soft i2c sda pin: '%s', err %d\n", - CONFIG_VIDEO_LCD_PANEL_I2C_SDA, soft_i2c_gpio_sda); - return soft_i2c_gpio_sda; - } - ret = gpio_request(soft_i2c_gpio_sda, "soft-i2c-sda"); - if (ret) { - printf("Error requesting soft i2c sda pin: '%s', err %d\n", - CONFIG_VIDEO_LCD_PANEL_I2C_SDA, ret); - return ret; - } - - soft_i2c_gpio_scl = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_PANEL_I2C_SCL); - if (soft_i2c_gpio_scl < 0) { - printf("Error invalid soft i2c scl pin: '%s', err %d\n", - CONFIG_VIDEO_LCD_PANEL_I2C_SCL, soft_i2c_gpio_scl); - return soft_i2c_gpio_scl; - } - ret = gpio_request(soft_i2c_gpio_scl, "soft-i2c-scl"); - if (ret) { - printf("Error requesting soft i2c scl pin: '%s', err %d\n", - CONFIG_VIDEO_LCD_PANEL_I2C_SCL, ret); - return ret; - } - - return 0; -} -#else -static int soft_i2c_board_init(void) { return 0; } -#endif - DECLARE_GLOBAL_DATA_PTR; void i2c_init_board(void) @@ -312,8 +271,7 @@ int board_init(void) #endif #endif /* CONFIG_DM_MMC */ - /* Uses dm gpio code so do this here and not in i2c_init_board() */ - return soft_i2c_board_init(); + return 0; } /* diff --git a/configs/Colombus_defconfig b/configs/Colombus_defconfig index 31541f898d4..270bd7d351a 100644 --- a/configs/Colombus_defconfig +++ b/configs/Colombus_defconfig @@ -13,15 +13,9 @@ CONFIG_VIDEO_LCD_DCLK_PHASE=0 CONFIG_VIDEO_LCD_POWER="PH27" CONFIG_VIDEO_LCD_BL_EN="PM1" CONFIG_VIDEO_LCD_BL_PWM="PH13" -CONFIG_VIDEO_LCD_PANEL_I2C_SDA="PA23" -CONFIG_VIDEO_LCD_PANEL_I2C_SCL="PA24" CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_SYS_I2C_LEGACY=y CONFIG_SPL_SYS_I2C_LEGACY=y -CONFIG_SYS_I2C_SOFT=y -CONFIG_SYS_I2C_SOFT_SPEED=50000 -CONFIG_SYS_I2C_SOFT_SLAVE=0x00 CONFIG_SYS_I2C_MVTWSI=y CONFIG_SYS_I2C_SLAVE=0x7f CONFIG_SYS_I2C_SPEED=400000 diff --git a/configs/UTOO_P66_defconfig b/configs/UTOO_P66_defconfig index b5728073086..b021b0a8865 100644 --- a/configs/UTOO_P66_defconfig +++ b/configs/UTOO_P66_defconfig @@ -21,9 +21,6 @@ CONFIG_VIDEO_LCD_BL_PWM="PB2" CONFIG_VIDEO_LCD_TL059WV5C0=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y -CONFIG_SYS_I2C_SOFT=y -CONFIG_SYS_I2C_SOFT_SPEED=50000 -CONFIG_SYS_I2C_SOFT_SLAVE=0x00 CONFIG_SYS_I2C_MVTWSI=y CONFIG_SYS_I2C_SLAVE=0x7f CONFIG_SYS_I2C_SPEED=400000 diff --git a/drivers/video/anx9804.c b/drivers/video/anx9804.c index 3037ff39b41..52b5988ba5f 100644 --- a/drivers/video/anx9804.c +++ b/drivers/video/anx9804.c @@ -21,18 +21,23 @@ * This function will init an anx9804 parallel lcd to dp bridge chip * using the passed in parameters. * - * @i2c_bus: Number of the i2c bus to which the anx9804 is connected. + * @i2c_bus: Device of the i2c bus to which the anx9804 is connected. * @lanes: Number of displayport lanes to use * @data_rate: Register value for the bandwidth reg 0x06: 1.62G, 0x0a: 2.7G * @bpp: Bits per pixel, must be 18 or 24 */ -void anx9804_init(unsigned int i2c_bus, u8 lanes, u8 data_rate, int bpp) +void anx9804_init(struct udevice *i2c_bus, u8 lanes, u8 data_rate, int bpp) { - unsigned int orig_i2c_bus = i2c_get_bus_num(); - u8 c, colordepth; - int i; + struct udevice *chip0, *chip1; + int c, colordepth, i, ret; - i2c_set_bus_num(i2c_bus); + ret = i2c_get_chip(i2c_bus, 0x38, 1, &chip0); + if (ret) + return; + + ret = i2c_get_chip(i2c_bus, 0x39, 1, &chip1); + if (ret) + return; if (bpp == 18) colordepth = 0x00; /* 6 bit */ @@ -40,24 +45,23 @@ void anx9804_init(unsigned int i2c_bus, u8 lanes, u8 data_rate, int bpp) colordepth = 0x10; /* 8 bit */ /* Reset */ - i2c_reg_write(0x39, ANX9804_RST_CTRL_REG, 1); + dm_i2c_reg_write(chip1, ANX9804_RST_CTRL_REG, 1); mdelay(100); - i2c_reg_write(0x39, ANX9804_RST_CTRL_REG, 0); + dm_i2c_reg_write(chip1, ANX9804_RST_CTRL_REG, 0); /* Write 0 to the powerdown reg (powerup everything) */ - i2c_reg_write(0x39, ANX9804_POWERD_CTRL_REG, 0); + dm_i2c_reg_write(chip1, ANX9804_POWERD_CTRL_REG, 0); - c = i2c_reg_read(0x39, ANX9804_DEV_IDH_REG); + c = dm_i2c_reg_read(chip1, ANX9804_DEV_IDH_REG); if (c != 0x98) { printf("Error anx9804 chipid mismatch\n"); - i2c_set_bus_num(orig_i2c_bus); return; } for (i = 0; i < 100; i++) { - c = i2c_reg_read(0x38, ANX9804_SYS_CTRL2_REG); - i2c_reg_write(0x38, ANX9804_SYS_CTRL2_REG, c); - c = i2c_reg_read(0x38, ANX9804_SYS_CTRL2_REG); + c = dm_i2c_reg_read(chip0, ANX9804_SYS_CTRL2_REG); + dm_i2c_reg_write(chip0, ANX9804_SYS_CTRL2_REG, c); + c = dm_i2c_reg_read(chip0, ANX9804_SYS_CTRL2_REG); if ((c & ANX9804_SYS_CTRL2_CHA_STA) == 0) break; @@ -66,51 +70,51 @@ void anx9804_init(unsigned int i2c_bus, u8 lanes, u8 data_rate, int bpp) if (i == 100) printf("Error anx9804 clock is not stable\n"); - i2c_reg_write(0x39, ANX9804_VID_CTRL2_REG, colordepth); + dm_i2c_reg_write(chip1, ANX9804_VID_CTRL2_REG, colordepth); /* Set a bunch of analog related register values */ - i2c_reg_write(0x38, ANX9804_PLL_CTRL_REG, 0x07); - i2c_reg_write(0x39, ANX9804_PLL_FILTER_CTRL3, 0x19); - i2c_reg_write(0x39, ANX9804_PLL_CTRL3, 0xd9); - i2c_reg_write(0x39, ANX9804_RST_CTRL2_REG, ANX9804_RST_CTRL2_AC_MODE); - i2c_reg_write(0x39, ANX9804_ANALOG_DEBUG_REG1, 0xf0); - i2c_reg_write(0x39, ANX9804_ANALOG_DEBUG_REG3, 0x99); - i2c_reg_write(0x39, ANX9804_PLL_FILTER_CTRL1, 0x7b); - i2c_reg_write(0x38, ANX9804_LINK_DEBUG_REG, 0x30); - i2c_reg_write(0x39, ANX9804_PLL_FILTER_CTRL, 0x06); + dm_i2c_reg_write(chip0, ANX9804_PLL_CTRL_REG, 0x07); + dm_i2c_reg_write(chip1, ANX9804_PLL_FILTER_CTRL3, 0x19); + dm_i2c_reg_write(chip1, ANX9804_PLL_CTRL3, 0xd9); + dm_i2c_reg_write(chip1, ANX9804_RST_CTRL2_REG, ANX9804_RST_CTRL2_AC_MODE); + dm_i2c_reg_write(chip1, ANX9804_ANALOG_DEBUG_REG1, 0xf0); + dm_i2c_reg_write(chip1, ANX9804_ANALOG_DEBUG_REG3, 0x99); + dm_i2c_reg_write(chip1, ANX9804_PLL_FILTER_CTRL1, 0x7b); + dm_i2c_reg_write(chip0, ANX9804_LINK_DEBUG_REG, 0x30); + dm_i2c_reg_write(chip1, ANX9804_PLL_FILTER_CTRL, 0x06); /* Force HPD */ - i2c_reg_write(0x38, ANX9804_SYS_CTRL3_REG, - ANX9804_SYS_CTRL3_F_HPD | ANX9804_SYS_CTRL3_HPD_CTRL); + dm_i2c_reg_write(chip0, ANX9804_SYS_CTRL3_REG, + ANX9804_SYS_CTRL3_F_HPD | ANX9804_SYS_CTRL3_HPD_CTRL); /* Power up and configure lanes */ - i2c_reg_write(0x38, ANX9804_ANALOG_POWER_DOWN_REG, 0x00); - i2c_reg_write(0x38, ANX9804_TRAINING_LANE0_SET_REG, 0x00); - i2c_reg_write(0x38, ANX9804_TRAINING_LANE1_SET_REG, 0x00); - i2c_reg_write(0x38, ANX9804_TRAINING_LANE2_SET_REG, 0x00); - i2c_reg_write(0x38, ANX9804_TRAINING_LANE3_SET_REG, 0x00); + dm_i2c_reg_write(chip0, ANX9804_ANALOG_POWER_DOWN_REG, 0x00); + dm_i2c_reg_write(chip0, ANX9804_TRAINING_LANE0_SET_REG, 0x00); + dm_i2c_reg_write(chip0, ANX9804_TRAINING_LANE1_SET_REG, 0x00); + dm_i2c_reg_write(chip0, ANX9804_TRAINING_LANE2_SET_REG, 0x00); + dm_i2c_reg_write(chip0, ANX9804_TRAINING_LANE3_SET_REG, 0x00); /* Reset AUX CH */ - i2c_reg_write(0x39, ANX9804_RST_CTRL2_REG, - ANX9804_RST_CTRL2_AC_MODE | ANX9804_RST_CTRL2_AUX); - i2c_reg_write(0x39, ANX9804_RST_CTRL2_REG, - ANX9804_RST_CTRL2_AC_MODE); + dm_i2c_reg_write(chip1, ANX9804_RST_CTRL2_REG, + ANX9804_RST_CTRL2_AC_MODE | ANX9804_RST_CTRL2_AUX); + dm_i2c_reg_write(chip1, ANX9804_RST_CTRL2_REG, + ANX9804_RST_CTRL2_AC_MODE); /* Powerdown audio and some other unused bits */ - i2c_reg_write(0x39, ANX9804_POWERD_CTRL_REG, ANX9804_POWERD_AUDIO); - i2c_reg_write(0x38, ANX9804_HDCP_CONTROL_0_REG, 0x00); - i2c_reg_write(0x38, 0xa7, 0x00); + dm_i2c_reg_write(chip1, ANX9804_POWERD_CTRL_REG, ANX9804_POWERD_AUDIO); + dm_i2c_reg_write(chip0, ANX9804_HDCP_CONTROL_0_REG, 0x00); + dm_i2c_reg_write(chip0, 0xa7, 0x00); /* Set data-rate / lanes */ - i2c_reg_write(0x38, ANX9804_LINK_BW_SET_REG, data_rate); - i2c_reg_write(0x38, ANX9804_LANE_COUNT_SET_REG, lanes); + dm_i2c_reg_write(chip0, ANX9804_LINK_BW_SET_REG, data_rate); + dm_i2c_reg_write(chip0, ANX9804_LANE_COUNT_SET_REG, lanes); /* Link training */ - i2c_reg_write(0x38, ANX9804_LINK_TRAINING_CTRL_REG, - ANX9804_LINK_TRAINING_CTRL_EN); + dm_i2c_reg_write(chip0, ANX9804_LINK_TRAINING_CTRL_REG, + ANX9804_LINK_TRAINING_CTRL_EN); mdelay(5); for (i = 0; i < 100; i++) { - c = i2c_reg_read(0x38, ANX9804_LINK_TRAINING_CTRL_REG); + c = dm_i2c_reg_read(chip0, ANX9804_LINK_TRAINING_CTRL_REG); if ((c & 0x01) == 0) break; @@ -118,17 +122,14 @@ void anx9804_init(unsigned int i2c_bus, u8 lanes, u8 data_rate, int bpp) } if(i == 100) { printf("Error anx9804 link training timeout\n"); - i2c_set_bus_num(orig_i2c_bus); return; } /* Enable */ - i2c_reg_write(0x39, ANX9804_VID_CTRL1_REG, - ANX9804_VID_CTRL1_VID_EN | ANX9804_VID_CTRL1_EDGE); + dm_i2c_reg_write(chip1, ANX9804_VID_CTRL1_REG, + ANX9804_VID_CTRL1_VID_EN | ANX9804_VID_CTRL1_EDGE); /* Force stream valid */ - i2c_reg_write(0x38, ANX9804_SYS_CTRL3_REG, - ANX9804_SYS_CTRL3_F_HPD | ANX9804_SYS_CTRL3_HPD_CTRL | - ANX9804_SYS_CTRL3_F_VALID | ANX9804_SYS_CTRL3_VALID_CTRL); - - i2c_set_bus_num(orig_i2c_bus); + dm_i2c_reg_write(chip0, ANX9804_SYS_CTRL3_REG, + ANX9804_SYS_CTRL3_F_HPD | ANX9804_SYS_CTRL3_HPD_CTRL | + ANX9804_SYS_CTRL3_F_VALID | ANX9804_SYS_CTRL3_VALID_CTRL); } diff --git a/drivers/video/anx9804.h b/drivers/video/anx9804.h index c0fe3b393b4..ea6c9f2d558 100644 --- a/drivers/video/anx9804.h +++ b/drivers/video/anx9804.h @@ -16,9 +16,10 @@ #define ANX9804_DATA_RATE_2700M 0x0a #ifdef CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804 -void anx9804_init(unsigned int i2c_bus, u8 lanes, u8 data_rate, int bpp); +void anx9804_init(struct udevice *i2c_bus, u8 lanes, u8 data_rate, int bpp); #else -static inline void anx9804_init(unsigned int i2c_bus, u8 lanes, u8 data_rate, +static inline void anx9804_init(struct udevice *i2c_bus, u8 lanes, u8 data_rate, int bpp) {} #endif + #endif diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index da3e8988296..5a21f7af668 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -901,6 +901,42 @@ static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode) } #endif /* CONFIG_VIDEO_LCD_SSD2828 */ +#ifdef CONFIG_VIDEO_LCD_PANEL_I2C +static void sunxi_panel_i2c_init(struct sunxi_display_priv *sunxi_display) +{ + const char *name = CONFIG_VIDEO_LCD_PANEL_I2C_NAME; + struct udevice *i2c_bus; + int ret; + + ret = uclass_get_device_by_name(UCLASS_I2C, name, &i2c_bus); + if (ret) + return; + + if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804)) { + /* + * The anx9804 needs 1.8V from eldo3, we do this here + * and not via CONFIG_AXP_ELDO3_VOLT from board_init() + * to avoid turning this on when using hdmi output. + */ + axp_set_eldo(3, 1800); + anx9804_init(i2c_bus, 4, + ANX9804_DATA_RATE_1620M, + sunxi_display->depth); + } + if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) { + struct udevice *chip; + + ret = i2c_get_chip(i2c_bus, 0x5c, 1, &chip); + if (ret) + return; + + dm_i2c_reg_write(chip, 0x04, 0x42); /* Turn on the LCD */ + } +} +#else +static void sunxi_panel_i2c_init(struct sunxi_display_priv *sunxi_display) {} +#endif + static void sunxi_engines_init(void) { sunxi_composer_init(); @@ -935,27 +971,12 @@ static void sunxi_mode_set(struct sunxi_display_priv *sunxi_display, break; case sunxi_monitor_lcd: sunxi_lcdc_panel_enable(); - if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804)) { - /* - * The anx9804 needs 1.8V from eldo3, we do this here - * and not via CONFIG_AXP_ELDO3_VOLT from board_init() - * to avoid turning this on when using hdmi output. - */ - axp_set_eldo(3, 1800); - anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4, - ANX9804_DATA_RATE_1620M, - sunxi_display->depth); - } if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) { mdelay(50); /* Wait for lcd controller power on */ hitachi_tx18d42vm_init(); } - if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) { - unsigned int orig_i2c_bus = i2c_get_bus_num(); - i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS); - i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */ - i2c_set_bus_num(orig_i2c_bus); - } + if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_I2C)) + sunxi_panel_i2c_init(sunxi_display); sunxi_composer_mode_set(mode, address, monitor); sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, false); sunxi_composer_enable(); diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 5d8b6052e4f..c576d65efaf 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -160,23 +160,6 @@ #define CONFIG_SPL_PAD_TO 32768 /* decimal for 'dd' */ #endif - -/* I2C */ -#if defined(CONFIG_VIDEO_LCD_PANEL_I2C) -/* We use pin names in Kconfig and sunxi_name_to_gpio() */ -#define CONFIG_SOFT_I2C_GPIO_SDA soft_i2c_gpio_sda -#define CONFIG_SOFT_I2C_GPIO_SCL soft_i2c_gpio_scl -#ifndef __ASSEMBLY__ -extern int soft_i2c_gpio_sda; -extern int soft_i2c_gpio_scl; -#endif -#define CONFIG_VIDEO_LCD_I2C_BUS 0 /* The lcd panel soft i2c is bus 0 */ -#define CONFIG_SYS_SPD_BUS_NUM 1 /* And the axp209 i2c bus is bus 1 */ -#else -#define CONFIG_SYS_SPD_BUS_NUM 0 /* The axp209 i2c bus is bus 0 */ -#define CONFIG_VIDEO_LCD_I2C_BUS -1 /* NA, but necessary to compile */ -#endif - /* Ethernet support */ #ifdef CONFIG_USB_EHCI_HCD -- cgit v1.3.1 From f9437b00c06382d3edc623c10c69901786ad6317 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 8 Oct 2021 00:17:25 -0500 Subject: sunxi: Enable DM_I2C for all sunxi boards Now that the last users of legacy I2C (outside of SPL) have been resolved, we can enable DM_I2C at the sunxi architecture level. Reviewed-by: Heiko Schocher Signed-off-by: Samuel Holland Signed-off-by: Andre Przywara --- arch/arm/Kconfig | 1 + arch/arm/mach-sunxi/Kconfig | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ebb19272708..d8c041a8773 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1028,6 +1028,7 @@ config ARCH_SUNXI select DM select DM_ETH select DM_GPIO + select DM_I2C if I2C select DM_KEYBOARD select DM_MMC if MMC select DM_SCSI if SCSI diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index c1e762a5184..2c18cf02d1a 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -165,7 +165,6 @@ endif config MACH_SUNXI_H3_H5 bool - select DM_I2C select PHY_SUN4I_USB select SUNXI_DE2 select SUNXI_DRAM_DW @@ -326,7 +325,6 @@ config MACH_SUN50I bool "sun50i (Allwinner A64)" select ARM64 select SPI - select DM_I2C select DM_SPI if SPI select DM_SPI_FLASH select PHY_SUN4I_USB @@ -909,7 +907,6 @@ config VIDEO_LCD_BL_PWM_ACTIVE_LOW config VIDEO_LCD_PANEL_I2C bool "LCD panel needs to be configured via i2c" depends on VIDEO_SUNXI - select DM_I2C select DM_I2C_GPIO ---help--- Say y here if the LCD panel needs to be configured via i2c. This -- cgit v1.3.1