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
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 \
--- /dev/null
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ *
+ * Based on sun50i-h5-nanopi-neo-plus2.dts, which is:
+ * 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 = <®_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii-id";
+ status = "okay";
+};
+
+&external_mdio {
+ ext_rgmii_phy: ethernet-phy@7 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <7>;
+ };
+};
+
+&i2c0 {
+ status = "okay";
+
+ eeprom@51 {
+ compatible = "microchip,24c02";
+ reg = <0x51>;
+ pagesize = <16>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <®_vcc3v3>;
+ bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ status = "okay";
+};
+
+&mmc1 {
+ vmmc-supply = <®_vcc3v3>;
+ vqmmc-supply = <®_vcc3v3>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+
+ rtl8189etv: sdio_wifi@1 {
+ reg = <1>;
+ };
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&ohci2 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pa_pins>;
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ /* USB Type-A port's VBUS is always on */
+ usb0_id_det-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
+ usb0_vbus-supply = <®_usb0_vbus>;
+ status = "okay";
+};
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2018 Amarula Solutions.
- */
-
-#ifndef _ASM_ARCH_CCU_H
-#define _ASM_ARCH_CCU_H
-
-#ifndef __ASSEMBLY__
-#include <linux/bitops.h>
-#endif
-
-/**
- * enum ccu_flags - ccu clock/reset flags
- *
- * @CCU_CLK_F_IS_VALID: is given clock gate is valid?
- * @CCU_RST_F_IS_VALID: is given reset control is valid?
- */
-enum ccu_flags {
- CCU_CLK_F_IS_VALID = BIT(0),
- CCU_RST_F_IS_VALID = BIT(1),
-};
-
-/**
- * struct ccu_clk_gate - ccu clock gate
- * @off: gate offset
- * @bit: gate bit
- * @flags: ccu clock gate flags
- */
-struct ccu_clk_gate {
- u16 off;
- u32 bit;
- enum ccu_flags flags;
-};
-
-#define GATE(_off, _bit) { \
- .off = _off, \
- .bit = _bit, \
- .flags = CCU_CLK_F_IS_VALID, \
-}
-
-/**
- * struct ccu_reset - ccu reset
- * @off: reset offset
- * @bit: reset bit
- * @flags: ccu reset control flags
- */
-struct ccu_reset {
- u16 off;
- u32 bit;
- enum ccu_flags flags;
-};
-
-#define RESET(_off, _bit) { \
- .off = _off, \
- .bit = _bit, \
- .flags = CCU_RST_F_IS_VALID, \
-}
-
-/**
- * struct ccu_desc - clock control unit descriptor
- *
- * @gates: clock gates
- * @resets: reset unit
- */
-struct ccu_desc {
- const struct ccu_clk_gate *gates;
- const struct ccu_reset *resets;
-};
-
-/**
- * struct ccu_priv - sunxi clock control unit
- *
- * @base: base address
- * @desc: ccu descriptor
- */
-struct ccu_priv {
- void *base;
- const struct ccu_desc *desc;
-};
-
-/**
- * sunxi_clk_probe - common sunxi clock probe
- * @dev: clock device
- */
-int sunxi_clk_probe(struct udevice *dev);
-
-extern struct clk_ops sunxi_clk_ops;
-
-/**
- * sunxi_reset_bind() - reset binding
- *
- * @dev: reset device
- * @count: reset count
- * @return 0 success, or error value
- */
-int sunxi_reset_bind(struct udevice *dev, ulong count);
-
-#endif /* _ASM_ARCH_CCU_H */
#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,
#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
#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
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);
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
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
config MACH_SUNXI_H3_H5
bool
- select DM_I2C
select PHY_SUN4I_USB
select SUNXI_DE2
select SUNXI_DRAM_DW
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
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
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
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)"
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
# 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
---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"
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.
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
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
#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>
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
#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>
#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
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Sunxi A31 Power Management Unit
- *
- * 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>
- */
-
-#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();
-}
* 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
#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
}
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0+
-/*
- *
- * Based on allwinner u-boot sources rsb code which is:
- * (C) Copyright 2007-2013
- * Allwinner Technology Co., Ltd. <www.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;
-}
S: Maintained
F: configs/nanopi_neo_air_defconfig
+NANOPI-R1S-H5 BOARD
+S: Maintained
+F: configs/nanopi_r1s_h5_defconfig
+
NANOPI-A64 BOARD
S: Maintained
S: Maintained
F: configs/pinephone_defconfig
+PINETAB BOARD
+S: Maintained
+F: configs/pinetab_defconfig
+
R16 EVB PARROT BOARD
S: Maintained
#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>
#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;
#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;
}
/*
static void mmc_pinmux_setup(int sdc)
{
unsigned int pin;
- __maybe_unused int pins;
switch (sdc) {
case 0:
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);
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++) {
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++) {
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 */
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;
{
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
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
-#include <asm/arch/gpio.h>
void eth_init_board(void)
{
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"
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
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
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
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=""
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
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"
--- /dev/null
+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
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"
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
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
--- /dev/null
+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
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
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
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
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
#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>
[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)),
#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>
[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)),
#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>
[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)),
[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)),
#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>
[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)),
[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)),
--- /dev/null
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ */
+
+#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,
+};
#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>
[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)),
[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)),
#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>
[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)),
[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)),
#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>
[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)),
[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)),
#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>
[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)),
[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)),
#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>
[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)),
[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)),
#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>
[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)),
[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)),
--- /dev/null
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ */
+
+#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,
+};
#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>
[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)),
[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)),
#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>
#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>
[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)),
[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)),
*/
#include <common.h>
-#include <asm/arch/gpio.h>
#include <asm/arch/pmic_bus.h>
#include <asm/gpio.h>
#include <axp_pmic.h>
#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" */
}
#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)
int sunxi_name_to_gpio(const char *name)
_ 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
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
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Sunxi A31 Power Management Unit
+ *
+ * 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>
+ */
+
+#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) */
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *
+ * Based on allwinner u-boot sources rsb code which is:
+ * (C) Copyright 2007-2013
+ * Allwinner Technology Co., Ltd. <www.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) */
#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
#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>
#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)
#include <common.h>
#include <command.h>
#include <errno.h>
-#include <asm/arch/gpio.h>
#include <asm/arch/pmic_bus.h>
#include <axp_pmic.h>
#include <common.h>
#include <command.h>
#include <errno.h>
-#include <asm/arch/gpio.h>
#include <asm/arch/pmic_bus.h>
#include <axp_pmic.h>
- '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.
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
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
config PMIC_AB8500
bool "Enable driver for ST-Ericsson AB8500 PMIC via PRCMU"
- depends on DM_PMIC
select REGMAP
select SYSCON
help
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.
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
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
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
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.
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:
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
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
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
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:
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
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
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
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
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.
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.
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
--- /dev/null
+// 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,
+};
#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;
break;
}
- pin = name_to_gpio(pin_name);
+ pin = sunxi_name_to_gpio(pin_name);
if (pin < 0)
break;
#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>
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"
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"
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"
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)"
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"
* 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 */
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;
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;
}
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);
}
#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
};
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");
#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>
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
}
#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();
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();
#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>
*/
#ifndef _AXP_PMIC_H_
+#include <stdbool.h>
+
#ifdef CONFIG_AXP152_POWER
#include <axp152.h>
#endif
#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);
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ */
+
+#ifndef _CLK_SUNXI_H
+#define _CLK_SUNXI_H
+
+#include <linux/bitops.h>
+
+/**
+ * enum ccu_flags - ccu clock/reset flags
+ *
+ * @CCU_CLK_F_IS_VALID: is given clock gate is valid?
+ * @CCU_RST_F_IS_VALID: is given reset control is valid?
+ */
+enum ccu_flags {
+ CCU_CLK_F_IS_VALID = BIT(0),
+ CCU_RST_F_IS_VALID = BIT(1),
+};
+
+/**
+ * struct ccu_clk_gate - ccu clock gate
+ * @off: gate offset
+ * @bit: gate bit
+ * @flags: ccu clock gate flags
+ */
+struct ccu_clk_gate {
+ u16 off;
+ u32 bit;
+ enum ccu_flags flags;
+};
+
+#define GATE(_off, _bit) { \
+ .off = _off, \
+ .bit = _bit, \
+ .flags = CCU_CLK_F_IS_VALID, \
+}
+
+/**
+ * struct ccu_reset - ccu reset
+ * @off: reset offset
+ * @bit: reset bit
+ * @flags: ccu reset control flags
+ */
+struct ccu_reset {
+ u16 off;
+ u32 bit;
+ enum ccu_flags flags;
+};
+
+#define RESET(_off, _bit) { \
+ .off = _off, \
+ .bit = _bit, \
+ .flags = CCU_RST_F_IS_VALID, \
+}
+
+/**
+ * struct ccu_desc - clock control unit descriptor
+ *
+ * @gates: clock gates
+ * @resets: reset unit
+ */
+struct ccu_desc {
+ const struct ccu_clk_gate *gates;
+ const struct ccu_reset *resets;
+};
+
+/**
+ * struct ccu_priv - sunxi clock control unit
+ *
+ * @base: base address
+ * @desc: ccu descriptor
+ */
+struct ccu_priv {
+ void *base;
+ const struct ccu_desc *desc;
+};
+
+/**
+ * sunxi_clk_probe - common sunxi clock probe
+ * @dev: clock device
+ */
+int sunxi_clk_probe(struct udevice *dev);
+
+extern struct clk_ops sunxi_clk_ops;
+
+/**
+ * sunxi_reset_bind() - reset binding
+ *
+ * @dev: reset device
+ * @count: reset count
+ * @return 0 success, or error value
+ */
+int sunxi_reset_bind(struct udevice *dev, ulong count);
+
+#endif /* _CLK_SUNXI_H */
#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