Browse Source

Merge https://source.denx.de/u-boot/custodians/u-boot-sunxi

The bulk of it is Samuel's DM_I2C rework, which removes the nasty I2C
deprecation warnings for most 32-bit boards. It also includes some
smaller refactorings that pave the way for more changes, mostly driven
by needing to support the Allwinner RISC-V SoC later on.

Board wise we gain support for the FriendlyARM NanoPi R1S H5 router
board and official Pinetab support.

Build-tested for all 160 sunxi boards, and boot tested on a A64, A20,
H3, H6, and H616 board. USB, SD card, eMMC, and Ethernet all work there
(where applicable).
Tom Rini 2 years ago
parent
commit
2aab77f726
68 changed files with 1315 additions and 750 deletions
  1. 1 0
      arch/arm/Kconfig
  2. 1 0
      arch/arm/dts/Makefile
  3. 195 0
      arch/arm/dts/sun50i-h5-nanopi-r1s-h5.dts
  4. 2 18
      arch/arm/include/asm/arch-sunxi/gpio.h
  5. 22 57
      arch/arm/mach-sunxi/Kconfig
  6. 0 2
      arch/arm/mach-sunxi/Makefile
  7. 1 2
      arch/arm/mach-sunxi/board.c
  8. 0 1
      arch/arm/mach-sunxi/clock.c
  9. 0 1
      arch/arm/mach-sunxi/clock_sun4i.c
  10. 0 117
      arch/arm/mach-sunxi/p2wi.c
  11. 56 53
      arch/arm/mach-sunxi/pmic_bus.c
  12. 0 175
      arch/arm/mach-sunxi/rsb.c
  13. 10 0
      board/sunxi/MAINTAINERS
  14. 36 116
      board/sunxi/board.c
  15. 0 1
      board/sunxi/gmac.c
  16. 0 1
      configs/A20-Olimex-SOM-EVB_defconfig
  17. 0 6
      configs/Colombus_defconfig
  18. 1 0
      configs/Cubieboard4_defconfig
  19. 1 0
      configs/Merrii_A80_Optimus_defconfig
  20. 0 1
      configs/Sinlinx_SinA31s_defconfig
  21. 0 3
      configs/UTOO_P66_defconfig
  22. 1 1
      configs/Yones_Toptech_BD1078_defconfig
  23. 14 0
      configs/nanopi_r1s_h5_defconfig
  24. 0 1
      configs/parrot_r16_defconfig
  25. 6 0
      configs/pinephone_defconfig
  26. 10 0
      configs/pinetab_defconfig
  27. 14 0
      drivers/clk/sunxi/Kconfig
  28. 2 0
      drivers/clk/sunxi/Makefile
  29. 6 1
      drivers/clk/sunxi/clk_a10.c
  30. 4 1
      drivers/clk/sunxi/clk_a10s.c
  31. 7 1
      drivers/clk/sunxi/clk_a23.c
  32. 9 1
      drivers/clk/sunxi/clk_a31.c
  33. 59 0
      drivers/clk/sunxi/clk_a31_r.c
  34. 7 1
      drivers/clk/sunxi/clk_a64.c
  35. 11 1
      drivers/clk/sunxi/clk_a80.c
  36. 7 1
      drivers/clk/sunxi/clk_a83t.c
  37. 7 1
      drivers/clk/sunxi/clk_h3.c
  38. 11 1
      drivers/clk/sunxi/clk_h6.c
  39. 13 1
      drivers/clk/sunxi/clk_h616.c
  40. 61 0
      drivers/clk/sunxi/clk_h6_r.c
  41. 11 1
      drivers/clk/sunxi/clk_r40.c
  42. 1 1
      drivers/clk/sunxi/clk_sunxi.c
  43. 5 1
      drivers/clk/sunxi/clk_v3s.c
  44. 0 1
      drivers/gpio/axp_gpio.c
  45. 0 17
      drivers/gpio/sunxi_gpio.c
  46. 16 0
      drivers/i2c/Kconfig
  47. 2 0
      drivers/i2c/Makefile
  48. 220 0
      drivers/i2c/sun6i_p2wi.c
  49. 281 0
      drivers/i2c/sun8i_rsb.c
  50. 1 2
      drivers/mmc/sunxi_mmc.c
  51. 1 4
      drivers/net/sun8i_emac.c
  52. 0 1
      drivers/power/axp809.c
  53. 0 1
      drivers/power/axp818.c
  54. 40 44
      drivers/power/pmic/Kconfig
  55. 1 0
      drivers/power/pmic/Makefile
  56. 38 0
      drivers/power/pmic/axp.c
  57. 1 1
      drivers/reset/reset-sunxi.c
  58. 1 1
      drivers/spi/spi-sunxi.c
  59. 0 2
      drivers/usb/musb-new/sunxi.c
  60. 5 5
      drivers/video/Kconfig
  61. 52 51
      drivers/video/anx9804.c
  62. 3 2
      drivers/video/anx9804.h
  63. 3 3
      drivers/video/hitachi_tx18d42vm_lcd.c
  64. 43 23
      drivers/video/sunxi/sunxi_display.c
  65. 0 1
      drivers/video/sunxi/sunxi_lcd.c
  66. 12 0
      include/axp_pmic.h
  67. 3 5
      include/clk/sunxi.h
  68. 0 17
      include/configs/sunxi-common.h

+ 1 - 0
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

+ 1 - 0
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 \

+ 195 - 0
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 <amadeus@jmu.edu.cn>
+ *
+ * Based on sun50i-h5-nanopi-neo-plus2.dts, which is:
+ *   Copyright (C) 2017 Antony Antony <antony@phenome.org>
+ *   Copyright (C) 2016 ARM Ltd.
+ */
+
+/dts-v1/;
+#include "sun50i-h5.dtsi"
+#include "sun50i-h5-cpu-opp.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+	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 = <LED_COLOR_ID_GREEN>;
+			gpios = <&pio 0 9 GPIO_ACTIVE_HIGH>;
+		};
+
+		led-1 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_RED>;
+			gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led-2 {
+			function = LED_FUNCTION_WAN;
+			color = <LED_COLOR_ID_GREEN>;
+			gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	r-gpio-keys {
+		compatible = "gpio-keys";
+
+		reset {
+			label = "reset";
+			linux,code = <KEY_RESTART>;
+			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 = <&reg_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 = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+	status = "okay";
+};
+
+&mmc1 {
+	vmmc-supply = <&reg_vcc3v3>;
+	vqmmc-supply = <&reg_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 = <&reg_usb0_vbus>;
+	status = "okay";
+};

+ 2 - 18
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,
@@ -148,8 +138,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 +161,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
 
@@ -242,9 +228,7 @@ 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)
 
 #if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
 int axp_gpio_init(void);

+ 22 - 57
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
@@ -106,19 +95,13 @@ config SUN6I_PRCM
 	  in A31 SoC.
 
 config AXP_PMIC_BUS
-	bool "Sunxi AXP PMIC bus access helpers"
+	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.
 
-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
@@ -182,7 +165,6 @@ endif
 
 config MACH_SUNXI_H3_H5
 	bool
-	select DM_I2C
 	select PHY_SUN4I_USB
 	select SUNXI_DE2
 	select SUNXI_DRAM_DW
@@ -232,10 +214,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
@@ -260,8 +243,10 @@ config MACH_SUN8I_A23
 	select ARCH_SUPPORT_PSCI
 	select DRAM_SUN8I_A23
 	select PHY_SUN4I_USB
+	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
 
@@ -273,8 +258,10 @@ config MACH_SUN8I_A33
 	select ARCH_SUPPORT_PSCI
 	select DRAM_SUN8I_A33
 	select PHY_SUN4I_USB
+	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
 
@@ -283,10 +270,12 @@ config MACH_SUN8I_A83T
 	select CPU_V7A
 	select DRAM_SUN8I_A83T
 	select PHY_SUN4I_USB
+	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)"
@@ -327,16 +316,15 @@ config MACH_SUN9I
 	bool "sun9i (Allwinner A80)"
 	select CPU_V7A
 	select DRAM_SUN9I
+	select SPL_I2C
 	select SUN6I_PRCM
 	select SUNXI_GEN_SUN6I
-	select SUN8I_RSB
 	select SUPPORT_SPL
 
 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
@@ -377,7 +365,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
@@ -677,24 +664,11 @@ config MMC3_CD_PIN
 	---help---
 	See MMC0_CD_PIN help text.
 
-config MMC1_PINS
-	string "Pins for mmc1"
-	default ""
+config MMC1_PINS_PH
+	bool "Pins for mmc1 are on Port H"
+	depends on MACH_SUN4I || MACH_SUN7I || MACH_SUN8I_R40
 	---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 ""
-	---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"
@@ -807,6 +781,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.
 
@@ -932,27 +907,17 @@ 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_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"
+config VIDEO_LCD_PANEL_I2C_NAME
+	string "LCD panel i2c interface node name"
 	depends on VIDEO_LCD_PANEL_I2C
-	default "PG12"
+	default "i2c@0"
 	---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"
-	depends on VIDEO_LCD_PANEL_I2C
-	default "PG10"
-	---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

+ 0 - 2
arch/arm/mach-sunxi/Makefile

@@ -11,10 +11,8 @@ 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
 obj-$(CONFIG_MACH_SUN4I)	+= clock_sun4i.o
 obj-$(CONFIG_MACH_SUN5I)	+= clock_sun4i.o
 obj-$(CONFIG_MACH_SUN6I)	+= clock_sun6i.o

+ 1 - 2
arch/arm/mach-sunxi/board.c

@@ -21,7 +21,6 @@
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/spl.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/timer.h>
@@ -339,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

+ 0 - 1
arch/arm/mach-sunxi/clock.c

@@ -10,7 +10,6 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/prcm.h>
 #include <asm/arch/gtbus.h>
 #include <asm/arch/sys_proto.h>

+ 0 - 1
arch/arm/mach-sunxi/clock_sun4i.c

@@ -12,7 +12,6 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/sys_proto.h>
 
 #ifdef CONFIG_SPL_BUILD

+ 0 - 117
arch/arm/mach-sunxi/p2wi.c

@@ -1,117 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Sunxi A31 Power Management Unit
- *
- * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
- * http://linux-sunxi.org
- *
- * Based on sun6i sources and earlier U-Boot Allwinner A10 SPL work
- *
- * (C) Copyright 2006-2013
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- * Berg Xing <bergxing@allwinnertech.com>
- * Tom Cubie <tangliang@allwinnertech.com>
- */
-
-#include <common.h>
-#include <errno.h>
-#include <time.h>
-#include <asm/io.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/p2wi.h>
-#include <asm/arch/prcm.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/sys_proto.h>
-
-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();
-}

+ 56 - 53
arch/arm/mach-sunxi/pmic_bus.c

@@ -8,10 +8,13 @@
  * axp223 uses the rsb bus, these functions abstract this.
  */
 
+#include <axp_pmic.h>
 #include <common.h>
+#include <dm.h>
 #include <asm/arch/p2wi.h>
 #include <asm/arch/rsb.h>
 #include <i2c.h>
+#include <power/pmic.h>
 #include <asm/arch/pmic_bus.h>
 
 #define AXP152_I2C_ADDR			0x30
@@ -21,80 +24,80 @@
 #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
-#define AXP223_RUNTIME_ADDR		0x2d
+#if CONFIG_IS_ENABLED(PMIC_AXP)
+static struct udevice *pmic;
+#else
+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;
+}
+#endif
 
 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, AXP221_CTRL_ADDR,
-				       AXP221_INIT_DATA);
-# elif defined CONFIG_MACH_SUN8I_R40
-	/* Nothing. R40 uses the AXP221s in I2C mode */
-	ret = 0;
-# else
-	ret = rsb_init();
-	if (ret)
-		return ret;
-
-	ret = rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
-# endif
-	if (ret)
-		return ret;
+#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,
+					       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
 
-	needs_init = 0;
-	return 0;
+	needs_init = ret;
+
+	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(AXP223_RUNTIME_ADDR, reg, data);
-# endif
+#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)
 {
-#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(AXP223_RUNTIME_ADDR, reg, data);
-# endif
+#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
 }
 

+ 0 - 175
arch/arm/mach-sunxi/rsb.c

@@ -1,175 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
- *
- * Based on allwinner u-boot sources rsb code which is:
- * (C) Copyright 2007-2013
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- * lixiang <lixiang@allwinnertech.com>
- */
-
-#include <common.h>
-#include <errno.h>
-#include <time.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/prcm.h>
-#include <asm/arch/rsb.h>
-
-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;
-}

+ 10 - 0
board/sunxi/MAINTAINERS

@@ -358,6 +358,11 @@ M:	Jelle van der Waa <jelle@vdwaa.nl>
 S:	Maintained
 F:	configs/nanopi_neo_air_defconfig
 
+NANOPI-R1S-H5 BOARD
+M:	Chukun Pan <amadeus@jmu.edu.cn>
+S:	Maintained
+F:	configs/nanopi_r1s_h5_defconfig
+
 NANOPI-A64 BOARD
 M:	Jagan Teki <jagan@amarulasolutions.com>
 S:	Maintained
@@ -471,6 +476,11 @@ M:	Samuel Holland <samuel@sholland.org>
 S:	Maintained
 F:	configs/pinephone_defconfig
 
+PINETAB BOARD
+M:	Arnaud Ferraris <arnaud.ferraris@collabora.com>
+S:	Maintained
+F:	configs/pinetab_defconfig
+
 R16 EVB PARROT BOARD
 M:	Quentin Schulz <quentin.schulz@free-electrons.com>
 S:	Maintained

+ 36 - 116
board/sunxi/board.c

@@ -25,7 +25,6 @@
 #include <asm/arch/cpu.h>
 #include <asm/arch/display.h>
 #include <asm/arch/dram.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/prcm.h>
 #include <asm/arch/spl.h>
@@ -46,47 +45,7 @@
 #include <spl.h>
 #include <sy8106a.h>
 #include <asm/setup.h>
-
-#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
+#include <status_led.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -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;
 }
 
 /*
@@ -413,7 +371,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 +383,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 +415,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 +433,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 +505,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 +514,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;
 
@@ -672,6 +587,11 @@ void sunxi_board_init(void)
 {
 	int power_failed = 0;
 
+#ifdef CONFIG_LED_STATUS
+	if (IS_ENABLED(CONFIG_SPL_DRIVERS_MISC))
+		status_led_init();
+#endif
+
 #ifdef CONFIG_SY8106A_POWER
 	power_failed = sy8106a_set_vout1(CONFIG_SY8106A_VOUT1_VOLT);
 #endif

+ 0 - 1
board/sunxi/gmac.c

@@ -4,7 +4,6 @@
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
-#include <asm/arch/gpio.h>
 
 void eth_init_board(void)
 {

+ 0 - 1
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"

+ 0 - 6
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

+ 1 - 0
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_SYS_I2C_SUN8I_RSB=y
 CONFIG_AXP_GPIO=y
 CONFIG_AXP809_POWER=y

+ 1 - 0
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_SYS_I2C_SUN8I_RSB=y
 CONFIG_AXP_GPIO=y
 CONFIG_AXP809_POWER=y

+ 0 - 1
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=""

+ 0 - 3
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

+ 1 - 1
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"

+ 14 - 0
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

+ 0 - 1
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"

+ 6 - 0
configs/pinephone_defconfig

@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_SUNXI=y
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pinephone-1.2"
+CONFIG_SPL_DRIVERS_MISC=y
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I=y
 CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y
@@ -10,3 +11,8 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_PINEPHONE_DT_SELECTION=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_OF_LIST="sun50i-a64-pinephone-1.1 sun50i-a64-pinephone-1.2"
+CONFIG_LED_STATUS=y
+CONFIG_LED_STATUS_GPIO=y
+CONFIG_LED_STATUS0=y
+CONFIG_LED_STATUS_BIT=114
+CONFIG_LED_STATUS_STATE=2

+ 10 - 0
configs/pinetab_defconfig

@@ -0,0 +1,10 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pinetab"
+CONFIG_SPL=y
+CONFIG_MACH_SUN50I=y
+CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y
+CONFIG_DRAM_CLK=552
+CONFIG_DRAM_ZQ=3881949
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set

+ 14 - 0
drivers/clk/sunxi/Kconfig

@@ -30,6 +30,13 @@ config CLK_SUN6I_A31
 	  This enables common clock driver support for platforms based
 	  on Allwinner A31/A31s SoC.
 
+config CLK_SUN6I_A31_R
+	bool "Clock driver for Allwinner A31 generation PRCM"
+	default SUNXI_GEN_SUN6I
+	help
+	  This enables common clock driver support for the PRCM
+	  in Allwinner A31/A31s/A23/A33/A83T/H3/A64/H5 SoCs.
+
 config CLK_SUN8I_A23
 	bool "Clock driver for Allwinner A23/A33"
 	default MACH_SUN8I_A23 || MACH_SUN8I_A33
@@ -79,6 +86,13 @@ config CLK_SUN50I_H6
 	  This enables common clock driver support for platforms based
 	  on Allwinner H6 SoC.
 
+config CLK_SUN50I_H6_R
+	bool "Clock driver for Allwinner H6 generation PRCM"
+	default SUN50I_GEN_H6
+	help
+	  This enables common clock driver support for the PRCM
+	  in Allwinner H6/H616 SoCs.
+
 config CLK_SUN50I_H616
 	bool "Clock driver for Allwinner H616"
 	default MACH_SUN50I_H616

+ 2 - 0
drivers/clk/sunxi/Makefile

@@ -11,6 +11,7 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sun6i_rtc.o
 obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o
 obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o
 obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o
+obj-$(CONFIG_CLK_SUN6I_A31_R) += clk_a31_r.o
 obj-$(CONFIG_CLK_SUN8I_A23) += clk_a23.o
 obj-$(CONFIG_CLK_SUN8I_A83T) += clk_a83t.o
 obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o
@@ -18,5 +19,6 @@ obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o
 obj-$(CONFIG_CLK_SUN9I_A80) += clk_a80.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
 obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o
+obj-$(CONFIG_CLK_SUN50I_H6_R) += clk_h6_r.o
 obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o

+ 6 - 1
drivers/clk/sunxi/clk_a10.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun4i-a10-ccu.h>
 #include <dt-bindings/reset/sun4i-a10-ccu.h>
 #include <linux/bitops.h>
@@ -31,6 +31,11 @@ static struct ccu_clk_gate a10_gates[] = {
 
 	[CLK_AHB_GMAC]		= GATE(0x064, BIT(17)),
 
+	[CLK_APB1_I2C0]		= GATE(0x06c, BIT(0)),
+	[CLK_APB1_I2C1]		= GATE(0x06c, BIT(1)),
+	[CLK_APB1_I2C2]		= GATE(0x06c, BIT(2)),
+	[CLK_APB1_I2C3]		= GATE(0x06c, BIT(3)),
+	[CLK_APB1_I2C4]		= GATE(0x06c, BIT(15)),
 	[CLK_APB1_UART0]	= GATE(0x06c, BIT(16)),
 	[CLK_APB1_UART1]	= GATE(0x06c, BIT(17)),
 	[CLK_APB1_UART2]	= GATE(0x06c, BIT(18)),

+ 4 - 1
drivers/clk/sunxi/clk_a10s.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun5i-ccu.h>
 #include <dt-bindings/reset/sun5i-ccu.h>
 #include <linux/bitops.h>
@@ -25,6 +25,9 @@ static struct ccu_clk_gate a10s_gates[] = {
 	[CLK_AHB_SPI1]		= GATE(0x060, BIT(21)),
 	[CLK_AHB_SPI2]		= GATE(0x060, BIT(22)),
 
+	[CLK_APB1_I2C0]		= GATE(0x06c, BIT(0)),
+	[CLK_APB1_I2C1]		= GATE(0x06c, BIT(1)),
+	[CLK_APB1_I2C2]		= GATE(0x06c, BIT(2)),
 	[CLK_APB1_UART0]	= GATE(0x06c, BIT(16)),
 	[CLK_APB1_UART1]	= GATE(0x06c, BIT(17)),
 	[CLK_APB1_UART2]	= GATE(0x06c, BIT(18)),

+ 7 - 1
drivers/clk/sunxi/clk_a23.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun8i-a23-a33-ccu.h>
 #include <dt-bindings/reset/sun8i-a23-a33-ccu.h>
 #include <linux/bitops.h>
@@ -23,6 +23,9 @@ static struct ccu_clk_gate a23_gates[] = {
 	[CLK_BUS_EHCI]		= GATE(0x060, BIT(26)),
 	[CLK_BUS_OHCI]		= GATE(0x060, BIT(29)),
 
+	[CLK_BUS_I2C0]		= GATE(0x06c, BIT(0)),
+	[CLK_BUS_I2C1]		= GATE(0x06c, BIT(1)),
+	[CLK_BUS_I2C2]		= GATE(0x06c, BIT(2)),
 	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
 	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
 	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
@@ -53,6 +56,9 @@ static struct ccu_reset a23_resets[] = {
 	[RST_BUS_EHCI]		= RESET(0x2c0, BIT(26)),
 	[RST_BUS_OHCI]		= RESET(0x2c0, BIT(29)),
 
+	[RST_BUS_I2C0]		= RESET(0x2d8, BIT(0)),
+	[RST_BUS_I2C1]		= RESET(0x2d8, BIT(1)),
+	[RST_BUS_I2C2]		= RESET(0x2d8, BIT(2)),
 	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
 	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
 	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),

+ 9 - 1
drivers/clk/sunxi/clk_a31.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun6i-a31-ccu.h>
 #include <dt-bindings/reset/sun6i-a31-ccu.h>
 #include <linux/bitops.h>
@@ -30,6 +30,10 @@ static struct ccu_clk_gate a31_gates[] = {
 	[CLK_AHB1_OHCI1]	= GATE(0x060, BIT(30)),
 	[CLK_AHB1_OHCI2]	= GATE(0x060, BIT(31)),
 
+	[CLK_APB2_I2C0]		= GATE(0x06c, BIT(0)),
+	[CLK_APB2_I2C1]		= GATE(0x06c, BIT(1)),
+	[CLK_APB2_I2C2]		= GATE(0x06c, BIT(2)),
+	[CLK_APB2_I2C3]		= GATE(0x06c, BIT(3)),
 	[CLK_APB2_UART0]	= GATE(0x06c, BIT(16)),
 	[CLK_APB2_UART1]	= GATE(0x06c, BIT(17)),
 	[CLK_APB2_UART2]	= GATE(0x06c, BIT(18)),
@@ -71,6 +75,10 @@ static struct ccu_reset a31_resets[] = {
 	[RST_AHB1_OHCI1]	= RESET(0x2c0, BIT(30)),
 	[RST_AHB1_OHCI2]	= RESET(0x2c0, BIT(31)),
 
+	[RST_APB2_I2C0]		= RESET(0x2d8, BIT(0)),
+	[RST_APB2_I2C1]		= RESET(0x2d8, BIT(1)),
+	[RST_APB2_I2C2]		= RESET(0x2d8, BIT(2)),
+	[RST_APB2_I2C3]		= RESET(0x2d8, BIT(3)),
 	[RST_APB2_UART0]	= RESET(0x2d8, BIT(16)),
 	[RST_APB2_UART1]	= RESET(0x2d8, BIT(17)),
 	[RST_APB2_UART2]	= RESET(0x2d8, BIT(18)),

+ 59 - 0
drivers/clk/sunxi/clk_a31_r.c

@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) Samuel Holland <samuel@sholland.org>
+ */
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <clk/sunxi.h>
+#include <dt-bindings/clock/sun8i-r-ccu.h>
+#include <dt-bindings/reset/sun8i-r-ccu.h>
+#include <linux/bitops.h>
+
+static struct ccu_clk_gate a31_r_gates[] = {
+	[CLK_APB0_PIO]		= GATE(0x028, BIT(0)),
+	[CLK_APB0_IR]		= GATE(0x028, BIT(1)),
+	[CLK_APB0_TIMER]	= GATE(0x028, BIT(2)),
+	[CLK_APB0_RSB]		= GATE(0x028, BIT(3)),
+	[CLK_APB0_UART]		= GATE(0x028, BIT(4)),
+	[CLK_APB0_I2C]		= GATE(0x028, BIT(6)),
+	[CLK_APB0_TWD]		= GATE(0x028, BIT(7)),
+};
+
+static struct ccu_reset a31_r_resets[] = {
+	[RST_APB0_IR]		= RESET(0x0b0, BIT(1)),
+	[RST_APB0_TIMER]	= RESET(0x0b0, BIT(2)),
+	[RST_APB0_RSB]		= RESET(0x0b0, BIT(3)),
+	[RST_APB0_UART]		= RESET(0x0b0, BIT(4)),
+	[RST_APB0_I2C]		= RESET(0x0b0, BIT(6)),
+};
+
+static const struct ccu_desc a31_r_ccu_desc = {
+	.gates = a31_r_gates,
+	.resets = a31_r_resets,
+};
+
+static int a31_r_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, ARRAY_SIZE(a31_r_resets));
+}
+
+static const struct udevice_id a31_r_clk_ids[] = {
+	{ .compatible = "allwinner,sun8i-a83t-r-ccu",
+	  .data = (ulong)&a31_r_ccu_desc },
+	{ .compatible = "allwinner,sun8i-h3-r-ccu",
+	  .data = (ulong)&a31_r_ccu_desc },
+	{ .compatible = "allwinner,sun50i-a64-r-ccu",
+	  .data = (ulong)&a31_r_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun6i_a31_r) = {
+	.name		= "sun6i_a31_r_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= a31_r_clk_ids,
+	.priv_auto	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= a31_r_clk_bind,
+};

+ 7 - 1
drivers/clk/sunxi/clk_a64.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun50i-a64-ccu.h>
 #include <dt-bindings/reset/sun50i-a64-ccu.h>
 #include <linux/bitops.h>
@@ -26,6 +26,9 @@ static const struct ccu_clk_gate a64_gates[] = {
 	[CLK_BUS_OHCI0]		= GATE(0x060, BIT(28)),
 	[CLK_BUS_OHCI1]		= GATE(0x060, BIT(29)),
 
+	[CLK_BUS_I2C0]		= GATE(0x06c, BIT(0)),
+	[CLK_BUS_I2C1]		= GATE(0x06c, BIT(1)),
+	[CLK_BUS_I2C2]		= GATE(0x06c, BIT(2)),
 	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
 	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
 	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
@@ -60,6 +63,9 @@ static const struct ccu_reset a64_resets[] = {
 	[RST_BUS_OHCI0]         = RESET(0x2c0, BIT(28)),
 	[RST_BUS_OHCI1]         = RESET(0x2c0, BIT(29)),
 
+	[RST_BUS_I2C0]		= RESET(0x2d8, BIT(0)),
+	[RST_BUS_I2C1]		= RESET(0x2d8, BIT(1)),
+	[RST_BUS_I2C2]		= RESET(0x2d8, BIT(2)),
 	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
 	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
 	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),

+ 11 - 1
drivers/clk/sunxi/clk_a80.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun9i-a80-ccu.h>
 #include <dt-bindings/reset/sun9i-a80-ccu.h>
 #include <linux/bitops.h>
@@ -25,6 +25,11 @@ static const struct ccu_clk_gate a80_gates[] = {
 	[CLK_BUS_SPI2]		= GATE(0x580, BIT(22)),
 	[CLK_BUS_SPI3]		= GATE(0x580, BIT(23)),
 
+	[CLK_BUS_I2C0]		= GATE(0x594, BIT(0)),
+	[CLK_BUS_I2C1]		= GATE(0x594, BIT(1)),
+	[CLK_BUS_I2C2]		= GATE(0x594, BIT(2)),
+	[CLK_BUS_I2C3]		= GATE(0x594, BIT(3)),
+	[CLK_BUS_I2C4]		= GATE(0x594, BIT(4)),
 	[CLK_BUS_UART0]		= GATE(0x594, BIT(16)),
 	[CLK_BUS_UART1]		= GATE(0x594, BIT(17)),
 	[CLK_BUS_UART2]		= GATE(0x594, BIT(18)),
@@ -40,6 +45,11 @@ static const struct ccu_reset a80_resets[] = {
 	[RST_BUS_SPI2]		= RESET(0x5a0, BIT(22)),
 	[RST_BUS_SPI3]		= RESET(0x5a0, BIT(23)),
 
+	[RST_BUS_I2C0]		= RESET(0x5b4, BIT(0)),
+	[RST_BUS_I2C1]		= RESET(0x5b4, BIT(1)),
+	[RST_BUS_I2C2]		= RESET(0x5b4, BIT(2)),
+	[RST_BUS_I2C3]		= RESET(0x5b4, BIT(3)),
+	[RST_BUS_I2C4]		= RESET(0x5b4, BIT(4)),
 	[RST_BUS_UART0]		= RESET(0x5b4, BIT(16)),
 	[RST_BUS_UART1]		= RESET(0x5b4, BIT(17)),
 	[RST_BUS_UART2]		= RESET(0x5b4, BIT(18)),

+ 7 - 1
drivers/clk/sunxi/clk_a83t.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun8i-a83t-ccu.h>
 #include <dt-bindings/reset/sun8i-a83t-ccu.h>
 #include <linux/bitops.h>
@@ -25,6 +25,9 @@ static struct ccu_clk_gate a83t_gates[] = {
 	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(27)),
 	[CLK_BUS_OHCI0]		= GATE(0x060, BIT(29)),
 
+	[CLK_BUS_I2C0]		= GATE(0x06c, BIT(0)),
+	[CLK_BUS_I2C1]		= GATE(0x06c, BIT(1)),
+	[CLK_BUS_I2C2]		= GATE(0x06c, BIT(2)),
 	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
 	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
 	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
@@ -57,6 +60,9 @@ static struct ccu_reset a83t_resets[] = {
 	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(27)),
 	[RST_BUS_OHCI0]		= RESET(0x2c0, BIT(29)),
 
+	[RST_BUS_I2C0]		= RESET(0x2d8, BIT(0)),
+	[RST_BUS_I2C1]		= RESET(0x2d8, BIT(1)),
+	[RST_BUS_I2C2]		= RESET(0x2d8, BIT(2)),
 	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
 	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
 	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),

+ 7 - 1
drivers/clk/sunxi/clk_h3.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun8i-h3-ccu.h>
 #include <dt-bindings/reset/sun8i-h3-ccu.h>
 #include <linux/bitops.h>
@@ -30,6 +30,9 @@ static struct ccu_clk_gate h3_gates[] = {
 	[CLK_BUS_OHCI2]		= GATE(0x060, BIT(30)),
 	[CLK_BUS_OHCI3]		= GATE(0x060, BIT(31)),
 
+	[CLK_BUS_I2C0]		= GATE(0x06c, BIT(0)),
+	[CLK_BUS_I2C1]		= GATE(0x06c, BIT(1)),
+	[CLK_BUS_I2C2]		= GATE(0x06c, BIT(2)),
 	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
 	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
 	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
@@ -74,6 +77,9 @@ static struct ccu_reset h3_resets[] = {
 
 	[RST_BUS_EPHY]		= RESET(0x2c8, BIT(2)),
 
+	[RST_BUS_I2C0]		= RESET(0x2d8, BIT(0)),
+	[RST_BUS_I2C1]		= RESET(0x2d8, BIT(1)),
+	[RST_BUS_I2C2]		= RESET(0x2d8, BIT(2)),
 	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
 	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
 	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),

+ 11 - 1
drivers/clk/sunxi/clk_h6.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun50i-h6-ccu.h>
 #include <dt-bindings/reset/sun50i-h6-ccu.h>
 #include <linux/bitops.h>
@@ -22,6 +22,11 @@ static struct ccu_clk_gate h6_gates[] = {
 	[CLK_BUS_UART2]		= GATE(0x90c, BIT(2)),
 	[CLK_BUS_UART3]		= GATE(0x90c, BIT(3)),
 
+	[CLK_BUS_I2C0]		= GATE(0x91c, BIT(0)),
+	[CLK_BUS_I2C1]		= GATE(0x91c, BIT(1)),
+	[CLK_BUS_I2C2]		= GATE(0x91c, BIT(2)),
+	[CLK_BUS_I2C3]		= GATE(0x91c, BIT(3)),
+
 	[CLK_SPI0]		= GATE(0x940, BIT(31)),
 	[CLK_SPI1]		= GATE(0x944, BIT(31)),
 
@@ -57,6 +62,11 @@ static struct ccu_reset h6_resets[] = {
 	[RST_BUS_UART2]		= RESET(0x90c, BIT(18)),
 	[RST_BUS_UART3]		= RESET(0x90c, BIT(19)),
 
+	[RST_BUS_I2C0]		= RESET(0x91c, BIT(16)),
+	[RST_BUS_I2C1]		= RESET(0x91c, BIT(17)),
+	[RST_BUS_I2C2]		= RESET(0x91c, BIT(18)),
+	[RST_BUS_I2C3]		= RESET(0x91c, BIT(19)),
+
 	[RST_BUS_SPI0]		= RESET(0x96c, BIT(16)),
 	[RST_BUS_SPI1]		= RESET(0x96c, BIT(17)),
 

+ 13 - 1
drivers/clk/sunxi/clk_h616.c

@@ -7,7 +7,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun50i-h616-ccu.h>
 #include <dt-bindings/reset/sun50i-h616-ccu.h>
 #include <linux/bitops.h>
@@ -24,6 +24,12 @@ static struct ccu_clk_gate h616_gates[] = {
 	[CLK_BUS_UART4]		= GATE(0x90c, BIT(4)),
 	[CLK_BUS_UART5]		= GATE(0x90c, BIT(5)),
 
+	[CLK_BUS_I2C0]		= GATE(0x91c, BIT(0)),
+	[CLK_BUS_I2C1]		= GATE(0x91c, BIT(1)),
+	[CLK_BUS_I2C2]		= GATE(0x91c, BIT(2)),
+	[CLK_BUS_I2C3]		= GATE(0x91c, BIT(3)),
+	[CLK_BUS_I2C4]		= GATE(0x91c, BIT(4)),
+
 	[CLK_SPI0]		= GATE(0x940, BIT(31)),
 	[CLK_SPI1]		= GATE(0x944, BIT(31)),
 
@@ -68,6 +74,12 @@ static struct ccu_reset h616_resets[] = {
 	[RST_BUS_UART4]		= RESET(0x90c, BIT(20)),
 	[RST_BUS_UART5]		= RESET(0x90c, BIT(21)),
 
+	[RST_BUS_I2C0]		= RESET(0x91c, BIT(16)),
+	[RST_BUS_I2C1]		= RESET(0x91c, BIT(17)),
+	[RST_BUS_I2C2]		= RESET(0x91c, BIT(18)),
+	[RST_BUS_I2C3]		= RESET(0x91c, BIT(19)),
+	[RST_BUS_I2C4]		= RESET(0x91c, BIT(20)),
+
 	[RST_BUS_SPI0]		= RESET(0x96c, BIT(16)),
 	[RST_BUS_SPI1]		= RESET(0x96c, BIT(17)),
 

+ 61 - 0
drivers/clk/sunxi/clk_h6_r.c

@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) Samuel Holland <samuel@sholland.org>
+ */
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <clk/sunxi.h>
+#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
+#include <linux/bitops.h>
+
+static struct ccu_clk_gate h6_r_gates[] = {
+	[CLK_R_APB1_TIMER]	= GATE(0x11c, BIT(0)),
+	[CLK_R_APB1_TWD]	= GATE(0x12c, BIT(0)),
+	[CLK_R_APB1_PWM]	= GATE(0x13c, BIT(0)),
+	[CLK_R_APB2_UART]	= GATE(0x18c, BIT(0)),
+	[CLK_R_APB2_I2C]	= GATE(0x19c, BIT(0)),
+	[CLK_R_APB2_RSB]	= GATE(0x1bc, BIT(0)),
+	[CLK_R_APB1_IR]		= GATE(0x1cc, BIT(0)),
+	[CLK_R_APB1_W1]		= GATE(0x1ec, BIT(0)),
+};
+
+static struct ccu_reset h6_r_resets[] = {
+	[RST_R_APB1_TIMER]	= RESET(0x11c, BIT(16)),
+	[RST_R_APB1_TWD]	= RESET(0x12c, BIT(16)),
+	[RST_R_APB1_PWM]	= RESET(0x13c, BIT(16)),
+	[RST_R_APB2_UART]	= RESET(0x18c, BIT(16)),
+	[RST_R_APB2_I2C]	= RESET(0x19c, BIT(16)),
+	[RST_R_APB2_RSB]	= RESET(0x1bc, BIT(16)),
+	[RST_R_APB1_IR]		= RESET(0x1cc, BIT(16)),
+	[RST_R_APB1_W1]		= RESET(0x1ec, BIT(16)),
+};
+
+static const struct ccu_desc h6_r_ccu_desc = {
+	.gates = h6_r_gates,
+	.resets = h6_r_resets,
+};
+
+static int h6_r_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, ARRAY_SIZE(h6_r_resets));
+}
+
+static const struct udevice_id h6_r_clk_ids[] = {
+	{ .compatible = "allwinner,sun50i-h6-r-ccu",
+	  .data = (ulong)&h6_r_ccu_desc },
+	{ .compatible = "allwinner,sun50i-h616-r-ccu",
+	  .data = (ulong)&h6_r_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun6i_h6_r) = {
+	.name		= "sun6i_h6_r_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= h6_r_clk_ids,
+	.priv_auto	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= h6_r_clk_bind,
+};

+ 11 - 1
drivers/clk/sunxi/clk_r40.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun8i-r40-ccu.h>
 #include <dt-bindings/reset/sun8i-r40-ccu.h>
 #include <linux/bitops.h>
@@ -32,6 +32,11 @@ static struct ccu_clk_gate r40_gates[] = {
 
 	[CLK_BUS_GMAC]		= GATE(0x064, BIT(17)),
 
+	[CLK_BUS_I2C0]		= GATE(0x06c, BIT(0)),
+	[CLK_BUS_I2C1]		= GATE(0x06c, BIT(1)),
+	[CLK_BUS_I2C2]		= GATE(0x06c, BIT(2)),
+	[CLK_BUS_I2C3]		= GATE(0x06c, BIT(3)),
+	[CLK_BUS_I2C4]		= GATE(0x06c, BIT(15)),
 	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
 	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
 	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
@@ -77,6 +82,11 @@ static struct ccu_reset r40_resets[] = {
 
 	[RST_BUS_GMAC]		= RESET(0x2c4, BIT(17)),
 
+	[RST_BUS_I2C0]		= RESET(0x2d8, BIT(0)),
+	[RST_BUS_I2C1]		= RESET(0x2d8, BIT(1)),
+	[RST_BUS_I2C2]		= RESET(0x2d8, BIT(2)),
+	[RST_BUS_I2C3]		= RESET(0x2d8, BIT(3)),
+	[RST_BUS_I2C4]		= RESET(0x2d8, BIT(15)),
 	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
 	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
 	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),

+ 1 - 1
drivers/clk/sunxi/clk_sunxi.c

@@ -11,7 +11,7 @@
 #include <log.h>
 #include <reset.h>
 #include <asm/io.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <linux/bitops.h>
 #include <linux/log2.h>
 

+ 5 - 1
drivers/clk/sunxi/clk_v3s.c

@@ -8,7 +8,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
-#include <asm/arch/ccu.h>
+#include <clk/sunxi.h>
 #include <dt-bindings/clock/sun8i-v3s-ccu.h>
 #include <dt-bindings/reset/sun8i-v3s-ccu.h>
 #include <linux/bitops.h>
@@ -20,6 +20,8 @@ static struct ccu_clk_gate v3s_gates[] = {
 	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
 
+	[CLK_BUS_I2C0]		= GATE(0x06c, BIT(0)),
+	[CLK_BUS_I2C1]		= GATE(0x06c, BIT(1)),
 	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
 	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
 	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
@@ -38,6 +40,8 @@ static struct ccu_reset v3s_resets[] = {
 	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
 	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
 
+	[RST_BUS_I2C0]		= RESET(0x2d8, BIT(0)),
+	[RST_BUS_I2C1]		= RESET(0x2d8, BIT(1)),
 	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
 	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
 	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),

+ 0 - 1
drivers/gpio/axp_gpio.c

@@ -6,7 +6,6 @@
  */
 
 #include <common.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/pmic_bus.h>
 #include <asm/gpio.h>
 #include <axp_pmic.h>

+ 0 - 17
drivers/gpio/sunxi_gpio.c

@@ -14,14 +14,11 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
-#include <asm/arch/gpio.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <dm/device-internal.h>
 #include <dt-bindings/gpio/gpio.h>
 
-#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" */
@@ -118,20 +115,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)

+ 16 - 0
drivers/i2c/Kconfig

@@ -575,6 +575,22 @@ 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_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

+ 2 - 0
drivers/i2c/Makefile

@@ -43,6 +43,8 @@ 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_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

+ 220 - 0
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 <oliver@schinagl.nl>
+ * http://linux-sunxi.org
+ *
+ * Based on sun6i sources and earlier U-Boot Allwinner A10 SPL work
+ *
+ * (C) Copyright 2006-2013
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Berg Xing <bergxing@allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ */
+
+#include <axp_pmic.h>
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+#include <time.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/p2wi.h>
+#include <asm/arch/prcm.h>
+#include <asm/arch/sys_proto.h>
+
+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) */

+ 281 - 0
drivers/i2c/sun8i_rsb.c

@@ -0,0 +1,281 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on allwinner u-boot sources rsb code which is:
+ * (C) Copyright 2007-2013
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * lixiang <lixiang@allwinnertech.com>
+ */
+
+#include <axp_pmic.h>
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+#include <time.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/prcm.h>
+#include <asm/arch/rsb.h>
+
+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) */

+ 1 - 2
drivers/mmc/sunxi_mmc.c

@@ -15,12 +15,11 @@
 #include <mmc.h>
 #include <clk.h>
 #include <reset.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
-#include <asm-generic/gpio.h>
 #include <linux/delay.h>
 
 #ifndef CCM_MMC_CTRL_MODE_SEL_NEW

+ 1 - 4
drivers/net/sun8i_emac.c

@@ -14,9 +14,9 @@
 #include <log.h>
 #include <asm/cache.h>
 #include <asm/global_data.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
-#include <asm/arch/gpio.h>
 #include <common.h>
 #include <clk.h>
 #include <dm.h>
@@ -31,9 +31,6 @@
 #include <reset.h>
 #include <dt-bindings/pinctrl/sun4i-a10.h>
 #include <wait_bit.h>
-#if CONFIG_IS_ENABLED(DM_GPIO)
-#include <asm-generic/gpio.h>
-#endif
 
 #define MDIO_CMD_MII_BUSY		BIT(0)
 #define MDIO_CMD_MII_WRITE		BIT(1)

+ 0 - 1
drivers/power/axp809.c

@@ -13,7 +13,6 @@
 #include <common.h>
 #include <command.h>
 #include <errno.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/pmic_bus.h>
 #include <axp_pmic.h>
 

+ 0 - 1
drivers/power/axp818.c

@@ -13,7 +13,6 @@
 #include <common.h>
 #include <command.h>
 #include <errno.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/pmic_bus.h>
 #include <axp_pmic.h>
 

+ 40 - 44
drivers/power/pmic/Kconfig

@@ -10,10 +10,12 @@ config DM_PMIC
 	- 'drivers/power/pmic/pmic-uclass.c'
 	- 'include/power/pmic.h'
 
+if DM_PMIC
+
 config SPL_DM_PMIC
 	bool "Enable Driver Model for PMIC drivers (UCLASS_PMIC) in SPL"
 	depends on SPL_DM
-	default y if DM_PMIC
+	default y
 	---help---
 	This config enables the driver-model PMIC support in SPL.
 	UCLASS_PMIC - designed to provide an I/O interface for PMIC devices.
@@ -25,7 +27,6 @@ config SPL_DM_PMIC
 
 config PMIC_CHILDREN
 	bool "Allow child devices for PMICs"
-	depends on DM_PMIC
 	default y
 	---help---
 	This allows PMICs to support child devices (such as regulators) in
@@ -35,7 +36,7 @@ config PMIC_CHILDREN
 
 config SPL_PMIC_CHILDREN
 	bool "Allow child devices for PMICs in SPL"
-	depends on DM_PMIC
+	depends on SPL_DM_PMIC
 	default y
 	---help---
 	This allows PMICs to support child devices (such as regulators) in
@@ -46,7 +47,6 @@ config SPL_PMIC_CHILDREN
 
 config PMIC_AB8500
 	bool "Enable driver for ST-Ericsson AB8500 PMIC via PRCMU"
-	depends on DM_PMIC
 	select REGMAP
 	select SYSCON
 	help
@@ -56,23 +56,36 @@ config PMIC_AB8500
 
 config PMIC_ACT8846
 	bool "Enable support for the active-semi 8846 PMIC"
-	depends on DM_PMIC && DM_I2C
+	depends on DM_I2C
 	---help---
 	This PMIC includes 4 DC/DC step-down buck regulators and 8 low-dropout
 	regulators (LDOs). It also provides some GPIO, reset and battery
 	functions. It uses an I2C interface and is designed for use with
 	tablets and smartphones.
 
+config PMIC_AXP
+	bool "Enable Driver Model for X-Powers AXP PMICs"
+	depends on DM_I2C
+	help
+	  This config enables driver-model PMIC uclass features for
+	  X-Powers AXP152, AXP2xx, and AXP8xx PMICs.
+
+config SPL_PMIC_AXP
+	bool "Enable Driver Model for X-Powers AXP PMICs in SPL"
+	depends on SPL_DM_I2C && SPL_DM_PMIC
+	help
+	  This config enables driver-model PMIC uclass features in the SPL for
+	  X-Powers AXP152, AXP2xx, and AXP8xx PMICs.
+
 config DM_PMIC_DA9063
 	bool "Enable Driver Model for the Dialog DA9063 PMIC"
-	depends on DM_PMIC
 	help
 	  This config enables implementation of driver-model pmic uclass features
 	  for PMIC DA9063. The driver implements read/write operations.
 
 config SPL_DM_PMIC_DA9063
 	bool "Enable Driver Model for the Dialog DA9063 PMIC in SPL"
-	depends on DM_PMIC && SPL
+	depends on SPL_DM_PMIC
 	help
 	  This config enables implementation of driver-model pmic uclass features
 	  for PMIC DA9063. The driver implements read/write operations.
@@ -87,14 +100,13 @@ config PMIC_AS3722
 
 config DM_PMIC_BD71837
  	bool "Enable Driver Model for PMIC BD71837"
- 	depends on DM_PMIC
  	help
 	  This config enables implementation of driver-model pmic uclass features
 	  for PMIC BD71837. The driver implements read/write operations.
 
 config SPL_DM_PMIC_BD71837
 	bool "Enable Driver Model for PMIC BD71837 in SPL stage"
-	depends on DM_PMIC
+	depends on SPL_DM_PMIC
 	help
 	  This config enables implementation of driver-model pmic uclass
 	  features for PMIC BD71837. The driver implements read/write
@@ -102,7 +114,7 @@ config SPL_DM_PMIC_BD71837
 
 config DM_PMIC_FAN53555
 	bool "Enable support for OnSemi FAN53555"
-	depends on DM_PMIC && DM_REGULATOR && DM_I2C
+	depends on DM_REGULATOR && DM_I2C
 	select DM_REGULATOR_FAN53555
 	help
 	  This config enables implementation of driver-model PMIC
@@ -116,14 +128,13 @@ config DM_PMIC_FAN53555
 
 config DM_PMIC_MP5416
 	bool "Enable Driver Model for PMIC MP5416"
-	depends on DM_PMIC
 	help
 	  This config enables implementation of driver-model pmic uclass features
 	  for PMIC MP5416. The driver implements read/write operations.
 
 config SPL_DM_PMIC_MP5416
 	bool "Enable Driver Model for PMIC MP5416 in SPL stage"
-	depends on DM_PMIC
+	depends on SPL_DM_PMIC
 	help
 	  This config enables implementation of driver-model pmic uclass
 	  features for PMIC MP5416. The driver implements read/write
@@ -131,56 +142,50 @@ config SPL_DM_PMIC_MP5416
 
 config DM_PMIC_PCA9450
 	bool "Enable Driver Model for PMIC PCA9450"
-	depends on DM_PMIC
 	help
 	  This config enables implementation of driver-model pmic uclass features
 	  for PMIC PCA9450. The driver implements read/write operations.
 
 config SPL_DM_PMIC_PCA9450
 	bool "Enable Driver Model for PMIC PCA9450"
-	depends on DM_PMIC
+	depends on SPL_DM_PMIC
 	help
 	  This config enables implementation of driver-model pmic uclass features
 	  for PMIC PCA9450 in SPL. The driver implements read/write operations.
 
 config DM_PMIC_PFUZE100
 	bool "Enable Driver Model for PMIC PFUZE100"
-	depends on DM_PMIC
 	---help---
 	This config enables implementation of driver-model pmic uclass features
 	for PMIC PFUZE100. The driver implements read/write operations.
 
 config SPL_DM_PMIC_PFUZE100
 	bool "Enable Driver Model for PMIC PFUZE100 in SPL"
-	depends on DM_PMIC
+	depends on SPL_DM_PMIC
 	---help---
 	This config enables implementation of driver-model pmic uclass features
 	for PMIC PFUZE100 in SPL. The driver implements read/write operations.
 
 config DM_PMIC_MAX77686
 	bool "Enable Driver Model for PMIC MAX77686"
-	depends on DM_PMIC
 	---help---
 	This config enables implementation of driver-model pmic uclass features
 	for PMIC MAX77686. The driver implements read/write operations.
 
 config DM_PMIC_MAX8998
 	bool "Enable Driver Model for PMIC MAX8998"
-	depends on DM_PMIC
 	---help---
 	This config enables implementation of driver-model pmic uclass features
 	for PMIC MAX8998. The driver implements read/write operations.
 
 config DM_PMIC_MC34708
 	bool "Enable Driver Model for PMIC MC34708"
-	depends on DM_PMIC
 	help
 	 This config enables implementation of driver-model pmic uclass features
 	 for PMIC MC34708. The driver implements read/write operations.
 
 config PMIC_MAX8997
 	bool "Enable Driver Model for PMIC MAX8997"
-	depends on DM_PMIC
 	---help---
 	This config enables implementation of driver-model pmic uclass features
 	for PMIC MAX8997. The driver implements read/write operations.
@@ -195,7 +200,6 @@ config PMIC_MAX8997
 
 config PMIC_PM8916
 	bool "Enable Driver Model for Qualcomm PM8916 PMIC"
-	depends on DM_PMIC
 	---help---
 	The PM8916 is a PMIC connected to one (or several) processors
 	with SPMI bus. It has 2 slaves with several peripherals:
@@ -211,7 +215,6 @@ config PMIC_PM8916
 
 config PMIC_RK8XX
 	bool "Enable support for Rockchip PMIC RK8XX"
-	depends on DM_PMIC
 	---help---
 	The Rockchip RK808 PMIC provides four buck DC-DC convertors, 8 LDOs,
 	an RTC and two low Rds (resistance (drain to source)) switches. It is
@@ -220,7 +223,7 @@ config PMIC_RK8XX
 
 config SPL_PMIC_RK8XX
 	bool "Enable support for Rockchip PMIC RK8XX"
-	depends on DM_PMIC
+	depends on SPL_DM_PMIC
 	---help---
 	The Rockchip RK808 PMIC provides four buck DC-DC convertors, 8 LDOs,
 	an RTC and two low Rds (resistance (drain to source)) switches. It is
@@ -229,7 +232,6 @@ config SPL_PMIC_RK8XX
 
 config PMIC_S2MPS11
 	bool "Enable Driver Model for PMIC Samsung S2MPS11"
-	depends on DM_PMIC
 	---help---
 	The Samsung S2MPS11 PMIC provides:
 	 - 38 adjustable LDO regulators
@@ -243,7 +245,6 @@ config PMIC_S2MPS11
 
 config DM_PMIC_SANDBOX
 	bool "Enable Driver Model for emulated Sandbox PMIC"
-	depends on DM_PMIC
 	---help---
 	Enable the driver for Sandbox PMIC emulation. The emulated PMIC device
 	depends on two drivers:
@@ -268,7 +269,6 @@ config DM_PMIC_SANDBOX
 
 config PMIC_S5M8767
 	bool "Enable Driver Model for the Samsung S5M8767 PMIC"
-	depends on DM_PMIC
 	---help---
 	The S5M8767 PMIC provides a large array of LDOs and BUCKs for use
 	as a SoC power controller. It also provides 32KHz clock outputs. This
@@ -277,7 +277,6 @@ config PMIC_S5M8767
 
 config PMIC_RN5T567
 	bool "Enable driver for Ricoh RN5T567 PMIC"
-	depends on DM_PMIC
 	---help---
 	The RN5T567 is a PMIC with 4 step-down DC/DC converters, 5 LDO
 	regulators Real-Time Clock and 4 GPIOs. This driver provides
@@ -285,7 +284,6 @@ config PMIC_RN5T567
 
 config PMIC_TPS65090
 	bool "Enable driver for Texas Instruments TPS65090 PMIC"
-	depends on DM_PMIC
 	---help---
 	The TPS65090 is a PMIC containing several LDOs, DC to DC convertors,
 	FETs and a battery charger. This driver provides register access
@@ -294,35 +292,24 @@ config PMIC_TPS65090
 
 config PMIC_PALMAS
 	bool "Enable driver for Texas Instruments PALMAS PMIC"
-	depends on DM_PMIC
 	---help---
 	The PALMAS is a PMIC containing several LDOs, SMPS.
 	This driver binds the pmic children.
 
 config PMIC_LP873X
 	bool "Enable driver for Texas Instruments LP873X PMIC"
-	depends on DM_PMIC
 	---help---
 	The LP873X is a PMIC containing couple of LDOs and couple of SMPS.
 	This driver binds the pmic children.
 
 config PMIC_LP87565
 	bool "Enable driver for Texas Instruments LP87565 PMIC"
-	depends on DM_PMIC
 	---help---
 	The LP87565 is a PMIC containing a bunch of SMPS.
 	This driver binds the pmic children.
 
-config POWER_MC34VR500
-	bool "Enable driver for Freescale MC34VR500 PMIC"
-	---help---
-	The MC34VR500 is used in conjunction with the FSL T1 and LS1 series
-	SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is accessed
-	via an I2C interface.
-
 config DM_PMIC_TPS65910
 	bool "Enable driver for Texas Instruments TPS65910 PMIC"
-	depends on DM_PMIC
 	---help---
 	The TPS65910 is a PMIC containing 3 buck DC-DC converters, one boost
 	DC-DC converter, 8 LDOs and a RTC. This driver binds the SMPS and LDO
@@ -330,7 +317,7 @@ config DM_PMIC_TPS65910
 
 config PMIC_STPMIC1
 	bool "Enable support for STMicroelectronics STPMIC1 PMIC"
-	depends on DM_PMIC && DM_I2C
+	depends on DM_I2C
 	select SYSRESET_CMD_POWEROFF if CMD_POWEROFF && !ARM_PSCI_FW
 	---help---
 	The STPMIC1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches.
@@ -339,28 +326,37 @@ config PMIC_STPMIC1
 
 config SPL_PMIC_PALMAS
 	bool "Enable driver for Texas Instruments PALMAS PMIC"
-	depends on DM_PMIC
+	depends on SPL_DM_PMIC
 	help
 	The PALMAS is a PMIC containing several LDOs, SMPS.
 	This driver binds the pmic children in SPL.
 
 config SPL_PMIC_LP873X
 	bool "Enable driver for Texas Instruments LP873X PMIC"
-	depends on DM_PMIC
+	depends on SPL_DM_PMIC
 	help
 	The LP873X is a PMIC containing couple of LDOs and couple of SMPS.
 	This driver binds the pmic children in SPL.
 
 config SPL_PMIC_LP87565
 	bool "Enable driver for Texas Instruments LP87565 PMIC"
-	depends on DM_PMIC
+	depends on SPL_DM_PMIC
 	help
 	The LP87565 is a PMIC containing a bunch of SMPS.
 	This driver binds the pmic children in SPL.
 
 config PMIC_TPS65941
 	bool "Enable driver for Texas Instruments TPS65941 PMIC"
-	depends on DM_PMIC
 	help
 	The TPS65941 is a PMIC containing a bunch of SMPS & LDOs.
 	This driver binds the pmic children.
+
+endif
+
+config POWER_MC34VR500
+	bool "Enable driver for Freescale MC34VR500 PMIC"
+	depends on !DM_PMIC
+	---help---
+	The MC34VR500 is used in conjunction with the FSL T1 and LS1 series
+	SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is accessed
+	via an I2C interface.

+ 1 - 0
drivers/power/pmic/Makefile

@@ -18,6 +18,7 @@ obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
 obj-$(CONFIG_PMIC_AB8500) += ab8500.o
 obj-$(CONFIG_PMIC_ACT8846) += act8846.o
 obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o
+obj-$(CONFIG_$(SPL_)PMIC_AXP) += axp.o
 obj-$(CONFIG_PMIC_MAX8997) += max8997.o
 obj-$(CONFIG_PMIC_PM8916) += pm8916.o
 obj-$(CONFIG_$(SPL_TPL_)PMIC_RK8XX) += rk8xx.o

+ 38 - 0
drivers/power/pmic/axp.c

@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+
+static int axp_pmic_reg_count(struct udevice *dev)
+{
+	/* TODO: Get the specific value from driver data. */
+	return 0x100;
+}
+
+static struct dm_pmic_ops axp_pmic_ops = {
+	.reg_count	= axp_pmic_reg_count,
+	.read		= dm_i2c_read,
+	.write		= dm_i2c_write,
+};
+
+static const struct udevice_id axp_pmic_ids[] = {
+	{ .compatible = "x-powers,axp152" },
+	{ .compatible = "x-powers,axp202" },
+	{ .compatible = "x-powers,axp209" },
+	{ .compatible = "x-powers,axp221" },
+	{ .compatible = "x-powers,axp223" },
+	{ .compatible = "x-powers,axp803" },
+	{ .compatible = "x-powers,axp806" },
+	{ .compatible = "x-powers,axp809" },
+	{ .compatible = "x-powers,axp813" },
+	{ }
+};
+
+U_BOOT_DRIVER(axp_pmic) = {
+	.name		= "axp_pmic",
+	.id		= UCLASS_PMIC,
+	.of_match	= axp_pmic_ids,
+	.bind		= dm_scan_fdt_dev,
+	.ops		= &axp_pmic_ops,
+};

+ 1 - 1
drivers/reset/reset-sunxi.c

@@ -11,11 +11,11 @@
 #include <malloc.h>
 #include <reset-uclass.h>
 #include <asm/io.h>
+#include <clk/sunxi.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 #include <linux/bitops.h>
 #include <linux/log2.h>
-#include <asm/arch/ccu.h>
 
 struct sunxi_reset_priv {
 	void *base;

+ 1 - 1
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;
 

+ 0 - 2
drivers/usb/musb-new/sunxi.c

@@ -25,8 +25,6 @@
 #include <reset.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/clock.h>
-#include <asm/arch/gpio.h>
-#include <asm-generic/gpio.h>
 #include <dm/device_compat.h>
 #include <dm/lists.h>
 #include <dm/root.h>

+ 5 - 5
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"

+ 52 - 51
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);
 }

+ 3 - 2
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

+ 3 - 3
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");

+ 43 - 23
drivers/video/sunxi/sunxi_display.c

@@ -17,7 +17,6 @@
 
 #include <asm/arch/clock.h>
 #include <asm/arch/display.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/lcdc.h>
 #include <asm/arch/pwm.h>
 #include <asm/arch/tve.h>
@@ -872,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
@@ -902,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();
@@ -936,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();

+ 0 - 1
drivers/video/sunxi/sunxi_lcd.c

@@ -15,7 +15,6 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/lcdc.h>
-#include <asm/arch/gpio.h>
 #include <asm/global_data.h>
 #include <asm/gpio.h>
 

+ 12 - 0
include/axp_pmic.h

@@ -6,6 +6,8 @@
  */
 #ifndef _AXP_PMIC_H_
 
+#include <stdbool.h>
+
 #ifdef CONFIG_AXP152_POWER
 #include <axp152.h>
 #endif
@@ -25,6 +27,16 @@
 #include <axp818.h>
 #endif
 
+#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);
 int axp_set_dcdc3(unsigned int mvolt);

+ 3 - 5
arch/arm/include/asm/arch-sunxi/ccu.h → include/clk/sunxi.h

@@ -4,12 +4,10 @@
  * Author: Jagan Teki <jagan@amarulasolutions.com>
  */
 
-#ifndef _ASM_ARCH_CCU_H
-#define _ASM_ARCH_CCU_H
+#ifndef _CLK_SUNXI_H
+#define _CLK_SUNXI_H
 
-#ifndef __ASSEMBLY__
 #include <linux/bitops.h>
-#endif
 
 /**
  * enum ccu_flags - ccu clock/reset flags
@@ -97,4 +95,4 @@ extern struct clk_ops sunxi_clk_ops;
  */
 int sunxi_reset_bind(struct udevice *dev, ulong count);
 
-#endif /* _ASM_ARCH_CCU_H */
+#endif /* _CLK_SUNXI_H */

+ 0 - 17
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