rockchip: bump rk322x u-boot to v2024.01

* update the defconfig and accomodate upstream changes
 * introduce hdmi/vop/phy drivers and enable hdmi
 * fix clock driver
This commit is contained in:
Paolo Sabatino 2024-04-30 22:38:09 +02:00 committed by Igor
parent 8402d9b4c8
commit fb7484f3f9
21 changed files with 2990 additions and 161 deletions

View File

@ -16,7 +16,7 @@ setenv docker_optimizations "on"
# If gpio3 pin 25 is 0, write magic to GRF os_reg[0] register and
# reset to trigger maskrom mode
if gpio input D25; then
if gpio input 121; then
echo "Resetting into MASKROM mode..."
mw.l 0x110005c8 0xEF08A53C 1
reset

View File

@ -40,10 +40,10 @@ elif [[ "$BOOT_SOC" == "rk322x" ]]; then
BOOTSCRIPT="boot-rk322x.cmd:boot.cmd"
BOOTENV_FILE='rk322x.txt'
OVERLAY_PREFIX='rk322x'
UBOOT_TARGET_MAP="all u-boot.itb;;u-boot-rk322x-with-spl.bin"
UBOOT_TARGET_MAP="ROCKCHIP_TPL=$SRC/packages/blobs/rockchip/rk322x_ddr_333MHz_v1.11_2t.bin TEE=$SRC/packages/blobs/rockchip/rk322x_tee.bin;;u-boot-rk322x-with-spl.bin"
BOOTBRANCH='tag:v2022.04'
BOOTPATCHDIR='v2022.04'
BOOTBRANCH='tag:v2024.01'
BOOTPATCHDIR='v2024.01'
fi
@ -180,8 +180,13 @@ elif [[ "$BOOT_SOC" == "rk322x" ]]; then
# tools/mkimage -n rk322x -T rksd -d tpl/u-boot-tpl.bin u-boot-rk322x-with-spl.bin
#
run_host_command_logged tools/mkimage -n rk322x -T rksd -d $SRC/packages/blobs/rockchip/rk322x_ddr_333MHz_v1.11_2t.bin u-boot-rk322x-with-spl.bin
run_host_command_logged cat spl/u-boot-spl.bin ">>" u-boot-rk322x-with-spl.bin
# As of u-boot v2024.01, binman takes care of building the idbloader, so there is
# no need anymore for mkimage and cat commands to assemble the thing, but we keep
# the commands here for reference:
# - run_host_command_logged tools/mkimage -n rk322x -T rksd -d $SRC/packages/blobs/rockchip/rk322x_ddr_333MHz_v1.11_2t.bin u-boot-rk322x-with-spl.bin
# - run_host_command_logged cat spl/u-boot-spl.bin ">>" u-boot-rk322x-with-spl.bin
#
run_host_command_logged cat idbloader.img > u-boot-rk322x-with-spl.bin
run_host_command_logged dd if=u-boot.itb of=u-boot-rk322x-with-spl.bin seek=$((0x200 - 0x40)) conv=notrunc
}

View File

@ -1,20 +1,21 @@
From c6c14957e96c46f0f197f787f407f8c3c152c17a Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Sun, 19 Feb 2023 00:01:34 +0530
From db428dbc58ba2788fb13d4bf1985f0540fd7f4b3 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Tue, 30 Apr 2024 22:09:57 +0200
Subject: [PATCH] video: dw_hdmi: Add Vendor PHY handling
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
original work by Jagan Teki
---
drivers/video/dw_hdmi.c | 29 +++++++++++++++++++++++++++-
drivers/video/meson/meson_dw_hdmi.c | 11 ++++++++++-
drivers/video/rockchip/rk3399_hdmi.c | 8 +++++++-
drivers/video/dw_hdmi.c | 46 +++++++++++++++++++++++++++-
drivers/video/meson/meson_dw_hdmi.c | 11 ++++++-
drivers/video/rockchip/rk3399_hdmi.c | 8 ++++-
drivers/video/rockchip/rk_hdmi.c | 2 +-
drivers/video/sunxi/sunxi_dw_hdmi.c | 11 ++++++++++-
include/dw_hdmi.h | 14 +++++++++++++-
6 files changed, 69 insertions(+), 6 deletions(-)
drivers/video/rockchip/rk_hdmi.h | 3 ++
drivers/video/sunxi/sunxi_dw_hdmi.c | 11 ++++++-
include/dw_hdmi.h | 14 ++++++++-
7 files changed, 89 insertions(+), 6 deletions(-)
diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index c4fbb182944..ea12a094074 100644
index c4fbb18294..fc8c8bb366 100644
--- a/drivers/video/dw_hdmi.c
+++ b/drivers/video/dw_hdmi.c
@@ -988,7 +988,7 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
@ -26,7 +27,7 @@ index c4fbb182944..ea12a094074 100644
if (ret)
return ret;
@@ -1009,10 +1009,37 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
@@ -1009,10 +1009,54 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
return 0;
}
@ -55,23 +56,6 @@ index c4fbb182944..ea12a094074 100644
+ hdmi->ops = hdmi->data->phy_ops;
+}
+
void dw_hdmi_init(struct dw_hdmi *hdmi)
{
uint ih_mute;
+ dw_hdmi_detect_phy(hdmi);
+
/*
* boot up defaults are:
* hdmi_ih_mute = 0x03 (disabled)
diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index c4fbb18294..1c5ee25280 100644
--- a/drivers/video/dw_hdmi.c
+++ b/drivers/video/dw_hdmi.c
@@ -1009,6 +1025,23 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
return 0;
}
+int dw_hdmi_disable(struct dw_hdmi *hdmi)
+{
+ uint clkdis;
@ -92,16 +76,22 @@ index c4fbb18294..1c5ee25280 100644
void dw_hdmi_init(struct dw_hdmi *hdmi)
{
uint ih_mute;
+ dw_hdmi_detect_phy(hdmi);
+
/*
* boot up defaults are:
* hdmi_ih_mute = 0x03 (disabled)
diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
index e5f28132053..d03e8e493b7 100644
index 5db01904b5..d0d878b6af 100644
--- a/drivers/video/meson/meson_dw_hdmi.c
+++ b/drivers/video/meson/meson_dw_hdmi.c
@@ -374,6 +374,15 @@ static int meson_dw_hdmi_wait_hpd(struct dw_hdmi *hdmi)
@@ -375,6 +375,15 @@ static int meson_dw_hdmi_wait_hpd(struct dw_hdmi *hdmi)
return -ETIMEDOUT;
}
+static const struct dw_hdmi_phy_ops dw_hdmi_meson_phy_ops = {
+ .phy_set = meson_dw_hdmi_phy_cfg,
+ .phy_set = meson_dw_hdmi_phy_init,
+};
+
+static const struct dw_hdmi_plat_data dw_hdmi_meson_plat_data = {
@ -112,7 +102,7 @@ index e5f28132053..d03e8e493b7 100644
static int meson_dw_hdmi_probe(struct udevice *dev)
{
struct meson_dw_hdmi *priv = dev_get_priv(dev);
@@ -396,7 +405,7 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
@@ -397,7 +406,7 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
@ -122,7 +112,7 @@ index e5f28132053..d03e8e493b7 100644
priv->hdmi.reg_io_width = 1;
else {
diff --git a/drivers/video/rockchip/rk3399_hdmi.c b/drivers/video/rockchip/rk3399_hdmi.c
index 3041360c6ed..b32139a8a6e 100644
index 3041360c6e..b32139a8a6 100644
--- a/drivers/video/rockchip/rk3399_hdmi.c
+++ b/drivers/video/rockchip/rk3399_hdmi.c
@@ -64,8 +64,14 @@ static const struct dm_display_ops rk3399_hdmi_ops = {
@ -142,7 +132,7 @@ index 3041360c6ed..b32139a8a6e 100644
};
diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
index b75a1744896..e34f532cd68 100644
index 8dcd4d5964..e545d69e3b 100644
--- a/drivers/video/rockchip/rk_hdmi.c
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -83,6 +83,7 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
@ -161,11 +151,32 @@ index b75a1744896..e34f532cd68 100644
priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
diff --git a/drivers/video/rockchip/rk_hdmi.h b/drivers/video/rockchip/rk_hdmi.h
index 200dbaea74..dcfba3d3d7 100644
--- a/drivers/video/rockchip/rk_hdmi.h
+++ b/drivers/video/rockchip/rk_hdmi.h
@@ -6,6 +6,8 @@
#ifndef __RK_HDMI_H__
#define __RK_HDMI_H__
+#include <generic-phy.h>
+
struct rkhdmi_driverdata {
/* configuration */
u8 i2c_clk_high;
@@ -19,6 +21,7 @@ struct rkhdmi_driverdata {
struct rk_hdmi_priv {
struct dw_hdmi hdmi;
+ struct phy phy;
void *grf;
};
diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 19ed80b48a..8e4922c759 100644
index 0324a050d0..f7ecbb923b 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -322,6 +322,15 @@ static int sunxi_dw_hdmi_enable(struct udevice *dev, int panel_bpp,
@@ -328,6 +328,15 @@ static int sunxi_dw_hdmi_enable(struct udevice *dev, int panel_bpp,
return 0;
}
@ -181,7 +192,7 @@ index 19ed80b48a..8e4922c759 100644
static int sunxi_dw_hdmi_probe(struct udevice *dev)
{
struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
@@ -379,7 +386,7 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
@@ -379,7 +388,7 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
hdmi->i2c_clk_high = 0xd8;
hdmi->i2c_clk_low = 0xfe;
hdmi->reg_io_width = 1;
@ -191,7 +202,7 @@ index 19ed80b48a..8e4922c759 100644
ret = reset_get_bulk(dev, &priv->resets);
if (ret)
diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
index 8acae3839fb..4ad8b39f84d 100644
index 8acae3839f..4ad8b39f84 100644
--- a/include/dw_hdmi.h
+++ b/include/dw_hdmi.h
@@ -534,6 +534,17 @@ struct hdmi_data_info {
@ -223,3 +234,6 @@ index 8acae3839fb..4ad8b39f84d 100644
void (*write_reg)(struct dw_hdmi *hdmi, u8 val, int offset);
u8 (*read_reg)(struct dw_hdmi *hdmi, int offset);
};
--
2.34.1

View File

@ -0,0 +1,227 @@
From 497b401b7ec7f0fa52efa4765b8421e21b8840ff Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Mon, 29 Apr 2024 16:18:46 +0200
Subject: [PATCH 4/4] clock entries to accomodate rk3228 HDMI features
---
.../include/asm/arch-rockchip/cru_rk322x.h | 14 ++
drivers/clk/rockchip/clk_rk322x.c | 133 +++++++++++++++++-
2 files changed, 144 insertions(+), 3 deletions(-)
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk322x.h b/arch/arm/include/asm/arch-rockchip/cru_rk322x.h
index cfbc7e92f7..de3c4bf310 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk322x.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk322x.h
@@ -194,6 +194,10 @@ enum {
/* CRU_CLKSEL27_CON */
VOP_DCLK_DIV_SHIFT = 8,
VOP_DCLK_DIV_MASK = 0xff << VOP_DCLK_DIV_SHIFT,
+ VOP_DCLK_PLL_SEL_SHIFT = 0,
+ VOP_DCLK_PLL_SEL_MASK = 1 << VOP_DCLK_PLL_SEL_SHIFT,
+ VOP_DCLK_SEL_GPLL = 0,
+ VOP_DCLK_SEL_CPLL = 1,
VOP_PLL_SEL_SHIFT = 1,
VOP_PLL_SEL_MASK = 1 << VOP_PLL_SEL_SHIFT,
@@ -201,6 +205,16 @@ enum {
GMAC_CLK_SRC_SHIFT = 12,
GMAC_CLK_SRC_MASK = 1 << GMAC_CLK_SRC_SHIFT,
+ /* CRU_CLKSEL33_CON */
+ VOP_ACLK_DIV_SHIFT = 0,
+ VOP_ACLK_DIV_MASK = 0x1f << VOP_ACLK_DIV_SHIFT,
+ VOP_ACLK_PLL_SEL_SHIFT = 5,
+ VOP_ACLK_PLL_SEL_MASK = 3 << VOP_ACLK_PLL_SEL_SHIFT,
+ VOP_ACLK_SEL_CPLL = 0,
+ VOP_ACLK_SEL_GPLL = 1,
+ VOP_ACLK_SEL_HDMIPHY = 2,
+ VOP_ACLK_SEL_USBPHY = 3,
+
/* CRU_SOFTRST5_CON */
DDRCTRL_PSRST_SHIFT = 11,
DDRCTRL_SRST_SHIFT = 10,
diff --git a/drivers/clk/rockchip/clk_rk322x.c b/drivers/clk/rockchip/clk_rk322x.c
index 44b5778589..418164e63b 100644
--- a/drivers/clk/rockchip/clk_rk322x.c
+++ b/drivers/clk/rockchip/clk_rk322x.c
@@ -371,6 +371,14 @@ static ulong rk322x_clk_get_rate(struct clk *clk)
case SCLK_SDMMC:
rate = rockchip_mmc_get_clk(priv->cru, gclk_rate, clk->id);
break;
+ case SCLK_HDMI_PHY:
+ case PCLK_HDMI_PHY:
+ case DCLK_HDMI_PHY:
+ case SCLK_HDMI_HDCP:
+ case PCLK_HDMI_CTRL:
+ case SCLK_HDMI_CEC:
+ printf("Attempt to get clk id %ld\n", clk->id);
+ return 0;
default:
return -ENOENT;
}
@@ -378,6 +386,68 @@ static ulong rk322x_clk_get_rate(struct clk *clk)
return rate;
}
+#ifndef CONFIG_SPL_BUILD
+static ulong rk3228_vop_get_clk(struct rk322x_cru *cru, ulong clk_id)
+{
+ u32 div, con, parent;
+
+ switch (clk_id) {
+ case DCLK_VOP:
+ con = readl(&cru->cru_clksel_con[27]);
+ div = (con & VOP_DCLK_DIV_MASK) >> VOP_DCLK_DIV_SHIFT;
+ parent = GPLL_HZ;
+ break;
+ case ACLK_VOP:
+ con = readl(&cru->cru_clksel_con[33]);
+ div = (con & VOP_ACLK_DIV_MASK) >> VOP_ACLK_DIV_SHIFT;
+ parent = GPLL_HZ;
+ break;
+ default:
+ debug("%s: Unsupported vop get clk#%ld\n", __func__, clk_id);
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3228_vop_set_clk(struct rk322x_cru *cru,
+ ulong clk_id, uint hz)
+{
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+ assert(src_clk_div - 1 < 31);
+
+ switch (clk_id) {
+ case DCLK_VOP:
+
+ /*
+ * Set HDMI parent clock to HDMIPHY. Normally, this is done
+ * by .set_parent, but u-boot does not seem to work well with
+ * device tree references
+ */
+ rk_clrsetreg(&cru->cru_misc_con, BIT(13), 0);
+
+ rk_clrsetreg(&cru->cru_clksel_con[27],
+ VOP_DCLK_DIV_MASK | VOP_DCLK_PLL_SEL_MASK,
+ VOP_DCLK_SEL_GPLL << VOP_DCLK_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << VOP_DCLK_DIV_SHIFT);
+ break;
+ case ACLK_VOP:
+ rk_clrsetreg(&cru->cru_clksel_con[33],
+ VOP_ACLK_DIV_MASK | VOP_ACLK_PLL_SEL_MASK,
+ VOP_ACLK_SEL_GPLL << VOP_ACLK_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << VOP_ACLK_DIV_SHIFT);
+ break;
+ default:
+ printf("%s: Unable to set vop clk#%ld\n", __func__, clk_id);
+ return -EINVAL;
+ }
+
+ return rk3228_vop_get_clk(cru, clk_id);
+}
+#endif
+
static ulong rk322x_clk_set_rate(struct clk *clk, ulong rate)
{
struct rk322x_clk_priv *priv = dev_get_priv(clk->dev);
@@ -400,7 +470,29 @@ static ulong rk322x_clk_set_rate(struct clk *clk, ulong rate)
new_rate = rk322x_mac_set_clk(priv->cru, rate);
break;
case PLL_GPLL:
- return 0;
+ case PLL_CPLL:
+ case ACLK_PERI:
+ case HCLK_PERI:
+ case PCLK_PERI:
+ case ACLK_CPU:
+ case HCLK_CPU:
+ case PCLK_CPU:
+ case ARMCLK:
+ case SCLK_HDMI_PHY:
+ case PCLK_HDMI_PHY:
+ case DCLK_HDMI_PHY:
+ case SCLK_HDMI_HDCP:
+ case PCLK_HDMI_CTRL:
+ case SCLK_HDMI_CEC:
+ debug("Attempt to set clkid %ld, rate=%ld\n", clk->id, rate);
+ return rate;
+#ifndef CONFIG_SPL_BUILD
+ case ACLK_VOP:
+ case DCLK_VOP:
+ debug("VOP set rate clkid %ld, rate=%ld\n", clk->id, rate);
+ rate = rk3228_vop_set_clk(priv->cru, clk->id, rate);
+ break;
+#endif
default:
return -ENOENT;
}
@@ -461,13 +553,44 @@ static int rk322x_gmac_extclk_set_parent(struct clk *clk, struct clk *parent)
return -EINVAL;
}
+static int rk322x_hdmi_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct rk322x_clk_priv *priv = dev_get_priv(clk->dev);
+ const char *clock_output_name;
+ struct rk322x_cru *cru = priv->cru;
+ int ret;
+
+ ret = dev_read_string_index(parent->dev, "clock-output-names",
+ parent->id, &clock_output_name);
+ if (ret < 0)
+ return -ENODATA;
+
+ if (!strcmp(clock_output_name, "hdmiphy_phy")) {
+ debug("%s: switching hdmi_sclk to hdmiphy_phy\n", __func__);
+ rk_clrsetreg(&cru->cru_misc_con, BIT(13), 0);
+ return 0;
+ } else if (!strcmp(clock_output_name, "xin24m")) {
+ debug("%s: switching hdmi_sclk to xin24m\n", __func__);
+ rk_clrsetreg(&cru->cru_misc_con, BIT(13), BIT(13));
+ return 0;
+ }
+
+ return -EINVAL;
+
+}
+
static int rk322x_clk_set_parent(struct clk *clk, struct clk *parent)
{
+
+ debug("%s, clkid=%ld, parent=%ld\n", __func__, clk->id, parent->id);
+
switch (clk->id) {
case SCLK_MAC:
return rk322x_gmac_set_parent(clk, parent);
case SCLK_MAC_EXTCLK:
return rk322x_gmac_extclk_set_parent(clk, parent);
+ case SCLK_HDMI_PHY:
+ return rk322x_hdmi_set_parent(clk, parent);
}
debug("%s: unsupported clk %ld\n", __func__, clk->id);
@@ -646,7 +773,7 @@ static int rk322x_clk_bind(struct udevice *dev)
debug("Warning: software reset driver bind failed\n");
#endif
- return 0;
+ return ret;
}
static const struct udevice_id rk322x_clk_ids[] = {
@@ -655,7 +782,7 @@ static const struct udevice_id rk322x_clk_ids[] = {
};
U_BOOT_DRIVER(rockchip_rk322x_cru) = {
- .name = "clk_rk322x",
+ .name = "rockchip_rk322x_cru",
.id = UCLASS_CLK,
.of_match = rk322x_clk_ids,
.priv_auto = sizeof(struct rk322x_clk_priv),
--
2.34.1

View File

@ -0,0 +1,193 @@
From eb306bf33a53aabf66754f70f61c01348e768d91 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Mon, 29 Apr 2024 16:18:27 +0200
Subject: [PATCH 3/4] rockchip rk3228 HDMI driver
---
drivers/video/rockchip/rk3228_hdmi.c | 161 +++++++++++++++++++++++++++
1 file changed, 161 insertions(+)
create mode 100644 drivers/video/rockchip/rk3228_hdmi.c
diff --git a/drivers/video/rockchip/rk3228_hdmi.c b/drivers/video/rockchip/rk3228_hdmi.c
new file mode 100644
index 0000000000..b07ac35ce1
--- /dev/null
+++ b/drivers/video/rockchip/rk3228_hdmi.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <dw_hdmi.h>
+#include <asm/io.h>
+#include <inno/phy-inno-hdmi.h>
+#include "rk_hdmi.h"
+
+#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
+
+#define RK3228_GRF_SOC_CON2 0x0408
+#define RK3228_GRF_SOC_CON6 0x0418
+
+#define RK3228_HDMI_HPD_VSEL BIT(6)
+#define RK3228_HDMI_SDA_VSEL BIT(5)
+#define RK3228_HDMI_SCL_VSEL BIT(4)
+
+#define RK3228_HDMI_SDAIN_MSK BIT(14)
+#define RK3228_HDMI_SCLIN_MSK BIT(13)
+
+static int rk3228_hdmi_enable(struct udevice *dev, int panel_bpp,
+ const struct display_timing *edid)
+{
+ struct rk_hdmi_priv *priv = dev_get_priv(dev);
+
+ return dw_hdmi_enable(&priv->hdmi, edid);
+}
+
+static int rk3228_dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint pixclock)
+{
+ struct rk_hdmi_priv *priv = container_of(hdmi, struct rk_hdmi_priv, hdmi);
+ struct phy_configure_opts_inno_hdmi params;
+ int ret;
+
+ params.pixel_clock = pixclock;
+ params.bus_width = 8;
+
+ ret = generic_phy_configure(&priv->phy, &params);
+ if (ret < 0) {
+ printf("failed to configure phy (pixel_clock=%d, bus_width=%d)\n",
+ params.pixel_clock, params.bus_width);
+ return ret;
+ }
+
+ ret = generic_phy_power_on(&priv->phy);
+ if (ret) {
+ printf("failed to power on hdmi phy (ret=%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void rk3228_dw_hdmi_setup_hpd(struct dw_hdmi *hdmi)
+{
+ struct rk_hdmi_priv *priv = container_of(hdmi, struct rk_hdmi_priv, hdmi);
+ void *grf = priv->grf;
+
+ /*
+ * Undocumented registers, write them to get correct access to EDID
+ */
+ writel(HIWORD_UPDATE(RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL | RK3228_HDMI_SCL_VSEL,
+ RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL | RK3228_HDMI_SCL_VSEL),
+ grf + RK3228_GRF_SOC_CON6);
+
+ writel(HIWORD_UPDATE(RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK,
+ RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK),
+ grf + RK3228_GRF_SOC_CON2);
+
+}
+
+static const struct dw_hdmi_phy_ops dw_hdmi_rk3228_phy_ops = {
+ .phy_set = rk3228_dw_hdmi_phy_cfg,
+ .setup_hpd = rk3228_dw_hdmi_setup_hpd,
+};
+
+static const struct dw_hdmi_plat_data dw_hdmi_rk3228_plat_data = {
+ .phy_force_vendor = true,
+ .phy_ops = &dw_hdmi_rk3228_phy_ops,
+};
+
+static int rk3228_hdmi_of_to_plat(struct udevice *dev)
+{
+ struct rk_hdmi_priv *priv = dev_get_priv(dev);
+ struct dw_hdmi *hdmi = &priv->hdmi;
+
+ hdmi->i2c_clk_high = 0x71;
+ hdmi->i2c_clk_low = 0x76;
+
+ rk_hdmi_of_to_plat(dev);
+
+ hdmi->data = &dw_hdmi_rk3228_plat_data;
+
+ return 0;
+}
+
+static int rk3228_hdmi_probe(struct udevice *dev)
+{
+ struct rk_hdmi_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = generic_phy_get_by_name(dev, "hdmi", &priv->phy);
+ if (ret) {
+ printf("failed to get hdmi phy\n");
+ return ret;
+ };
+
+ ret = rk_hdmi_probe(dev);
+ if (ret) {
+ printf("failed to probe rk hdmi\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rk3228_hdmi_remove(struct udevice *dev)
+{
+ struct rk_hdmi_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ debug("%s\n", __func__);
+
+ dw_hdmi_disable(&priv->hdmi);
+
+ ret = generic_phy_power_off(&priv->phy);
+ if (ret) {
+ printf("failed to on hdmi phy (ret=%d)\n", ret);
+ }
+
+ return 0;
+
+}
+
+static const struct dm_display_ops rk3228_hdmi_ops = {
+ .read_edid = rk_hdmi_read_edid,
+ .enable = rk3228_hdmi_enable,
+};
+
+static const struct udevice_id rk3228_hdmi_ids[] = {
+ { .compatible = "rockchip,rk3228-dw-hdmi" },
+ { }
+};
+
+U_BOOT_DRIVER(rk3228_hdmi_rockchip) = {
+ .name = "rk3228_hdmi_rockchip",
+ .id = UCLASS_DISPLAY,
+ .of_match = rk3228_hdmi_ids,
+ .ops = &rk3228_hdmi_ops,
+ .of_to_plat = rk3228_hdmi_of_to_plat,
+ .probe = rk3228_hdmi_probe,
+ .priv_auto = sizeof(struct rk_hdmi_priv),
+ .remove = rk3228_hdmi_remove,
+ .flags = DM_FLAG_OS_PREPARE
+};
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 8128289cc8..10a98e8c5a 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399_vop.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
obj-hdmi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_hdmi.o
+obj-hdmi-$(CONFIG_ROCKCHIP_RK322X) += rk3228_hdmi.o
obj-hdmi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_hdmi.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o $(obj-hdmi-y)
obj-mipi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_mipi.o
--
2.34.1

View File

@ -0,0 +1,141 @@
From d62c24664878bd4ca198806580a7dc9aea41db1f Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Mon, 29 Apr 2024 16:18:05 +0200
Subject: [PATCH 2/4] rockchip rk3228 VOP driver
---
drivers/video/rockchip/rk3228_vop.c | 109 ++++++++++++++++++++++++++++
1 file changed, 109 insertions(+)
create mode 100644 drivers/video/rockchip/rk3228_vop.c
diff --git a/drivers/video/rockchip/rk3228_vop.c b/drivers/video/rockchip/rk3228_vop.c
new file mode 100644
index 0000000000..f09097709a
--- /dev/null
+++ b/drivers/video/rockchip/rk3228_vop.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <video.h>
+#include <asm/io.h>
+#include <reset.h>
+#include <clk.h>
+#include <linux/delay.h>
+#include "rk_vop.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void rk3228_set_pin_polarity(struct udevice *dev,
+ enum vop_modes mode, u32 polarity)
+{
+ struct rk_vop_priv *priv = dev_get_priv(dev);
+ struct rk3288_vop *regs = priv->regs;
+
+ switch (mode) {
+ case VOP_MODE_HDMI:
+ clrsetbits_le32(&regs->dsp_ctrl1,
+ M_RK3399_DSP_HDMI_POL,
+ V_RK3399_DSP_HDMI_POL(polarity));
+ break;
+ default:
+ debug("%s: unsupported output mode %x\n", __func__, mode);
+ }
+}
+
+static int rk3228_vop_probe(struct udevice *dev)
+{
+ /* Before relocation we don't need to do anything */
+ if (!(gd->flags & GD_FLG_RELOC))
+ return 0;
+
+ return rk_vop_probe(dev);
+}
+
+/**
+ * Remove the device deasserting the dclk, thus disabling the VOP.
+ * This is essential to avoid iommu complaining later during kernel boot
+ * @see https://lore.kernel.org/linux-arm-kernel/20230330131746.1475514-1-jagan@amarulasolutions.com/
+ */
+static int rk3228_vop_remove(struct udevice *dev)
+{
+ struct rk_vop_priv *priv = dev_get_priv(dev);
+ struct rk3288_vop *regs = priv->regs;
+ struct reset_ctl dclk_rst;
+
+ int ret;
+
+ debug("%s\n", __func__);
+
+ /* set to standby */
+ setbits_le32(&regs->sys_ctrl, V_STANDBY_EN(1));
+ clrsetbits_le32(&regs->sys_ctrl, M_ALL_OUT_EN, 0x0);
+
+ ret = reset_get_by_name(dev, "dclk", &dclk_rst);
+ if (ret)
+ printf("failed to get dclk reset (ret=%d)\n", ret);
+
+ /* assert and deassert reset */
+ ret = reset_assert(&dclk_rst);
+ if (ret)
+ printf("failed to assert dclk reset (ret=%d)\n", ret);
+
+ udelay(20);
+
+ ret = reset_deassert(&dclk_rst);
+ if (ret)
+ printf("failed to deassert dclk reset (ret=%d)\n", ret);
+
+ return 0;
+
+}
+
+struct rkvop_driverdata rk3228_driverdata = {
+ .dsp_offset = 0x0,
+ .win_offset = 0x0,
+ .features = VOP_FEATURE_OUTPUT_10BIT,
+ .set_pin_polarity = rk3228_set_pin_polarity,
+};
+
+static const struct udevice_id rk3228_vop_ids[] = {
+ {
+ .compatible = "rockchip,rk3228-vop",
+ .data = (ulong)&rk3228_driverdata
+ },
+ { /* sentile */ }
+};
+
+static const struct video_ops rk3228_vop_ops = {
+};
+
+U_BOOT_DRIVER(rockchip_rk3228_vop) = {
+ .name = "rockchip_rk3228_vop",
+ .id = UCLASS_VIDEO,
+ .of_match = rk3228_vop_ids,
+ .ops = &rk3228_vop_ops,
+ .bind = rk_vop_bind,
+ .probe = rk3228_vop_probe,
+ .remove = rk3228_vop_remove,
+ .priv_auto = sizeof(struct rk_vop_priv),
+ .flags = DM_FLAG_OS_PREPARE
+};
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 8128289cc8..0e4cc65fdf 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -6,6 +6,7 @@
ifdef CONFIG_VIDEO_ROCKCHIP
obj-y += rk_vop.o
obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288_vop.o
+obj-$(CONFIG_ROCKCHIP_RK322X) += rk3228_vop.o
obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399_vop.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
--
2.34.1

View File

@ -0,0 +1,139 @@
diff --git a/configs/rk322x-box_defconfig b/configs/rk322x-box_defconfig
new file mode 100644
index 0000000000..98eec32a53
--- /dev/null
+++ b/configs/rk322x-box_defconfig
@@ -0,0 +1,133 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_SPL_SKIP_LOWLEVEL_INIT=y
+CONFIG_TPL_SKIP_LOWLEVEL_INIT=y
+CONFIG_SYS_ARCH_TIMER=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_TEXT_BASE=0x61000000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x61100000
+CONFIG_ENV_SIZE=0x8000
+CONFIG_DEFAULT_DEVICE_TREE="rk322x-box"
+CONFIG_SPL_TEXT_BASE=0x60000000
+CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_DM_RESET=y
+CONFIG_ROCKCHIP_RK322X=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
+CONFIG_ROCKCHIP_EXTERNAL_TPL=y
+CONFIG_SPL_MMC=y
+CONFIG_TARGET_RK322X_BOX=y
+CONFIG_SPL_STACK_R_ADDR=0x60600000
+CONFIG_DEBUG_UART_BASE=0x11030000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_SYS_LOAD_ADDR=0x61800800
+CONFIG_DEBUG_UART=y
+CONFIG_LOCALVERSION="-armbian"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_ANDROID_BOOT_IMAGE is not set
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SD_BOOT=y
+CONFIG_BOOTDELAY=1
+CONFIG_USE_PREBOOT=y
+CONFIG_DEFAULT_FDT_FILE="rk322x-box.dtb"
+CONFIG_SILENT_CONSOLE=y
+# CONFIG_SPL_SILENT_CONSOLE is not set
+# CONFIG_TPL_SILENT_CONSOLE is not set
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_MISC_INIT_R=y
+CONFIG_SPL_MAX_SIZE=0x100000
+CONFIG_SPL_PAD_TO=0x7f8000
+CONFIG_SPL_NO_BSS_LIMIT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+CONFIG_SPL_STACK_R=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
+CONFIG_SYS_BOOTM_LEN=0x4000000
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_ROCKUSB=y
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_CLS is not set
+CONFIG_CMD_TIME=y
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_PARTITION_UUIDS is not set
+CONFIG_PARTITION_TYPE_GUID=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_TPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_EXT4=y
+CONFIG_ENV_EXT4_INTERFACE="mmc"
+CONFIG_ENV_EXT4_DEVICE_AND_PART="0:auto"
+CONFIG_ENV_EXT4_FILE="/boot/boot.env"
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_TPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_TPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_TPL_CLK=y
+CONFIG_CLK_CCF=y
+CONFIG_CLK_COMPOSITE_CCF=y
+CONFIG_CLK_GPIO=y
+CONFIG_FASTBOOT_BUF_SIZE=0x04000000
+CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_MISC=y
+CONFIG_ROCKCHIP_EFUSE=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY_ROCKCHIP_INNO_HDMI=y
+CONFIG_PHY_ROCKCHIP_INNO_USB2=y
+CONFIG_PINCTRL=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_SPL_DM_REGULATOR_FIXED=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_TPL_RAM=y
+# CONFIG_RAM_ROCKCHIP is not set
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550_MEM32=y
+CONFIG_SYSRESET=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_USB=y
+# CONFIG_SPL_DM_USB is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_GENERIC=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DWC2_OTG_PHY=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_FUNCTION_MASS_STORAGE=y
+CONFIG_USB_FUNCTION_ROCKUSB=y
+CONFIG_VIDEO=y
+# CONFIG_BACKLIGHT_PWM is not set
+# CONFIG_PANEL is not set
+CONFIG_DISPLAY=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
+CONFIG_FS_BTRFS=y
+CONFIG_TPL_TINY_MEMSET=y
+CONFIG_ERRNO_STR=y
+CONFIG_BOOTM_OPTEE=y

View File

@ -0,0 +1,247 @@
From 9a4db18c4405d06cb3339f55463259259577d1a1 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Thu, 25 Apr 2024 21:24:15 +0200
Subject: [PATCH] Makefile and basic configuration for rk322x-box
---
arch/arm/dts/Makefile | 3 +-
arch/arm/mach-rockchip/rk322x/Kconfig | 5 ++
board/rockchip/rk322x-box/Kconfig | 15 ++++++
board/rockchip/rk322x-box/MAINTAINERS | 6 +++
board/rockchip/rk322x-box/Makefile | 7 +++
board/rockchip/rk322x-box/README | 72 ++++++++++++++++++++++++++
board/rockchip/rk322x-box/rk322x-box.c | 21 ++++++++
include/configs/rk322x-box.h | 27 ++++++++++
8 files changed, 155 insertions(+), 1 deletion(-)
create mode 100644 board/rockchip/rk322x-box/Kconfig
create mode 100644 board/rockchip/rk322x-box/MAINTAINERS
create mode 100644 board/rockchip/rk322x-box/Makefile
create mode 100644 board/rockchip/rk322x-box/README
create mode 100644 board/rockchip/rk322x-box/rk322x-box.c
create mode 100644 include/configs/rk322x-box.h
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 9d28a485be..c26b05b948 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -100,7 +100,8 @@ dtb-$(CONFIG_ROCKCHIP_RK3188) += \
rk3188-radxarock.dtb
dtb-$(CONFIG_ROCKCHIP_RK322X) += \
- rk3229-evb.dtb
+ rk3229-evb.dtb \
+ rk322x-box.dtb
dtb-$(CONFIG_ROCKCHIP_RK3288) += \
rk3288-evb.dtb \
diff --git a/arch/arm/mach-rockchip/rk322x/Kconfig b/arch/arm/mach-rockchip/rk322x/Kconfig
index 9ad1f54055..f5f36b5bf4 100644
--- a/arch/arm/mach-rockchip/rk322x/Kconfig
+++ b/arch/arm/mach-rockchip/rk322x/Kconfig
@@ -11,6 +11,10 @@ config ROCKCHIP_BOOT_MODE_REG
config ROCKCHIP_STIMER_BASE
default 0x110d0020
+config TARGET_RK322X_BOX
+ bool "RK322X-BOX"
+ select BOARD_LATE_INIT
+
config SYS_SOC
default "rk322x"
@@ -33,5 +37,6 @@ config TPL_TEXT_BASE
default 0x10081000
source "board/rockchip/evb_rk3229/Kconfig"
+source "board/rockchip/rk322x-box/Kconfig"
endif
diff --git a/board/rockchip/rk322x-box/Kconfig b/board/rockchip/rk322x-box/Kconfig
new file mode 100644
index 0000000000..db6378f6ba
--- /dev/null
+++ b/board/rockchip/rk322x-box/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_RK322X_BOX
+
+config SYS_BOARD
+ default "rk322x-box"
+
+config SYS_VENDOR
+ default "rockchip"
+
+config SYS_CONFIG_NAME
+ default "rk322x-box"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+
+endif
diff --git a/board/rockchip/rk322x-box/MAINTAINERS b/board/rockchip/rk322x-box/MAINTAINERS
new file mode 100644
index 0000000000..d8513d319a
--- /dev/null
+++ b/board/rockchip/rk322x-box/MAINTAINERS
@@ -0,0 +1,6 @@
+XT-MX4VR-V10
+M: Paolo Sabatino <paolo.sabatino@gmail.com>
+S: Out of tree
+F: board/rockchip/rk322x-box
+F: include/configs/rk322x-box.h
+F: configs/rk322x-box_defconfig
diff --git a/board/rockchip/rk322x-box/Makefile b/board/rockchip/rk322x-box/Makefile
new file mode 100644
index 0000000000..66afec79aa
--- /dev/null
+++ b/board/rockchip/rk322x-box/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2015 Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += rk322x-box.o
diff --git a/board/rockchip/rk322x-box/README b/board/rockchip/rk322x-box/README
new file mode 100644
index 0000000000..86e7055051
--- /dev/null
+++ b/board/rockchip/rk322x-box/README
@@ -0,0 +1,72 @@
+Get the Source and prebuild binary
+==================================
+
+ > mkdir ~/rk322x-box
+ > cd ~/rk322x-box
+ > git clone git://git.denx.de/u-boot.git
+ > git clone https://github.com/OP-TEE/optee_os.git
+ > git clone https://github.com/rockchip-linux/rkbin.git
+ > git clone https://github.com/rockchip-linux/rkdeveloptool.git
+
+Compile the OP-TEE
+===============
+
+ > cd optee_os
+ > make clean
+ > make CROSS_COMPILE_ta_arm32=arm-none-eabi- PLATFORM=rockchip-rk322x
+ Get tee.bin in this step, copy it to U-Boot root dir:
+ > cp out/arm-plat-rockchip/core/tee-pager.bin ../u-boot/tee.bin
+
+Compile the U-Boot
+==================
+
+ > cd ../u-boot
+ > export CROSS_COMPILE=arm-linux-gnueabihf-
+ > export ARCH=arm
+ > make rk322x-box_defconfig
+ > make
+ > make u-boot.itb
+
+ Get tpl/u-boot-tpl.bin, spl/u-boot-spl.bin and u-boot.itb in this step.
+
+Compile the rkdeveloptool
+=======================
+ Follow instructions in latest README
+ > cd ../rkflashtool
+ > autoreconf -i
+ > ./configure
+ > make
+ > sudo make install
+
+ Get rkdeveloptool in you Host in this step.
+
+Both origin binaries and Tool are ready now, choose either option 1 or
+option 2 to deploy U-Boot.
+
+Package the image
+=================
+
+ > cd ../u-boot
+ > tools/mkimage -n rk322x -T rksd -d tpl/u-boot-spl.bin idbloader.img
+ > cat spl/u-boot-spl.bin >> idbloader.img
+
+ Get idbloader.img in this step.
+
+Flash the image to eMMC
+=======================
+Power on(or reset with RESET KEY) with MASKROM KEY preesed, and then:
+ > cd ..
+ > rkdeveloptool db rkbin/rk32/rk322x_loader_v1.04.232.bin
+ > rkdeveloptool wl 64 u-boot/idbloader.img
+ > rkdeveloptool wl 0x4000 u-boot/u-boot.itb
+ > rkdeveloptool rd
+
+Flash the image to SD card
+==========================
+ > dd if=u-boot/idbloader.img of=/dev/sdb seek=64
+ > dd if=u-boot/u-boot.itb of=/dev/sdb seek=16384
+
+You should be able to get U-Boot log message with OP-TEE boot info.
+
+For more detail, please reference to:
+http://opensource.rock-chips.com/wiki_Boot_option
diff --git a/board/rockchip/rk322x-box/rk322x-box.c b/board/rockchip/rk322x-box/rk322x-box.c
new file mode 100644
index 0000000000..ff7d8c98fe
--- /dev/null
+++ b/board/rockchip/rk322x-box/rk322x-box.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/uart.h>
+#include <led.h>
+
+int board_early_init_r(void) {
+
+ /* LED setup */
+ //if (IS_ENABLED(CONFIG_LED))
+ //led_default_state();
+
+ return 0;
+
+}
+
diff --git a/include/configs/rk322x-box.h b/include/configs/rk322x-box.h
new file mode 100644
index 0000000000..994685dba3
--- /dev/null
+++ b/include/configs/rk322x-box.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/rk322x_common.h>
+
+#define ROCKCHIP_DEVICE_SETTINGS \
+ "stdin=serial,usbkbd\0" \
+ "stdout=serial,vidconsole\0" \
+ "stderr=serial,vidconsole\0" \
+ "fdt_high=0xffffffff\0" \
+ "initrd_high=0xffffffff\0"
+
+#undef BOOT_TARGETS
+#undef CFG_EXTRA_ENV_SETTINGS
+
+#define BOOT_TARGETS "mmc1 usb mmc0 pxe dhcp"
+
+#define CFG_EXTRA_ENV_SETTINGS \
+ "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
+ ENV_MEM_LAYOUT_SETTINGS \
+ ROCKCHIP_DEVICE_SETTINGS \
+ "boot_targets=" BOOT_TARGETS "\0"
+
+#endif
--
2.34.1

View File

@ -0,0 +1,272 @@
diff --git a/arch/arm/dts/rk322x-box.dts b/arch/arm/dts/rk322x-box.dts
new file mode 100755
index 0000000000..91d4afd29c
--- /dev/null
+++ b/arch/arm/dts/rk322x-box.dts
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * (C) Copyright 2019 Paolo Sabatino
+ *
+ * Generic rk322x tv box device tree include file.
+ *
+ * This dtsi covers most of the common hardware included in generic tv boxes around the market.
+ * Include this dtsi in your configuration and make the necessary adjustments there for base support.
+ *
+ */
+
+/dts-v1/;
+
+#include "rk322x.dtsi"
+
+/ {
+ model = "Generic Rockchip RK322x TV Box board";
+ compatible = "rockchip,rk322x-box";
+
+ chosen {
+ bootph-all;
+ stdout-path = &uart2;
+ u-boot,spl-boot-order = "same-as-spl", &emmc, &sdmmc;
+ };
+
+ memory@60000000 {
+ device_type = "memory";
+ reg = <0x60000000 0x40000000>;
+ };
+
+ leds: leds {
+ compatible = "gpio-leds";
+
+ /*
+ * Main led is available on all boards.
+ * Default state is honoured only if led_default_state() is called inside
+ * an early init hook function.
+ */
+ main {
+ label = "working";
+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ };
+
+ };
+
+ vcc_sys: vcc-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc_phy: vcc-phy-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ regulator-name = "vcc_phy";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vcc_otg_vbus: otg-vbus-regulator {
+ compatible = "regulator-fixed";
+ gpio = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&otg_vbus_drv>;
+ regulator-name = "vcc_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ // regulator-always-on;
+ enable-active-high;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vcc_host_vbus: vcc-host-regulator {
+ compatible = "regulator-fixed";
+ gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&host_vbus_drv>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "vcc_host";
+ // regulator-always-on;
+ regulator-boot-on;
+ enable-active-high;
+ vin-supply = <&vcc_sys>;
+ };
+
+};
+
+&gmac {
+
+ assigned-clocks = <&cru SCLK_MAC_SRC>;
+ assigned-clock-rates = <50000000>;
+
+ clock_in_out = "output";
+ phy-supply = <&vcc_phy>;
+ phy-mode = "rmii";
+ phy-is-integrated;
+
+ tx_delay = < 0x26 >; // Default is 0x30, but original dts proposes 0x26
+ rx_delay = < 0x11 >; // Default is 0x10, but original dts proposes 0x11
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&phy_pins>;
+
+ status = "okay";
+
+};
+
+&emmc {
+
+ bootph-pre-ram;
+ clock-frequency = <50000000>;
+ clock-freq-min-max = <400000 50000000>;
+ broken-cd;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ supports-emmc;
+ disable-wp;
+ non-removable;
+ /delete-property/ pinctrl-names;
+ /delete-property/ pinctrl-0;
+ status = "okay";
+
+};
+
+&sdmmc {
+
+ bootph-pre-ram;
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ card-detect-delay = <200>;
+ cd-gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ num-slots = <1>;
+ supports-sd;
+
+ status = "okay";
+
+};
+
+&uart2 {
+ pinctrl-0 = <&uart21_xfer>;
+ pinctrl-names = "default";
+ bootph-all;
+ status = "okay";
+};
+
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ status = "okay";
+};
+
+&u2phy0_host {
+ status = "okay";
+};
+
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_otg {
+ status = "okay";
+};
+
+&u2phy1_host {
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ vbus-supply = <&vcc_host_vbus>;
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ vbus-supply = <&vcc_host_vbus>;
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ vbus-supply = <&vcc_host_vbus>;
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ vbus-supply = <&vcc_host_vbus>;
+ status = "okay";
+};
+
+&usb_host2_ehci {
+ vbus-supply = <&vcc_host_vbus>;
+ status = "okay";
+};
+
+&usb_host2_ohci {
+ vbus-supply = <&vcc_host_vbus>;
+ status = "okay";
+};
+
+&usb_otg{
+ vbus-supply = <&vcc_otg_vbus>;
+ status = "okay";
+};
+
+&pinctrl {
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_leds>;
+
+ gpio {
+ gpio_leds: gpio-leds {
+ rockchip,pins = <3 21 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ usb {
+ host_vbus_drv: host-vbus-drv {
+ rockchip,pins = <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+
+ otg_vbus_drv: otg-vbus-drv {
+ rockchip,pins = <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ uart2 {
+ uart21_xfer: uart21-xfer {
+ rockchip,pins = <1 RK_PB2 2 &pcfg_pull_up>,
+ <1 RK_PB1 2 &pcfg_pull_none>;
+ };
+ };
+
+};
+
+&hdmi {
+ /*
+ * u-boot clk driver is not yet capable to handle parents correctly;
+ * these properties will prevent the video output features if present
+ */
+ /delete-property/assigned-clocks;
+ /delete-property/assigned-clock-parents;
+ status = "okay";
+};
+
+&hdmi_phy {
+ status = "okay";
+};
+
+&vop {
+ bootph-all;
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};

View File

@ -0,0 +1,423 @@
From f860502331f1c1700db222a80cfb9bd0026954cb Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Thu, 25 Apr 2024 21:44:55 +0200
Subject: [PATCH] support gmac rmii phy for rk322x
---
arch/arm/dts/rk322x.dtsi | 8 +-
.../include/asm/arch-rockchip/cru_rk322x.h | 1 +
doc/device-tree-bindings/net/phy.txt | 13 ++
drivers/clk/rockchip/clk_rk322x.c | 14 +-
drivers/net/gmac_rockchip.c | 186 +++++++++++++++++-
5 files changed, 205 insertions(+), 17 deletions(-)
diff --git a/arch/arm/dts/rk322x.dtsi b/arch/arm/dts/rk322x.dtsi
index 8eed9e3a92..e3109afa7b 100644
--- a/arch/arm/dts/rk322x.dtsi
+++ b/arch/arm/dts/rk322x.dtsi
@@ -870,13 +870,13 @@
clocks = <&cru SCLK_MAC>, <&cru SCLK_MAC_RX>,
<&cru SCLK_MAC_TX>, <&cru SCLK_MAC_REF>,
<&cru SCLK_MAC_REFOUT>, <&cru ACLK_GMAC>,
- <&cru PCLK_GMAC>;
+ <&cru PCLK_GMAC>, <&cru SCLK_MAC_PHY>;
clock-names = "stmmaceth", "mac_clk_rx",
"mac_clk_tx", "clk_mac_ref",
"clk_mac_refout", "aclk_mac",
- "pclk_mac";
- resets = <&cru SRST_GMAC>;
- reset-names = "stmmaceth";
+ "pclk_mac", "clk_macphy";
+ resets = <&cru SRST_GMAC>, <&cru SRST_MACPHY>;
+ reset-names = "stmmaceth", "mac-phy";
rockchip,grf = <&grf>;
status = "disabled";
};
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk322x.h b/arch/arm/include/asm/arch-rockchip/cru_rk322x.h
index ee12fa831f..cfbc7e92f7 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk322x.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk322x.h
@@ -10,6 +10,7 @@
#define APLL_HZ (600 * MHz)
#define GPLL_HZ (594 * MHz)
+#define CPLL_HZ (500 * MHz)
#define CORE_PERI_HZ 150000000
#define CORE_ACLK_HZ 300000000
diff --git a/doc/device-tree-bindings/net/phy.txt b/doc/device-tree-bindings/net/phy.txt
index 6599c667b5..ca1a4a8526 100644
--- a/doc/device-tree-bindings/net/phy.txt
+++ b/doc/device-tree-bindings/net/phy.txt
@@ -8,6 +8,19 @@ Required properties:
- reg : The ID number for the phy, usually a small integer
+Optional Properties:
+
+- compatible: Compatible list, may contain
+ "ethernet-phy-ieee802.3-c22" or "ethernet-phy-ieee802.3-c45" for
+ PHYs that implement IEEE802.3 clause 22 or IEEE802.3 clause 45
+ specifications. If neither of these are specified, the default is to
+ assume clause 22.
+
+- phy-is-integrated: If set, indicates that the PHY is integrated into the same
+ physical package as the Ethernet MAC. If needed, muxers should be configured
+ to ensure the integrated PHY is used. The absence of this property indicates
+ the muxers should be configured so that the external PHY is used.
+
Example:
ethernet-phy@0 {
diff --git a/drivers/clk/rockchip/clk_rk322x.c b/drivers/clk/rockchip/clk_rk322x.c
index 28cdba7575..f6d2ca6134 100644
--- a/drivers/clk/rockchip/clk_rk322x.c
+++ b/drivers/clk/rockchip/clk_rk322x.c
@@ -43,6 +43,7 @@ enum {
/* use integer mode*/
static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
+static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 2, 3, 1);
static int rkclk_set_pll(struct rk322x_cru *cru, enum rk_clk_id clk_id,
const struct pll_div *div)
@@ -92,11 +93,13 @@ static void rkclk_init(struct rk322x_cru *cru)
rk_clrsetreg(&cru->cru_mode_con,
GPLL_MODE_MASK | APLL_MODE_MASK,
GPLL_MODE_SLOW << GPLL_MODE_SHIFT |
- APLL_MODE_SLOW << APLL_MODE_SHIFT);
+ APLL_MODE_SLOW << APLL_MODE_SHIFT |
+ CPLL_MODE_SLOW << CPLL_MODE_SHIFT);
/* init pll */
rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
+ rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg);
/*
* select apll as cpu/core clock pll source and
@@ -169,7 +172,8 @@ static void rkclk_init(struct rk322x_cru *cru)
rk_clrsetreg(&cru->cru_mode_con,
GPLL_MODE_MASK | APLL_MODE_MASK,
GPLL_MODE_NORM << GPLL_MODE_SHIFT |
- APLL_MODE_NORM << APLL_MODE_SHIFT);
+ APLL_MODE_NORM << APLL_MODE_SHIFT |
+ CPLL_MODE_NORM << CPLL_MODE_SHIFT);
}
/* Get pll rate by id */
@@ -259,11 +263,10 @@ static ulong rk322x_mac_set_clk(struct rk322x_cru *cru, uint freq)
ulong pll_rate;
u8 div;
- if ((con >> MAC_PLL_SEL_SHIFT) & MAC_PLL_SEL_MASK)
+ if (con & MAC_PLL_SEL_MASK)
pll_rate = GPLL_HZ;
else
- /* CPLL is not set */
- return -EPERM;
+ pll_rate = CPLL_HZ;
div = DIV_ROUND_UP(pll_rate, freq) - 1;
if (div <= 0x1f)
@@ -392,6 +395,7 @@ static ulong rk322x_clk_set_rate(struct clk *clk, ulong rate)
case CLK_DDR:
new_rate = rk322x_ddr_set_clk(priv->cru, rate);
break;
+ case SCLK_MAC_SRC:
case SCLK_MAC:
new_rate = rk322x_mac_set_clk(priv->cru, rate);
break;
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index 04008d2b19..7a917e09cd 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -11,6 +11,7 @@
#include <log.h>
#include <net.h>
#include <phy.h>
+#include <reset.h>
#include <syscon.h>
#include <asm/global_data.h>
#include <asm/io.h>
@@ -26,6 +27,8 @@
#include <asm/arch-rockchip/grf_rk3399.h>
#include <asm/arch-rockchip/grf_rv1108.h>
#include <dm/pinctrl.h>
+#include <dm/of_access.h>
+#include <linux/delay.h>
#include <dt-bindings/clock/rk3288-cru.h>
#include <linux/bitops.h>
#include "designware.h"
@@ -43,21 +46,30 @@ DECLARE_GLOBAL_DATA_PTR;
struct gmac_rockchip_plat {
struct dw_eth_pdata dw_eth_pdata;
bool clock_input;
+ bool integrated_phy;
+ struct reset_ctl phy_reset;
int tx_delay;
int rx_delay;
};
struct rk_gmac_ops {
int (*fix_mac_speed)(struct dw_eth_dev *priv);
+ int (*fix_rmii_speed)(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv);
+ int (*fix_rgmii_speed)(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv);
void (*set_to_rmii)(struct gmac_rockchip_plat *pdata);
void (*set_to_rgmii)(struct gmac_rockchip_plat *pdata);
+ void (*integrated_phy_powerup)(struct gmac_rockchip_plat *pdata);
};
static int gmac_rockchip_of_to_plat(struct udevice *dev)
{
struct gmac_rockchip_plat *pdata = dev_get_plat(dev);
+ struct ofnode_phandle_args args;
const char *string;
+ int ret;
string = dev_read_string(dev, "clock_in_out");
if (!strcmp(string, "input"))
@@ -65,6 +77,25 @@ static int gmac_rockchip_of_to_plat(struct udevice *dev)
else
pdata->clock_input = false;
+ /* If phy-handle property is passed from DT, use it as the PHY */
+ ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, &args);
+ if (ret) {
+ debug("Cannot get phy phandle: ret=%d\n", ret);
+ pdata->integrated_phy = dev_read_bool(dev, "phy-is-integrated");
+ } else {
+ debug("Found phy-handle subnode\n");
+ pdata->integrated_phy = ofnode_read_bool(args.node,
+ "phy-is-integrated");
+ }
+
+ if (pdata->integrated_phy) {
+ ret = reset_get_by_name(dev, "mac-phy", &pdata->phy_reset);
+ if (ret) {
+ debug("No PHY reset control found: ret=%d\n", ret);
+ return ret;
+ }
+ }
+
/* Check the new naming-style first... */
pdata->tx_delay = dev_read_u32_default(dev, "tx_delay", -ENOENT);
pdata->rx_delay = dev_read_u32_default(dev, "rx_delay", -ENOENT);
@@ -119,7 +150,43 @@ static int px30_gmac_fix_mac_speed(struct dw_eth_dev *priv)
return 0;
}
-static int rk3228_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3228_gmac_fix_rmii_speed(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv)
+{
+ struct rk322x_grf *grf;
+ int clk;
+ enum {
+ RK3228_GMAC_RMII_CLK_MASK = BIT(7),
+ RK3228_GMAC_RMII_CLK_2_5M = 0,
+ RK3228_GMAC_RMII_CLK_25M = BIT(7),
+
+ RK3228_GMAC_RMII_SPEED_MASK = BIT(2),
+ RK3228_GMAC_RMII_SPEED_10 = 0,
+ RK3228_GMAC_RMII_SPEED_100 = BIT(2),
+ };
+
+ switch (priv->phydev->speed) {
+ case 10:
+ clk = RK3228_GMAC_RMII_CLK_2_5M | RK3228_GMAC_RMII_SPEED_10;
+ break;
+ case 100:
+ clk = RK3228_GMAC_RMII_CLK_25M | RK3228_GMAC_RMII_SPEED_100;
+ break;
+ default:
+ debug("Unknown phy speed: %d\n", priv->phydev->speed);
+ return -EINVAL;
+ }
+
+ grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ rk_clrsetreg(&grf->mac_con[1],
+ RK3228_GMAC_RMII_CLK_MASK | RK3228_GMAC_RMII_SPEED_MASK,
+ clk);
+
+ return 0;
+}
+
+static int rk3228_gmac_fix_rgmii_speed(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv)
{
struct rk322x_grf *grf;
int clk;
@@ -361,6 +428,28 @@ static void px30_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata)
PX30_GMAC_PHY_INTF_SEL_RMII);
}
+static void rk3228_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata)
+{
+ struct rk322x_grf *grf;
+ enum {
+ RK3228_GRF_CON_RMII_MODE_MASK = BIT(11),
+ RK3228_GRF_CON_RMII_MODE_SEL = BIT(11),
+ RK3228_RMII_MODE_MASK = BIT(10),
+ RK3228_RMII_MODE_SEL = BIT(10),
+ RK3228_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4),
+ RK3228_GMAC_PHY_INTF_SEL_RMII = BIT(6),
+ };
+
+ grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ rk_clrsetreg(&grf->mac_con[1],
+ RK3228_GRF_CON_RMII_MODE_MASK |
+ RK3228_RMII_MODE_MASK |
+ RK3228_GMAC_PHY_INTF_SEL_MASK,
+ RK3228_GRF_CON_RMII_MODE_SEL |
+ RK3228_RMII_MODE_SEL |
+ RK3228_GMAC_PHY_INTF_SEL_RMII);
+}
+
static void rk3228_gmac_set_to_rgmii(struct gmac_rockchip_plat *pdata)
{
struct rk322x_grf *grf;
@@ -554,6 +643,66 @@ static void rv1108_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata)
RV1108_GMAC_PHY_INTF_SEL_RMII);
}
+static void rk3228_gmac_integrated_phy_powerup(struct gmac_rockchip_plat *pdata)
+{
+ struct rk322x_grf *grf;
+ enum {
+ RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY_MASK = BIT(15),
+ RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY = BIT(15),
+ };
+ enum {
+ RK3228_MACPHY_CFG_CLK_50M_MASK = BIT(14),
+ RK3228_MACPHY_CFG_CLK_50M = BIT(14),
+
+ RK3228_MACPHY_RMII_MODE_MASK = GENMASK(7, 6),
+ RK3228_MACPHY_RMII_MODE = BIT(6),
+
+ RK3228_MACPHY_ENABLE_MASK = BIT(0),
+ RK3228_MACPHY_DISENABLE = 0,
+ RK3228_MACPHY_ENABLE = BIT(0),
+ };
+ enum {
+ RK3228_RK_GRF_CON2_MACPHY_ID_MASK = GENMASK(6, 0),
+ RK3228_RK_GRF_CON2_MACPHY_ID = 0x1234,
+ };
+ enum {
+ RK3228_RK_GRF_CON3_MACPHY_ID_MASK = GENMASK(5, 0),
+ RK3228_RK_GRF_CON3_MACPHY_ID = 0x35,
+ };
+
+ grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ rk_clrsetreg(&grf->con_iomux,
+ RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY_MASK,
+ RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY);
+
+ rk_clrsetreg(&grf->macphy_con[2],
+ RK3228_RK_GRF_CON2_MACPHY_ID_MASK,
+ RK3228_RK_GRF_CON2_MACPHY_ID);
+
+ rk_clrsetreg(&grf->macphy_con[3],
+ RK3228_RK_GRF_CON3_MACPHY_ID_MASK,
+ RK3228_RK_GRF_CON3_MACPHY_ID);
+
+ /* disabled before trying to reset it */
+ rk_clrsetreg(&grf->macphy_con[0],
+ RK3228_MACPHY_CFG_CLK_50M_MASK |
+ RK3228_MACPHY_RMII_MODE_MASK |
+ RK3228_MACPHY_ENABLE_MASK,
+ RK3228_MACPHY_CFG_CLK_50M |
+ RK3228_MACPHY_RMII_MODE |
+ RK3228_MACPHY_DISENABLE);
+
+ reset_assert(&pdata->phy_reset);
+ udelay(10);
+ reset_deassert(&pdata->phy_reset);
+ udelay(10);
+
+ rk_clrsetreg(&grf->macphy_con[0],
+ RK3228_MACPHY_ENABLE_MASK,
+ RK3228_MACPHY_ENABLE);
+ udelay(30 * 1000);
+}
+
static int gmac_rockchip_probe(struct udevice *dev)
{
struct gmac_rockchip_plat *pdata = dev_get_plat(dev);
@@ -573,6 +722,9 @@ static int gmac_rockchip_probe(struct udevice *dev)
if (ret)
return ret;
+ if (pdata->integrated_phy && ops->integrated_phy_powerup)
+ ops->integrated_phy_powerup(pdata);
+
switch (eth_pdata->phy_interface) {
case PHY_INTERFACE_MODE_RGMII:
/* Set to RGMII mode */
@@ -656,7 +808,7 @@ static int gmac_rockchip_probe(struct udevice *dev)
break;
default:
- debug("NO interface defined!\n");
+ debug("%s: no interface defined!\n", __func__);
return -ENXIO;
}
@@ -665,18 +817,33 @@ static int gmac_rockchip_probe(struct udevice *dev)
static int gmac_rockchip_eth_start(struct udevice *dev)
{
- struct eth_pdata *pdata = dev_get_plat(dev);
+ struct eth_pdata *eth_pdata = dev_get_plat(dev);
struct dw_eth_dev *priv = dev_get_priv(dev);
struct rk_gmac_ops *ops =
(struct rk_gmac_ops *)dev_get_driver_data(dev);
+ struct gmac_rockchip_plat *pdata = dev_get_plat(dev);
int ret;
- ret = designware_eth_init(priv, pdata->enetaddr);
- if (ret)
- return ret;
- ret = ops->fix_mac_speed(priv);
+ ret = designware_eth_init(priv, eth_pdata->enetaddr);
if (ret)
return ret;
+
+ switch (eth_pdata->phy_interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ ret = ops->fix_rgmii_speed(pdata, priv);
+ if (ret)
+ return ret;
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ ret = ops->fix_rmii_speed(pdata, priv);
+ if (ret)
+ return ret;
+ break;
+ default:
+ debug("%s: no interface defined!\n", __func__);
+ return -ENXIO;
+ }
+
ret = designware_eth_enable(priv);
if (ret)
return ret;
@@ -699,8 +866,11 @@ const struct rk_gmac_ops px30_gmac_ops = {
};
const struct rk_gmac_ops rk3228_gmac_ops = {
- .fix_mac_speed = rk3228_gmac_fix_mac_speed,
+ .fix_rmii_speed = rk3228_gmac_fix_rmii_speed,
+ .fix_rgmii_speed = rk3228_gmac_fix_rgmii_speed,
+ .set_to_rmii = rk3228_gmac_set_to_rmii,
.set_to_rgmii = rk3228_gmac_set_to_rgmii,
+ .integrated_phy_powerup = rk3228_gmac_integrated_phy_powerup,
};
const struct rk_gmac_ops rk3288_gmac_ops = {
--
2.34.1

View File

@ -0,0 +1,24 @@
From 0add0274f4b7c1fbcb2c2795c3e6f5ce00e484c8 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Thu, 25 Apr 2024 21:48:17 +0200
Subject: [PATCH] Set register r1 to CONFIG_SYS_TEXT_BASE to support rockchip
proprietary OP-TEE binaries
---
common/spl/spl_optee.S | 1 +
1 file changed, 1 insertion(+)
diff --git a/common/spl/spl_optee.S b/common/spl/spl_optee.S
index a269904d38..a3891f0071 100644
--- a/common/spl/spl_optee.S
+++ b/common/spl/spl_optee.S
@@ -8,5 +8,6 @@
ENTRY(spl_optee_entry)
ldr lr, =CONFIG_TEXT_BASE
+ ldr r1, =CONFIG_TEXT_BASE
mov pc, r3
ENDPROC(spl_optee_entry)
--
2.34.1

View File

@ -0,0 +1,230 @@
From 62b9c5ea4a5d41f8adf122797958b202d566f735 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Thu, 25 Apr 2024 21:59:34 +0200
Subject: [PATCH] OTG/EHCI USB support for rk322x
---
arch/arm/mach-rockchip/rk322x/syscon_rk322x.c | 3 +
drivers/clk/rockchip/clk_rk322x.c | 121 ++++++++++++++++++
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 49 +++++++
3 files changed, 173 insertions(+)
diff --git a/arch/arm/mach-rockchip/rk322x/syscon_rk322x.c b/arch/arm/mach-rockchip/rk322x/syscon_rk322x.c
index 0d9dca8173..37c040950b 100644
--- a/arch/arm/mach-rockchip/rk322x/syscon_rk322x.c
+++ b/arch/arm/mach-rockchip/rk322x/syscon_rk322x.c
@@ -17,5 +17,8 @@ static const struct udevice_id rk322x_syscon_ids[] = {
U_BOOT_DRIVER(syscon_rk322x) = {
.name = "rk322x_syscon",
.id = UCLASS_SYSCON,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+ .bind = dm_scan_fdt_dev,
+#endif
.of_match = rk322x_syscon_ids,
};
diff --git a/drivers/clk/rockchip/clk_rk322x.c b/drivers/clk/rockchip/clk_rk322x.c
index f6d2ca6134..44b5778589 100644
--- a/drivers/clk/rockchip/clk_rk322x.c
+++ b/drivers/clk/rockchip/clk_rk322x.c
@@ -474,10 +474,131 @@ static int rk322x_clk_set_parent(struct clk *clk, struct clk *parent)
return -ENOENT;
}
+static int rk322x_clk_enable(struct clk *clk)
+{
+
+ struct rk322x_clk_priv *priv = dev_get_priv(clk->dev);
+ struct rk322x_cru *cru = priv->cru;
+
+ switch (clk->id) {
+ case SCLK_OTGPHY0:
+ rk_clrreg(&cru->cru_clkgate_con[1], BIT(5));
+ break;
+ case SCLK_OTGPHY1:
+ rk_clrreg(&cru->cru_clkgate_con[1], BIT(6));
+ break;
+ case HCLK_OTG:
+ rk_clrreg(&cru->cru_clkgate_con[11], BIT(12));
+ break;
+ case HCLK_HOST0:
+ rk_clrreg(&cru->cru_clkgate_con[11], BIT(6));
+ break;
+ case HCLK_HOST1:
+ rk_clrreg(&cru->cru_clkgate_con[11], BIT(8));
+ break;
+ case HCLK_HOST2:
+ rk_clrreg(&cru->cru_clkgate_con[11], BIT(10));
+ break;
+ case SCLK_MAC:
+ rk_clrreg(&cru->cru_clkgate_con[1], BIT(6));
+ break;
+ case SCLK_MAC_SRC:
+ rk_clrreg(&cru->cru_clkgate_con[1], BIT(7));
+ break;
+ case SCLK_MAC_RX:
+ rk_clrreg(&cru->cru_clkgate_con[5], BIT(5));
+ break;
+ case SCLK_MAC_TX:
+ rk_clrreg(&cru->cru_clkgate_con[5], BIT(6));
+ break;
+ case SCLK_MAC_REF:
+ rk_clrreg(&cru->cru_clkgate_con[5], BIT(3));
+ break;
+ case SCLK_MAC_REFOUT:
+ rk_clrreg(&cru->cru_clkgate_con[5], BIT(4));
+ break;
+ case SCLK_MAC_PHY:
+ rk_clrreg(&cru->cru_clkgate_con[5], BIT(7));
+ break;
+ case ACLK_GMAC:
+ rk_clrreg(&cru->cru_clkgate_con[11], BIT(4));
+ break;
+ case PCLK_GMAC:
+ rk_clrreg(&cru->cru_clkgate_con[11], BIT(5));
+ break;
+ default:
+ log_debug("%s: unsupported clk %ld\n", __func__, clk->id);
+ return -ENOENT;
+ }
+
+ return 0;
+
+}
+
+static int rk322x_clk_disable(struct clk *clk)
+{
+
+ struct rk322x_clk_priv *priv = dev_get_priv(clk->dev);
+ struct rk322x_cru *cru = priv->cru;
+
+ switch (clk->id) {
+ case SCLK_OTGPHY0:
+ rk_setreg(&cru->cru_clkgate_con[1], BIT(5));
+ break;
+ case SCLK_OTGPHY1:
+ rk_setreg(&cru->cru_clkgate_con[1], BIT(6));
+ break;
+ case HCLK_OTG:
+ rk_setreg(&cru->cru_clkgate_con[11], BIT(12));
+ break;
+ case HCLK_HOST0:
+ rk_setreg(&cru->cru_clkgate_con[11], BIT(6));
+ break;
+ case HCLK_HOST1:
+ rk_setreg(&cru->cru_clkgate_con[11], BIT(8));
+ break;
+ case HCLK_HOST2:
+ rk_setreg(&cru->cru_clkgate_con[11], BIT(10));
+ break;
+ case SCLK_MAC_SRC:
+ rk_setreg(&cru->cru_clkgate_con[1], BIT(7));
+ break;
+ case SCLK_MAC_RX:
+ rk_setreg(&cru->cru_clkgate_con[5], BIT(5));
+ break;
+ case SCLK_MAC_TX:
+ rk_setreg(&cru->cru_clkgate_con[5], BIT(6));
+ break;
+ case SCLK_MAC_REF:
+ rk_setreg(&cru->cru_clkgate_con[5], BIT(3));
+ break;
+ case SCLK_MAC_REFOUT:
+ rk_setreg(&cru->cru_clkgate_con[5], BIT(4));
+ break;
+ case SCLK_MAC_PHY:
+ rk_setreg(&cru->cru_clkgate_con[5], BIT(7));
+ break;
+ case ACLK_GMAC:
+ rk_setreg(&cru->cru_clkgate_con[11], BIT(4));
+ break;
+ case PCLK_GMAC:
+ rk_setreg(&cru->cru_clkgate_con[11], BIT(5));
+ break;
+ default:
+ log_debug("%s: unsupported clk %ld\n", __func__, clk->id);
+ return -ENOENT;
+ }
+
+ return 0;
+
+}
+
static struct clk_ops rk322x_clk_ops = {
.get_rate = rk322x_clk_get_rate,
.set_rate = rk322x_clk_set_rate,
.set_parent = rk322x_clk_set_parent,
+ .enable = rk322x_clk_enable,
+ .disable = rk322x_clk_disable
};
static int rk322x_clk_of_to_plat(struct udevice *dev)
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 70e61eccb7..c905ccb8f9 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -375,6 +375,51 @@ static const struct rockchip_usb2phy_cfg rk3328_usb2phy_cfgs[] = {
{ /* sentinel */ }
};
+static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = {
+ {
+ .reg = 0x760,
+ .clkout_ctl = { 0x0768, 4, 4, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x0760, 15, 0, 0, 0x1d1 },
+ .bvalid_det_en = { 0x0680, 3, 3, 0, 1 },
+ .bvalid_det_st = { 0x0690, 3, 3, 0, 1 },
+ .bvalid_det_clr = { 0x06a0, 3, 3, 0, 1 },
+ .ls_det_en = { 0x0680, 2, 2, 0, 1 },
+ .ls_det_st = { 0x0690, 2, 2, 0, 1 },
+ .ls_det_clr = { 0x06a0, 2, 2, 0, 1 },
+ .utmi_bvalid = { 0x0480, 4, 4, 0, 1 },
+ .utmi_ls = { 0x0480, 3, 2, 0, 1 },
+ },
+ [USB2PHY_PORT_HOST] = {
+ .phy_sus = { 0x0764, 15, 0, 0, 0x1d1 },
+ .ls_det_en = { 0x0680, 4, 4, 0, 1 },
+ .ls_det_st = { 0x0690, 4, 4, 0, 1 },
+ .ls_det_clr = { 0x06a0, 4, 4, 0, 1 }
+ }
+ },
+ },
+ {
+ .reg = 0x800,
+ .clkout_ctl = { 0x0808, 4, 4, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x800, 15, 0, 0, 0x1d1 },
+ .ls_det_en = { 0x0684, 0, 0, 0, 1 },
+ .ls_det_st = { 0x0694, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x06a4, 0, 0, 0, 1 }
+ },
+ [USB2PHY_PORT_HOST] = {
+ .phy_sus = { 0x804, 15, 0, 0, 0x1d1 },
+ .ls_det_en = { 0x0684, 1, 1, 0, 1 },
+ .ls_det_st = { 0x0694, 1, 1, 0, 1 },
+ .ls_det_clr = { 0x06a4, 1, 1, 0, 1 }
+ }
+ },
+ },
+ { /* sentinel */ }
+};
+
static const struct rockchip_usb2phy_cfg rk3399_usb2phy_cfgs[] = {
{
.reg = 0xe450,
@@ -532,6 +577,10 @@ static const struct udevice_id rockchip_usb2phy_ids[] = {
.compatible = "rockchip,rk3328-usb2phy",
.data = (ulong)&rk3328_usb2phy_cfgs,
},
+ {
+ .compatible = "rockchip,rk3228-usb2phy",
+ .data = (ulong)&rk3228_phy_cfgs,
+ },
{
.compatible = "rockchip,rk3399-usb2phy",
.data = (ulong)&rk3399_usb2phy_cfgs,
--
2.34.1

View File

@ -0,0 +1,242 @@
From dc0ea12fdeb6843839ee1a182166bc2506fa0ec7 Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Sun, 19 Feb 2023 00:47:19 +0530
Subject: [PATCH] video: rockchip: vop: Simplify rkvop_enable
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/rockchip/rk_vop.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index bc98ab6875a..7e8ce9b29aa 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -39,11 +39,13 @@ enum vop_pol {
DCLK_INVERT = 3
};
-static void rkvop_enable(struct udevice *dev, struct rk3288_vop *regs, ulong fbbase,
+static void rkvop_enable(struct udevice *dev, ulong fbbase,
int fb_bits_per_pixel,
const struct display_timing *edid,
struct reset_ctl *dclk_rst)
{
+ struct rk_vop_priv *priv = dev_get_priv(dev);
+ struct rk3288_vop *regs = priv->regs;
u32 lb_mode;
u32 rgb_mode;
u32 hactive = edid->hactive.typ;
@@ -243,9 +245,7 @@ static void rkvop_mode_set(struct udevice *dev,
static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
{
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
- struct rk_vop_priv *priv = dev_get_priv(dev);
int vop_id, remote_vop_id;
- struct rk3288_vop *regs = priv->regs;
struct display_timing timing;
struct udevice *disp;
int ret;
@@ -379,7 +379,7 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
return ret;
}
- rkvop_enable(dev, regs, fbbase, 1 << l2bpp, &timing, &dclk_rst);
+ rkvop_enable(dev, fbbase, 1 << l2bpp, &timing, &dclk_rst);
ret = display_enable(disp, 1 << l2bpp, &timing);
if (ret)
From a9b623a13c0c7ba8867875c0267deabd0fed733c Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Sun, 19 Feb 2023 00:53:06 +0530
Subject: [PATCH] video: rockchip: vop: Add win offset support
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/rockchip/rk_vop.c | 23 ++++++++++++++---------
drivers/video/rockchip/rk_vop.h | 2 ++
2 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index 7e8ce9b29aa..757fe7a4338 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -46,6 +46,7 @@ static void rkvop_enable(struct udevice *dev, ulong fbbase,
{
struct rk_vop_priv *priv = dev_get_priv(dev);
struct rk3288_vop *regs = priv->regs;
+ struct rk3288_vop *win_regs = priv->regs + priv->win_offset;
u32 lb_mode;
u32 rgb_mode;
u32 hactive = edid->hactive.typ;
@@ -53,32 +54,33 @@ static void rkvop_enable(struct udevice *dev, ulong fbbase,
int ret;
writel(V_ACT_WIDTH(hactive - 1) | V_ACT_HEIGHT(vactive - 1),
- &regs->win0_act_info);
+ &win_regs->win0_act_info);
writel(V_DSP_XST(edid->hsync_len.typ + edid->hback_porch.typ) |
V_DSP_YST(edid->vsync_len.typ + edid->vback_porch.typ),
- &regs->win0_dsp_st);
+ &win_regs->win0_dsp_st);
writel(V_DSP_WIDTH(hactive - 1) |
V_DSP_HEIGHT(vactive - 1),
- &regs->win0_dsp_info);
+ &win_regs->win0_dsp_info);
- clrsetbits_le32(&regs->win0_color_key, M_WIN0_KEY_EN | M_WIN0_KEY_COLOR,
+ clrsetbits_le32(&win_regs->win0_color_key,
+ M_WIN0_KEY_EN | M_WIN0_KEY_COLOR,
V_WIN0_KEY_EN(0) | V_WIN0_KEY_COLOR(0));
switch (fb_bits_per_pixel) {
case 16:
rgb_mode = RGB565;
- writel(V_RGB565_VIRWIDTH(hactive), &regs->win0_vir);
+ writel(V_RGB565_VIRWIDTH(hactive), &win_regs->win0_vir);
break;
case 24:
rgb_mode = RGB888;
- writel(V_RGB888_VIRWIDTH(hactive), &regs->win0_vir);
+ writel(V_RGB888_VIRWIDTH(hactive), &win_regs->win0_vir);
break;
case 32:
default:
rgb_mode = ARGB8888;
- writel(V_ARGB888_VIRWIDTH(hactive), &regs->win0_vir);
+ writel(V_ARGB888_VIRWIDTH(hactive), &win_regs->win0_vir);
break;
}
@@ -91,12 +93,12 @@ static void rkvop_enable(struct udevice *dev, ulong fbbase,
else
lb_mode = LB_RGB_1280X8;
- clrsetbits_le32(&regs->win0_ctrl0,
+ clrsetbits_le32(&win_regs->win0_ctrl0,
M_WIN0_LB_MODE | M_WIN0_DATA_FMT | M_WIN0_EN,
V_WIN0_LB_MODE(lb_mode) | V_WIN0_DATA_FMT(rgb_mode) |
V_WIN0_EN(1));
- writel(fbbase, &regs->win0_yrgb_mst);
+ writel(fbbase, &win_regs->win0_yrgb_mst);
writel(0x01, &regs->reg_cfg_done); /* enable reg config */
ret = reset_assert(dclk_rst);
@@ -414,6 +416,8 @@ int rk_vop_probe(struct udevice *dev)
{
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
struct rk_vop_priv *priv = dev_get_priv(dev);
+ struct rkvop_driverdata *ops =
+ (struct rkvop_driverdata *)dev_get_driver_data(dev);
int ret = 0;
ofnode port, node;
struct reset_ctl ahb_rst;
@@ -448,6 +453,8 @@ int rk_vop_probe(struct udevice *dev)
#endif
priv->regs = dev_read_addr_ptr(dev);
+ priv->win_offset = ops->win_offset;
+ priv->dsp_offset = ops->dsp_offset;
/*
* Try all the ports until we find one that works. In practice this
diff --git a/drivers/video/rockchip/rk_vop.h b/drivers/video/rockchip/rk_vop.h
index 0528fb23f59..909f5602e53 100644
--- a/drivers/video/rockchip/rk_vop.h
+++ b/drivers/video/rockchip/rk_vop.h
@@ -11,6 +11,7 @@
struct rk_vop_priv {
void *grf;
void *regs;
+ int win_offset;
};
enum vop_features {
@@ -18,6 +19,7 @@ enum vop_features {
};
struct rkvop_driverdata {
+ int win_offset;
/* configuration */
u32 features;
/* block-specific setters/getters */
From cd5115979e60d360e546ea683e77209e2011e752 Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Mon, 20 Feb 2023 00:52:32 +0530
Subject: [PATCH] video: rockchip: vop: Add dsp offset support
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/rockchip/rk_vop.c | 14 ++++++++------
drivers/video/rockchip/rk_vop.h | 2 ++
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index 757fe7a4338..f7c6b4cc25a 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -166,6 +166,7 @@ static void rkvop_mode_set(struct udevice *dev,
{
struct rk_vop_priv *priv = dev_get_priv(dev);
struct rk3288_vop *regs = priv->regs;
+ struct rk3288_vop *dsp_regs = priv->regs + priv->dsp_offset;
struct rkvop_driverdata *data =
(struct rkvop_driverdata *)dev_get_driver_data(dev);
@@ -199,27 +200,27 @@ static void rkvop_mode_set(struct udevice *dev,
writel(V_HSYNC(hsync_len) |
V_HORPRD(hsync_len + hback_porch + hactive + hfront_porch),
- &regs->dsp_htotal_hs_end);
+ &dsp_regs->dsp_htotal_hs_end);
writel(V_HEAP(hsync_len + hback_porch + hactive) |
V_HASP(hsync_len + hback_porch),
- &regs->dsp_hact_st_end);
+ &dsp_regs->dsp_hact_st_end);
writel(V_VSYNC(vsync_len) |
V_VERPRD(vsync_len + vback_porch + vactive + vfront_porch),
- &regs->dsp_vtotal_vs_end);
+ &dsp_regs->dsp_vtotal_vs_end);
writel(V_VAEP(vsync_len + vback_porch + vactive)|
V_VASP(vsync_len + vback_porch),
- &regs->dsp_vact_st_end);
+ &dsp_regs->dsp_vact_st_end);
writel(V_HEAP(hsync_len + hback_porch + hactive) |
V_HASP(hsync_len + hback_porch),
- &regs->post_dsp_hact_info);
+ &dsp_regs->post_dsp_hact_info);
writel(V_VAEP(vsync_len + vback_porch + vactive)|
V_VASP(vsync_len + vback_porch),
- &regs->post_dsp_vact_info);
+ &dsp_regs->post_dsp_vact_info);
writel(0x01, &regs->reg_cfg_done); /* enable reg config */
}
diff --git a/drivers/video/rockchip/rk_vop.h b/drivers/video/rockchip/rk_vop.h
index 909f5602e53..7d2581d6a78 100644
--- a/drivers/video/rockchip/rk_vop.h
+++ b/drivers/video/rockchip/rk_vop.h
@@ -11,6 +11,7 @@
struct rk_vop_priv {
void *grf;
void *regs;
+ int dsp_offset;
int win_offset;
};
@@ -19,6 +20,7 @@ enum vop_features {
};
struct rkvop_driverdata {
+ int dsp_offset;
int win_offset;
/* configuration */
u32 features;

View File

@ -0,0 +1,239 @@
From db428dbc58ba2788fb13d4bf1985f0540fd7f4b3 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Tue, 30 Apr 2024 22:09:57 +0200
Subject: [PATCH] video: dw_hdmi: Add Vendor PHY handling
original work by Jagan Teki
---
drivers/video/dw_hdmi.c | 46 +++++++++++++++++++++++++++-
drivers/video/meson/meson_dw_hdmi.c | 11 ++++++-
drivers/video/rockchip/rk3399_hdmi.c | 8 ++++-
drivers/video/rockchip/rk_hdmi.c | 2 +-
drivers/video/rockchip/rk_hdmi.h | 3 ++
drivers/video/sunxi/sunxi_dw_hdmi.c | 11 ++++++-
include/dw_hdmi.h | 14 ++++++++-
7 files changed, 89 insertions(+), 6 deletions(-)
diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index c4fbb18294..fc8c8bb366 100644
--- a/drivers/video/dw_hdmi.c
+++ b/drivers/video/dw_hdmi.c
@@ -988,7 +988,7 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
hdmi_av_composer(hdmi, edid);
- ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
+ ret = hdmi->ops->phy_set(hdmi, edid->pixelclock.typ);
if (ret)
return ret;
@@ -1009,10 +1009,54 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
return 0;
}
+static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
+ .phy_set = dw_hdmi_phy_cfg,
+};
+
+static void dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
+{
+ if (!hdmi->data)
+ return;
+
+ /* hook Synopsys PHYs ops */
+ if (!hdmi->data->phy_force_vendor) {
+ hdmi->ops = &dw_hdmi_synopsys_phy_ops;
+ return;
+ }
+
+ /* Vendor HDMI PHYs must assign phy_ops in plat_data */
+ if (!hdmi->data->phy_ops) {
+ printf("Unsupported Vendor HDMI phy_ops\n");
+ return;
+ }
+
+ /* hook Vendor HDMI PHYs ops */
+ hdmi->ops = hdmi->data->phy_ops;
+}
+
+int dw_hdmi_disable(struct dw_hdmi *hdmi)
+{
+ uint clkdis;
+
+ /* disable pixel clock and tmds data path */
+ clkdis = 0x7f;
+ hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
+
+ /* disable phy */
+ hdmi_phy_sel_interface_control(hdmi, 0);
+ hdmi_phy_enable_tmds(hdmi, 0);
+ hdmi_phy_enable_power(hdmi, 0);
+
+ return 0;
+
+}
+
void dw_hdmi_init(struct dw_hdmi *hdmi)
{
uint ih_mute;
+ dw_hdmi_detect_phy(hdmi);
+
/*
* boot up defaults are:
* hdmi_ih_mute = 0x03 (disabled)
diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
index 5db01904b5..d0d878b6af 100644
--- a/drivers/video/meson/meson_dw_hdmi.c
+++ b/drivers/video/meson/meson_dw_hdmi.c
@@ -375,6 +375,15 @@ static int meson_dw_hdmi_wait_hpd(struct dw_hdmi *hdmi)
return -ETIMEDOUT;
}
+static const struct dw_hdmi_phy_ops dw_hdmi_meson_phy_ops = {
+ .phy_set = meson_dw_hdmi_phy_init,
+};
+
+static const struct dw_hdmi_plat_data dw_hdmi_meson_plat_data = {
+ .phy_force_vendor = true,
+ .phy_ops = &dw_hdmi_meson_phy_ops,
+};
+
static int meson_dw_hdmi_probe(struct udevice *dev)
{
struct meson_dw_hdmi *priv = dev_get_priv(dev);
@@ -397,7 +406,7 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
- priv->hdmi.phy_set = meson_dw_hdmi_phy_init;
+ priv->hdmi.data = &dw_hdmi_meson_plat_data;
if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
priv->hdmi.reg_io_width = 1;
else {
diff --git a/drivers/video/rockchip/rk3399_hdmi.c b/drivers/video/rockchip/rk3399_hdmi.c
index 3041360c6e..b32139a8a6 100644
--- a/drivers/video/rockchip/rk3399_hdmi.c
+++ b/drivers/video/rockchip/rk3399_hdmi.c
@@ -64,8 +64,14 @@ static const struct dm_display_ops rk3399_hdmi_ops = {
.enable = rk3399_hdmi_enable,
};
+static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
+};
+
static const struct udevice_id rk3399_hdmi_ids[] = {
- { .compatible = "rockchip,rk3399-dw-hdmi" },
+ {
+ .compatible = "rockchip,rk3399-dw-hdmi",
+ .data = (ulong)&rk3399_hdmi_drv_data
+ },
{ }
};
diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
index 8dcd4d5964..e545d69e3b 100644
--- a/drivers/video/rockchip/rk_hdmi.c
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -83,6 +83,7 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
struct rk_hdmi_priv *priv = dev_get_priv(dev);
struct dw_hdmi *hdmi = &priv->hdmi;
+ hdmi->data = (const struct dw_hdmi_plat_data *)dev_get_driver_data(dev);
hdmi->ioaddr = (ulong)dev_read_addr(dev);
hdmi->mpll_cfg = rockchip_mpll_cfg;
hdmi->phy_cfg = rockchip_phy_config;
@@ -90,7 +91,6 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
/* hdmi->i2c_clk_{high,low} are set up by the SoC driver */
hdmi->reg_io_width = 4;
- hdmi->phy_set = dw_hdmi_phy_cfg;
priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
diff --git a/drivers/video/rockchip/rk_hdmi.h b/drivers/video/rockchip/rk_hdmi.h
index 200dbaea74..dcfba3d3d7 100644
--- a/drivers/video/rockchip/rk_hdmi.h
+++ b/drivers/video/rockchip/rk_hdmi.h
@@ -6,6 +6,8 @@
#ifndef __RK_HDMI_H__
#define __RK_HDMI_H__
+#include <generic-phy.h>
+
struct rkhdmi_driverdata {
/* configuration */
u8 i2c_clk_high;
@@ -19,6 +21,7 @@ struct rkhdmi_driverdata {
struct rk_hdmi_priv {
struct dw_hdmi hdmi;
+ struct phy phy;
void *grf;
};
diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 0324a050d0..f7ecbb923b 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -328,6 +328,15 @@ static int sunxi_dw_hdmi_enable(struct udevice *dev, int panel_bpp,
return 0;
}
+static const struct dw_hdmi_phy_ops dw_hdmi_sunxi_phy_ops = {
+ .phy_set = sunxi_dw_hdmi_phy_cfg,
+};
+
+static const struct dw_hdmi_plat_data dw_hdmi_sunxi_plat_data = {
+ .phy_force_vendor = true,
+ .phy_ops = &dw_hdmi_sunxi_phy_ops,
+};
+
static int sunxi_dw_hdmi_probe(struct udevice *dev)
{
struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
@@ -379,7 +388,7 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
hdmi->i2c_clk_high = 0xd8;
hdmi->i2c_clk_low = 0xfe;
hdmi->reg_io_width = 1;
- hdmi->phy_set = sunxi_dw_hdmi_phy_cfg;
+ hdmi->data = &dw_hdmi_sunxi_plat_data;
ret = reset_get_bulk(dev, &priv->resets);
if (ret)
diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
index 8acae3839f..4ad8b39f84 100644
--- a/include/dw_hdmi.h
+++ b/include/dw_hdmi.h
@@ -534,6 +534,17 @@ struct hdmi_data_info {
struct hdmi_vmode video_mode;
};
+struct dw_hdmi;
+
+struct dw_hdmi_phy_ops {
+ int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
+};
+
+struct dw_hdmi_plat_data {
+ bool phy_force_vendor;
+ const struct dw_hdmi_phy_ops *phy_ops;
+};
+
struct dw_hdmi {
ulong ioaddr;
const struct hdmi_mpll_config *mpll_cfg;
@@ -543,8 +554,9 @@ struct dw_hdmi {
u8 reg_io_width;
struct hdmi_data_info hdmi_data;
struct udevice *ddc_bus;
+ const struct dw_hdmi_phy_ops *ops;
+ const struct dw_hdmi_plat_data *data;
- int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
void (*write_reg)(struct dw_hdmi *hdmi, u8 val, int offset);
u8 (*read_reg)(struct dw_hdmi *hdmi, int offset);
};
--
2.34.1

View File

@ -0,0 +1,193 @@
From d2804380b05b4e8e6557ce7239a1680853dd5258 Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Sat, 18 Feb 2023 00:30:30 +0530
Subject: [PATCH] video: rockchip: hdmi: Detect hpd after controller init
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/rockchip/rk_hdmi.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
index 8dcd4d59645..b75a1744896 100644
--- a/drivers/video/rockchip/rk_hdmi.c
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -112,14 +112,14 @@ int rk_hdmi_probe(struct udevice *dev)
struct dw_hdmi *hdmi = &priv->hdmi;
int ret;
+ dw_hdmi_init(hdmi);
+ dw_hdmi_phy_init(hdmi);
+
ret = dw_hdmi_phy_wait_for_hpd(hdmi);
if (ret < 0) {
debug("hdmi can not get hpd signal\n");
return -1;
}
- dw_hdmi_init(hdmi);
- dw_hdmi_phy_init(hdmi);
-
return 0;
}
From 3569108607b8569c16aa5df540cf35db2bf58b05 Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Sun, 19 Feb 2023 00:20:52 +0530
Subject: [PATCH] video: dw_hdmi: Simplify HPD detection
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/dw_hdmi.c | 13 +++++++++++++
drivers/video/rockchip/rk_hdmi.c | 8 +++-----
drivers/video/sunxi/sunxi_dw_hdmi.c | 8 +++-----
include/dw_hdmi.h | 1 +
4 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index ea12a094074..0a597206f06 100644
--- a/drivers/video/dw_hdmi.c
+++ b/drivers/video/dw_hdmi.c
@@ -936,6 +936,19 @@ int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi)
return -1;
}
+int dw_hdmi_detect_hpd(struct dw_hdmi *hdmi)
+{
+ int ret;
+
+ ret = dw_hdmi_phy_wait_for_hpd(hdmi);
+ if (ret < 0) {
+ debug("hdmi can not get hpd signal\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
void dw_hdmi_phy_init(struct dw_hdmi *hdmi)
{
/* enable phy i2cm done irq */
diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
index e34f532cd68..8a65f2440e4 100644
--- a/drivers/video/rockchip/rk_hdmi.c
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -115,11 +115,9 @@ int rk_hdmi_probe(struct udevice *dev)
dw_hdmi_init(hdmi);
dw_hdmi_phy_init(hdmi);
- ret = dw_hdmi_phy_wait_for_hpd(hdmi);
- if (ret < 0) {
- debug("hdmi can not get hpd signal\n");
- return -1;
- }
+ ret = dw_hdmi_detect_hpd(hdmi);
+ if (ret < 0)
+ return ret;
return 0;
}
diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 46ad9d137b1..6738950fd00 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -347,11 +347,9 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
sunxi_dw_hdmi_phy_init(&priv->hdmi);
- ret = dw_hdmi_phy_wait_for_hpd(&priv->hdmi);
- if (ret < 0) {
- debug("hdmi can not get hpd signal\n");
- return -1;
- }
+ ret = dw_hdmi_detect_hpd(&priv->hdmi);
+ if (ret < 0)
+ return ret;
dw_hdmi_init(&priv->hdmi);
diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
index 4ad8b39f84d..756560e0928 100644
--- a/include/dw_hdmi.h
+++ b/include/dw_hdmi.h
@@ -554,7 +568,9 @@ int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi);
void dw_hdmi_phy_init(struct dw_hdmi *hdmi);
int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid);
+int dw_hdmi_disable(struct dw_hdmi *hdmi);
int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size);
void dw_hdmi_init(struct dw_hdmi *hdmi);
+int dw_hdmi_detect_hpd(struct dw_hdmi *hdmi);
#endif
From 89431ed902443d0c62e88ca71ac31059c413b4bf Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Sun, 19 Feb 2023 00:30:37 +0530
Subject: [PATCH] video: dw_hdmi: Add read_hpd hook
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/dw_hdmi.c | 3 +++
include/dw_hdmi.h | 1 +
2 files changed, 4 insertions(+)
diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index 0a597206f06..172e6b45a60 100644
--- a/drivers/video/dw_hdmi.c
+++ b/drivers/video/dw_hdmi.c
@@ -946,6 +946,9 @@ int dw_hdmi_detect_hpd(struct dw_hdmi *hdmi)
return -ENODEV;
}
+ if (hdmi->ops->read_hpd)
+ hdmi->ops->read_hpd(hdmi, true);
+
return 0;
}
diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
index 756560e0928..d6de472cee8 100644
--- a/include/dw_hdmi.h
+++ b/include/dw_hdmi.h
@@ -538,6 +538,7 @@ struct dw_hdmi;
struct dw_hdmi_phy_ops {
int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
+ void (*read_hpd)(struct dw_hdmi *hdmi, bool hdp_status);
};
struct dw_hdmi_plat_data {
From 40405cb1924f60ff27923d5d11e6558117ced815 Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Sun, 19 Feb 2023 00:33:18 +0530
Subject: [PATCH] video: dw_hdmi: Add setup_hpd hook
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/dw_hdmi.c | 3 +++
include/dw_hdmi.h | 1 +
2 files changed, 4 insertions(+)
diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index 172e6b45a60..3e0e20e59ba 100644
--- a/drivers/video/dw_hdmi.c
+++ b/drivers/video/dw_hdmi.c
@@ -1080,4 +1080,7 @@ void dw_hdmi_init(struct dw_hdmi *hdmi)
/* enable i2c client nack % arbitration error irq */
hdmi_write(hdmi, ~0x44, HDMI_I2CM_CTLINT);
+
+ if (hdmi->ops->setup_hpd)
+ hdmi->ops->setup_hpd(hdmi);
}
diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
index d6de472cee8..9a44b9e90c3 100644
--- a/include/dw_hdmi.h
+++ b/include/dw_hdmi.h
@@ -539,6 +539,7 @@ struct dw_hdmi;
struct dw_hdmi_phy_ops {
int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
void (*read_hpd)(struct dw_hdmi *hdmi, bool hdp_status);
+ void (*setup_hpd)(struct dw_hdmi *hdmi);
};
struct dw_hdmi_plat_data {

View File

@ -187,24 +187,4 @@ index 0000000000..6f562d0ed8
+ .remove = rk3328_hdmi_remove,
+ .flags = DM_FLAG_OS_PREPARE
+};
diff --git a/drivers/video/rockchip/rk_hdmi.h b/drivers/video/rockchip/rk_hdmi.h
index 200dbaea740..dcfba3d3d7e 100644
--- a/drivers/video/rockchip/rk_hdmi.h
+++ b/drivers/video/rockchip/rk_hdmi.h
@@ -6,6 +6,8 @@
#ifndef __RK_HDMI_H__
#define __RK_HDMI_H__
+#include <generic-phy.h>
+
struct rkhdmi_driverdata {
/* configuration */
u8 i2c_clk_high;
@@ -19,6 +21,7 @@ struct rkhdmi_driverdata {
struct rk_hdmi_priv {
struct dw_hdmi hdmi;
+ struct phy phy;
void *grf;
};

View File

@ -272,13 +272,13 @@ index b825ff4cf83..195247d9e02 100644
+ case ACLK_VOP_PRE:
+ rk_clrsetreg(&cru->clksel_con[39],
+ ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
+ ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT |
+ ACLK_VOP_PLL_SEL_GPLL << ACLK_VOP_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT);
+ break;
+ case ACLK_VIO_PRE:
+ rk_clrsetreg(&cru->clksel_con[37],
+ ACLK_VIO_PLL_SEL_MASK | ACLK_VIO_DIV_CON_MASK,
+ ACLK_VIO_PLL_SEL_CPLL << ACLK_VIO_PLL_SEL_SHIFT |
+ ACLK_VIO_PLL_SEL_GPLL << ACLK_VIO_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << ACLK_VIO_DIV_CON_SHIFT);
+ break;
+ case DCLK_LCDC:

View File

@ -44,10 +44,10 @@ index a236877234b..800d5c61ef2 100644
obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
new file mode 100644
index 0000000000..99cf174214
index 0000000000..207bb0acf6
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -0,0 +1,759 @@
@@ -0,0 +1,989 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Rockchip Innosilicon HDMI PHY
@ -72,118 +72,97 @@ index 0000000000..99cf174214
+#define PRE_PLL_REFCLK_SEL_PCLK BIT(0)
+#define PRE_PLL_REFCLK_SEL_OSCCLK 0
+/* REG: 0x01 */
+#define BYPASS_RXSENSE_EN_MASK BIT(2)
+#define BYPASS_RXSENSE_EN BIT(2)
+#define BYPASS_PWRON_EN_MASK BIT(1)
+#define BYPASS_PWRON_EN BIT(1)
+#define BYPASS_PLLPD_EN_MASK BIT(0)
+#define BYPASS_PLLPD_EN BIT(0)
+/* REG: 0x02 */
+#define BYPASS_PDATA_EN_MASK BIT(4)
+#define INT_POL_HIGH BIT(7)
+#define BYPASS_PDATA_EN BIT(4)
+#define PDATAEN_MASK BIT(0)
+#define PDATAEN_DISABLE BIT(0)
+#define PDATAEN_ENABLE 0
+#define RK3328_PDATA_EN BIT(0)
+#define RK3228_PDATA_EN_DISABLE BIT(0)
+/* REG: 0x03 */
+#define BYPASS_AUTO_TERM_RES_CAL BIT(7)
+#define AUDO_TERM_RES_CAL_SPEED_14_8(x) UPDATE(x, 6, 0)
+/* REG: 0x04 */
+#define AUDO_TERM_RES_CAL_SPEED_7_0(x) UPDATE(x, 7, 0)
+/* REG: 0xaa */
+#define POST_PLL_CTRL_MASK BIT(0)
+#define POST_PLL_CTRL_MANUAL BIT(0)
+/* REG: 0xe0 */
+#define POST_PLL_POWER_MASK BIT(5)
+#define POST_PLL_POWER_DOWN BIT(5)
+#define POST_PLL_POWER_UP 0
+#define PRE_PLL_POWER_MASK BIT(4)
+#define PRE_PLL_POWER_DOWN BIT(4)
+#define PRE_PLL_POWER_UP 0
+#define RXSENSE_CLK_CH_MASK BIT(3)
+#define RXSENSE_CLK_CH_ENABLE BIT(3)
+#define RXSENSE_DATA_CH2_MASK BIT(2)
+#define RXSENSE_DATA_CH2_ENABLE BIT(2)
+#define RXSENSE_DATA_CH1_MASK BIT(1)
+#define RXSENSE_DATA_CH1_ENABLE BIT(1)
+#define RXSENSE_DATA_CH0_MASK BIT(0)
+#define RXSENSE_DATA_CH0_ENABLE BIT(0)
+#define RK3228_POST_PLL_POWER_DOWN BIT(5)
+#define RK3228_POST_PLL_POWER_UP 0
+#define RK3228_PRE_PLL_POWER_DOWN BIT(4)
+#define RK3228_RXSENSE_CLK_CH_MASK BIT(3)
+#define RK3228_RXSENSE_CLK_CH_ENABLE BIT(3)
+#define RK3228_RXSENSE_DATA_CH2_MASK BIT(2)
+#define RK3228_RXSENSE_DATA_CH2_ENABLE BIT(2)
+#define RK3228_RXSENSE_DATA_CH1_MASK BIT(1)
+#define RK3228_RXSENSE_DATA_CH1_ENABLE BIT(1)
+#define RK3228_RXSENSE_DATA_CH0_MASK BIT(0)
+#define RK3228_RXSENSE_DATA_CH0_ENABLE BIT(0)
+/* REG: 0xe1 */
+#define BANDGAP_MASK BIT(4)
+#define BANDGAP_ENABLE BIT(4)
+#define BANDGAP_DISABLE 0
+#define TMDS_DRIVER_MASK GENMASK(3, 0)
+#define TMDS_DRIVER_ENABLE UPDATE(0xf, 3, 0)
+#define TMDS_DRIVER_DISABLE 0
+#define RK3228_BANDGAP_ENABLE BIT(4)
+#define RK3228_TMDS_DRIVER_ENABLE GENMASK(3, 0)
+/* REG: 0xe2 */
+#define PRE_PLL_FB_DIV_8_MASK BIT(7)
+#define PRE_PLL_FB_DIV_8_SHIFT 7
+#define PRE_PLL_FB_DIV_8(x) UPDATE(x, 7, 7)
+#define PCLK_VCO_DIV_5_MASK BIT(5)
+#define PCLK_VCO_DIV_5_SHIFT 5
+#define PCLK_VCO_DIV_5(x) UPDATE(x, 5, 5)
+#define PRE_PLL_PRE_DIV_MASK GENMASK(4, 0)
+#define PRE_PLL_PRE_DIV(x) UPDATE(x, 4, 0)
+#define RK3228_PRE_PLL_FB_DIV_8_MASK BIT(7)
+#define RK3228_PRE_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7)
+#define RK3228_PCLK_VCO_DIV_5_MASK BIT(5)
+#define RK3228_PCLK_VCO_DIV_5(x) UPDATE(x, 5, 5)
+#define RK3228_PRE_PLL_PRE_DIV_MASK GENMASK(4, 0)
+#define RK3228_PRE_PLL_PRE_DIV(x) UPDATE(x, 4, 0)
+/* REG: 0xe3 */
+#define PRE_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0)
+#define RK3228_PRE_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0)
+/* REG: 0xe4 */
+#define PRE_PLL_PCLK_DIV_B_MASK GENMASK(6, 5)
+#define PRE_PLL_PCLK_DIV_B_SHIFT 5
+#define PRE_PLL_PCLK_DIV_B(x) UPDATE(x, 6, 5)
+#define PRE_PLL_PCLK_DIV_A_MASK GENMASK(4, 0)
+#define PRE_PLL_PCLK_DIV_A_SHIFT 0
+#define PRE_PLL_PCLK_DIV_A(x) UPDATE(x, 4, 0)
+#define RK3228_PRE_PLL_PCLK_DIV_B_MASK GENMASK(6, 5)
+#define RK3228_PRE_PLL_PCLK_DIV_B_SHIFT 5
+#define RK3228_PRE_PLL_PCLK_DIV_B(x) UPDATE(x, 6, 5)
+#define RK3228_PRE_PLL_PCLK_DIV_A_MASK GENMASK(4, 0)
+#define RK3228_PRE_PLL_PCLK_DIV_A(x) UPDATE(x, 4, 0)
+/* REG: 0xe5 */
+#define PRE_PLL_PCLK_DIV_C_MASK GENMASK(6, 5)
+#define PRE_PLL_PCLK_DIV_C_SHIFT 5
+#define PRE_PLL_PCLK_DIV_C(x) UPDATE(x, 6, 5)
+#define PRE_PLL_PCLK_DIV_D_MASK GENMASK(4, 0)
+#define PRE_PLL_PCLK_DIV_D_SHIFT 0
+#define PRE_PLL_PCLK_DIV_D(x) UPDATE(x, 4, 0)
+#define RK3228_PRE_PLL_PCLK_DIV_C_MASK GENMASK(6, 5)
+#define RK3228_PRE_PLL_PCLK_DIV_C(x) UPDATE(x, 6, 5)
+#define RK3228_PRE_PLL_PCLK_DIV_D_MASK GENMASK(4, 0)
+#define RK3228_PRE_PLL_PCLK_DIV_D(x) UPDATE(x, 4, 0)
+/* REG: 0xe6 */
+#define PRE_PLL_TMDSCLK_DIV_C_MASK GENMASK(5, 4)
+#define PRE_PLL_TMDSCLK_DIV_C(x) UPDATE(x, 5, 4)
+#define PRE_PLL_TMDSCLK_DIV_A_MASK GENMASK(3, 2)
+#define PRE_PLL_TMDSCLK_DIV_A(x) UPDATE(x, 3, 2)
+#define PRE_PLL_TMDSCLK_DIV_B_MASK GENMASK(1, 0)
+#define PRE_PLL_TMDSCLK_DIV_B(x) UPDATE(x, 1, 0)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_C_MASK GENMASK(5, 4)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_C(x) UPDATE(x, 5, 4)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_A_MASK GENMASK(3, 2)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_A(x) UPDATE(x, 3, 2)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_B_MASK GENMASK(1, 0)
+#define RK3228_PRE_PLL_TMDSCLK_DIV_B(x) UPDATE(x, 1, 0)
+/* REG: 0xe8 */
+#define PRE_PLL_LOCK_STATUS BIT(0)
+#define RK3228_PRE_PLL_LOCK_STATUS BIT(0)
+/* REG: 0xe9 */
+#define POST_PLL_POST_DIV_EN_MASK GENMASK(7, 6)
+#define POST_PLL_POST_DIV_ENABLE UPDATE(3, 7, 6)
+#define POST_PLL_POST_DIV_DISABLE 0
+#define POST_PLL_PRE_DIV_MASK GENMASK(4, 0)
+#define POST_PLL_PRE_DIV(x) UPDATE(x, 4, 0)
+#define RK3228_POST_PLL_POST_DIV_ENABLE UPDATE(3, 7, 6)
+#define RK3228_POST_PLL_PRE_DIV_MASK GENMASK(4, 0)
+#define RK3228_POST_PLL_PRE_DIV(x) UPDATE(x, 4, 0)
+/* REG: 0xea */
+#define POST_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0)
+#define RK3228_POST_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0)
+/* REG: 0xeb */
+#define POST_PLL_FB_DIV_8_MASK BIT(7)
+#define POST_PLL_FB_DIV_8(x) UPDATE(x, 7, 7)
+#define POST_PLL_POST_DIV_MASK GENMASK(5, 4)
+#define POST_PLL_POST_DIV(x) UPDATE(x, 5, 4)
+#define POST_PLL_LOCK_STATUS BIT(0)
+#define RK3228_POST_PLL_FB_DIV_8_MASK BIT(7)
+#define RK3228_POST_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7)
+#define RK3228_POST_PLL_POST_DIV_MASK GENMASK(5, 4)
+#define RK3228_POST_PLL_POST_DIV(x) UPDATE(x, 5, 4)
+#define RK3228_POST_PLL_LOCK_STATUS BIT(0)
+/* REG: 0xee */
+#define TMDS_CH_TA_MASK GENMASK(7, 4)
+#define TMDS_CH_TA_ENABLE UPDATE(0xf, 7, 4)
+#define TMDS_CH_TA_DISABLE 0
+#define RK3228_TMDS_CH_TA_ENABLE GENMASK(7, 4)
+/* REG: 0xef */
+#define TMDS_CLK_CH_TA(x) UPDATE(x, 7, 6)
+#define TMDS_DATA_CH2_TA(x) UPDATE(x, 5, 4)
+#define TMDS_DATA_CH1_TA(x) UPDATE(x, 3, 2)
+#define TMDS_DATA_CH0_TA(x) UPDATE(x, 1, 0)
+#define RK3228_TMDS_CLK_CH_TA(x) UPDATE(x, 7, 6)
+#define RK3228_TMDS_DATA_CH2_TA(x) UPDATE(x, 5, 4)
+#define RK3228_TMDS_DATA_CH1_TA(x) UPDATE(x, 3, 2)
+#define RK3228_TMDS_DATA_CH0_TA(x) UPDATE(x, 1, 0)
+/* REG: 0xf0 */
+#define TMDS_DATA_CH2_PRE_EMPHASIS_MASK GENMASK(5, 4)
+#define TMDS_DATA_CH2_PRE_EMPHASIS(x) UPDATE(x, 5, 4)
+#define TMDS_DATA_CH1_PRE_EMPHASIS_MASK GENMASK(3, 2)
+#define TMDS_DATA_CH1_PRE_EMPHASIS(x) UPDATE(x, 3, 2)
+#define TMDS_DATA_CH0_PRE_EMPHASIS_MASK GENMASK(1, 0)
+#define TMDS_DATA_CH0_PRE_EMPHASIS(x) UPDATE(x, 1, 0)
+#define RK3228_TMDS_DATA_CH2_PRE_EMPHASIS_MASK GENMASK(5, 4)
+#define RK3228_TMDS_DATA_CH2_PRE_EMPHASIS(x) UPDATE(x, 5, 4)
+#define RK3228_TMDS_DATA_CH1_PRE_EMPHASIS_MASK GENMASK(3, 2)
+#define RK3228_TMDS_DATA_CH1_PRE_EMPHASIS(x) UPDATE(x, 3, 2)
+#define RK3228_TMDS_DATA_CH0_PRE_EMPHASIS_MASK GENMASK(1, 0)
+#define RK3228_TMDS_DATA_CH0_PRE_EMPHASIS(x) UPDATE(x, 1, 0)
+/* REG: 0xf1 */
+#define TMDS_CLK_CH_OUTPUT_SWING(x) UPDATE(x, 7, 4)
+#define TMDS_DATA_CH2_OUTPUT_SWING(x) UPDATE(x, 3, 0)
+#define RK3228_TMDS_CLK_CH_OUTPUT_SWING(x) UPDATE(x, 7, 4)
+#define RK3228_TMDS_DATA_CH2_OUTPUT_SWING(x) UPDATE(x, 3, 0)
+/* REG: 0xf2 */
+#define TMDS_DATA_CH1_OUTPUT_SWING(x) UPDATE(x, 7, 4)
+#define TMDS_DATA_CH0_OUTPUT_SWING(x) UPDATE(x, 3, 0)
+#define RK3228_TMDS_DATA_CH1_OUTPUT_SWING(x) UPDATE(x, 7, 4)
+#define RK3228_TMDS_DATA_CH0_OUTPUT_SWING(x) UPDATE(x, 3, 0)
+
+struct inno_hdmi_phy;
+
@ -226,9 +205,13 @@ index 0000000000..99cf174214
+ const struct pre_pll_config *cfg);
+ unsigned long (*recalc_rate)(struct inno_hdmi_phy *inno,
+ unsigned long parent_rate);
+ int (*clk_is_prepared)(struct inno_hdmi_phy *inno);
+ int (*clk_prepare)(struct inno_hdmi_phy *inno);
+
+};
+
+enum inno_hdmi_phy_type {
+ INNO_HDMI_PHY_RK3228,
+ INNO_HDMI_PHY_RK3328,
+};
+
@ -295,6 +278,26 @@ index 0000000000..99cf174214
+ { ~0UL, 0, 0, 0, 0}
+};
+
+/* phy tuning values for an undocumented set of registers */
+static const struct phy_config rk3228_phy_cfg[] = {
+ { 165000000, {
+ 0xaa, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }, {
+ 340000000, {
+ 0xaa, 0x15, 0x6a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }, {
+ 594000000, {
+ 0xaa, 0x15, 0x7a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }, { /* sentinel */ },
+};
+
+/* phy tuning values for an undocumented set of registers */
+static const struct phy_config rk3328_phy_cfg[] = {
+ { 165000000, {
+ 0x07, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08,
@ -424,20 +427,40 @@ index 0000000000..99cf174214
+ return 0;
+}
+
+static int inno_hdmi_phy_clk_is_prepared(struct inno_hdmi_phy *inno)
+static int inno_hdmi_phy_rk3328_clk_is_prepared(struct inno_hdmi_phy *inno)
+{
+ u8 status = inno_read(inno, 0xa0) & 1;
+
+ return status ? 0 : 1;
+}
+
+static int inno_hdmi_phy_clk_prepare(struct inno_hdmi_phy *inno)
+static int inno_hdmi_phy_rk3328_clk_prepare(struct inno_hdmi_phy *inno)
+{
+ inno_update_bits(inno, 0xa0, 1, 0);
+
+ return 0;
+}
+
+static int inno_hdmi_phy_rk3228_clk_is_prepared(struct inno_hdmi_phy *inno)
+{
+ u8 status = inno_read(inno, 0xe0) & RK3228_PRE_PLL_POWER_DOWN;
+
+ status = status ? 0 : 1;
+
+ debug("%s: status=%d\n", __func__, status);
+
+ return status;
+}
+
+static int inno_hdmi_phy_rk3228_clk_prepare(struct inno_hdmi_phy *inno)
+{
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN, 0);
+
+ debug("%s\n", __func__);
+
+ return 0;
+}
+
+static int inno_hdmi_phy_clk_set_rate(struct inno_hdmi_phy *inno,
+ unsigned long rate)
+{
@ -620,7 +643,7 @@ index 0000000000..99cf174214
+}
+
+static unsigned long
+inno_hdmi_3328_phy_pll_recalc_rate(struct inno_hdmi_phy *inno,
+inno_hdmi_phy_rk3328_pll_recalc_rate(struct inno_hdmi_phy *inno,
+ unsigned long parent_rate)
+{
+ unsigned long rate, vco, frac;
@ -661,8 +684,8 @@ index 0000000000..99cf174214
+ * Use phy internal register control
+ * rxsense/poweron/pllpd/pdataen signal.
+ */
+ inno_write(inno, 0x01, 0x07);
+ inno_write(inno, 0x02, 0x91);
+ inno_write(inno, 0x01, BYPASS_RXSENSE_EN | BYPASS_PWRON_EN | BYPASS_PLLPD_EN);
+ inno_write(inno, 0x02, INT_POL_HIGH | BYPASS_PDATA_EN | RK3328_PDATA_EN);
+ debug("[PHY] %s: done!\n", __func__);
+}
+
@ -671,7 +694,197 @@ index 0000000000..99cf174214
+ .power_on = inno_hdmi_phy_rk3328_power_on,
+ .power_off = inno_hdmi_phy_rk3328_power_off,
+ .pre_pll_update = inno_hdmi_phy_rk3328_pre_pll_update,
+ .recalc_rate = inno_hdmi_3328_phy_pll_recalc_rate,
+ .recalc_rate = inno_hdmi_phy_rk3328_pll_recalc_rate,
+ .clk_is_prepared = inno_hdmi_phy_rk3328_clk_is_prepared,
+ .clk_prepare = inno_hdmi_phy_rk3328_clk_prepare
+};
+
+static void inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno)
+{
+ debug("[PHY] %s: In?\n", __func__);
+ /*
+ * Use phy internal register control
+ * rxsense/poweron/pllpd/pdataen signal.
+ */
+ inno_write(inno, 0x01, BYPASS_RXSENSE_EN | BYPASS_PWRON_EN | BYPASS_PLLPD_EN);
+ inno_update_bits(inno, 0x02, BYPASS_PDATA_EN, BYPASS_PDATA_EN);
+
+ /* manual power down post-PLL */
+ inno_update_bits(inno, 0xaa, POST_PLL_CTRL_MANUAL, POST_PLL_CTRL_MANUAL);
+
+ debug("[PHY] %s: done!\n", __func__);
+}
+
+static int
+inno_hdmi_phy_rk3228_power_on(struct inno_hdmi_phy *inno,
+ const struct post_pll_config *cfg,
+ const struct phy_config *phy_cfg)
+{
+ u32 val;
+
+ /* set pdata_en to 0 */
+ inno_update_bits(inno, 0x02, RK3228_PDATA_EN_DISABLE, RK3228_PDATA_EN_DISABLE);
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN | RK3228_POST_PLL_POWER_DOWN,
+ RK3228_PRE_PLL_POWER_DOWN | RK3228_POST_PLL_POWER_DOWN);
+
+ /* Post-PLL update */
+ inno_update_bits(inno, 0xe9, RK3228_POST_PLL_PRE_DIV_MASK,
+ RK3228_POST_PLL_PRE_DIV(cfg->prediv));
+ inno_update_bits(inno, 0xeb, RK3228_POST_PLL_FB_DIV_8_MASK,
+ RK3228_POST_PLL_FB_DIV_8(cfg->fbdiv));
+ inno_write(inno, 0xea, RK3228_POST_PLL_FB_DIV_7_0(cfg->fbdiv));
+
+ if (cfg->postdiv == 1) {
+ inno_update_bits(inno, 0xe9, RK3228_POST_PLL_POST_DIV_ENABLE, 0);
+ } else {
+ int div = cfg->postdiv / 2 - 1;
+
+ inno_update_bits(inno, 0xe9, RK3228_POST_PLL_POST_DIV_ENABLE,
+ RK3228_POST_PLL_POST_DIV_ENABLE);
+ inno_update_bits(inno, 0xeb, RK3228_POST_PLL_POST_DIV_MASK,
+ RK3228_POST_PLL_POST_DIV(div));
+ }
+
+ for (val = 0; val < 4; val++)
+ inno_write(inno, 0xef + val, phy_cfg->regs[val]);
+
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN |
+ RK3228_POST_PLL_POWER_DOWN, 0);
+ inno_update_bits(inno, 0xe1, RK3228_BANDGAP_ENABLE,
+ RK3228_BANDGAP_ENABLE);
+ inno_update_bits(inno, 0xe1, RK3228_TMDS_DRIVER_ENABLE,
+ RK3228_TMDS_DRIVER_ENABLE);
+
+ /* Wait for post PLL lock, up to 100ms */
+ for (val = 0; val < 100; val++) {
+ if (inno_read(inno, 0xeb) & RK3228_POST_PLL_LOCK_STATUS)
+ break;
+ udelay(1000);
+ }
+
+ if (!(inno_read(inno, 0xeb) & RK3228_POST_PLL_LOCK_STATUS)) {
+ printf("%s: HDMI PHY Post PLL unlock\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ if (phy_cfg->tmdsclock > 340000000)
+ mdelay(100);
+
+ /* set pdata_en_disable to 0 */
+ inno_update_bits(inno, 0x02, RK3228_PDATA_EN_DISABLE, 0);
+
+ return 0;
+}
+
+static void inno_hdmi_phy_rk3228_power_off(struct inno_hdmi_phy *inno)
+{
+
+ debug("%s\n", __func__);
+
+ inno_update_bits(inno, 0xe1, RK3228_TMDS_DRIVER_ENABLE, 0);
+ inno_update_bits(inno, 0xe1, RK3228_BANDGAP_ENABLE, 0);
+ inno_update_bits(inno, 0xe0, RK3228_POST_PLL_POWER_DOWN,
+ RK3228_POST_PLL_POWER_DOWN);
+}
+
+static unsigned long
+inno_hdmi_phy_rk3228_pll_recalc_rate(struct inno_hdmi_phy *inno,
+ unsigned long parent_rate)
+{
+ u64 rate, vco;
+ u8 nd, no_a, no_b, no_d;
+ __maybe_unused u8 no_c;
+ u16 nf;
+
+ nd = inno_read(inno, 0xe2) & RK3228_PRE_PLL_PRE_DIV_MASK;
+ nf = (inno_read(inno, 0xe2) & RK3228_PRE_PLL_FB_DIV_8_MASK) << 1;
+ nf |= inno_read(inno, 0xe3);
+ vco = parent_rate * nf;
+
+ if (inno_read(inno, 0xe2) & RK3228_PCLK_VCO_DIV_5_MASK) {
+ rate = vco / (nd * 5);
+ } else {
+ no_a = inno_read(inno, 0xe4) & RK3228_PRE_PLL_PCLK_DIV_A_MASK;
+ if (!no_a)
+ no_a = 1;
+ no_b = inno_read(inno, 0xe4) & RK3228_PRE_PLL_PCLK_DIV_B_MASK;
+ no_b >>= RK3228_PRE_PLL_PCLK_DIV_B_SHIFT;
+ no_b += 2;
+ no_d = inno_read(inno, 0xe5) & RK3228_PRE_PLL_PCLK_DIV_D_MASK;
+
+ if (no_a == 1)
+ rate = vco / (nd * no_b * no_d * 2);
+ else
+ rate = vco / (nd * no_a * no_d * 2);
+
+ }
+
+ inno->pixclock = rate;
+
+ debug("%s, pixclock=%llu\n", __func__, rate);
+
+ return rate;
+}
+
+static int
+inno_hdmi_phy_rk3228_pre_pll_update(struct inno_hdmi_phy *inno,
+ const struct pre_pll_config *cfg)
+{
+ u32 val;
+
+ debug("%s\n", __func__);
+
+ /* Power down PRE-PLL */
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN,
+ RK3228_PRE_PLL_POWER_DOWN);
+
+ inno_update_bits(inno, 0xe2, RK3228_PRE_PLL_FB_DIV_8_MASK |
+ RK3228_PCLK_VCO_DIV_5_MASK |
+ RK3228_PRE_PLL_PRE_DIV_MASK,
+ RK3228_PRE_PLL_FB_DIV_8(cfg->fbdiv) |
+ RK3228_PCLK_VCO_DIV_5(cfg->vco_div_5_en) |
+ RK3228_PRE_PLL_PRE_DIV(cfg->prediv));
+ inno_write(inno, 0xe3, RK3228_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
+ inno_update_bits(inno, 0xe4, RK3228_PRE_PLL_PCLK_DIV_B_MASK |
+ RK3228_PRE_PLL_PCLK_DIV_A_MASK,
+ RK3228_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b) |
+ RK3228_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a));
+ inno_update_bits(inno, 0xe5, RK3228_PRE_PLL_PCLK_DIV_C_MASK |
+ RK3228_PRE_PLL_PCLK_DIV_D_MASK,
+ RK3228_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
+ RK3228_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d));
+ inno_update_bits(inno, 0xe6, RK3228_PRE_PLL_TMDSCLK_DIV_C_MASK |
+ RK3228_PRE_PLL_TMDSCLK_DIV_A_MASK |
+ RK3228_PRE_PLL_TMDSCLK_DIV_B_MASK,
+ RK3228_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
+ RK3228_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
+ RK3228_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b));
+
+ /* Power up PRE-PLL */
+ inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN, 0);
+
+ /* Wait for PLL lock, up to 100ms*/
+ for (val = 0; val < 100; val++) {
+ if (inno_read(inno, 0xe8) & RK3228_PRE_PLL_LOCK_STATUS)
+ break;
+ udelay(1000);
+ }
+ if (!(inno_read(inno, 0xe8) & RK3228_PRE_PLL_LOCK_STATUS)) {
+ printf("%s, failed to lock Pre-PLL, left unlocked\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static const struct inno_hdmi_phy_plat_ops rk3228_hdmi_phy_plat_ops = {
+ .init = inno_hdmi_phy_rk3228_init,
+ .power_on = inno_hdmi_phy_rk3228_power_on,
+ .power_off = inno_hdmi_phy_rk3228_power_off,
+ .pre_pll_update = inno_hdmi_phy_rk3228_pre_pll_update,
+ .recalc_rate = inno_hdmi_phy_rk3228_pll_recalc_rate,
+ .clk_is_prepared = inno_hdmi_phy_rk3228_clk_is_prepared,
+ .clk_prepare = inno_hdmi_phy_rk3228_clk_prepare
+};
+
+static unsigned long inno_hdmi_phy_set_pll(struct phy *phy,
@ -680,10 +893,17 @@ index 0000000000..99cf174214
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+
+ debug("[PHY] %s: In?\n", __func__);
+ inno_hdmi_phy_clk_prepare(inno);
+ inno_hdmi_phy_clk_is_prepared(inno);
+
+ if (inno->data->plat_ops->clk_prepare)
+ inno->data->plat_ops->clk_prepare(inno);
+
+ if (inno->data->plat_ops->clk_is_prepared)
+ inno->data->plat_ops->clk_is_prepared(inno);
+
+ inno_hdmi_phy_clk_set_rate(inno, rate);
+
+ debug("[PHY] %s: done!\n", __func__);
+
+ return 0;
+}
+
@ -791,8 +1011,18 @@ index 0000000000..99cf174214
+ .phy_cfg_table = rk3328_phy_cfg,
+};
+
+static const struct inno_hdmi_phy_data rk3228_inno_hdmi_phy_drv_data = {
+ .phy_type = INNO_HDMI_PHY_RK3228,
+ .plat_ops = &rk3228_hdmi_phy_plat_ops,
+ .phy_cfg_table = rk3228_phy_cfg,
+};
+
+static const struct udevice_id inno_hdmi_phy_ids[] = {
+ {
+ .compatible = "rockchip,rk3228-hdmi-phy",
+ .data = (ulong)&rk3228_inno_hdmi_phy_drv_data,
+ },
+ {
+ .compatible = "rockchip,rk3328-hdmi-phy",
+ .data = (ulong)&rk3328_inno_hdmi_phy_drv_data,
+ },

View File

@ -0,0 +1,30 @@
From ac3f6f2e9cbe96d11a0db2801699669b2941cd09 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Mon, 29 Apr 2024 16:17:17 +0200
Subject: [PATCH 1/4] fix borked DWC2 OTG driver
---
drivers/usb/gadget/dwc2_udc_otg_phy.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg_phy.c b/drivers/usb/gadget/dwc2_udc_otg_phy.c
index 7f8e9564b9..e87f8b5e47 100644
--- a/drivers/usb/gadget/dwc2_udc_otg_phy.c
+++ b/drivers/usb/gadget/dwc2_udc_otg_phy.c
@@ -59,12 +59,7 @@ void otg_phy_init(struct dwc2_udc *dev)
writel((readl(&phy->phypwr) &~(OTG_DISABLE_0 | ANALOG_PWRDOWN)
&~FORCE_SUSPEND_0), &phy->phypwr);
- if (s5p_cpu_id == 0x4412)
- writel((readl(&phy->phyclk) & ~(EXYNOS4X12_ID_PULLUP0 |
- EXYNOS4X12_COMMON_ON_N0)) | EXYNOS4X12_CLK_SEL_24MHZ,
- &phy->phyclk); /* PLL 24Mhz */
- else
- writel((readl(&phy->phyclk) & ~(ID_PULLUP0 | COMMON_ON_N0)) |
+ writel((readl(&phy->phyclk) & ~(ID_PULLUP0 | COMMON_ON_N0)) |
CLK_SEL_24MHZ, &phy->phyclk); /* PLL 24Mhz */
writel((readl(&phy->rstcon) &~(LINK_SW_RST | PHYLNK_SW_RST))
--
2.34.1