mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-17 12:21:23 +00:00
Add Pinebook LCD display driver for mainline u-boot
Pulled from https://github.com/anarsoul/u-boot-pine64/ with a couple of changes and compilation fixes
This commit is contained in:
parent
524fffa2ef
commit
85928946b0
11 changed files with 2621 additions and 34 deletions
274
patch/u-boot/u-boot-sunxi/01-add-sunxi-pwm-driver.patch
Normal file
274
patch/u-boot/u-boot-sunxi/01-add-sunxi-pwm-driver.patch
Normal file
|
@ -0,0 +1,274 @@
|
|||
From 485a09477c96edda8dd737493efd6f6e03ecf06e Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
Date: Sun, 17 Sep 2017 09:19:52 -0700
|
||||
Subject: [PATCH] pwm: sunxi: add support for PWM found on Allwinner A64 and H3
|
||||
|
||||
This commit adds basic support for PWM found on Allwinner A64 and H3
|
||||
It can be used for pwm_backlight driver (e.g. for Pinebook)
|
||||
|
||||
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
---
|
||||
arch/arm/include/asm/arch-sunxi/gpio.h | 1 +
|
||||
arch/arm/include/asm/arch-sunxi/pwm.h | 12 +++
|
||||
drivers/pwm/Kconfig | 7 ++
|
||||
drivers/pwm/Makefile | 1 +
|
||||
drivers/pwm/sunxi_pwm.c | 184 +++++++++++++++++++++++++++++++++
|
||||
5 files changed, 205 insertions(+)
|
||||
create mode 100644 drivers/pwm/sunxi_pwm.c
|
||||
|
||||
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
|
||||
index 24f85206c8..7265d18099 100644
|
||||
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
|
||||
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
|
||||
@@ -173,6 +173,7 @@ enum sunxi_gpio_number {
|
||||
#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
|
||||
diff --git a/arch/arm/include/asm/arch-sunxi/pwm.h b/arch/arm/include/asm/arch-sunxi/pwm.h
|
||||
index 5884b5dbe7..673e0eb7b5 100644
|
||||
--- a/arch/arm/include/asm/arch-sunxi/pwm.h
|
||||
+++ b/arch/arm/include/asm/arch-sunxi/pwm.h
|
||||
@@ -11,8 +11,15 @@
|
||||
#define SUNXI_PWM_CH0_PERIOD (SUNXI_PWM_BASE + 4)
|
||||
|
||||
#define SUNXI_PWM_CTRL_PRESCALE0(x) ((x) & 0xf)
|
||||
+#define SUNXI_PWM_CTRL_PRESCALE0_MASK (0xf)
|
||||
#define SUNXI_PWM_CTRL_ENABLE0 (0x5 << 4)
|
||||
#define SUNXI_PWM_CTRL_POLARITY0(x) ((x) << 5)
|
||||
+#define SUNXI_PWM_CTRL_POLARITY0_MASK (1 << 5)
|
||||
+#define SUNXI_PWM_CTRL_CLK_GATE (1 << 6)
|
||||
+
|
||||
+#define SUNXI_PWM_CH0_PERIOD_MAX (0xffff)
|
||||
+#define SUNXI_PWM_CH0_PERIOD_PRD(x) ((x & 0xffff) << 16)
|
||||
+#define SUNXI_PWM_CH0_PERIOD_DUTY(x) ((x) & 0xffff)
|
||||
|
||||
#define SUNXI_PWM_PERIOD_80PCT 0x04af03c0
|
||||
|
||||
@@ -31,4 +38,9 @@
|
||||
#define SUNXI_PWM_MUX SUN8I_GPH_PWM
|
||||
#endif
|
||||
|
||||
+struct sunxi_pwm {
|
||||
+ u32 ctrl;
|
||||
+ u32 ch0_period;
|
||||
+};
|
||||
+
|
||||
#endif
|
||||
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
|
||||
index e827558052..2984b79766 100644
|
||||
--- a/drivers/pwm/Kconfig
|
||||
+++ b/drivers/pwm/Kconfig
|
||||
@@ -43,3 +43,10 @@ config PWM_TEGRA
|
||||
four channels with a programmable period and duty cycle. Only a
|
||||
32KHz clock is supported by the driver but the duty cycle is
|
||||
configurable.
|
||||
+
|
||||
+config PWM_SUNXI
|
||||
+ bool "Enable support for the Allwinner Sunxi PWM"
|
||||
+ depends on DM_PWM
|
||||
+ help
|
||||
+ This PWM is found on H3, A64 and other Allwinner SoCs. It supports a
|
||||
+ programmable period and duty cycle. A 16-bit counter is used.
|
||||
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
|
||||
index 29d59916cb..1a8f8a58bc 100644
|
||||
--- a/drivers/pwm/Makefile
|
||||
+++ b/drivers/pwm/Makefile
|
||||
@@ -17,3 +17,4 @@ obj-$(CONFIG_PWM_IMX) += pwm-imx.o pwm-imx-util.o
|
||||
obj-$(CONFIG_PWM_ROCKCHIP) += rk_pwm.o
|
||||
obj-$(CONFIG_PWM_SANDBOX) += sandbox_pwm.o
|
||||
obj-$(CONFIG_PWM_TEGRA) += tegra_pwm.o
|
||||
+obj-$(CONFIG_PWM_SUNXI) += sunxi_pwm.o
|
||||
diff --git a/drivers/pwm/sunxi_pwm.c b/drivers/pwm/sunxi_pwm.c
|
||||
new file mode 100644
|
||||
index 0000000000..cfea7d69f3
|
||||
--- /dev/null
|
||||
+++ b/drivers/pwm/sunxi_pwm.c
|
||||
@@ -0,0 +1,184 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#include <common.h>
|
||||
+#include <div64.h>
|
||||
+#include <dm.h>
|
||||
+#include <pwm.h>
|
||||
+#include <regmap.h>
|
||||
+#include <syscon.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <asm/arch/pwm.h>
|
||||
+#include <asm/arch/gpio.h>
|
||||
+#include <power/regulator.h>
|
||||
+
|
||||
+DECLARE_GLOBAL_DATA_PTR;
|
||||
+
|
||||
+struct sunxi_pwm_priv {
|
||||
+ struct sunxi_pwm *regs;
|
||||
+ ulong freq;
|
||||
+ bool invert;
|
||||
+ uint32_t prescaler;
|
||||
+};
|
||||
+
|
||||
+static const uint32_t prescaler_table[] = {
|
||||
+ 120, /* 0000 */
|
||||
+ 180, /* 0001 */
|
||||
+ 240, /* 0010 */
|
||||
+ 360, /* 0011 */
|
||||
+ 480, /* 0100 */
|
||||
+ 0, /* 0101 */
|
||||
+ 0, /* 0110 */
|
||||
+ 0, /* 0111 */
|
||||
+ 12000, /* 1000 */
|
||||
+ 24000, /* 1001 */
|
||||
+ 36000, /* 1010 */
|
||||
+ 48000, /* 1011 */
|
||||
+ 72000, /* 1100 */
|
||||
+ 0, /* 1101 */
|
||||
+ 0, /* 1110 */
|
||||
+ 1, /* 1111 */
|
||||
+};
|
||||
+
|
||||
+static const uint64_t nsecs_per_sec = 1000000000L;
|
||||
+
|
||||
+static int sunxi_pwm_config_pinmux(void)
|
||||
+{
|
||||
+#ifdef CONFIG_MACH_SUN50I
|
||||
+ sunxi_gpio_set_cfgpin(SUNXI_GPD(22), SUNXI_GPD_PWM);
|
||||
+#endif
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sunxi_pwm_set_invert(struct udevice *dev, uint channel, bool polarity)
|
||||
+{
|
||||
+ struct sunxi_pwm_priv *priv = dev_get_priv(dev);
|
||||
+
|
||||
+ debug("%s: polarity=%u\n", __func__, polarity);
|
||||
+ priv->invert = polarity;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sunxi_pwm_set_config(struct udevice *dev, uint channel, uint period_ns,
|
||||
+ uint duty_ns)
|
||||
+{
|
||||
+ struct sunxi_pwm_priv *priv = dev_get_priv(dev);
|
||||
+ struct sunxi_pwm *regs = priv->regs;
|
||||
+ int prescaler;
|
||||
+ u32 v, period, duty;
|
||||
+ uint64_t div = 0, pval = 0, scaled_freq = 0;
|
||||
+
|
||||
+ debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns);
|
||||
+
|
||||
+ for (prescaler = 0; prescaler < SUNXI_PWM_CTRL_PRESCALE0_MASK; prescaler++) {
|
||||
+ if (!prescaler_table[prescaler])
|
||||
+ continue;
|
||||
+ div = priv->freq;
|
||||
+ pval = prescaler_table[prescaler];
|
||||
+ scaled_freq = lldiv(div, pval);
|
||||
+ div = scaled_freq * period_ns;
|
||||
+ div = lldiv(div, nsecs_per_sec);
|
||||
+ if (div - 1 <= SUNXI_PWM_CH0_PERIOD_MAX)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (div - 1 > SUNXI_PWM_CH0_PERIOD_MAX) {
|
||||
+ debug("%s: failed to find prescaler value\n", __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ period = div;
|
||||
+ div = scaled_freq * duty_ns;
|
||||
+ div = lldiv(div, nsecs_per_sec);
|
||||
+ duty = div;
|
||||
+
|
||||
+ if (priv->prescaler != prescaler) {
|
||||
+ /* Mask clock to update prescaler */
|
||||
+ v = readl(®s->ctrl);
|
||||
+ v &= ~SUNXI_PWM_CTRL_CLK_GATE;
|
||||
+ writel(v, ®s->ctrl);
|
||||
+ v &= ~SUNXI_PWM_CTRL_PRESCALE0_MASK;
|
||||
+ v |= (priv->prescaler & SUNXI_PWM_CTRL_PRESCALE0_MASK);
|
||||
+ writel(v, ®s->ctrl);
|
||||
+ v |= SUNXI_PWM_CTRL_CLK_GATE;
|
||||
+ writel(v, ®s->ctrl);
|
||||
+ priv->prescaler = prescaler;
|
||||
+ }
|
||||
+
|
||||
+ writel(SUNXI_PWM_CH0_PERIOD_PRD(period) |
|
||||
+ SUNXI_PWM_CH0_PERIOD_DUTY(duty), ®s->ch0_period);
|
||||
+
|
||||
+ debug("%s: prescaler: %d, period: %d, duty: %d\n", __func__, priv->prescaler,
|
||||
+ period, duty);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sunxi_pwm_set_enable(struct udevice *dev, uint channel, bool enable)
|
||||
+{
|
||||
+ struct sunxi_pwm_priv *priv = dev_get_priv(dev);
|
||||
+ struct sunxi_pwm *regs = priv->regs;
|
||||
+ uint32_t v;
|
||||
+
|
||||
+ debug("%s: Enable '%s'\n", __func__, dev->name);
|
||||
+
|
||||
+ v = readl(®s->ctrl);
|
||||
+ if (!enable) {
|
||||
+ v &= ~SUNXI_PWM_CTRL_ENABLE0;
|
||||
+ writel(v, ®s->ctrl);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ sunxi_pwm_config_pinmux();
|
||||
+
|
||||
+ v &= ~SUNXI_PWM_CTRL_POLARITY0_MASK;
|
||||
+ v |= priv->invert ? SUNXI_PWM_CTRL_POLARITY0(0) :
|
||||
+ SUNXI_PWM_CTRL_POLARITY0(1);
|
||||
+ v |= SUNXI_PWM_CTRL_ENABLE0;
|
||||
+ writel(v, ®s->ctrl);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sunxi_pwm_ofdata_to_platdata(struct udevice *dev)
|
||||
+{
|
||||
+ struct sunxi_pwm_priv *priv = dev_get_priv(dev);
|
||||
+
|
||||
+ priv->regs = (struct sunxi_pwm *)devfdt_get_addr(dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sunxi_pwm_probe(struct udevice *dev)
|
||||
+{
|
||||
+ struct sunxi_pwm_priv *priv = dev_get_priv(dev);
|
||||
+
|
||||
+ priv->freq = 24000000;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct pwm_ops sunxi_pwm_ops = {
|
||||
+ .set_invert = sunxi_pwm_set_invert,
|
||||
+ .set_config = sunxi_pwm_set_config,
|
||||
+ .set_enable = sunxi_pwm_set_enable,
|
||||
+};
|
||||
+
|
||||
+static const struct udevice_id sunxi_pwm_ids[] = {
|
||||
+ { .compatible = "allwinner,sun8i-h3-pwm" },
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
+U_BOOT_DRIVER(sunxi_pwm) = {
|
||||
+ .name = "sunxi_pwm",
|
||||
+ .id = UCLASS_PWM,
|
||||
+ .of_match = sunxi_pwm_ids,
|
||||
+ .ops = &sunxi_pwm_ops,
|
||||
+ .ofdata_to_platdata = sunxi_pwm_ofdata_to_platdata,
|
||||
+ .probe = sunxi_pwm_probe,
|
||||
+ .priv_auto_alloc_size = sizeof(struct sunxi_pwm_priv),
|
||||
+};
|
821
patch/u-boot/u-boot-sunxi/02-add-axp803-pmic-support.patch
Normal file
821
patch/u-boot/u-boot-sunxi/02-add-axp803-pmic-support.patch
Normal file
|
@ -0,0 +1,821 @@
|
|||
From 15d68b2115b24dcf3a20f67942db867e5887b624 Mon Sep 17 00:00:00 2001
|
||||
From: Icenowy Zheng <icenowy@aosc.xyz>
|
||||
Date: Mon, 27 Mar 2017 19:22:34 +0200
|
||||
Subject: [PATCH] sunxi: add AXP803 support
|
||||
|
||||
The A64 uses the AXP803 as its PMIC.
|
||||
|
||||
Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
arch/arm/mach-sunxi/Makefile | 3 +
|
||||
arch/arm/mach-sunxi/pmic_bus.c | 6 +-
|
||||
arch/arm/mach-sunxi/rsb.c | 2 +-
|
||||
board/sunxi/board.c | 31 ++---
|
||||
drivers/power/Kconfig | 85 +++++++++-----
|
||||
drivers/power/Makefile | 1 +
|
||||
drivers/power/axp803.c | 259 +++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/power/axp818.c | 2 +-
|
||||
include/axp803.h | 73 ++++++++++++
|
||||
include/axp_pmic.h | 3 +
|
||||
10 files changed, 415 insertions(+), 50 deletions(-)
|
||||
create mode 100644 drivers/power/axp803.c
|
||||
create mode 100644 include/axp803.h
|
||||
|
||||
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
|
||||
index 2a3c379b72..0bbfda9364 100644
|
||||
--- a/arch/arm/mach-sunxi/Makefile
|
||||
+++ b/arch/arm/mach-sunxi/Makefile
|
||||
@@ -19,9 +19,11 @@ endif
|
||||
obj-$(CONFIG_MACH_SUN6I) += prcm.o
|
||||
obj-$(CONFIG_MACH_SUN8I) += prcm.o
|
||||
obj-$(CONFIG_MACH_SUN9I) += prcm.o
|
||||
+obj-$(CONFIG_MACH_SUN50I) += prcm.o
|
||||
obj-$(CONFIG_MACH_SUN6I) += p2wi.o
|
||||
obj-$(CONFIG_MACH_SUN8I) += rsb.o
|
||||
obj-$(CONFIG_MACH_SUN9I) += rsb.o
|
||||
+obj-$(CONFIG_MACH_SUN50I) += rsb.o
|
||||
obj-$(CONFIG_MACH_SUN4I) += clock_sun4i.o
|
||||
obj-$(CONFIG_MACH_SUN5I) += clock_sun4i.o
|
||||
obj-$(CONFIG_MACH_SUN6I) += clock_sun6i.o
|
||||
@@ -37,6 +39,7 @@ obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o gtbus_sun9i.o
|
||||
obj-$(CONFIG_AXP152_POWER) += pmic_bus.o
|
||||
obj-$(CONFIG_AXP209_POWER) += pmic_bus.o
|
||||
obj-$(CONFIG_AXP221_POWER) += pmic_bus.o
|
||||
+obj-$(CONFIG_AXP803_POWER) += pmic_bus.o
|
||||
obj-$(CONFIG_AXP809_POWER) += pmic_bus.o
|
||||
obj-$(CONFIG_AXP818_POWER) += pmic_bus.o
|
||||
|
||||
diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
|
||||
index f917c3e070..e021b58b60 100644
|
||||
--- a/arch/arm/mach-sunxi/pmic_bus.c
|
||||
+++ b/arch/arm/mach-sunxi/pmic_bus.c
|
||||
@@ -36,7 +36,7 @@ int pmic_bus_init(void)
|
||||
if (!needs_init)
|
||||
return 0;
|
||||
|
||||
-#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
|
||||
+#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP803_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,
|
||||
@@ -65,7 +65,7 @@ int pmic_bus_read(u8 reg, u8 *data)
|
||||
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_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
|
||||
+#elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP803_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
|
||||
# ifdef CONFIG_MACH_SUN6I
|
||||
return p2wi_read(reg, data);
|
||||
# elif defined CONFIG_MACH_SUN8I_R40
|
||||
@@ -82,7 +82,7 @@ int pmic_bus_write(u8 reg, u8 data)
|
||||
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_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
|
||||
+#elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP803_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
|
||||
# ifdef CONFIG_MACH_SUN6I
|
||||
return p2wi_write(reg, data);
|
||||
# elif defined CONFIG_MACH_SUN8I_R40
|
||||
diff --git a/arch/arm/mach-sunxi/rsb.c b/arch/arm/mach-sunxi/rsb.c
|
||||
index 6fd11f1529..28d05e962a 100644
|
||||
--- a/arch/arm/mach-sunxi/rsb.c
|
||||
+++ b/arch/arm/mach-sunxi/rsb.c
|
||||
@@ -20,7 +20,7 @@ static int rsb_set_device_mode(void);
|
||||
|
||||
static void rsb_cfg_io(void)
|
||||
{
|
||||
-#ifdef CONFIG_MACH_SUN8I
|
||||
+#if defined CONFIG_MACH_SUN8I || defined CONFIG_MACH_SUN50I
|
||||
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);
|
||||
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
|
||||
index 70e01437c4..192cf8ca45 100644
|
||||
--- a/board/sunxi/board.c
|
||||
+++ b/board/sunxi/board.c
|
||||
@@ -519,26 +519,27 @@ void sunxi_board_init(void)
|
||||
#endif
|
||||
|
||||
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
|
||||
- defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
|
||||
- defined CONFIG_AXP818_POWER
|
||||
+ defined CONFIG_AXP221_POWER || defined CONFIG_AXP803_POWER || \
|
||||
+ defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
|
||||
power_failed = axp_init();
|
||||
|
||||
-#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
|
||||
- defined CONFIG_AXP818_POWER
|
||||
+#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP803_POWER || \
|
||||
+ defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
|
||||
power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
|
||||
#endif
|
||||
power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
|
||||
power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
|
||||
-#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
|
||||
+#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP803_POWER) && \
|
||||
+ !defined(CONFIG_AXP818_POWER)
|
||||
power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
|
||||
#endif
|
||||
-#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
|
||||
- defined CONFIG_AXP818_POWER
|
||||
+#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP803_POWER || \
|
||||
+ defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
|
||||
power_failed |= axp_set_dcdc5(CONFIG_AXP_DCDC5_VOLT);
|
||||
#endif
|
||||
|
||||
-#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
|
||||
- defined CONFIG_AXP818_POWER
|
||||
+#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP803_POWER || \
|
||||
+ defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
|
||||
power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
|
||||
#endif
|
||||
power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
|
||||
@@ -549,8 +550,8 @@ void sunxi_board_init(void)
|
||||
power_failed |= axp_set_aldo4(CONFIG_AXP_ALDO4_VOLT);
|
||||
#endif
|
||||
|
||||
-#if defined(CONFIG_AXP221_POWER) || defined(CONFIG_AXP809_POWER) || \
|
||||
- defined(CONFIG_AXP818_POWER)
|
||||
+#if defined(CONFIG_AXP221_POWER) || defined(CONFIG_AXP803_POWER) || \
|
||||
+ defined(CONFIG_AXP809_POWER) || defined(CONFIG_AXP818_POWER)
|
||||
power_failed |= axp_set_dldo(1, CONFIG_AXP_DLDO1_VOLT);
|
||||
power_failed |= axp_set_dldo(2, CONFIG_AXP_DLDO2_VOLT);
|
||||
#if !defined CONFIG_AXP809_POWER
|
||||
@@ -562,13 +563,17 @@ void sunxi_board_init(void)
|
||||
power_failed |= axp_set_eldo(3, CONFIG_AXP_ELDO3_VOLT);
|
||||
#endif
|
||||
|
||||
-#ifdef CONFIG_AXP818_POWER
|
||||
+#if defined CONFIG_AXP803_POWER || defined CONFIG_AXP818_POWER
|
||||
power_failed |= axp_set_fldo(1, CONFIG_AXP_FLDO1_VOLT);
|
||||
power_failed |= axp_set_fldo(2, CONFIG_AXP_FLDO2_VOLT);
|
||||
+#endif
|
||||
+
|
||||
+#ifdef CONFIG_AXP818_POWER
|
||||
power_failed |= axp_set_fldo(3, CONFIG_AXP_FLDO3_VOLT);
|
||||
#endif
|
||||
|
||||
-#if defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
|
||||
+#if defined CONFIG_AXP803_POWER || defined CONFIG_AXP809_POWER || \
|
||||
+ defined CONFIG_AXP818_POWER
|
||||
power_failed |= axp_set_sw(IS_ENABLED(CONFIG_AXP_SW_ON));
|
||||
#endif
|
||||
#endif
|
||||
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
|
||||
index d8c107e206..2da80ae04b 100644
|
||||
--- a/drivers/power/Kconfig
|
||||
+++ b/drivers/power/Kconfig
|
||||
@@ -11,8 +11,9 @@ choice
|
||||
depends on ARCH_SUNXI
|
||||
default AXP209_POWER if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
|
||||
default AXP221_POWER if MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_R40
|
||||
+ default AXP803_POWER if MACH_SUN50I
|
||||
default AXP818_POWER if MACH_SUN8I_A83T
|
||||
- default SUNXI_NO_PMIC if MACH_SUNXI_H3_H5 || MACH_SUN50I
|
||||
+ default SUNXI_NO_PMIC if MACH_SUNXI_H3_H5
|
||||
|
||||
config SUNXI_NO_PMIC
|
||||
bool "board without a pmic"
|
||||
@@ -43,6 +44,13 @@ config AXP221_POWER
|
||||
Select this to enable support for the axp221/axp223 pmic found on most
|
||||
A23 and A31 boards.
|
||||
|
||||
+config AXP803_POWER
|
||||
+ bool "axp803 pmic support"
|
||||
+ depends on MACH_SUN50I
|
||||
+ select CMD_POWEROFF
|
||||
+ ---help---
|
||||
+ Say y here to enable support for the axp803 pmic found on A64 boards.
|
||||
+
|
||||
config AXP809_POWER
|
||||
bool "axp809 pmic support"
|
||||
depends on MACH_SUN9I
|
||||
@@ -69,25 +77,25 @@ endchoice
|
||||
|
||||
config AXP_DCDC1_VOLT
|
||||
int "axp pmic dcdc1 voltage"
|
||||
- depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
- default 3300 if AXP818_POWER || MACH_SUN8I_R40
|
||||
+ depends on AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ default 3300 if AXP818_POWER || MACH_SUN8I_R40 || MACH_SUN50I
|
||||
default 3000 if MACH_SUN6I || MACH_SUN8I || MACH_SUN9I
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic dcdc1 at, set to 0 to
|
||||
disable dcdc1. On A23 / A31 / A33 (axp221) boards dcdc1 is used for
|
||||
generic 3.3V IO voltage for external devices like the lcd-panal and
|
||||
sdcard interfaces, etc. On most boards dcdc1 is undervolted to 3.0V to
|
||||
- save battery. On A31 devices dcdc1 is also used for VCC-IO. On A83T
|
||||
- dcdc1 is used for VCC-IO, nand, usb0, sd , etc. On A80 dcdc1 normally
|
||||
- powers some of the pingroups, NAND/eMMC, SD/MMC, and USB OTG.
|
||||
+ save battery. On A31 devices dcdc1 is also used for VCC-IO. On A83T and
|
||||
+ A64 dcdc1 is used for VCC-IO, nand, usb0, sd , etc. On A80 dcdc1
|
||||
+ normally powers some of the pingroups, NAND/eMMC, SD/MMC, and USB OTG.
|
||||
|
||||
config AXP_DCDC2_VOLT
|
||||
int "axp pmic dcdc2 voltage"
|
||||
- depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default 900 if AXP818_POWER
|
||||
default 1400 if AXP152_POWER || AXP209_POWER
|
||||
default 1200 if MACH_SUN6I
|
||||
- default 1100 if MACH_SUN8I
|
||||
+ default 1100 if MACH_SUN8I || MACH_SUN50I
|
||||
default 0 if MACH_SUN9I
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic dcdc2 at, set to 0 to
|
||||
@@ -98,14 +106,15 @@ config AXP_DCDC2_VOLT
|
||||
On A80 boards dcdc2 powers the GPU and can be left off.
|
||||
On A83T boards dcdc2 is used for VDD-CPUA(cluster 0) and should be 0.9V.
|
||||
On R40 boards dcdc2 is VDD-CPU and should be 1.1V
|
||||
+ On A64 boards dcdc2 is used with dcdc3 for VDD-CPU and should be 1.1V.
|
||||
|
||||
config AXP_DCDC3_VOLT
|
||||
int "axp pmic dcdc3 voltage"
|
||||
- depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default 900 if AXP809_POWER || AXP818_POWER
|
||||
default 1500 if AXP152_POWER
|
||||
default 1250 if AXP209_POWER
|
||||
- default 1100 if MACH_SUN8I_R40
|
||||
+ default 1100 if MACH_SUN8I_R40 || MACH_SUN50I
|
||||
default 1200 if MACH_SUN6I || MACH_SUN8I
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic dcdc3 at, set to 0 to
|
||||
@@ -117,39 +126,42 @@ config AXP_DCDC3_VOLT
|
||||
On A80 boards dcdc3 is used for VDD-CPUA(cluster 0) and should be 0.9V.
|
||||
On A83T boards dcdc3 is used for VDD-CPUB(cluster 1) and should be 0.9V.
|
||||
On R40 boards dcdc3 is VDD-SYS and VDD-GPU and should be 1.1V.
|
||||
+ On A64 boards dcdc3 is used with dcdc2 for VDD-CPU and should be 1.1V.
|
||||
|
||||
config AXP_DCDC4_VOLT
|
||||
int "axp pmic dcdc4 voltage"
|
||||
- depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP152_POWER || AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default 1250 if AXP152_POWER
|
||||
default 1200 if MACH_SUN6I
|
||||
- default 0 if MACH_SUN8I
|
||||
+ default 0 if MACH_SUN8I || MACH_SUN50I
|
||||
default 900 if MACH_SUN9I
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to
|
||||
disable dcdc4.
|
||||
On A10s boards with an axp152 dcdc4 is VDD-INT-DLL and should be 1.25V.
|
||||
On A31 boards dcdc4 is used for VDD-SYS and should be 1.2V.
|
||||
- On A23 / A33 boards dcdc4 is unused and should be disabled.
|
||||
+ On A23 / A33 / A64 boards dcdc4 is unused and should be disabled.
|
||||
On A80 boards dcdc4 powers VDD-SYS, HDMI, USB OTG and should be 0.9V.
|
||||
On A83T boards dcdc4 is used for VDD-GPU.
|
||||
|
||||
config AXP_DCDC5_VOLT
|
||||
int "axp pmic dcdc5 voltage"
|
||||
- depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default 1500 if MACH_SUN6I || MACH_SUN8I || MACH_SUN9I
|
||||
+ default 1350 if MACH_SUN50I
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic dcdc5 at, set to 0 to
|
||||
disable dcdc5.
|
||||
- On A23 / A31 / A33 / A80 / A83T / R40 boards dcdc5 is VCC-DRAM and
|
||||
+ On A23 / A31 / A33 / A64 / A80 / A83T / R40 boards dcdc5 is VCC-DRAM and
|
||||
should be 1.5V, 1.35V if DDR3L is used.
|
||||
|
||||
config AXP_ALDO1_VOLT
|
||||
int "axp pmic (a)ldo1 voltage"
|
||||
- depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default 0 if MACH_SUN6I || MACH_SUN8I_R40
|
||||
default 1800 if MACH_SUN8I_A83T
|
||||
default 3000 if MACH_SUN8I || MACH_SUN9I
|
||||
+ default 2800 if MACH_SUN50I
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic aldo1 at, set to 0 to
|
||||
disable aldo1.
|
||||
@@ -158,14 +170,16 @@ config AXP_ALDO1_VOLT
|
||||
On A80 boards aldo1 powers the USB hosts and should be 3.0V.
|
||||
On A83T / H8 boards aldo1 is used for MIPI CSI, DSI, HDMI, EFUSE, and
|
||||
should be 1.8V.
|
||||
+ On A64 boards aldo1 powers PE pingroup and CSI and should be 2.8V.
|
||||
|
||||
config AXP_ALDO2_VOLT
|
||||
int "axp pmic (a)ldo2 voltage"
|
||||
- depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default 3000 if AXP152_POWER || AXP209_POWER
|
||||
default 0 if MACH_SUN6I || MACH_SUN9I
|
||||
default 1800 if MACH_SUN8I_A83T
|
||||
default 2500 if MACH_SUN8I
|
||||
+ default 1800 if MACH_SUN50I
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic aldo2 at, set to 0 to
|
||||
disable aldo2.
|
||||
@@ -176,17 +190,18 @@ config AXP_ALDO2_VOLT
|
||||
On A80 boards aldo2 powers PB pingroup and camera IO and can be left off.
|
||||
On A83T / H8 boards aldo2 powers VDD-DLL, VCC18-PLL, CPVDD, VDD18-ADC,
|
||||
LPDDR2, and the codec. It should be 1.8V.
|
||||
+ On A64 boards aldo2 powers PL pingroup and should be 1.8V.
|
||||
|
||||
config AXP_ALDO3_VOLT
|
||||
int "axp pmic (a)ldo3 voltage"
|
||||
- depends on AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP209_POWER || AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default 0 if AXP209_POWER || MACH_SUN9I
|
||||
- default 3000 if MACH_SUN6I || MACH_SUN8I
|
||||
+ default 3000 if MACH_SUN6I || MACH_SUN8I || MACH_SUN50I
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic aldo3 at, set to 0 to
|
||||
disable aldo3.
|
||||
On A10(s) / A13 / A20 boards aldo3 should be 2.8V.
|
||||
- On A23 / A31 / A33 / R40 boards aldo3 is VCC-PLL and AVCC and should
|
||||
+ On A23 / A31 / A33 / A64 / R40 boards aldo3 is VCC-PLL and AVCC and should
|
||||
be 3.0V.
|
||||
On A80 boards aldo3 is normally not used.
|
||||
On A83T / H8 boards aldo3 is AVCC, VCC-PL, and VCC-LED, and should be
|
||||
@@ -203,17 +218,19 @@ config AXP_ALDO4_VOLT
|
||||
|
||||
config AXP_DLDO1_VOLT
|
||||
int "axp pmic dldo1 voltage"
|
||||
- depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ default 3300 if MACH_SUN50I
|
||||
default 0
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic dldo1 at, set to 0 to
|
||||
disable dldo1. On sun6i (A31) boards with ethernet dldo1 is often used
|
||||
to power the ethernet phy. On A23, A33 and A80 boards this is often
|
||||
- used to power the wifi.
|
||||
+ used to power the wifi. On A64 boards this is often used to power the
|
||||
+ HDMI.
|
||||
|
||||
config AXP_DLDO2_VOLT
|
||||
int "axp pmic dldo2 voltage"
|
||||
- depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default 3000 if MACH_SUN9I
|
||||
default 0
|
||||
---help---
|
||||
@@ -223,7 +240,7 @@ config AXP_DLDO2_VOLT
|
||||
|
||||
config AXP_DLDO3_VOLT
|
||||
int "axp pmic dldo3 voltage"
|
||||
- depends on AXP221_POWER || AXP818_POWER
|
||||
+ depends on AXP221_POWER || AXP803_POWER || AXP818_POWER
|
||||
default 0
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic dldo3 at, set to 0 to
|
||||
@@ -231,7 +248,7 @@ config AXP_DLDO3_VOLT
|
||||
|
||||
config AXP_DLDO4_VOLT
|
||||
int "axp pmic dldo4 voltage"
|
||||
- depends on AXP221_POWER || AXP818_POWER
|
||||
+ depends on AXP221_POWER || AXP803_POWER || AXP818_POWER
|
||||
default 0
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic dldo4 at, set to 0 to
|
||||
@@ -239,15 +256,17 @@ config AXP_DLDO4_VOLT
|
||||
|
||||
config AXP_ELDO1_VOLT
|
||||
int "axp pmic eldo1 voltage"
|
||||
- depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ default 1800 if MACH_SUN50I
|
||||
default 0
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic eldo1 at, set to 0 to
|
||||
disable eldo1.
|
||||
+ On A64 boards it's used for the codec and should be 1.8V.
|
||||
|
||||
config AXP_ELDO2_VOLT
|
||||
int "axp pmic eldo2 voltage"
|
||||
- depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default 0
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic eldo2 at, set to 0 to
|
||||
@@ -255,7 +274,7 @@ config AXP_ELDO2_VOLT
|
||||
|
||||
config AXP_ELDO3_VOLT
|
||||
int "axp pmic eldo3 voltage"
|
||||
- depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP221_POWER || AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default 3000 if MACH_SUN9I
|
||||
default 0
|
||||
---help---
|
||||
@@ -267,8 +286,8 @@ config AXP_ELDO3_VOLT
|
||||
|
||||
config AXP_FLDO1_VOLT
|
||||
int "axp pmic fldo1 voltage"
|
||||
- depends on AXP818_POWER
|
||||
- default 0 if MACH_SUN8I_A83T
|
||||
+ depends on AXP803_POWER || AXP818_POWER
|
||||
+ default 0
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic fldo1 at, set to 0 to
|
||||
disable fldo1.
|
||||
@@ -277,11 +296,13 @@ config AXP_FLDO1_VOLT
|
||||
|
||||
config AXP_FLDO2_VOLT
|
||||
int "axp pmic fldo2 voltage"
|
||||
- depends on AXP818_POWER
|
||||
+ depends on AXP803_POWER || AXP818_POWER
|
||||
+ default 1100 if MACH_SUN50I
|
||||
default 900 if MACH_SUN8I_A83T
|
||||
---help---
|
||||
Set the voltage (mV) to program the axp pmic fldo2 at, set to 0 to
|
||||
disable fldo2.
|
||||
+ On A64 boards fldo2 is VCC-CPUS and should be 1.1V.
|
||||
On A83T / H8 boards fldo2 is VCC-CPUS and should be 0.9V.
|
||||
|
||||
config AXP_FLDO3_VOLT
|
||||
@@ -294,7 +315,7 @@ config AXP_FLDO3_VOLT
|
||||
|
||||
config AXP_SW_ON
|
||||
bool "axp pmic sw on"
|
||||
- depends on AXP809_POWER || AXP818_POWER
|
||||
+ depends on AXP803_POWER || AXP809_POWER || AXP818_POWER
|
||||
default n
|
||||
---help---
|
||||
Enable to turn on axp pmic sw.
|
||||
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
|
||||
index 90a3b00a7c..55413a66d2 100644
|
||||
--- a/drivers/power/Makefile
|
||||
+++ b/drivers/power/Makefile
|
||||
@@ -8,6 +8,7 @@
|
||||
obj-$(CONFIG_AXP152_POWER) += axp152.o
|
||||
obj-$(CONFIG_AXP209_POWER) += axp209.o
|
||||
obj-$(CONFIG_AXP221_POWER) += axp221.o
|
||||
+obj-$(CONFIG_AXP803_POWER) += axp803.o
|
||||
obj-$(CONFIG_AXP809_POWER) += axp809.o
|
||||
obj-$(CONFIG_AXP818_POWER) += axp818.o
|
||||
obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o
|
||||
diff --git a/drivers/power/axp803.c b/drivers/power/axp803.c
|
||||
new file mode 100644
|
||||
index 0000000000..af20fce8b1
|
||||
--- /dev/null
|
||||
+++ b/drivers/power/axp803.c
|
||||
@@ -0,0 +1,259 @@
|
||||
+/*
|
||||
+ * AXP803 driver based on AXP818 driver
|
||||
+ *
|
||||
+ * Based on axp818.c
|
||||
+ * (C) Copyright 2015 Vishnu Patekar <vishnuptekar0510@gmail.com>
|
||||
+ *
|
||||
+ * Based on axp221.c
|
||||
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
|
||||
+ * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#include <common.h>
|
||||
+#include <errno.h>
|
||||
+#include <asm/arch/gpio.h>
|
||||
+#include <asm/arch/pmic_bus.h>
|
||||
+#include <axp_pmic.h>
|
||||
+
|
||||
+static u8 axp803_mvolt_to_cfg(int mvolt, int min, int max, int div)
|
||||
+{
|
||||
+ if (mvolt < min)
|
||||
+ mvolt = min;
|
||||
+ else if (mvolt > max)
|
||||
+ mvolt = max;
|
||||
+
|
||||
+ return (mvolt - min) / div;
|
||||
+}
|
||||
+
|
||||
+int axp_set_dcdc1(unsigned int mvolt)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 cfg = axp803_mvolt_to_cfg(mvolt, 1600, 3400, 100);
|
||||
+
|
||||
+ if (mvolt == 0)
|
||||
+ return pmic_bus_clrbits(AXP803_OUTPUT_CTRL1,
|
||||
+ AXP803_OUTPUT_CTRL1_DCDC1_EN);
|
||||
+
|
||||
+ ret = pmic_bus_write(AXP803_DCDC1_CTRL, cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return pmic_bus_setbits(AXP803_OUTPUT_CTRL1,
|
||||
+ AXP803_OUTPUT_CTRL1_DCDC1_EN);
|
||||
+}
|
||||
+
|
||||
+int axp_set_dcdc2(unsigned int mvolt)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 cfg;
|
||||
+
|
||||
+ if (mvolt >= 1220)
|
||||
+ cfg = 70 + axp803_mvolt_to_cfg(mvolt, 1220, 1300, 20);
|
||||
+ else
|
||||
+ cfg = axp803_mvolt_to_cfg(mvolt, 500, 1200, 10);
|
||||
+
|
||||
+ if (mvolt == 0)
|
||||
+ return pmic_bus_clrbits(AXP803_OUTPUT_CTRL1,
|
||||
+ AXP803_OUTPUT_CTRL1_DCDC2_EN);
|
||||
+
|
||||
+ ret = pmic_bus_write(AXP803_DCDC2_CTRL, cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return pmic_bus_setbits(AXP803_OUTPUT_CTRL1,
|
||||
+ AXP803_OUTPUT_CTRL1_DCDC2_EN);
|
||||
+}
|
||||
+
|
||||
+int axp_set_dcdc3(unsigned int mvolt)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 cfg;
|
||||
+
|
||||
+ if (mvolt >= 1220)
|
||||
+ cfg = 70 + axp803_mvolt_to_cfg(mvolt, 1220, 1300, 20);
|
||||
+ else
|
||||
+ cfg = axp803_mvolt_to_cfg(mvolt, 500, 1200, 10);
|
||||
+
|
||||
+ if (mvolt == 0)
|
||||
+ return pmic_bus_clrbits(AXP803_OUTPUT_CTRL1,
|
||||
+ AXP803_OUTPUT_CTRL1_DCDC3_EN);
|
||||
+
|
||||
+ ret = pmic_bus_write(AXP803_DCDC3_CTRL, cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return pmic_bus_setbits(AXP803_OUTPUT_CTRL1,
|
||||
+ AXP803_OUTPUT_CTRL1_DCDC3_EN);
|
||||
+}
|
||||
+
|
||||
+int axp_set_dcdc5(unsigned int mvolt)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 cfg;
|
||||
+
|
||||
+ if (mvolt >= 1140)
|
||||
+ cfg = 32 + axp803_mvolt_to_cfg(mvolt, 1140, 1840, 20);
|
||||
+ else
|
||||
+ cfg = axp803_mvolt_to_cfg(mvolt, 800, 1120, 10);
|
||||
+
|
||||
+ if (mvolt == 0)
|
||||
+ return pmic_bus_clrbits(AXP803_OUTPUT_CTRL1,
|
||||
+ AXP803_OUTPUT_CTRL1_DCDC5_EN);
|
||||
+
|
||||
+ ret = pmic_bus_write(AXP803_DCDC5_CTRL, cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return pmic_bus_setbits(AXP803_OUTPUT_CTRL1,
|
||||
+ AXP803_OUTPUT_CTRL1_DCDC5_EN);
|
||||
+}
|
||||
+
|
||||
+int axp_set_aldo(int aldo_num, unsigned int mvolt)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 cfg;
|
||||
+
|
||||
+ if (aldo_num < 1 || aldo_num > 3)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (mvolt == 0)
|
||||
+ return pmic_bus_clrbits(AXP803_OUTPUT_CTRL3,
|
||||
+ AXP803_OUTPUT_CTRL3_ALDO1_EN << (aldo_num - 1));
|
||||
+
|
||||
+ cfg = axp803_mvolt_to_cfg(mvolt, 700, 3300, 100);
|
||||
+ ret = pmic_bus_write(AXP803_ALDO1_CTRL + (aldo_num - 1), cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return pmic_bus_setbits(AXP803_OUTPUT_CTRL3,
|
||||
+ AXP803_OUTPUT_CTRL3_ALDO1_EN << (aldo_num - 1));
|
||||
+}
|
||||
+
|
||||
+/* TODO: re-work other AXP drivers to consolidate ALDO functions. */
|
||||
+int axp_set_aldo1(unsigned int mvolt)
|
||||
+{
|
||||
+ return axp_set_aldo(1, mvolt);
|
||||
+}
|
||||
+
|
||||
+int axp_set_aldo2(unsigned int mvolt)
|
||||
+{
|
||||
+ return axp_set_aldo(2, mvolt);
|
||||
+}
|
||||
+
|
||||
+int axp_set_aldo3(unsigned int mvolt)
|
||||
+{
|
||||
+ return axp_set_aldo(3, mvolt);
|
||||
+}
|
||||
+
|
||||
+int axp_set_dldo(int dldo_num, unsigned int mvolt)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 cfg;
|
||||
+
|
||||
+ if (dldo_num < 1 || dldo_num > 4)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (mvolt == 0)
|
||||
+ return pmic_bus_clrbits(AXP803_OUTPUT_CTRL2,
|
||||
+ AXP803_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
|
||||
+
|
||||
+ cfg = axp803_mvolt_to_cfg(mvolt, 700, 3300, 100);
|
||||
+ if (dldo_num == 2 && mvolt > 3300)
|
||||
+ cfg += 1 + axp803_mvolt_to_cfg(mvolt, 3400, 4200, 200);
|
||||
+ ret = pmic_bus_write(AXP803_DLDO1_CTRL + (dldo_num - 1), cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return pmic_bus_setbits(AXP803_OUTPUT_CTRL2,
|
||||
+ AXP803_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
|
||||
+}
|
||||
+
|
||||
+int axp_set_eldo(int eldo_num, unsigned int mvolt)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 cfg;
|
||||
+
|
||||
+ if (eldo_num < 1 || eldo_num > 3)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (mvolt == 0)
|
||||
+ return pmic_bus_clrbits(AXP803_OUTPUT_CTRL2,
|
||||
+ AXP803_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
|
||||
+
|
||||
+ cfg = axp803_mvolt_to_cfg(mvolt, 700, 1900, 50);
|
||||
+ ret = pmic_bus_write(AXP803_ELDO1_CTRL + (eldo_num - 1), cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return pmic_bus_setbits(AXP803_OUTPUT_CTRL2,
|
||||
+ AXP803_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
|
||||
+}
|
||||
+
|
||||
+int axp_set_fldo(int fldo_num, unsigned int mvolt)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 cfg;
|
||||
+
|
||||
+ if (fldo_num < 1 || fldo_num > 2)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (mvolt == 0)
|
||||
+ return pmic_bus_clrbits(AXP803_OUTPUT_CTRL3,
|
||||
+ AXP803_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1));
|
||||
+
|
||||
+ cfg = axp803_mvolt_to_cfg(mvolt, 700, 1450, 50);
|
||||
+ ret = pmic_bus_write(AXP803_FLDO1_CTRL + (fldo_num - 1), cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return pmic_bus_setbits(AXP803_OUTPUT_CTRL3,
|
||||
+ AXP803_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1));
|
||||
+}
|
||||
+
|
||||
+int axp_set_sw(bool on)
|
||||
+{
|
||||
+ if (on)
|
||||
+ return pmic_bus_setbits(AXP803_OUTPUT_CTRL2,
|
||||
+ AXP803_OUTPUT_CTRL2_SW_EN);
|
||||
+
|
||||
+ return pmic_bus_clrbits(AXP803_OUTPUT_CTRL2,
|
||||
+ AXP803_OUTPUT_CTRL2_SW_EN);
|
||||
+}
|
||||
+
|
||||
+int axp_init(void)
|
||||
+{
|
||||
+ u8 axp_chip_id;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = pmic_bus_init();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = pmic_bus_read(AXP803_CHIP_ID, &axp_chip_id);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!(axp_chip_id == 0x51))
|
||||
+ return -ENODEV;
|
||||
+ else
|
||||
+ return ret;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* ARM64 has its own poweroff implementation using PSCI */
|
||||
+#ifndef CONFIG_ARM64
|
||||
+int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
+{
|
||||
+ pmic_bus_write(AXP803_SHUTDOWN, AXP803_SHUTDOWN_POWEROFF);
|
||||
+
|
||||
+ /* infinite loop during shutdown */
|
||||
+ while (1)
|
||||
+ ;
|
||||
+
|
||||
+ /* not reached */
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
diff --git a/drivers/power/axp818.c b/drivers/power/axp818.c
|
||||
index af4d7a6903..ad0c330ca5 100644
|
||||
--- a/drivers/power/axp818.c
|
||||
+++ b/drivers/power/axp818.c
|
||||
@@ -162,7 +162,7 @@ int axp_set_dldo(int dldo_num, unsigned int mvolt)
|
||||
cfg = axp818_mvolt_to_cfg(mvolt, 700, 3300, 100);
|
||||
if (dldo_num == 2 && mvolt > 3300)
|
||||
cfg += 1 + axp818_mvolt_to_cfg(mvolt, 3400, 4200, 200);
|
||||
- ret = pmic_bus_write(AXP818_ELDO1_CTRL + (dldo_num - 1), cfg);
|
||||
+ ret = pmic_bus_write(AXP818_DLDO1_CTRL + (dldo_num - 1), cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
diff --git a/include/axp803.h b/include/axp803.h
|
||||
new file mode 100644
|
||||
index 0000000000..b382f3a5ec
|
||||
--- /dev/null
|
||||
+++ b/include/axp803.h
|
||||
@@ -0,0 +1,73 @@
|
||||
+/*
|
||||
+ * (C) Copyright 2016 Icenowy Zheng <icenowy@aosc.xyz>
|
||||
+ *
|
||||
+ * Based on axp818.h, which is:
|
||||
+ * (C) Copyright 2015 Vishnu Patekar <vishnupatekar0510@gmail.com>
|
||||
+ *
|
||||
+ * X-Powers AXP803 Power Management IC driver
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#define AXP803_CHIP_ID 0x03
|
||||
+
|
||||
+#define AXP803_OUTPUT_CTRL1 0x10
|
||||
+#define AXP803_OUTPUT_CTRL1_DCDC1_EN (1 << 0)
|
||||
+#define AXP803_OUTPUT_CTRL1_DCDC2_EN (1 << 1)
|
||||
+#define AXP803_OUTPUT_CTRL1_DCDC3_EN (1 << 2)
|
||||
+#define AXP803_OUTPUT_CTRL1_DCDC4_EN (1 << 3)
|
||||
+#define AXP803_OUTPUT_CTRL1_DCDC5_EN (1 << 4)
|
||||
+#define AXP803_OUTPUT_CTRL1_DCDC6_EN (1 << 5)
|
||||
+#define AXP803_OUTPUT_CTRL2 0x12
|
||||
+#define AXP803_OUTPUT_CTRL2_ELDO1_EN (1 << 0)
|
||||
+#define AXP803_OUTPUT_CTRL2_ELDO2_EN (1 << 1)
|
||||
+#define AXP803_OUTPUT_CTRL2_ELDO3_EN (1 << 2)
|
||||
+#define AXP803_OUTPUT_CTRL2_DLDO1_EN (1 << 3)
|
||||
+#define AXP803_OUTPUT_CTRL2_DLDO2_EN (1 << 4)
|
||||
+#define AXP803_OUTPUT_CTRL2_DLDO3_EN (1 << 5)
|
||||
+#define AXP803_OUTPUT_CTRL2_DLDO4_EN (1 << 6)
|
||||
+#define AXP803_OUTPUT_CTRL2_SW_EN (1 << 7)
|
||||
+#define AXP803_OUTPUT_CTRL3 0x13
|
||||
+#define AXP803_OUTPUT_CTRL3_FLDO1_EN (1 << 2)
|
||||
+#define AXP803_OUTPUT_CTRL3_FLDO2_EN (1 << 3)
|
||||
+#define AXP803_OUTPUT_CTRL3_ALDO1_EN (1 << 5)
|
||||
+#define AXP803_OUTPUT_CTRL3_ALDO2_EN (1 << 6)
|
||||
+#define AXP803_OUTPUT_CTRL3_ALDO3_EN (1 << 7)
|
||||
+
|
||||
+#define AXP803_DLDO1_CTRL 0x15
|
||||
+#define AXP803_DLDO2_CTRL 0x16
|
||||
+#define AXP803_DLDO3_CTRL 0x17
|
||||
+#define AXP803_DLDO4_CTRL 0x18
|
||||
+#define AXP803_ELDO1_CTRL 0x19
|
||||
+#define AXP803_ELDO2_CTRL 0x1a
|
||||
+#define AXP803_ELDO3_CTRL 0x1b
|
||||
+#define AXP803_FLDO1_CTRL 0x1c
|
||||
+#define AXP803_FLDO2_CTRL 0x1d
|
||||
+#define AXP803_DCDC1_CTRL 0x20
|
||||
+#define AXP803_DCDC2_CTRL 0x21
|
||||
+#define AXP803_DCDC3_CTRL 0x22
|
||||
+#define AXP803_DCDC4_CTRL 0x23
|
||||
+#define AXP803_DCDC5_CTRL 0x24
|
||||
+#define AXP803_DCDC6_CTRL 0x25
|
||||
+
|
||||
+#define AXP803_ALDO1_CTRL 0x28
|
||||
+#define AXP803_ALDO2_CTRL 0x29
|
||||
+#define AXP803_ALDO3_CTRL 0x2a
|
||||
+
|
||||
+#define AXP803_SHUTDOWN 0x32
|
||||
+#define AXP803_SHUTDOWN_POWEROFF (1 << 7)
|
||||
+
|
||||
+/* For axp_gpio.c */
|
||||
+#define AXP_POWER_STATUS 0x00
|
||||
+#define AXP_POWER_STATUS_VBUS_PRESENT (1 << 5)
|
||||
+#define AXP_VBUS_IPSOUT 0x30
|
||||
+#define AXP_VBUS_IPSOUT_DRIVEBUS (1 << 2)
|
||||
+#define AXP_MISC_CTRL 0x8f
|
||||
+#define AXP_MISC_CTRL_N_VBUSEN_FUNC (1 << 4)
|
||||
+#define AXP_GPIO0_CTRL 0x90
|
||||
+#define AXP_GPIO1_CTRL 0x92
|
||||
+#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */
|
||||
+#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */
|
||||
+#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */
|
||||
+#define AXP_GPIO_STATE 0x94
|
||||
+#define AXP_GPIO_STATE_OFFSET 0
|
||||
diff --git a/include/axp_pmic.h b/include/axp_pmic.h
|
||||
index d789ad8086..8cb4d5763c 100644
|
||||
--- a/include/axp_pmic.h
|
||||
+++ b/include/axp_pmic.h
|
||||
@@ -16,6 +16,9 @@
|
||||
#ifdef CONFIG_AXP221_POWER
|
||||
#include <axp221.h>
|
||||
#endif
|
||||
+#ifdef CONFIG_AXP803_POWER
|
||||
+#include <axp803.h>
|
||||
+#endif
|
||||
#ifdef CONFIG_AXP809_POWER
|
||||
#include <axp809.h>
|
||||
#endif
|
25
patch/u-boot/u-boot-sunxi/03-vidconsole-fix.patch
Normal file
25
patch/u-boot/u-boot-sunxi/03-vidconsole-fix.patch
Normal file
|
@ -0,0 +1,25 @@
|
|||
From e4421d697d889d1a802babfbd1d0839bc92884a8 Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
Date: Thu, 31 Aug 2017 21:53:07 -0700
|
||||
Subject: [PATCH] vidconsole: flush dcache on putc
|
||||
|
||||
Otherwise characters that are being typed are not displayed until
|
||||
user presses "enter".
|
||||
|
||||
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
---
|
||||
drivers/video/vidconsole-uclass.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
|
||||
index b5afd72227..44c716c665 100644
|
||||
--- a/drivers/video/vidconsole-uclass.c
|
||||
+++ b/drivers/video/vidconsole-uclass.c
|
||||
@@ -163,6 +163,7 @@ static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
|
||||
struct udevice *dev = sdev->priv;
|
||||
|
||||
vidconsole_put_char(dev, ch);
|
||||
+ video_sync(dev->parent);
|
||||
}
|
||||
|
||||
static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
|
|
@ -0,0 +1,62 @@
|
|||
From 732153bd114162e8afa22a025d065c5c1d5359f5 Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
Date: Sun, 17 Sep 2017 09:21:33 -0700
|
||||
Subject: [PATCH] video: pwm_backlight: make regulator optional
|
||||
|
||||
u-boot doesn't have dummy regulators, so pwm_backlight probe
|
||||
will fail if regulator is missing. Make it optional to get this
|
||||
driver working on platforms where there's no backlight regultor.
|
||||
|
||||
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
---
|
||||
drivers/video/pwm_backlight.c | 28 ++++++++++++++++------------
|
||||
1 file changed, 16 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/video/pwm_backlight.c b/drivers/video/pwm_backlight.c
|
||||
index fbd7bf7838..05e56ffead 100644
|
||||
--- a/drivers/video/pwm_backlight.c
|
||||
+++ b/drivers/video/pwm_backlight.c
|
||||
@@ -32,16 +32,21 @@ static int pwm_backlight_enable(struct udevice *dev)
|
||||
uint duty_cycle;
|
||||
int ret;
|
||||
|
||||
- plat = dev_get_uclass_platdata(priv->reg);
|
||||
- debug("%s: Enable '%s', regulator '%s'/'%s'\n", __func__, dev->name,
|
||||
- priv->reg->name, plat->name);
|
||||
- ret = regulator_set_enable(priv->reg, true);
|
||||
- if (ret) {
|
||||
- debug("%s: Cannot enable regulator for PWM '%s'\n", __func__,
|
||||
- dev->name);
|
||||
- return ret;
|
||||
+ if (priv->reg) {
|
||||
+ plat = dev_get_uclass_platdata(priv->reg);
|
||||
+ debug("%s: Enable '%s', regulator '%s'/'%s'\n", __func__, dev->name,
|
||||
+ priv->reg->name, plat->name);
|
||||
+ ret = regulator_set_enable(priv->reg, true);
|
||||
+ if (ret) {
|
||||
+ debug("%s: Cannot enable regulator for PWM '%s'\n", __func__,
|
||||
+ dev->name);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ mdelay(120);
|
||||
}
|
||||
- mdelay(120);
|
||||
+
|
||||
+ debug("%s: default: %d, min: %d, max: %d\n", __func__,
|
||||
+ priv->default_level, priv->min_level, priv->max_level);
|
||||
|
||||
duty_cycle = priv->period_ns * (priv->default_level - priv->min_level) /
|
||||
(priv->max_level - priv->min_level + 1);
|
||||
@@ -68,10 +73,9 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev)
|
||||
debug("%s: start\n", __func__);
|
||||
ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
|
||||
"power-supply", &priv->reg);
|
||||
- if (ret) {
|
||||
+ if (ret)
|
||||
debug("%s: Cannot get power supply: ret=%d\n", __func__, ret);
|
||||
- return ret;
|
||||
- }
|
||||
+
|
||||
ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable,
|
||||
GPIOD_IS_OUT);
|
||||
if (ret) {
|
31
patch/u-boot/u-boot-sunxi/05-add-pwm-node-DT.patch
Normal file
31
patch/u-boot/u-boot-sunxi/05-add-pwm-node-DT.patch
Normal file
|
@ -0,0 +1,31 @@
|
|||
From 4644c442c8b14585881995f1c901782c3dad0e46 Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
Date: Sun, 17 Sep 2017 09:24:13 -0700
|
||||
Subject: [PATCH] dts: sunxi: add PWM node for sun50i
|
||||
|
||||
Add PWM definition to sun50i-a64.dtsi - it's compatible with PWM found on H3
|
||||
|
||||
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
---
|
||||
arch/arm/dts/sun50i-a64.dtsi | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/dts/sun50i-a64.dtsi b/arch/arm/dts/sun50i-a64.dtsi
|
||||
index 65a344d9ce..00132855ff 100644
|
||||
--- a/arch/arm/dts/sun50i-a64.dtsi
|
||||
+++ b/arch/arm/dts/sun50i-a64.dtsi
|
||||
@@ -319,6 +319,14 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ pwm: pwm@01c21400 {
|
||||
+ compatible = "allwinner,sun8i-h3-pwm";
|
||||
+ reg = <0x01c21400 0x8>;
|
||||
+ clocks = <&osc24M>;
|
||||
+ #pwm-cells = <3>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
uart0: serial@1c28000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0x01c28000 0x400>;
|
78
patch/u-boot/u-boot-sunxi/06-bridge-read-edid.patch
Normal file
78
patch/u-boot/u-boot-sunxi/06-bridge-read-edid.patch
Normal file
|
@ -0,0 +1,78 @@
|
|||
From e7ce02a71b32cb1845a84dc54b8d596a0c5b04b5 Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
Date: Fri, 15 Sep 2017 21:14:41 -0700
|
||||
Subject: [PATCH] dm: video: bridge: add operation to read EDID
|
||||
|
||||
Add an operation to read EDID, since bridge may have ability to read
|
||||
EDID from the panel that is connected to it, for example LCD<->eDP bridge.
|
||||
|
||||
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
---
|
||||
drivers/video/bridge/video-bridge-uclass.c | 10 ++++++++++
|
||||
include/video_bridge.h | 20 ++++++++++++++++++++
|
||||
2 files changed, 30 insertions(+)
|
||||
|
||||
diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c
|
||||
index 07270bac9e..79facd02a6 100644
|
||||
--- a/drivers/video/bridge/video-bridge-uclass.c
|
||||
+++ b/drivers/video/bridge/video-bridge-uclass.c
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
+#include <edid.h>
|
||||
#include <video_bridge.h>
|
||||
|
||||
int video_bridge_set_backlight(struct udevice *dev, int percent)
|
||||
@@ -45,6 +46,15 @@ int video_bridge_check_attached(struct udevice *dev)
|
||||
return ops->check_attached(dev);
|
||||
}
|
||||
|
||||
+int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size)
|
||||
+{
|
||||
+ struct video_bridge_ops *ops = video_bridge_get_ops(dev);
|
||||
+
|
||||
+ if (!ops || !ops->read_edid)
|
||||
+ return -ENOSYS;
|
||||
+ return ops->read_edid(dev, buf, buf_size);
|
||||
+}
|
||||
+
|
||||
static int video_bridge_pre_probe(struct udevice *dev)
|
||||
{
|
||||
struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
diff --git a/include/video_bridge.h b/include/video_bridge.h
|
||||
index c7b8681849..0699a8dda8 100644
|
||||
--- a/include/video_bridge.h
|
||||
+++ b/include/video_bridge.h
|
||||
@@ -53,6 +53,16 @@ struct video_bridge_ops {
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int (*set_backlight)(struct udevice *dev, int percent);
|
||||
+
|
||||
+ /**
|
||||
+ * read_edid() - Read information from EDID
|
||||
+ *
|
||||
+ * @dev: Device to read from
|
||||
+ * @buf: Buffer to read into
|
||||
+ * @buf_size: Buffer size
|
||||
+ * @return number of bytes read, <=0 for error
|
||||
+ */
|
||||
+ int (*read_edid)(struct udevice *dev, u8 *buf, int buf_size);
|
||||
};
|
||||
|
||||
#define video_bridge_get_ops(dev) \
|
||||
@@ -89,4 +99,14 @@ int video_bridge_set_active(struct udevice *dev, bool active);
|
||||
*/
|
||||
int video_bridge_check_attached(struct udevice *dev);
|
||||
|
||||
+/**
|
||||
+ * video_bridge_read_edid() - Read information from EDID
|
||||
+ *
|
||||
+ * @dev: Device to read from
|
||||
+ * @buf: Buffer to read into
|
||||
+ * @buf_size: Buffer size
|
||||
+ * @return number of bytes read, <=0 for error
|
||||
+ */
|
||||
+int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size);
|
||||
+
|
||||
#endif
|
186
patch/u-boot/u-boot-sunxi/07-split-anx9804.patch
Normal file
186
patch/u-boot/u-boot-sunxi/07-split-anx9804.patch
Normal file
|
@ -0,0 +1,186 @@
|
|||
From 0b082a8e4e751a2b95ebf450945c055f2cf3d4e2 Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
Date: Fri, 15 Sep 2017 23:35:40 -0700
|
||||
Subject: [PATCH] video: anx9804: split out registers definitions into a
|
||||
separate header
|
||||
|
||||
This header will be used in anx6345 driver
|
||||
|
||||
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
---
|
||||
drivers/video/anx9804.c | 54 +--------------------------
|
||||
include/anx98xx-edp.h | 98 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 99 insertions(+), 53 deletions(-)
|
||||
create mode 100644 include/anx98xx-edp.h
|
||||
|
||||
diff --git a/drivers/video/anx9804.c b/drivers/video/anx9804.c
|
||||
index 37ad69a039..67f7da7d18 100755
|
||||
--- a/drivers/video/anx9804.c
|
||||
+++ b/drivers/video/anx9804.c
|
||||
@@ -12,61 +12,9 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
+#include <anx98xx-edp.h>
|
||||
#include "anx9804.h"
|
||||
|
||||
-/* Registers at i2c address 0x38 */
|
||||
-
|
||||
-#define ANX9804_HDCP_CONTROL_0_REG 0x01
|
||||
-
|
||||
-#define ANX9804_SYS_CTRL2_REG 0x81
|
||||
-#define ANX9804_SYS_CTRL2_CHA_STA 0x04
|
||||
-
|
||||
-#define ANX9804_SYS_CTRL3_REG 0x82
|
||||
-#define ANX9804_SYS_CTRL3_VALID_CTRL BIT(0)
|
||||
-#define ANX9804_SYS_CTRL3_F_VALID BIT(1)
|
||||
-#define ANX9804_SYS_CTRL3_HPD_CTRL BIT(4)
|
||||
-#define ANX9804_SYS_CTRL3_F_HPD BIT(5)
|
||||
-
|
||||
-#define ANX9804_LINK_BW_SET_REG 0xa0
|
||||
-#define ANX9804_LANE_COUNT_SET_REG 0xa1
|
||||
-#define ANX9804_TRAINING_PTN_SET_REG 0xa2
|
||||
-#define ANX9804_TRAINING_LANE0_SET_REG 0xa3
|
||||
-#define ANX9804_TRAINING_LANE1_SET_REG 0xa4
|
||||
-#define ANX9804_TRAINING_LANE2_SET_REG 0xa5
|
||||
-#define ANX9804_TRAINING_LANE3_SET_REG 0xa6
|
||||
-
|
||||
-#define ANX9804_LINK_TRAINING_CTRL_REG 0xa8
|
||||
-#define ANX9804_LINK_TRAINING_CTRL_EN BIT(0)
|
||||
-
|
||||
-#define ANX9804_LINK_DEBUG_REG 0xb8
|
||||
-#define ANX9804_PLL_CTRL_REG 0xc7
|
||||
-#define ANX9804_ANALOG_POWER_DOWN_REG 0xc8
|
||||
-
|
||||
-/* Registers at i2c address 0x39 */
|
||||
-
|
||||
-#define ANX9804_DEV_IDH_REG 0x03
|
||||
-
|
||||
-#define ANX9804_POWERD_CTRL_REG 0x05
|
||||
-#define ANX9804_POWERD_AUDIO BIT(4)
|
||||
-
|
||||
-#define ANX9804_RST_CTRL_REG 0x06
|
||||
-
|
||||
-#define ANX9804_RST_CTRL2_REG 0x07
|
||||
-#define ANX9804_RST_CTRL2_AUX BIT(2)
|
||||
-#define ANX9804_RST_CTRL2_AC_MODE BIT(6)
|
||||
-
|
||||
-#define ANX9804_VID_CTRL1_REG 0x08
|
||||
-#define ANX9804_VID_CTRL1_VID_EN BIT(7)
|
||||
-#define ANX9804_VID_CTRL1_EDGE BIT(0)
|
||||
-
|
||||
-#define ANX9804_VID_CTRL2_REG 0x09
|
||||
-#define ANX9804_ANALOG_DEBUG_REG1 0xdc
|
||||
-#define ANX9804_ANALOG_DEBUG_REG3 0xde
|
||||
-#define ANX9804_PLL_FILTER_CTRL1 0xdf
|
||||
-#define ANX9804_PLL_FILTER_CTRL3 0xe1
|
||||
-#define ANX9804_PLL_FILTER_CTRL 0xe2
|
||||
-#define ANX9804_PLL_CTRL3 0xe6
|
||||
-
|
||||
/**
|
||||
* anx9804_init() - Init anx9804 parallel lcd to edp bridge chip
|
||||
*
|
||||
diff --git a/include/anx98xx-edp.h b/include/anx98xx-edp.h
|
||||
new file mode 100644
|
||||
index 0000000000..f7e8baa167
|
||||
--- /dev/null
|
||||
+++ b/include/anx98xx-edp.h
|
||||
@@ -0,0 +1,98 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
|
||||
+ * Copyright (C) 2017 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+/* Registers at i2c address 0x38 */
|
||||
+
|
||||
+#define ANX9804_HDCP_CONTROL_0_REG 0x01
|
||||
+
|
||||
+#define ANX9804_SYS_CTRL1_REG 0x80
|
||||
+#define ANX9804_SYS_CTRL1_PD_IO 0x80
|
||||
+#define ANX9804_SYS_CTRL1_PD_VID 0x40
|
||||
+#define ANX9804_SYS_CTRL1_PD_LINK 0x20
|
||||
+#define ANX9804_SYS_CTRL1_PD_TOTAL 0x10
|
||||
+#define ANX9804_SYS_CTRL1_MODE_SEL 0x08
|
||||
+#define ANX9804_SYS_CTRL1_DET_STA 0x04
|
||||
+#define ANX9804_SYS_CTRL1_FORCE_DET 0x02
|
||||
+#define ANX9804_SYS_CTRL1_DET_CTRL 0x01
|
||||
+
|
||||
+#define ANX9804_SYS_CTRL2_REG 0x81
|
||||
+#define ANX9804_SYS_CTRL2_CHA_STA 0x04
|
||||
+
|
||||
+#define ANX9804_SYS_CTRL3_REG 0x82
|
||||
+#define ANX9804_SYS_CTRL3_VALID_CTRL BIT(0)
|
||||
+#define ANX9804_SYS_CTRL3_F_VALID BIT(1)
|
||||
+#define ANX9804_SYS_CTRL3_HPD_CTRL BIT(4)
|
||||
+#define ANX9804_SYS_CTRL3_F_HPD BIT(5)
|
||||
+
|
||||
+#define ANX9804_LINK_BW_SET_REG 0xa0
|
||||
+#define ANX9804_LANE_COUNT_SET_REG 0xa1
|
||||
+#define ANX9804_TRAINING_PTN_SET_REG 0xa2
|
||||
+#define ANX9804_TRAINING_LANE0_SET_REG 0xa3
|
||||
+#define ANX9804_TRAINING_LANE1_SET_REG 0xa4
|
||||
+#define ANX9804_TRAINING_LANE2_SET_REG 0xa5
|
||||
+#define ANX9804_TRAINING_LANE3_SET_REG 0xa6
|
||||
+
|
||||
+#define ANX9804_LINK_TRAINING_CTRL_REG 0xa8
|
||||
+#define ANX9804_LINK_TRAINING_CTRL_EN BIT(0)
|
||||
+
|
||||
+#define ANX9804_LINK_DEBUG_REG 0xb8
|
||||
+#define ANX9804_PLL_CTRL_REG 0xc7
|
||||
+#define ANX9804_ANALOG_POWER_DOWN_REG 0xc8
|
||||
+
|
||||
+#define ANX9804_AUX_CH_STA 0xe0
|
||||
+#define ANX9804_AUX_BUSY BIT(4)
|
||||
+#define ANX9804_AUX_STATUS_MASK 0x0f
|
||||
+
|
||||
+#define ANX9804_DP_AUX_RX_COMM 0xe3
|
||||
+#define ANX9804_AUX_RX_COMM_I2C_DEFER BIT(3)
|
||||
+#define ANX9804_AUX_RX_COMM_AUX_DEFER BIT(1)
|
||||
+
|
||||
+#define ANX9804_DP_AUX_CH_CTL_1 0xe5
|
||||
+#define ANX9804_AUX_LENGTH(x) (((x - 1) & 0x0f) << 4)
|
||||
+#define ANX9804_AUX_TX_COMM_MASK 0x0f
|
||||
+#define ANX9804_AUX_TX_COMM_DP_TRANSACTION BIT(3)
|
||||
+#define ANX9804_AUX_TX_COMM_MOT BIT(2)
|
||||
+#define ANX9804_AUX_TX_COMM_READ BIT(0)
|
||||
+
|
||||
+#define ANX9804_DP_AUX_ADDR_7_0 0xe6
|
||||
+#define ANX9804_DP_AUX_ADDR_15_8 0xe7
|
||||
+#define ANX9804_DP_AUX_ADDR_19_16 0xe8
|
||||
+
|
||||
+#define ANX9804_DP_AUX_CH_CTL_2 0xe9
|
||||
+#define ANX9804_ADDR_ONLY BIT(1)
|
||||
+#define ANX9804_AUX_EN BIT(0)
|
||||
+
|
||||
+#define ANX9804_BUF_DATA_0 0xf0
|
||||
+
|
||||
+/* Registers at i2c address 0x39 */
|
||||
+
|
||||
+#define ANX9804_DEV_IDH_REG 0x03
|
||||
+
|
||||
+#define ANX9804_POWERD_CTRL_REG 0x05
|
||||
+#define ANX9804_POWERD_AUDIO BIT(4)
|
||||
+
|
||||
+#define ANX9804_RST_CTRL_REG 0x06
|
||||
+
|
||||
+#define ANX9804_RST_CTRL2_REG 0x07
|
||||
+#define ANX9804_RST_CTRL2_AUX BIT(2)
|
||||
+#define ANX9804_RST_CTRL2_AC_MODE BIT(6)
|
||||
+
|
||||
+#define ANX9804_VID_CTRL1_REG 0x08
|
||||
+#define ANX9804_VID_CTRL1_VID_EN BIT(7)
|
||||
+#define ANX9804_VID_CTRL1_EDGE BIT(0)
|
||||
+
|
||||
+#define ANX9804_VID_CTRL2_REG 0x09
|
||||
+#define ANX9804_ANALOG_DEBUG_REG1 0xdc
|
||||
+#define ANX9804_ANALOG_DEBUG_REG3 0xde
|
||||
+#define ANX9804_PLL_FILTER_CTRL1 0xdf
|
||||
+#define ANX9804_PLL_FILTER_CTRL3 0xe1
|
||||
+#define ANX9804_PLL_FILTER_CTRL 0xe2
|
||||
+#define ANX9804_PLL_CTRL3 0xe6
|
||||
+
|
||||
+#define ANX9804_DP_INT_STA 0xf7
|
||||
+#define ANX9804_RPLY_RECEIV BIT(1)
|
||||
+#define ANX9804_AUX_ERR BIT(0)
|
466
patch/u-boot/u-boot-sunxi/08-add-anx6345-driver.patch
Normal file
466
patch/u-boot/u-boot-sunxi/08-add-anx6345-driver.patch
Normal file
|
@ -0,0 +1,466 @@
|
|||
From 713201f49e474d8d27c06db200c76c391f38c5f9 Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
Date: Fri, 15 Sep 2017 23:37:29 -0700
|
||||
Subject: [PATCH] video: add anx6345 DM driver
|
||||
|
||||
This is a eDP bridge similar to ANX9804, it allows to connect eDP panels
|
||||
to the chips that can output only parallel signal
|
||||
|
||||
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
---
|
||||
drivers/video/bridge/Kconfig | 8 +
|
||||
drivers/video/bridge/Makefile | 1 +
|
||||
drivers/video/bridge/anx6345.c | 419 +++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 428 insertions(+)
|
||||
create mode 100644 drivers/video/bridge/anx6345.c
|
||||
|
||||
diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig
|
||||
index 2a3b6c4bee..765f7380b8 100644
|
||||
--- a/drivers/video/bridge/Kconfig
|
||||
+++ b/drivers/video/bridge/Kconfig
|
||||
@@ -25,3 +25,11 @@ config VIDEO_BRIDGE_NXP_PTN3460
|
||||
signalling) converter. It enables an LVDS LCD panel to be connected
|
||||
to an eDP output device such as an SoC that lacks LVDS capability,
|
||||
or where LVDS requires too many signals to route on the PCB.
|
||||
+
|
||||
+config VIDEO_BRIDGE_ANALOGIX_ANX6345
|
||||
+ bool "Support Analogix ANX6345 RGB->DP bridge"
|
||||
+ depends on VIDEO_BRIDGE
|
||||
+ select DM_I2C
|
||||
+ help
|
||||
+ The Analogix ANX6345 is RGB-to-DP converter. It enables an eDP LCD
|
||||
+ panel to be connected to an parallel LCD interface.
|
||||
diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile
|
||||
index ce731fa4ca..2a746c6f8b 100644
|
||||
--- a/drivers/video/bridge/Makefile
|
||||
+++ b/drivers/video/bridge/Makefile
|
||||
@@ -7,3 +7,4 @@
|
||||
obj-$(CONFIG_VIDEO_BRIDGE) += video-bridge-uclass.o
|
||||
obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o
|
||||
obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o
|
||||
+obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o
|
||||
diff --git a/drivers/video/bridge/anx6345.c b/drivers/video/bridge/anx6345.c
|
||||
new file mode 100644
|
||||
index 0000000000..6bac9a51a9
|
||||
--- /dev/null
|
||||
+++ b/drivers/video/bridge/anx6345.c
|
||||
@@ -0,0 +1,419 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2017 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#include <common.h>
|
||||
+#include <dm.h>
|
||||
+#include <errno.h>
|
||||
+#include <i2c.h>
|
||||
+#include <edid.h>
|
||||
+#include <video_bridge.h>
|
||||
+#include <anx98xx-edp.h>
|
||||
+
|
||||
+#define DP_MAX_LINK_RATE 0x001
|
||||
+#define DP_MAX_LANE_COUNT 0x002
|
||||
+#define DP_MAX_LANE_COUNT_MASK 0x1f
|
||||
+
|
||||
+DECLARE_GLOBAL_DATA_PTR;
|
||||
+
|
||||
+struct anx6345_priv {
|
||||
+ u8 edid[EDID_SIZE];
|
||||
+};
|
||||
+
|
||||
+static int anx6345_write(struct udevice *dev, unsigned addr_off,
|
||||
+ unsigned char reg_addr, unsigned char value)
|
||||
+{
|
||||
+ uint8_t buf[2];
|
||||
+ struct i2c_msg msg;
|
||||
+ int ret;
|
||||
+
|
||||
+ msg.addr = addr_off;
|
||||
+ msg.flags = 0;
|
||||
+ buf[0] = reg_addr;
|
||||
+ buf[1] = value;
|
||||
+ msg.buf = buf;
|
||||
+ msg.len = 2;
|
||||
+ ret = dm_i2c_xfer(dev, &msg, 1);
|
||||
+ if (ret) {
|
||||
+ debug("%s: write failed, reg=%#x, value=%#x, ret=%d\n",
|
||||
+ __func__, reg_addr, value, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int anx6345_read(struct udevice *dev, unsigned addr_off,
|
||||
+ unsigned char reg_addr, unsigned char *value)
|
||||
+{
|
||||
+ uint8_t addr, val;
|
||||
+ struct i2c_msg msg[2];
|
||||
+ int ret;
|
||||
+
|
||||
+ msg[0].addr = addr_off;
|
||||
+ msg[0].flags = 0;
|
||||
+ addr = reg_addr;
|
||||
+ msg[0].buf = &addr;
|
||||
+ msg[0].len = 1;
|
||||
+ msg[1].addr = addr_off;
|
||||
+ msg[1].flags = I2C_M_RD;
|
||||
+ msg[1].buf = &val;
|
||||
+ msg[1].len = 1;
|
||||
+ ret = dm_i2c_xfer(dev, msg, 2);
|
||||
+ if (ret) {
|
||||
+ debug("%s: read failed, reg=%.2x, value=%p, ret=%d\n",
|
||||
+ __func__, (int)reg_addr, value, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ *value = val;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int anx6345_write_r0(struct udevice *dev, unsigned char reg_addr,
|
||||
+ unsigned char value)
|
||||
+{
|
||||
+ struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
|
||||
+ return anx6345_write(dev, chip->chip_addr, reg_addr, value);
|
||||
+}
|
||||
+
|
||||
+static int anx6345_read_r0(struct udevice *dev, unsigned char reg_addr,
|
||||
+ unsigned char *value)
|
||||
+{
|
||||
+ struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
|
||||
+ return anx6345_read(dev, chip->chip_addr, reg_addr, value);
|
||||
+}
|
||||
+
|
||||
+static int anx6345_write_r1(struct udevice *dev, unsigned char reg_addr,
|
||||
+ unsigned char value)
|
||||
+{
|
||||
+ struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
|
||||
+ return anx6345_write(dev, chip->chip_addr + 1, reg_addr, value);
|
||||
+}
|
||||
+
|
||||
+static int anx6345_read_r1(struct udevice *dev, unsigned char reg_addr,
|
||||
+ unsigned char *value)
|
||||
+{
|
||||
+ struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
|
||||
+ return anx6345_read(dev, chip->chip_addr + 1, reg_addr, value);
|
||||
+}
|
||||
+
|
||||
+static int anx6345_set_backlight(struct udevice *dev, int percent)
|
||||
+{
|
||||
+ return -ENOSYS;
|
||||
+}
|
||||
+
|
||||
+static int anx6345_aux_wait(struct udevice *dev)
|
||||
+{
|
||||
+ int ret = -ETIMEDOUT;
|
||||
+ u8 v;
|
||||
+ int retries = 1000;
|
||||
+ do {
|
||||
+ anx6345_read_r0(dev, ANX9804_DP_AUX_CH_CTL_2, &v);
|
||||
+ if (!(v & ANX9804_AUX_EN)) {
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ udelay(100);
|
||||
+ } while (retries--);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ debug("%s: timed out waiting for AUX_EN to clear\n", __func__);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = -ETIMEDOUT;
|
||||
+ retries = 1000;
|
||||
+ do {
|
||||
+ anx6345_read_r1(dev, ANX9804_DP_INT_STA, &v);
|
||||
+ if (v & ANX9804_RPLY_RECEIV) {
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ udelay(100);
|
||||
+ } while (retries--);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ debug("%s: timed out waiting to receive reply\n", __func__);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Clear RPLY_RECEIV bit */
|
||||
+ anx6345_write_r1(dev, ANX9804_DP_INT_STA, v);
|
||||
+
|
||||
+ anx6345_read_r0(dev, ANX9804_AUX_CH_STA, &v);
|
||||
+ if ((v & ANX9804_AUX_STATUS_MASK) != 0) {
|
||||
+ debug("AUX status: %d\n", v & ANX9804_AUX_STATUS_MASK);
|
||||
+ ret = -EIO;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void anx6345_aux_addr(struct udevice *dev, u32 addr)
|
||||
+{
|
||||
+ u8 val;
|
||||
+
|
||||
+ val = addr & 0xff;
|
||||
+ anx6345_write_r0(dev, ANX9804_DP_AUX_ADDR_7_0, val);
|
||||
+ val = (addr >> 8) & 0xff;
|
||||
+ anx6345_write_r0(dev, ANX9804_DP_AUX_ADDR_15_8, val);
|
||||
+ val = (addr >> 16) & 0x0f;
|
||||
+ anx6345_write_r0(dev, ANX9804_DP_AUX_ADDR_19_16, val);
|
||||
+}
|
||||
+
|
||||
+static int anx6345_aux_transfer(struct udevice *dev, u8 req, u32 addr, u8 *buf, size_t len)
|
||||
+{
|
||||
+ int i, ret;
|
||||
+ u8 ctrl1 = req;
|
||||
+ u8 ctrl2 = ANX9804_AUX_EN;
|
||||
+
|
||||
+ if (len > 16)
|
||||
+ return -E2BIG;
|
||||
+
|
||||
+ if (len)
|
||||
+ ctrl1 |= ANX9804_AUX_LENGTH(len);
|
||||
+ else
|
||||
+ ctrl2 |= ANX9804_ADDR_ONLY;
|
||||
+
|
||||
+ if (len && !(req & ANX9804_AUX_TX_COMM_READ)) {
|
||||
+ for (i = 0; i < len; i++)
|
||||
+ anx6345_write_r0(dev, ANX9804_BUF_DATA_0 + i, buf[i]);
|
||||
+ }
|
||||
+
|
||||
+ anx6345_aux_addr(dev, addr);
|
||||
+ anx6345_write_r0(dev, ANX9804_DP_AUX_CH_CTL_1, ctrl1);
|
||||
+ anx6345_write_r0(dev, ANX9804_DP_AUX_CH_CTL_2, ctrl2);
|
||||
+ ret = anx6345_aux_wait(dev);
|
||||
+ if (ret) {
|
||||
+ debug("AUX transaction timed out\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (len && (req & ANX9804_AUX_TX_COMM_READ)) {
|
||||
+ for (i = 0; i < len; i++)
|
||||
+ anx6345_read_r0(dev, ANX9804_BUF_DATA_0 + i, &buf[i]);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static int anx6345_read_aux_i2c(struct udevice *dev, u8 chip_addr,
|
||||
+ u8 offset,
|
||||
+ size_t count,
|
||||
+ u8 *buf)
|
||||
+{
|
||||
+ int i, ret;
|
||||
+ size_t cur_cnt;
|
||||
+ u8 cur_offset;
|
||||
+ for (i = 0; i < count; i += 16) {
|
||||
+ cur_cnt = (count - i) > 16 ? 16 : count - i;
|
||||
+ cur_offset = offset + i;
|
||||
+ ret = anx6345_aux_transfer(dev, ANX9804_AUX_TX_COMM_MOT,
|
||||
+ chip_addr, &cur_offset, 1);
|
||||
+ if (ret) {
|
||||
+ debug("%s: failed to set i2c offset: %d\n", __func__, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ret = anx6345_aux_transfer(dev, ANX9804_AUX_TX_COMM_READ,
|
||||
+ chip_addr, buf + i, cur_cnt);
|
||||
+ if (ret) {
|
||||
+ debug("%s: failed to read from i2c device: %d\n", __func__, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int anx6345_read_dpcd(struct udevice *dev, u32 reg, u8 *val)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = anx6345_aux_transfer(dev,
|
||||
+ ANX9804_AUX_TX_COMM_READ |
|
||||
+ ANX9804_AUX_TX_COMM_DP_TRANSACTION,
|
||||
+ reg, val, 1);
|
||||
+ if (ret) {
|
||||
+ debug ("Failed to read DPCD\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int anx6345_read_edid(struct udevice *dev, u8 *buf, int size)
|
||||
+{
|
||||
+ struct anx6345_priv *priv = dev_get_priv(dev);
|
||||
+
|
||||
+ if (size > EDID_SIZE)
|
||||
+ size = EDID_SIZE;
|
||||
+ memcpy(buf, priv->edid, size);
|
||||
+
|
||||
+ return size;
|
||||
+}
|
||||
+
|
||||
+static int anx6345_attach(struct udevice *dev)
|
||||
+{
|
||||
+ /* No-op */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int anx6345_enable(struct udevice *dev)
|
||||
+{
|
||||
+ u8 chipid, colordepth, lanes, data_rate, c;
|
||||
+ int ret, i, bpp;
|
||||
+ struct display_timing timing;
|
||||
+ struct anx6345_priv *priv = dev_get_priv(dev);
|
||||
+
|
||||
+ /* Deassert reset and enable power */
|
||||
+ ret = video_bridge_set_active(dev, true);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Reset */
|
||||
+ anx6345_write_r1(dev, ANX9804_RST_CTRL_REG, 1);
|
||||
+ mdelay(100);
|
||||
+ anx6345_write_r1(dev, ANX9804_RST_CTRL_REG, 0);
|
||||
+
|
||||
+ /* Write 0 to the powerdown reg (powerup everything) */
|
||||
+ anx6345_write_r1(dev, ANX9804_POWERD_CTRL_REG, 0);
|
||||
+
|
||||
+ ret = anx6345_read_r1(dev, ANX9804_DEV_IDH_REG, &chipid);
|
||||
+ if (ret)
|
||||
+ debug("%s: read id failed: %d\n", __func__, ret);
|
||||
+
|
||||
+ switch (chipid) {
|
||||
+ case 0x63:
|
||||
+ debug("ANX63xx detected.\n");
|
||||
+ break;
|
||||
+ default:
|
||||
+ debug("Error anx6345 chipid mismatch: %.2x\n", (int)chipid);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 100; i++) {
|
||||
+ anx6345_read_r0(dev, ANX9804_SYS_CTRL2_REG, &c);
|
||||
+ anx6345_write_r0(dev, ANX9804_SYS_CTRL2_REG, c);
|
||||
+ anx6345_read_r0(dev, ANX9804_SYS_CTRL2_REG, &c);
|
||||
+ if ((c & ANX9804_SYS_CTRL2_CHA_STA) == 0)
|
||||
+ break;
|
||||
+
|
||||
+ mdelay(5);
|
||||
+ }
|
||||
+ if (i == 100)
|
||||
+ debug("Error anx6345 clock is not stable\n");
|
||||
+
|
||||
+ /* Set a bunch of analog related register values */
|
||||
+ anx6345_write_r0(dev, ANX9804_PLL_CTRL_REG, 0x00);
|
||||
+ anx6345_write_r1(dev, ANX9804_ANALOG_DEBUG_REG1, 0x70);
|
||||
+ anx6345_write_r0(dev, ANX9804_LINK_DEBUG_REG, 0x30);
|
||||
+
|
||||
+ /* Force HPD */
|
||||
+ anx6345_write_r0(dev, ANX9804_SYS_CTRL3_REG,
|
||||
+ ANX9804_SYS_CTRL3_F_HPD | ANX9804_SYS_CTRL3_HPD_CTRL);
|
||||
+
|
||||
+ /* Power up and configure lanes */
|
||||
+ anx6345_write_r0(dev, ANX9804_ANALOG_POWER_DOWN_REG, 0x00);
|
||||
+ anx6345_write_r0(dev, ANX9804_TRAINING_LANE0_SET_REG, 0x00);
|
||||
+ anx6345_write_r0(dev, ANX9804_TRAINING_LANE1_SET_REG, 0x00);
|
||||
+ anx6345_write_r0(dev, ANX9804_TRAINING_LANE2_SET_REG, 0x00);
|
||||
+ anx6345_write_r0(dev, ANX9804_TRAINING_LANE3_SET_REG, 0x00);
|
||||
+
|
||||
+ /* Reset AUX CH */
|
||||
+ anx6345_write_r1(dev, ANX9804_RST_CTRL2_REG,
|
||||
+ ANX9804_RST_CTRL2_AUX);
|
||||
+ anx6345_write_r1(dev, ANX9804_RST_CTRL2_REG, 0);
|
||||
+
|
||||
+ /* Powerdown audio and some other unused bits */
|
||||
+ anx6345_write_r1(dev, ANX9804_POWERD_CTRL_REG, ANX9804_POWERD_AUDIO);
|
||||
+ anx6345_write_r0(dev, ANX9804_HDCP_CONTROL_0_REG, 0x00);
|
||||
+ anx6345_write_r0(dev, 0xa7, 0x00);
|
||||
+
|
||||
+ anx6345_read_aux_i2c(dev, 0x50, 0x0, EDID_SIZE, priv->edid);
|
||||
+ if (edid_get_timing(priv->edid, EDID_SIZE, &timing, &bpp) != 0) {
|
||||
+ debug("Failed to parse EDID\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ debug("%s: panel found: %dx%d, bpp %d\n", __func__,
|
||||
+ timing.hactive.typ, timing.vactive.typ,
|
||||
+ bpp);
|
||||
+ if (bpp == 6)
|
||||
+ colordepth = 0x00; /* 6 bit */
|
||||
+ else
|
||||
+ colordepth = 0x10; /* 8 bit */
|
||||
+ anx6345_write_r1(dev, ANX9804_VID_CTRL2_REG, colordepth);
|
||||
+
|
||||
+ if (anx6345_read_dpcd(dev, DP_MAX_LINK_RATE, &data_rate)) {
|
||||
+ debug("%s: Failed to DP_MAX_LINK_RATE\n", __func__);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ debug("%s: data_rate: %d\n", __func__, (int)data_rate);
|
||||
+ if (anx6345_read_dpcd(dev, DP_MAX_LANE_COUNT, &lanes)) {
|
||||
+ debug("%s: Failed to read DP_MAX_LANE_COUNT\n", __func__);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ lanes &= DP_MAX_LANE_COUNT_MASK;
|
||||
+ debug("%s: lanes: %d\n", __func__, (int)lanes);
|
||||
+
|
||||
+ /* Set data-rate / lanes */
|
||||
+ anx6345_write_r0(dev, ANX9804_LINK_BW_SET_REG, data_rate);
|
||||
+ anx6345_write_r0(dev, ANX9804_LANE_COUNT_SET_REG, lanes);
|
||||
+
|
||||
+ /* Link training */
|
||||
+ anx6345_write_r0(dev, ANX9804_LINK_TRAINING_CTRL_REG,
|
||||
+ ANX9804_LINK_TRAINING_CTRL_EN);
|
||||
+ mdelay(5);
|
||||
+ for (i = 0; i < 100; i++) {
|
||||
+ anx6345_read_r0(dev, ANX9804_LINK_TRAINING_CTRL_REG, &c);
|
||||
+ if ((chipid == 0x63) && (c & 0x80) == 0)
|
||||
+ break;
|
||||
+
|
||||
+ mdelay(5);
|
||||
+ }
|
||||
+ if(i == 100) {
|
||||
+ debug("Error anx6345 link training timeout\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /* Enable */
|
||||
+ anx6345_write_r1(dev, ANX9804_VID_CTRL1_REG,
|
||||
+ ANX9804_VID_CTRL1_VID_EN | ANX9804_VID_CTRL1_EDGE);
|
||||
+ /* Force stream valid */
|
||||
+ anx6345_write_r0(dev, ANX9804_SYS_CTRL3_REG,
|
||||
+ ANX9804_SYS_CTRL3_F_HPD | ANX9804_SYS_CTRL3_HPD_CTRL |
|
||||
+ ANX9804_SYS_CTRL3_F_VALID | ANX9804_SYS_CTRL3_VALID_CTRL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int anx6345_probe(struct udevice *dev)
|
||||
+{
|
||||
+ if (device_get_uclass_id(dev->parent) != UCLASS_I2C)
|
||||
+ return -EPROTONOSUPPORT;
|
||||
+
|
||||
+ return anx6345_enable(dev);
|
||||
+}
|
||||
+
|
||||
+struct video_bridge_ops anx6345_ops = {
|
||||
+ .attach = anx6345_attach,
|
||||
+ .set_backlight = anx6345_set_backlight,
|
||||
+ .read_edid = anx6345_read_edid,
|
||||
+};
|
||||
+
|
||||
+static const struct udevice_id anx6345_ids[] = {
|
||||
+ { .compatible = "analogix,anx6345", },
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
+U_BOOT_DRIVER(analogix_anx6345) = {
|
||||
+ .name = "analogix_anx6345",
|
||||
+ .id = UCLASS_VIDEO_BRIDGE,
|
||||
+ .of_match = anx6345_ids,
|
||||
+ .probe = anx6345_probe,
|
||||
+ .ops = &anx6345_ops,
|
||||
+ .priv_auto_alloc_size = sizeof(struct anx6345_priv),
|
||||
+};
|
325
patch/u-boot/u-boot-sunxi/10-video-sunxi-split-pll-code.patch
Normal file
325
patch/u-boot/u-boot-sunxi/10-video-sunxi-split-pll-code.patch
Normal file
|
@ -0,0 +1,325 @@
|
|||
From 67065ec3f2ea9b4bf375f60a09b29f9210814d1e Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
Date: Sat, 16 Sep 2017 07:05:49 -0700
|
||||
Subject: [PATCH] sunxi: video: split out PLL configuration code
|
||||
|
||||
It will be reused in new DM LCD driver.
|
||||
|
||||
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
---
|
||||
arch/arm/include/asm/arch-sunxi/lcdc.h | 2 +
|
||||
drivers/video/sunxi/lcdc.c | 117 ++++++++++++++++++++++++++++++-
|
||||
drivers/video/sunxi/sunxi_display.c | 121 ++-------------------------------
|
||||
3 files changed, 124 insertions(+), 116 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/include/asm/arch-sunxi/lcdc.h b/arch/arm/include/asm/arch-sunxi/lcdc.h
|
||||
index a751698b4f..5d9253aaa5 100644
|
||||
--- a/arch/arm/include/asm/arch-sunxi/lcdc.h
|
||||
+++ b/arch/arm/include/asm/arch-sunxi/lcdc.h
|
||||
@@ -124,5 +124,7 @@ void lcdc_tcon0_mode_set(struct sunxi_lcdc_reg * const lcdc,
|
||||
void lcdc_tcon1_mode_set(struct sunxi_lcdc_reg * const lcdc,
|
||||
const struct display_timing *mode,
|
||||
bool ext_hvsync, bool is_composite);
|
||||
+void lcdc_pll_set(struct sunxi_ccm_reg * const ccm, int tcon,
|
||||
+ int dotclock, int *clk_div, int *clk_double);
|
||||
|
||||
#endif /* _LCDC_H */
|
||||
diff --git a/drivers/video/sunxi/lcdc.c b/drivers/video/sunxi/lcdc.c
|
||||
index 7d215b713e..023a30cb1e 100644
|
||||
--- a/drivers/video/sunxi/lcdc.c
|
||||
+++ b/drivers/video/sunxi/lcdc.c
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <common.h>
|
||||
|
||||
+#include <asm/arch/clock.h>
|
||||
#include <asm/arch/lcdc.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
@@ -100,7 +101,7 @@ void lcdc_tcon0_mode_set(struct sunxi_lcdc_reg * const lcdc,
|
||||
writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
|
||||
SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
|
||||
|
||||
-#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
|
||||
+#if defined(CONFIG_VIDEO_LCD_IF_PARALLEL) || defined(CONFIG_VIDEO_DE2)
|
||||
writel(SUNXI_LCDC_X(mode->hsync_len.typ) |
|
||||
SUNXI_LCDC_Y(mode->vsync_len.typ), &lcdc->tcon0_timing_sync);
|
||||
|
||||
@@ -207,3 +208,117 @@ void lcdc_tcon1_mode_set(struct sunxi_lcdc_reg * const lcdc,
|
||||
SUNXI_LCDC_MUX_CTRL_SRC0(1));
|
||||
#endif
|
||||
}
|
||||
+
|
||||
+void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
|
||||
+ int *clk_div, int *clk_double)
|
||||
+{
|
||||
+ int value, n, m, min_m, max_m, diff;
|
||||
+ int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
|
||||
+ int best_double = 0;
|
||||
+ bool use_mipi_pll = false;
|
||||
+
|
||||
+ if (tcon == 0) {
|
||||
+#if defined(CONFIG_VIDEO_LCD_IF_PARALLEL) || defined(CONFIG_SUNXI_DE2)
|
||||
+ min_m = 6;
|
||||
+ max_m = 127;
|
||||
+#endif
|
||||
+#ifdef CONFIG_VIDEO_LCD_IF_LVDS
|
||||
+ min_m = max_m = 7;
|
||||
+#endif
|
||||
+ } else {
|
||||
+ min_m = 1;
|
||||
+ max_m = 15;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Find the lowest divider resulting in a matching clock, if there
|
||||
+ * is no match, pick the closest lower clock, as monitors tend to
|
||||
+ * not sync to higher frequencies.
|
||||
+ */
|
||||
+ for (m = min_m; m <= max_m; m++) {
|
||||
+#ifndef CONFIG_SUNXI_DE2
|
||||
+ n = (m * dotclock) / 3000;
|
||||
+
|
||||
+ if ((n >= 9) && (n <= 127)) {
|
||||
+ value = (3000 * n) / m;
|
||||
+ diff = dotclock - value;
|
||||
+ if (diff < best_diff) {
|
||||
+ best_diff = diff;
|
||||
+ best_m = m;
|
||||
+ best_n = n;
|
||||
+ best_double = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* These are just duplicates */
|
||||
+ if (!(m & 1))
|
||||
+ continue;
|
||||
+#endif
|
||||
+
|
||||
+ /* No double clock on DE2 */
|
||||
+ n = (m * dotclock) / 6000;
|
||||
+ if ((n >= 9) && (n <= 127)) {
|
||||
+ value = (6000 * n) / m;
|
||||
+ diff = dotclock - value;
|
||||
+ if (diff < best_diff) {
|
||||
+ best_diff = diff;
|
||||
+ best_m = m;
|
||||
+ best_n = n;
|
||||
+ best_double = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+#ifdef CONFIG_MACH_SUN6I
|
||||
+ /*
|
||||
+ * Use the MIPI pll if we've been unable to find any matching setting
|
||||
+ * for PLL3, this happens with high dotclocks because of min_m = 6.
|
||||
+ */
|
||||
+ if (tcon == 0 && best_n == 0) {
|
||||
+ use_mipi_pll = true;
|
||||
+ best_m = 6; /* Minimum m for tcon0 */
|
||||
+ }
|
||||
+
|
||||
+ if (use_mipi_pll) {
|
||||
+ clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */
|
||||
+ clock_set_mipi_pll(best_m * dotclock * 1000);
|
||||
+ debug("dotclock: %dkHz = %dkHz via mipi pll\n",
|
||||
+ dotclock, clock_get_mipi_pll() / best_m / 1000);
|
||||
+ } else
|
||||
+#endif
|
||||
+ {
|
||||
+ clock_set_pll3(best_n * 3000000);
|
||||
+ debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
|
||||
+ dotclock,
|
||||
+ (best_double + 1) * clock_get_pll3() / best_m / 1000,
|
||||
+ best_double + 1, best_n, best_m);
|
||||
+ }
|
||||
+
|
||||
+ if (tcon == 0) {
|
||||
+ u32 pll;
|
||||
+
|
||||
+ if (use_mipi_pll)
|
||||
+ pll = CCM_LCD_CH0_CTRL_MIPI_PLL;
|
||||
+ else if (best_double)
|
||||
+ pll = CCM_LCD_CH0_CTRL_PLL3_2X;
|
||||
+ else
|
||||
+ pll = CCM_LCD_CH0_CTRL_PLL3;
|
||||
+
|
||||
+ writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
|
||||
+ &ccm->lcd0_clk_cfg);
|
||||
+ }
|
||||
+#ifndef CONFIG_SUNXI_DE2
|
||||
+ else {
|
||||
+ writel(CCM_LCD_CH1_CTRL_GATE |
|
||||
+ (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
|
||||
+ CCM_LCD_CH1_CTRL_PLL3) |
|
||||
+ CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
|
||||
+ if (sunxi_is_composite())
|
||||
+ setbits_le32(&ccm->lcd0_ch1_clk_cfg,
|
||||
+ CCM_LCD_CH1_CTRL_HALF_SCLK1);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ *clk_div = best_m;
|
||||
+ *clk_double = best_double;
|
||||
+}
|
||||
diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
|
||||
index de768ba94a..f3db125305 100644
|
||||
--- a/drivers/video/sunxi/sunxi_display.c
|
||||
+++ b/drivers/video/sunxi/sunxi_display.c
|
||||
@@ -515,119 +515,6 @@ static void sunxi_composer_enable(void)
|
||||
setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
|
||||
}
|
||||
|
||||
-/*
|
||||
- * LCDC, what allwinner calls a CRTC, so timing controller and serializer.
|
||||
- */
|
||||
-static void sunxi_lcdc_pll_set(int tcon, int dotclock,
|
||||
- int *clk_div, int *clk_double)
|
||||
-{
|
||||
- struct sunxi_ccm_reg * const ccm =
|
||||
- (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
|
||||
- int value, n, m, min_m, max_m, diff;
|
||||
- int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
|
||||
- int best_double = 0;
|
||||
- bool use_mipi_pll = false;
|
||||
-
|
||||
- if (tcon == 0) {
|
||||
-#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
|
||||
- min_m = 6;
|
||||
- max_m = 127;
|
||||
-#endif
|
||||
-#ifdef CONFIG_VIDEO_LCD_IF_LVDS
|
||||
- min_m = max_m = 7;
|
||||
-#endif
|
||||
- } else {
|
||||
- min_m = 1;
|
||||
- max_m = 15;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * Find the lowest divider resulting in a matching clock, if there
|
||||
- * is no match, pick the closest lower clock, as monitors tend to
|
||||
- * not sync to higher frequencies.
|
||||
- */
|
||||
- for (m = min_m; m <= max_m; m++) {
|
||||
- n = (m * dotclock) / 3000;
|
||||
-
|
||||
- if ((n >= 9) && (n <= 127)) {
|
||||
- value = (3000 * n) / m;
|
||||
- diff = dotclock - value;
|
||||
- if (diff < best_diff) {
|
||||
- best_diff = diff;
|
||||
- best_m = m;
|
||||
- best_n = n;
|
||||
- best_double = 0;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* These are just duplicates */
|
||||
- if (!(m & 1))
|
||||
- continue;
|
||||
-
|
||||
- n = (m * dotclock) / 6000;
|
||||
- if ((n >= 9) && (n <= 127)) {
|
||||
- value = (6000 * n) / m;
|
||||
- diff = dotclock - value;
|
||||
- if (diff < best_diff) {
|
||||
- best_diff = diff;
|
||||
- best_m = m;
|
||||
- best_n = n;
|
||||
- best_double = 1;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
-#ifdef CONFIG_MACH_SUN6I
|
||||
- /*
|
||||
- * Use the MIPI pll if we've been unable to find any matching setting
|
||||
- * for PLL3, this happens with high dotclocks because of min_m = 6.
|
||||
- */
|
||||
- if (tcon == 0 && best_n == 0) {
|
||||
- use_mipi_pll = true;
|
||||
- best_m = 6; /* Minimum m for tcon0 */
|
||||
- }
|
||||
-
|
||||
- if (use_mipi_pll) {
|
||||
- clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */
|
||||
- clock_set_mipi_pll(best_m * dotclock * 1000);
|
||||
- debug("dotclock: %dkHz = %dkHz via mipi pll\n",
|
||||
- dotclock, clock_get_mipi_pll() / best_m / 1000);
|
||||
- } else
|
||||
-#endif
|
||||
- {
|
||||
- clock_set_pll3(best_n * 3000000);
|
||||
- debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
|
||||
- dotclock,
|
||||
- (best_double + 1) * clock_get_pll3() / best_m / 1000,
|
||||
- best_double + 1, best_n, best_m);
|
||||
- }
|
||||
-
|
||||
- if (tcon == 0) {
|
||||
- u32 pll;
|
||||
-
|
||||
- if (use_mipi_pll)
|
||||
- pll = CCM_LCD_CH0_CTRL_MIPI_PLL;
|
||||
- else if (best_double)
|
||||
- pll = CCM_LCD_CH0_CTRL_PLL3_2X;
|
||||
- else
|
||||
- pll = CCM_LCD_CH0_CTRL_PLL3;
|
||||
-
|
||||
- writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
|
||||
- &ccm->lcd0_ch0_clk_cfg);
|
||||
- } else {
|
||||
- writel(CCM_LCD_CH1_CTRL_GATE |
|
||||
- (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
|
||||
- CCM_LCD_CH1_CTRL_PLL3) |
|
||||
- CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
|
||||
- if (sunxi_is_composite())
|
||||
- setbits_le32(&ccm->lcd0_ch1_clk_cfg,
|
||||
- CCM_LCD_CH1_CTRL_HALF_SCLK1);
|
||||
- }
|
||||
-
|
||||
- *clk_div = best_m;
|
||||
- *clk_double = best_double;
|
||||
-}
|
||||
-
|
||||
static void sunxi_lcdc_init(void)
|
||||
{
|
||||
struct sunxi_ccm_reg * const ccm =
|
||||
@@ -754,6 +641,8 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
|
||||
{
|
||||
struct sunxi_lcdc_reg * const lcdc =
|
||||
(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
|
||||
+ struct sunxi_ccm_reg * const ccm =
|
||||
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
|
||||
int clk_div, clk_double, pin;
|
||||
struct display_timing timing;
|
||||
|
||||
@@ -773,7 +662,7 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
|
||||
#endif
|
||||
}
|
||||
|
||||
- sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
|
||||
+ lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double);
|
||||
|
||||
sunxi_ctfb_mode_to_display_timing(mode, &timing);
|
||||
lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
|
||||
@@ -787,6 +676,8 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
|
||||
{
|
||||
struct sunxi_lcdc_reg * const lcdc =
|
||||
(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
|
||||
+ struct sunxi_ccm_reg * const ccm =
|
||||
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
|
||||
struct display_timing timing;
|
||||
|
||||
sunxi_ctfb_mode_to_display_timing(mode, &timing);
|
||||
@@ -798,7 +689,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
|
||||
sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
|
||||
}
|
||||
|
||||
- sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
|
||||
+ lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double);
|
||||
}
|
||||
#endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
|
||||
|
223
patch/u-boot/u-boot-sunxi/11-de2-add-lcd-support.patch
Normal file
223
patch/u-boot/u-boot-sunxi/11-de2-add-lcd-support.patch
Normal file
|
@ -0,0 +1,223 @@
|
|||
From 32f419400bd74b4292fc2117091f9fb999941a28 Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
Date: Sat, 16 Sep 2017 07:37:50 -0700
|
||||
Subject: [PATCH] sunxi: video: add LCD support to DE2 driver
|
||||
|
||||
Extend DE2 driver with LCD support. Tested on Pinebook which is based
|
||||
on A64 and has ANX6345 eDP bridge with eDP panel connected to it.
|
||||
|
||||
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
---
|
||||
arch/arm/mach-sunxi/Kconfig | 2 +-
|
||||
drivers/video/sunxi/Makefile | 2 +-
|
||||
drivers/video/sunxi/sunxi_de2.c | 17 +++++
|
||||
drivers/video/sunxi/sunxi_lcd.c | 149 ++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 168 insertions(+), 2 deletions(-)
|
||||
create mode 100644 drivers/video/sunxi/sunxi_lcd.c
|
||||
|
||||
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
|
||||
index 2309f59999..06d697e3a7 100644
|
||||
--- a/arch/arm/mach-sunxi/Kconfig
|
||||
+++ b/arch/arm/mach-sunxi/Kconfig
|
||||
@@ -680,7 +680,7 @@ config VIDEO_LCD_MODE
|
||||
|
||||
config VIDEO_LCD_DCLK_PHASE
|
||||
int "LCD panel display clock phase"
|
||||
- depends on VIDEO
|
||||
+ depends on VIDEO || DM_VIDEO
|
||||
default 1
|
||||
---help---
|
||||
Select LCD panel display clock phase shift, range 0-3.
|
||||
diff --git a/drivers/video/sunxi/Makefile b/drivers/video/sunxi/Makefile
|
||||
index 0d64c2021f..8c91766c24 100644
|
||||
--- a/drivers/video/sunxi/Makefile
|
||||
+++ b/drivers/video/sunxi/Makefile
|
||||
@@ -6,4 +6,4 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o lcdc.o tve_common.o ../videomodes.o
|
||||
-obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o lcdc.o ../dw_hdmi.o
|
||||
+obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o lcdc.o ../dw_hdmi.o sunxi_lcd.o
|
||||
diff --git a/drivers/video/sunxi/sunxi_de2.c b/drivers/video/sunxi/sunxi_de2.c
|
||||
index ee67764ac5..a838bbacd1 100644
|
||||
--- a/drivers/video/sunxi/sunxi_de2.c
|
||||
+++ b/drivers/video/sunxi/sunxi_de2.c
|
||||
@@ -233,6 +233,23 @@ static int sunxi_de2_probe(struct udevice *dev)
|
||||
return 0;
|
||||
|
||||
ret = uclass_find_device_by_name(UCLASS_DISPLAY,
|
||||
+ "sunxi_lcd", &disp);
|
||||
+ if (!ret) {
|
||||
+ int mux;
|
||||
+
|
||||
+ mux = 0;
|
||||
+
|
||||
+ ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, mux,
|
||||
+ false);
|
||||
+ if (!ret) {
|
||||
+ video_set_flush_dcache(dev, 1);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ debug("%s: lcd display not found (ret=%d)\n", __func__, ret);
|
||||
+
|
||||
+ ret = uclass_find_device_by_name(UCLASS_DISPLAY,
|
||||
"sunxi_dw_hdmi", &disp);
|
||||
if (!ret) {
|
||||
int mux;
|
||||
diff --git a/drivers/video/sunxi/sunxi_lcd.c b/drivers/video/sunxi/sunxi_lcd.c
|
||||
new file mode 100644
|
||||
index 0000000000..b8e4b0e344
|
||||
--- /dev/null
|
||||
+++ b/drivers/video/sunxi/sunxi_lcd.c
|
||||
@@ -0,0 +1,149 @@
|
||||
+/*
|
||||
+ * Allwinner LCD driver
|
||||
+ *
|
||||
+ * (C) Copyright 2017 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#include <common.h>
|
||||
+#include <display.h>
|
||||
+#include <video_bridge.h>
|
||||
+#include <backlight.h>
|
||||
+#include <dm.h>
|
||||
+#include <edid.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <asm/arch/clock.h>
|
||||
+#include <asm/arch/lcdc.h>
|
||||
+#include <asm/arch/gpio.h>
|
||||
+#include <asm/gpio.h>
|
||||
+
|
||||
+struct sunxi_lcd_priv {
|
||||
+ struct display_timing timing;
|
||||
+ int panel_bpp;
|
||||
+};
|
||||
+
|
||||
+static void sunxi_lcdc_config_pinmux(void)
|
||||
+{
|
||||
+#ifdef CONFIG_MACH_SUN50I
|
||||
+ int pin;
|
||||
+ for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(21); pin++) {
|
||||
+ sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
|
||||
+ sunxi_gpio_set_drv(pin, 3);
|
||||
+ }
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static int sunxi_lcd_enable(struct udevice *dev, int bpp,
|
||||
+ const struct display_timing *edid)
|
||||
+{
|
||||
+ struct sunxi_ccm_reg * const ccm =
|
||||
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
|
||||
+ struct sunxi_lcdc_reg * const lcdc =
|
||||
+ (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
|
||||
+ struct sunxi_lcd_priv *priv = dev_get_priv(dev);
|
||||
+ struct udevice *backlight;
|
||||
+ int clk_div, clk_double, ret;
|
||||
+
|
||||
+ /* Reset off */
|
||||
+ setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0);
|
||||
+ /* Clock on */
|
||||
+ setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
|
||||
+
|
||||
+ lcdc_init(lcdc);
|
||||
+ sunxi_lcdc_config_pinmux();
|
||||
+ lcdc_pll_set(ccm, 0, edid->pixelclock.typ / 1000,
|
||||
+ &clk_div, &clk_double);
|
||||
+ lcdc_tcon0_mode_set(lcdc, edid, clk_div, false,
|
||||
+ priv->panel_bpp, CONFIG_VIDEO_LCD_DCLK_PHASE);
|
||||
+ lcdc_enable(lcdc, priv->panel_bpp);
|
||||
+
|
||||
+ ret = uclass_get_device(UCLASS_PANEL_BACKLIGHT, 0, &backlight);
|
||||
+ if (!ret)
|
||||
+ backlight_enable(backlight);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sunxi_lcd_read_timing(struct udevice *dev,
|
||||
+ struct display_timing *timing)
|
||||
+{
|
||||
+ struct sunxi_lcd_priv *priv = dev_get_priv(dev);
|
||||
+ memcpy(timing, &priv->timing, sizeof(struct display_timing));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sunxi_lcd_probe(struct udevice *dev)
|
||||
+{
|
||||
+ struct udevice *cdev;
|
||||
+ struct sunxi_lcd_priv *priv = dev_get_priv(dev);
|
||||
+ int ret;
|
||||
+ int node, timing_node, val;
|
||||
+
|
||||
+#ifdef CONFIG_VIDEO_BRIDGE
|
||||
+ /* Try to get timings from bridge first */
|
||||
+ ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &cdev);
|
||||
+ if (!ret) {
|
||||
+ u8 edid[EDID_SIZE];
|
||||
+ int channel_bpp;
|
||||
+
|
||||
+ ret = video_bridge_attach(cdev);
|
||||
+ if (ret) {
|
||||
+ debug("video bridge attach failed: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ret = video_bridge_read_edid(cdev, edid, EDID_SIZE);
|
||||
+ if (ret > 0) {
|
||||
+ ret = edid_get_timing(edid, ret, &priv->timing, &channel_bpp);
|
||||
+ priv->panel_bpp = channel_bpp * 3;
|
||||
+ if (!ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ /* Fallback to timings from DT if there's no bridge or
|
||||
+ * if reading EDID failed
|
||||
+ */
|
||||
+ ret = uclass_get_device(UCLASS_PANEL, 0, &cdev);
|
||||
+ if (ret) {
|
||||
+ debug("video panel not found: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (fdtdec_decode_display_timing(gd->fdt_blob, dev_of_offset(cdev),
|
||||
+ 0, &priv->timing)) {
|
||||
+ debug("%s: Failed to decode display timing\n", __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ timing_node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(cdev),
|
||||
+ "display-timings");
|
||||
+ node = fdt_first_subnode(gd->fdt_blob, timing_node);
|
||||
+ val = fdtdec_get_int(gd->fdt_blob, node, "bits-per-pixel", -1);
|
||||
+ if (val != -1)
|
||||
+ priv->panel_bpp = val;
|
||||
+ else
|
||||
+ priv->panel_bpp = 18;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct dm_display_ops sunxi_lcd_ops = {
|
||||
+ .read_timing = sunxi_lcd_read_timing,
|
||||
+ .enable = sunxi_lcd_enable,
|
||||
+};
|
||||
+
|
||||
+U_BOOT_DRIVER(sunxi_lcd) = {
|
||||
+ .name = "sunxi_lcd",
|
||||
+ .id = UCLASS_DISPLAY,
|
||||
+ .ops = &sunxi_lcd_ops,
|
||||
+ .probe = sunxi_lcd_probe,
|
||||
+ .priv_auto_alloc_size = sizeof(struct sunxi_lcd_priv),
|
||||
+};
|
||||
+
|
||||
+#ifdef CONFIG_MACH_SUN50I
|
||||
+U_BOOT_DEVICE(sunxi_lcd) = {
|
||||
+ .name = "sunxi_lcd"
|
||||
+};
|
||||
+#endif
|
|
@ -1,35 +1,27 @@
|
|||
diff --git a/configs/pinebook-a64_defconfig b/configs/pinebook-a64_defconfig
|
||||
new file mode 100644
|
||||
index 0000000000..ce4e36e5c3
|
||||
--- /dev/null
|
||||
+++ b/configs/pinebook-a64_defconfig
|
||||
@@ -0,0 +1,21 @@
|
||||
+CONFIG_ARM=y
|
||||
+CONFIG_ARCH_SUNXI=y
|
||||
+CONFIG_MACH_SUN50I=y
|
||||
+CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
|
||||
+CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y
|
||||
+CONFIG_DRAM_CLK=552
|
||||
+CONFIG_DRAM_ZQ=3881949
|
||||
+CONFIG_DRAM_ODT_EN=y
|
||||
+CONFIG_MMC0_CD_PIN=""
|
||||
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
|
||||
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pinebook"
|
||||
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
+CONFIG_SPL=y
|
||||
+# CONFIG_CMD_IMLS is not set
|
||||
+# CONFIG_CMD_FLASH is not set
|
||||
+# CONFIG_CMD_FPGA is not set
|
||||
+# CONFIG_SPL_DOS_PARTITION is not set
|
||||
+# CONFIG_SPL_ISO_PARTITION is not set
|
||||
+# CONFIG_SPL_EFI_PARTITION is not set
|
||||
+CONFIG_SUN8I_EMAC=y
|
||||
+CONFIG_USB_EHCI_HCD=y
|
||||
From 0e9350e3ff11c91eb6959d0d4589a4cc5e576e35 Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
Date: Sat, 16 Sep 2017 07:44:11 -0700
|
||||
Subject: [PATCH] sunxi: add support for Pinebook
|
||||
|
||||
Pinebook is a laptop produced by Pine64, with USB-connected keyboard,
|
||||
I2C-connected touchpad and an eDP LCD panel connected via a RGB-eDP
|
||||
bridge by Analogix.
|
||||
|
||||
Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
|
||||
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
---
|
||||
arch/arm/dts/Makefile | 3 +-
|
||||
arch/arm/dts/sun50i-a64-pinebook.dts | 114 +++++++++++++++++++++++++++++++++++
|
||||
configs/pinebook_defconfig | 36 +++++++++++
|
||||
3 files changed, 152 insertions(+), 1 deletion(-)
|
||||
create mode 100644 arch/arm/dts/sun50i-a64-pinebook.dts
|
||||
create mode 100644 configs/pinebook_defconfig
|
||||
|
||||
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
|
||||
index 762429c..98f57e0 100644
|
||||
index fee4680057..130d1944be 100644
|
||||
--- a/arch/arm/dts/Makefile
|
||||
+++ b/arch/arm/dts/Makefile
|
||||
@@ -338,7 +338,8 @@ dtb-$(CONFIG_MACH_SUN50I) += \
|
||||
@@ -342,7 +342,8 @@ dtb-$(CONFIG_MACH_SUN50I) += \
|
||||
sun50i-a64-olinuxino.dtb \
|
||||
sun50i-a64-orangepi-win.dtb \
|
||||
sun50i-a64-pine64-plus.dtb \
|
||||
|
@ -41,10 +33,10 @@ index 762429c..98f57e0 100644
|
|||
sun9i-a80-cubieboard4.dtb \
|
||||
diff --git a/arch/arm/dts/sun50i-a64-pinebook.dts b/arch/arm/dts/sun50i-a64-pinebook.dts
|
||||
new file mode 100644
|
||||
index 0000000..97d46d3
|
||||
index 0000000000..17d4c598b8
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/dts/sun50i-a64-pinebook.dts
|
||||
@@ -0,0 +1,50 @@
|
||||
@@ -0,0 +1,112 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2016 ARM Ltd.
|
||||
+ *
|
||||
|
@ -88,10 +80,114 @@ index 0000000..97d46d3
|
|||
+ */
|
||||
+
|
||||
+#include "sun50i-a64-pine64.dts"
|
||||
+#include <dt-bindings/pwm/pwm.h>
|
||||
+
|
||||
+/ {
|
||||
+ model = "Pinebook A64";
|
||||
+ compatible = "pine64,pine64-pinebook", "allwinner,sun50i-a64";
|
||||
+ model = "Pinebook";
|
||||
+ compatible = "pine64,pinebook", "allwinner,sun50i-a64";
|
||||
+
|
||||
+ /* TODO: Everything */
|
||||
+ aliases {
|
||||
+ serial0 = &uart0;
|
||||
+ i2c0 = "/i2c_gpio@0";
|
||||
+ };
|
||||
+
|
||||
+ backlight: backlight {
|
||||
+ compatible = "pwm-backlight";
|
||||
+ pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
|
||||
+ brightness-levels = <0 10 20 30 40 50 60 70 100>;
|
||||
+ default-brightness-level = <3>;
|
||||
+ enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* PD23 */
|
||||
+ };
|
||||
+
|
||||
+ chosen {
|
||||
+ stdout-path = "serial0:115200n8";
|
||||
+ };
|
||||
+
|
||||
+ memory {
|
||||
+ reg = <0x40000000 0x40000000>;
|
||||
+ };
|
||||
+
|
||||
+ soc {
|
||||
+ i2c_gpio@0 {
|
||||
+ compatible = "i2c-gpio";
|
||||
+ gpios = <&r_pio 0 9 GPIO_ACTIVE_HIGH>, /* sda - PL9 */
|
||||
+ <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* scl - PL8 */
|
||||
+ i2c-gpio,sda-open-drain;
|
||||
+ i2c-gpio,scl-open-drain;
|
||||
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ status = "okay";
|
||||
+
|
||||
+ anx6345: edp-bridge@38 {
|
||||
+ compatible = "analogix,anx6345";
|
||||
+ reg = <0x38>;
|
||||
+ sleep-gpios = <&pio 7 6 GPIO_ACTIVE_LOW>; /* PH6 */
|
||||
+ reset-gpios = <&pio 3 24 GPIO_ACTIVE_LOW>; /* PD24 */
|
||||
+ status = "okay";
|
||||
+
|
||||
+ /*
|
||||
+ ports {
|
||||
+ port@0 {
|
||||
+ bridge_out: endpoint {
|
||||
+ remote-endpoint = <&panel_in>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ port@1 {
|
||||
+ bridge_in: endpoint {
|
||||
+ remote-endpoint = <&rgb_out>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+ */
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&pwm {
|
||||
+ status = "okay";
|
||||
+};
|
||||
diff --git a/configs/pinebook-a64_defconfig b/configs/pinebook-a64_defconfig
|
||||
new file mode 100644
|
||||
index 0000000000..e90c863f76
|
||||
--- /dev/null
|
||||
+++ b/configs/pinebook-a64_defconfig
|
||||
@@ -0,0 +1,36 @@
|
||||
+CONFIG_ARM=y
|
||||
+CONFIG_ARCH_SUNXI=y
|
||||
+CONFIG_MACH_SUN50I=y
|
||||
+CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
|
||||
+CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y
|
||||
+CONFIG_DRAM_CLK=552
|
||||
+CONFIG_DRAM_ZQ=3881949
|
||||
+CONFIG_DRAM_ODT_EN=y
|
||||
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
|
||||
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pinebook"
|
||||
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
+CONFIG_SPL=y
|
||||
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
|
||||
+# CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set
|
||||
+CONFIG_SPL_ATF_SUPPORT=y
|
||||
+CONFIG_SPL_ATF_TEXT_BASE=0x44000
|
||||
+# CONFIG_CMD_IMLS is not set
|
||||
+# CONFIG_CMD_FLASH is not set
|
||||
+# CONFIG_CMD_FPGA is not set
|
||||
+CONFIG_CMD_I2C=y
|
||||
+# CONFIG_SPL_DOS_PARTITION is not set
|
||||
+# CONFIG_SPL_ISO_PARTITION is not set
|
||||
+# CONFIG_SPL_EFI_PARTITION is not set
|
||||
+CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
|
||||
+CONFIG_DM_I2C_GPIO=y
|
||||
+CONFIG_SPL_SPI_SUNXI=y
|
||||
+CONFIG_DM_REGULATOR=y
|
||||
+CONFIG_AXP_DLDO2_VOLT=2500
|
||||
+CONFIG_AXP_FLDO1_VOLT=1200
|
||||
+CONFIG_AXP_SW_ON=y
|
||||
+CONFIG_DM_PWM=y
|
||||
+CONFIG_PWM_SUNXI=y
|
||||
+CONFIG_USB_EHCI_HCD=y
|
||||
+CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
|
||||
+CONFIG_VIDEO_BRIDGE=y
|
||||
+CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345=y
|
Loading…
Add table
Reference in a new issue