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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <asm/arch/ccu.h>
|
||||
#include <clk/sunxi.h>
|
||||
#include <dt-bindings/clock/sun6i-a31-ccu.h>
|
||||
#include <dt-bindings/reset/sun6i-a31-ccu.h>
|
||||
#include <linux/bitops.h>
|
||||
@@ -30,6 +30,10 @@ static struct ccu_clk_gate a31_gates[] = {
|
||||
[CLK_AHB1_OHCI1] = GATE(0x060, BIT(30)),
|
||||
[CLK_AHB1_OHCI2] = GATE(0x060, BIT(31)),
|
||||
|
||||
[CLK_APB2_I2C0] = GATE(0x06c, BIT(0)),
|
||||
[CLK_APB2_I2C1] = GATE(0x06c, BIT(1)),
|
||||
[CLK_APB2_I2C2] = GATE(0x06c, BIT(2)),
|
||||
[CLK_APB2_I2C3] = GATE(0x06c, BIT(3)),
|
||||
[CLK_APB2_UART0] = GATE(0x06c, BIT(16)),
|
||||
[CLK_APB2_UART1] = GATE(0x06c, BIT(17)),
|
||||
[CLK_APB2_UART2] = GATE(0x06c, BIT(18)),
|
||||
@@ -71,6 +75,10 @@ static struct ccu_reset a31_resets[] = {
|
||||
[RST_AHB1_OHCI1] = RESET(0x2c0, BIT(30)),
|
||||
[RST_AHB1_OHCI2] = RESET(0x2c0, BIT(31)),
|
||||
|
||||
[RST_APB2_I2C0] = RESET(0x2d8, BIT(0)),
|
||||
[RST_APB2_I2C1] = RESET(0x2d8, BIT(1)),
|
||||
[RST_APB2_I2C2] = RESET(0x2d8, BIT(2)),
|
||||
[RST_APB2_I2C3] = RESET(0x2d8, BIT(3)),
|
||||
[RST_APB2_UART0] = RESET(0x2d8, BIT(16)),
|
||||
[RST_APB2_UART1] = RESET(0x2d8, BIT(17)),
|
||||
[RST_APB2_UART2] = RESET(0x2d8, BIT(18)),
|
||||
|
||||
59
drivers/clk/sunxi/clk_a31_r.c
Normal file
59
drivers/clk/sunxi/clk_a31_r.c
Normal 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,
|
||||
};
|
||||
@@ -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)),
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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)),
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <asm/arch/ccu.h>
|
||||
#include <clk/sunxi.h>
|
||||
#include <dt-bindings/clock/sun50i-h616-ccu.h>
|
||||
#include <dt-bindings/reset/sun50i-h616-ccu.h>
|
||||
#include <linux/bitops.h>
|
||||
@@ -24,6 +24,12 @@ static struct ccu_clk_gate h616_gates[] = {
|
||||
[CLK_BUS_UART4] = GATE(0x90c, BIT(4)),
|
||||
[CLK_BUS_UART5] = GATE(0x90c, BIT(5)),
|
||||
|
||||
[CLK_BUS_I2C0] = GATE(0x91c, BIT(0)),
|
||||
[CLK_BUS_I2C1] = GATE(0x91c, BIT(1)),
|
||||
[CLK_BUS_I2C2] = GATE(0x91c, BIT(2)),
|
||||
[CLK_BUS_I2C3] = GATE(0x91c, BIT(3)),
|
||||
[CLK_BUS_I2C4] = GATE(0x91c, BIT(4)),
|
||||
|
||||
[CLK_SPI0] = GATE(0x940, BIT(31)),
|
||||
[CLK_SPI1] = GATE(0x944, BIT(31)),
|
||||
|
||||
@@ -68,6 +74,12 @@ static struct ccu_reset h616_resets[] = {
|
||||
[RST_BUS_UART4] = RESET(0x90c, BIT(20)),
|
||||
[RST_BUS_UART5] = RESET(0x90c, BIT(21)),
|
||||
|
||||
[RST_BUS_I2C0] = RESET(0x91c, BIT(16)),
|
||||
[RST_BUS_I2C1] = RESET(0x91c, BIT(17)),
|
||||
[RST_BUS_I2C2] = RESET(0x91c, BIT(18)),
|
||||
[RST_BUS_I2C3] = RESET(0x91c, BIT(19)),
|
||||
[RST_BUS_I2C4] = RESET(0x91c, BIT(20)),
|
||||
|
||||
[RST_BUS_SPI0] = RESET(0x96c, BIT(16)),
|
||||
[RST_BUS_SPI1] = RESET(0x96c, BIT(17)),
|
||||
|
||||
|
||||
61
drivers/clk/sunxi/clk_h6_r.c
Normal file
61
drivers/clk/sunxi/clk_h6_r.c
Normal 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,
|
||||
};
|
||||
@@ -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)),
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
220
drivers/i2c/sun6i_p2wi.c
Normal 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
281
drivers/i2c/sun8i_rsb.c
Normal 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) */
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
38
drivers/power/pmic/axp.c
Normal 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,
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user