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).
This commit is contained in:
Tom Rini 2021-10-12 08:58:58 -04:00
commit 2aab77f726
68 changed files with 1314 additions and 749 deletions

View file

@ -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

View file

@ -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 \

View file

@ -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";
};

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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();
}

View file

@ -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;
#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(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
# endif
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
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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)
{

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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=""

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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
configs/pinetab_defconfig Normal file
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)),

View file

@ -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)),

View file

@ -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)),

View file

@ -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)),

View file

@ -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,
};

View file

@ -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)),

View file

@ -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)),

View file

@ -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)),

View file

@ -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)),

View file

@ -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)),

View file

@ -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)),

View file

@ -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,
};

View file

@ -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)),

View file

@ -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>

View file

@ -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)),

View file

@ -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>

View file

@ -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)

View file

@ -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

View file

@ -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
drivers/i2c/sun6i_p2wi.c Normal file
View file

@ -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
drivers/i2c/sun8i_rsb.c Normal file
View file

@ -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) */

View file

@ -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

View file

@ -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)

View file

@ -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>

View file

@ -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>

View file

@ -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.

View file

@ -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
drivers/power/pmic/axp.c Normal file
View file

@ -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,
};

View file

@ -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;

View file

@ -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;

View file

@ -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>

View file

@ -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"

View file

@ -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);
}

View file

@ -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

View file

@ -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");

View file

@ -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();

View file

@ -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>

View file

@ -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);

View file

@ -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 */

View file

@ -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