rockchip64: bump rk3318-box uboot to v2024.01

* bump uboot version to v2024.01
 * add hdmi, vop driver for rk3328, enable hdmi
 * add inno hdmi phy driver
This commit is contained in:
Paolo Sabatino 2024-04-21 16:11:06 +02:00 committed by Paolo
parent 3f928f799c
commit efee17f217
15 changed files with 4133 additions and 2 deletions

View File

@ -1,17 +1,31 @@
# Rockchip RK3318 quad core 2/16Gb 1xETH USB3 WiFi
BOARD_NAME="RK3318 Box"
BOARDFAMILY="rockchip64"
BOARD_MAINTAINER=""
BOARD_MAINTAINER="jock"
BOOTCONFIG="rk3318-box_defconfig"
BOOT_FDT_FILE="rockchip/rk3318-box.dtb"
KERNEL_TARGET="current,edge"
MODULES_BLACKLIST="analogix_dp bcmdhd"
BOOT_SCENARIO="tpl-blob-atf-mainline"
DDR_BLOB="rk33/rk3318_ddr_333Mhz_v1.16.bin"
BOOT_SOC="rk3328"
BOOTBRANCH_BOARD="tag:v2024.01"
BOOTPATCHDIR="v2024.01"
enable_extension xorg-lima-serverflags
# Change the u-boot command line; rockchip64 uses v2022.07
# but rk3318-box uses v2024.01. binman is already configured
# to produce idbloader.img and u-boot.itb, so there is no
# need anymore to specify those on the command line
function post_family_config__uboot_cmdline() {
BOOTDELAY=1
UBOOT_TARGET_MAP="BL31=bl31.elf;;idbloader.img u-boot.itb"
}
function post_family_tweaks_bsp__rk3318-box() {
display_alert "Installing BSP firmware and fixups"

View File

@ -0,0 +1,784 @@
From 42a891d30cd2c4c00ee674738128c03277d2d5f8 Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Thu, 16 Feb 2023 21:59:42 +0530
Subject: [PATCH] phy: rockchip: Add Rockchip INNO HDMI PHY driver
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
drivers/phy/rockchip/Kconfig | 7 +
drivers/phy/rockchip/Makefile | 1 +
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 734 ++++++++++++++++++
3 files changed, 742 insertions(+)
create mode 100644 drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 13057639403..4809c436c17 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -4,6 +4,13 @@
menu "Rockchip PHY driver"
+config PHY_ROCKCHIP_INNO_HDMI
+ bool "Rockchip INNO HDMI PHY Driver"
+ depends on ARCH_ROCKCHIP
+ select PHY
+ help
+ Enable this to support the Rockchip Innosilicon HDMI PHY.
+
config PHY_ROCKCHIP_INNO_USB2
bool "Rockchip INNO USB2PHY Driver"
depends on ARCH_ROCKCHIP
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
index a236877234b..800d5c61ef2 100644
--- a/drivers/phy/rockchip/Makefile
+++ b/drivers/phy/rockchip/Makefile
@@ -3,6 +3,7 @@
# Copyright (C) 2020 Amarula Solutions(India)
#
+obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY) += phy-rockchip-naneng-combphy.o
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 00000000000..f9f54c5ff82
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -0,0 +1,734 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Rockchip Innosilicon HDMI PHY
+ *
+ * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd.
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <generic-phy.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+
+#define INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT 1000
+#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
+
+/* REG: 0x00 */
+#define PRE_PLL_REFCLK_SEL_MASK BIT(0)
+#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 BYPASS_PDATA_EN BIT(4)
+#define PDATAEN_MASK BIT(0)
+#define PDATAEN_DISABLE BIT(0)
+#define PDATAEN_ENABLE 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)
+/* 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
+/* 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)
+/* REG: 0xe3 */
+#define 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)
+/* 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)
+/* 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)
+/* REG: 0xe8 */
+#define 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)
+/* REG: 0xea */
+#define 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)
+/* 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
+/* 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)
+/* 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)
+/* REG: 0xf1 */
+#define TMDS_CLK_CH_OUTPUT_SWING(x) UPDATE(x, 7, 4)
+#define 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)
+
+struct inno_hdmi_phy;
+
+struct phy_config {
+ unsigned long tmdsclock;
+ u8 regs[14];
+};
+
+struct pre_pll_config {
+ unsigned long pixclock;
+ unsigned long tmdsclock;
+ u8 prediv;
+ u16 fbdiv;
+ u8 tmds_div_a;
+ u8 tmds_div_b;
+ u8 tmds_div_c;
+ u8 pclk_div_a;
+ u8 pclk_div_b;
+ u8 pclk_div_c;
+ u8 pclk_div_d;
+ u8 vco_div_5_en;
+ u32 fracdiv;
+};
+
+struct post_pll_config {
+ unsigned long tmdsclock;
+ u8 prediv;
+ u16 fbdiv;
+ u8 postdiv;
+ u8 version;
+};
+
+struct inno_hdmi_phy_plat_ops {
+ void (*init)(struct inno_hdmi_phy *inno);
+ int (*power_on)(struct inno_hdmi_phy *inno,
+ const struct post_pll_config *cfg,
+ const struct phy_config *phy_cfg);
+ void (*power_off)(struct inno_hdmi_phy *inno);
+ int (*pre_pll_update)(struct inno_hdmi_phy *inno,
+ const struct pre_pll_config *cfg);
+ unsigned long (*recalc_rate)(struct inno_hdmi_phy *inno,
+ unsigned long parent_rate);
+};
+
+enum inno_hdmi_phy_type {
+ INNO_HDMI_PHY_RK3328,
+};
+
+struct inno_hdmi_phy_data {
+ enum inno_hdmi_phy_type phy_type;
+ const struct inno_hdmi_phy_plat_ops *plat_ops;
+ const struct phy_config *phy_cfg_table;
+};
+
+struct rockchip_inno_data {
+ char compatible[30];
+ const void *data;
+};
+
+struct inno_hdmi_phy {
+ struct udevice *dev;
+ ofnode node;
+ void *regs;
+
+ unsigned long pixclock;
+ u32 bus_width;
+ struct phy_config *phy_cfg;
+ const struct inno_hdmi_phy_data *data;
+};
+
+static const struct pre_pll_config pre_pll_cfg_table[] = {
+ { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0},
+ { 27000000, 33750000, 1, 90, 1, 3, 3, 10, 3, 3, 4, 0, 0},
+ { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0},
+ { 59341000, 59341000, 1, 98, 3, 1, 2, 1, 3, 3, 4, 0, 0xE6AE6B},
+ { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0},
+ { 59341000, 74176250, 1, 98, 0, 3, 3, 1, 3, 3, 4, 0, 0xE6AE6B},
+ { 59400000, 74250000, 1, 99, 1, 2, 2, 1, 3, 3, 4, 0, 0},
+ { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B},
+ { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0},
+ { 74176000, 92720000, 4, 494, 1, 2, 2, 1, 3, 3, 4, 0, 0x816817},
+ { 74250000, 92812500, 4, 495, 1, 2, 2, 1, 3, 3, 4, 0, 0},
+ {148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B},
+ {148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0},
+ {148352000, 185440000, 4, 494, 0, 2, 2, 1, 3, 2, 2, 0, 0x816817},
+ {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0},
+ {296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B},
+ {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0},
+ {296703000, 370878750, 4, 494, 1, 2, 0, 1, 3, 1, 1, 0, 0x816817},
+ {297000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 0, 0},
+ {593407000, 296703500, 1, 98, 0, 1, 1, 1, 0, 2, 1, 0, 0xE6AE6B},
+ {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 1, 0, 0},
+ {593407000, 370879375, 4, 494, 1, 2, 0, 1, 3, 1, 1, 1, 0x816817},
+ {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0},
+ {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B},
+ {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0},
+ { ~0UL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+static const struct post_pll_config post_pll_cfg_table[] = {
+ {33750000, 1, 40, 8, 1},
+ {33750000, 1, 80, 8, 2},
+ {33750000, 1, 10, 2, 4},
+ {74250000, 1, 40, 8, 1},
+ {74250000, 18, 80, 8, 2},
+ {148500000, 2, 40, 4, 3},
+ {297000000, 4, 40, 2, 3},
+ {594000000, 8, 40, 1, 3},
+ { ~0UL, 0, 0, 0, 0}
+};
+
+static const struct phy_config rk3328_phy_cfg[] = {
+ { 165000000, {
+ 0x07, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08,
+ 0x00, 0xac, 0xcc, 0xcc, 0xcc,
+ },
+ }, {
+ 340000000, {
+ 0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08,
+ 0x3f, 0xac, 0xcc, 0xcd, 0xdd,
+ },
+ }, {
+ 594000000, {
+ 0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
+ 0x00, 0xac, 0xcc, 0xcc, 0xcc,
+ },
+ }, {
+ ~0UL, {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }
+};
+
+static inline void inno_write(struct inno_hdmi_phy *inno, u32 reg, u8 val)
+{
+ writel(val, inno->regs + (reg * 4));
+}
+
+static inline u8 inno_read(struct inno_hdmi_phy *inno, u32 reg)
+{
+ u32 val;
+
+ val = readl(inno->regs + (reg * 4));
+
+ return val;
+}
+
+static inline void inno_update_bits(struct inno_hdmi_phy *inno, u8 reg,
+ u8 mask, u8 val)
+{
+ u32 tmp, orig;
+
+ orig = inno_read(inno, reg);
+ tmp = orig & ~mask;
+ tmp |= val & mask;
+ inno_write(inno, reg, tmp);
+}
+
+static u32 inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno,
+ unsigned long rate)
+{
+ u32 tmdsclk;
+
+ switch (inno->bus_width) {
+ case 4:
+ tmdsclk = (u32)rate / 2;
+ break;
+ case 5:
+ tmdsclk = (u32)rate * 5 / 8;
+ break;
+ case 6:
+ tmdsclk = (u32)rate * 3 / 4;
+ break;
+ case 10:
+ tmdsclk = (u32)rate * 5 / 4;
+ break;
+ case 12:
+ tmdsclk = (u32)rate * 3 / 2;
+ break;
+ case 16:
+ tmdsclk = (u32)rate * 2;
+ break;
+ default:
+ tmdsclk = rate;
+ }
+
+ return tmdsclk;
+}
+
+static int inno_hdmi_phy_power_on(struct phy *phy)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+ const struct post_pll_config *cfg = post_pll_cfg_table;
+ const struct phy_config *phy_cfg = inno->data->phy_cfg_table;
+ u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, inno->pixclock);
+ u32 chipversion = 1;
+
+ debug("[PHY] %s: In?\n", __func__);
+
+ if (inno->phy_cfg)
+ phy_cfg = inno->phy_cfg;
+
+ if (!tmdsclock) {
+ printf("TMDS clock is zero!\n");
+ return -EINVAL;
+ }
+
+ printf("tmdsclock = %d; chipversion = %d\n", tmdsclock, chipversion);
+
+ for (; cfg->tmdsclock != ~0UL; cfg++)
+ if (tmdsclock <= cfg->tmdsclock &&
+ cfg->version & chipversion)
+ break;
+
+ for (; phy_cfg->tmdsclock != ~0UL; phy_cfg++)
+ if (tmdsclock <= phy_cfg->tmdsclock)
+ break;
+
+ if (cfg->tmdsclock == ~0UL || phy_cfg->tmdsclock == ~0UL)
+ return -EINVAL;
+
+ debug("Inno HDMI PHY Power On\n");
+ if (inno->data->plat_ops->power_on)
+ return inno->data->plat_ops->power_on(inno, cfg, phy_cfg);
+ else
+ return -EINVAL;
+}
+
+static int inno_hdmi_phy_power_off(struct phy *phy)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+
+ if (inno->data->plat_ops->power_off)
+ inno->data->plat_ops->power_off(inno);
+ debug("Inno HDMI PHY Power Off\n");
+
+ return 0;
+}
+
+static int inno_hdmi_phy_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)
+{
+ inno_update_bits(inno, 0xa0, 1, 0);
+
+ return 0;
+}
+
+static int inno_hdmi_phy_clk_set_rate(struct inno_hdmi_phy *inno,
+ unsigned long rate)
+{
+ const struct pre_pll_config *cfg = pre_pll_cfg_table;
+ u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
+
+ for (; cfg->pixclock != ~0UL; cfg++)
+ if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock)
+ break;
+
+ if (cfg->pixclock == ~0UL) {
+ printf("unsupported rate %lu\n", rate);
+ return -EINVAL;
+ }
+
+ if (inno->data->plat_ops->pre_pll_update)
+ inno->data->plat_ops->pre_pll_update(inno, cfg);
+
+ inno->pixclock = rate;
+
+ return 0;
+}
+
+static int
+inno_hdmi_phy_rk3328_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, 1, 0);
+ /* Power off post PLL */
+ inno_update_bits(inno, 0xaa, 1, 1);
+
+ val = cfg->fbdiv & 0xff;
+ inno_write(inno, 0xac, val);
+ if (cfg->postdiv == 1) {
+ inno_write(inno, 0xaa, 2);
+ val = (cfg->fbdiv >> 8) | cfg->prediv;
+ inno_write(inno, 0xab, val);
+ } else {
+ val = (cfg->postdiv / 2) - 1;
+ inno_write(inno, 0xad, val);
+ val = (cfg->fbdiv >> 8) | cfg->prediv;
+ inno_write(inno, 0xab, val);
+ inno_write(inno, 0xaa, 0x0e);
+ }
+
+ for (val = 0; val < 14; val++)
+ inno_write(inno, 0xb5 + val, phy_cfg->regs[val]);
+
+ /* bit[7:6] of reg c8/c9/ca/c8 is ESD detect threshold:
+ * 00 - 340mV
+ * 01 - 280mV
+ * 10 - 260mV
+ * 11 - 240mV
+ * default is 240mV, now we set it to 340mV
+ */
+ inno_write(inno, 0xc8, 0);
+ inno_write(inno, 0xc9, 0);
+ inno_write(inno, 0xca, 0);
+ inno_write(inno, 0xcb, 0);
+
+ if (phy_cfg->tmdsclock > 340000000) {
+ /* Set termination resistor to 100ohm */
+ val = 75000000 / 100000;
+ inno_write(inno, 0xc5, ((val >> 8) & 0xff) | 0x80);
+ inno_write(inno, 0xc6, val & 0xff);
+ inno_write(inno, 0xc7, 3 << 1);
+ inno_write(inno, 0xc5, ((val >> 8) & 0xff));
+ } else if (phy_cfg->tmdsclock > 165000000) {
+ inno_write(inno, 0xc5, 0x81);
+ /* clk termination resistor is 50ohm
+ * data termination resistor is 150ohm
+ */
+ inno_write(inno, 0xc8, 0x30);
+ inno_write(inno, 0xc9, 0x10);
+ inno_write(inno, 0xca, 0x10);
+ inno_write(inno, 0xcb, 0x10);
+ } else {
+ inno_write(inno, 0xc5, 0x81);
+ }
+
+ /* set TMDS sync detection counter length */
+ val = 47520000000UL / phy_cfg->tmdsclock;
+ inno_write(inno, 0xd8, (val >> 8) & 0xff);
+ inno_write(inno, 0xd9, val & 0xff);
+
+ /* Power up post PLL */
+ inno_update_bits(inno, 0xaa, 1, 0);
+ /* Power up tmds driver */
+ inno_update_bits(inno, 0xb0, 4, 4);
+ inno_write(inno, 0xb2, 0x0f);
+
+ /* Wait for post PLL lock */
+ for (val = 0; val < 5; val++) {
+ if (inno_read(inno, 0xaf) & 1)
+ break;
+ udelay(1000);
+ }
+ if (!(inno_read(inno, 0xaf) & 1)) {
+ printf("HDMI PHY Post PLL unlock\n");
+ return -ETIMEDOUT;
+ }
+ if (phy_cfg->tmdsclock > 340000000)
+ mdelay(100);
+ /* set pdata_en to 1 */
+ inno_update_bits(inno, 0x02, 1, 1);
+
+ return 0;
+}
+
+static void inno_hdmi_phy_rk3328_power_off(struct inno_hdmi_phy *inno)
+{
+ /* Power off driver */
+ inno_write(inno, 0xb2, 0);
+ /* Power off band gap */
+ inno_update_bits(inno, 0xb0, 4, 0);
+ /* Power off post pll */
+ inno_update_bits(inno, 0xaa, 1, 1);
+}
+
+static int
+inno_hdmi_phy_rk3328_pre_pll_update(struct inno_hdmi_phy *inno,
+ const struct pre_pll_config *cfg)
+{
+ u32 val;
+
+ /* Power off PLL */
+ inno_update_bits(inno, 0xa0, 1, 1);
+ /* Configure pre-pll */
+ inno_update_bits(inno, 0xa0, 2, (cfg->vco_div_5_en & 1) << 1);
+ inno_write(inno, 0xa1, cfg->prediv);
+ if (cfg->fracdiv)
+ val = ((cfg->fbdiv >> 8) & 0x0f) | 0xc0;
+ else
+ val = ((cfg->fbdiv >> 8) & 0x0f) | 0xf0;
+ inno_write(inno, 0xa2, val);
+ inno_write(inno, 0xa3, cfg->fbdiv & 0xff);
+ val = (cfg->pclk_div_a & 0x1f) |
+ ((cfg->pclk_div_b & 3) << 5);
+ inno_write(inno, 0xa5, val);
+ val = (cfg->pclk_div_d & 0x1f) |
+ ((cfg->pclk_div_c & 3) << 5);
+ inno_write(inno, 0xa6, val);
+ val = ((cfg->tmds_div_a & 3) << 4) |
+ ((cfg->tmds_div_b & 3) << 2) |
+ (cfg->tmds_div_c & 3);
+ inno_write(inno, 0xa4, val);
+
+ if (cfg->fracdiv) {
+ val = cfg->fracdiv & 0xff;
+ inno_write(inno, 0xd3, val);
+ val = (cfg->fracdiv >> 8) & 0xff;
+ inno_write(inno, 0xd2, val);
+ val = (cfg->fracdiv >> 16) & 0xff;
+ inno_write(inno, 0xd1, val);
+ } else {
+ inno_write(inno, 0xd3, 0);
+ inno_write(inno, 0xd2, 0);
+ inno_write(inno, 0xd1, 0);
+ }
+
+ /* Power up PLL */
+ inno_update_bits(inno, 0xa0, 1, 0);
+
+ /* Wait for PLL lock */
+ for (val = 0; val < 5; val++) {
+ if (inno_read(inno, 0xa9) & 1)
+ break;
+ udelay(1000);
+ }
+ if (val == 5) {
+ printf("Pre-PLL unlock\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static unsigned long
+inno_hdmi_3328_phy_pll_recalc_rate(struct inno_hdmi_phy *inno,
+ unsigned long parent_rate)
+{
+ unsigned long rate, vco, frac;
+ u8 nd, no_a, no_b, no_d;
+ __maybe_unused u8 no_c;
+ u16 nf;
+
+ nd = inno_read(inno, 0xa1) & 0x3f;
+ nf = ((inno_read(inno, 0xa2) & 0x0f) << 8) | inno_read(inno, 0xa3);
+ vco = parent_rate * nf;
+ if ((inno_read(inno, 0xa2) & 0x30) == 0) {
+ frac = inno_read(inno, 0xd3) |
+ (inno_read(inno, 0xd2) << 8) |
+ (inno_read(inno, 0xd1) << 16);
+ vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
+ }
+ if (inno_read(inno, 0xa0) & 2) {
+ rate = vco / (nd * 5);
+ } else {
+ no_a = inno_read(inno, 0xa5) & 0x1f;
+ no_b = ((inno_read(inno, 0xa5) >> 5) & 7) + 2;
+ no_c = (1 << ((inno_read(inno, 0xa6) >> 5) & 7));
+ no_d = inno_read(inno, 0xa6) & 0x1f;
+ if (no_a == 1)
+ rate = vco / (nd * no_b * no_d * 2);
+ else
+ rate = vco / (nd * no_a * no_d * 2);
+ }
+ inno->pixclock = rate;
+
+ return rate;
+}
+
+static void inno_hdmi_phy_rk3328_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, 0x07);
+ inno_write(inno, 0x02, 0x91);
+ debug("[PHY] %s: done!\n", __func__);
+}
+
+static const struct inno_hdmi_phy_plat_ops rk3328_hdmi_phy_plat_ops = {
+ .init = inno_hdmi_phy_rk3328_init,
+ .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,
+};
+
+static unsigned long inno_hdmi_phy_set_pll(struct phy *phy,
+ unsigned long rate)
+{
+ 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);
+ inno_hdmi_phy_clk_set_rate(inno, rate);
+ debug("[PHY] %s: done!\n", __func__);
+ return 0;
+}
+
+static int
+inno_hdmi_phy_set_bus_width(struct phy *phy, u32 bus_width)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+
+ debug("[PHY] %s: In?\n", __func__);
+ inno->bus_width = bus_width;
+ debug("[PHY] %s: done!\n", __func__);
+
+ return 0;
+}
+
+static long
+inno_hdmi_phy_clk_round_rate(struct phy *phy, unsigned long rate)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+ const struct pre_pll_config *cfg = pre_pll_cfg_table;
+ u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
+ int i;
+
+ debug("[PHY] %s: [rate %ld] In?\n", __func__, rate);
+ for (; cfg->pixclock != ~0UL; cfg++)
+ if (cfg->pixclock == rate)
+ break;
+
+ /*
+ * If there is no dts phy cfg table, use default phy cfg table.
+ * The tmds clock maximum is 594MHz. So there is no need to check
+ * whether tmds clock is out of range.
+ */
+ if (!inno->phy_cfg)
+ return cfg->pixclock;
+
+ /* Check if tmds clock is out of dts phy config's range. */
+ for (i = 0; inno->phy_cfg[i].tmdsclock != ~0UL; i++) {
+ if (inno->phy_cfg[i].tmdsclock >= tmdsclock)
+ break;
+ }
+
+ if (inno->phy_cfg[i].tmdsclock == ~0UL)
+ return -EINVAL;
+
+ debug("[PHY] %s: [pixclock %ld] done!\n", __func__, cfg->pixclock);
+ return cfg->pixclock;
+}
+
+static struct phy_ops inno_hdmi_phy_ops = {
+ .power_on = inno_hdmi_phy_power_on,
+ .power_off = inno_hdmi_phy_power_off,
+ .set_pll = inno_hdmi_phy_set_pll,
+ .set_bus_width = inno_hdmi_phy_set_bus_width,
+ .round_rate = inno_hdmi_phy_clk_round_rate,
+};
+
+static int inno_hdmi_phy_probe(struct udevice *dev)
+{
+ struct inno_hdmi_phy *inno = dev_get_priv(dev);
+
+ debug("[PHY] %s: In?\n", __func__);
+ inno->regs = dev_read_addr_ptr(dev);
+ if (!inno->regs)
+ return -ENOMEM;
+
+ inno->data = (const struct inno_hdmi_phy_data *)dev_get_driver_data(dev);
+ if (!inno->data)
+ return -EINVAL;
+
+ if (inno->data->plat_ops->init)
+ inno->data->plat_ops->init(inno);
+
+ debug("[PHY] %s: done!\n", __func__);
+ return 0;
+}
+
+static const struct inno_hdmi_phy_data rk3328_inno_hdmi_phy_drv_data = {
+ .phy_type = INNO_HDMI_PHY_RK3328,
+ .plat_ops = &rk3328_hdmi_phy_plat_ops,
+ .phy_cfg_table = rk3328_phy_cfg,
+};
+
+static const struct udevice_id inno_hdmi_phy_ids[] = {
+ {
+ .compatible = "rockchip,rk3328-hdmi-phy",
+ .data = (ulong)&rk3328_inno_hdmi_phy_drv_data,
+ },
+ { /* sentile */ }
+};
+
+U_BOOT_DRIVER(inno_hdmi_phy) = {
+ .name = "inno_hdmi_phy",
+ .id = UCLASS_PHY,
+ .of_match = inno_hdmi_phy_ids,
+ .ops = &inno_hdmi_phy_ops,
+ .probe = inno_hdmi_phy_probe,
+ .priv_auto = sizeof(struct inno_hdmi_phy),
+};

View File

@ -0,0 +1,87 @@
diff --git a/include/generic-phy.h b/include/generic-phy.h
index eaab749166..d4dac4975c 100644
--- a/include/generic-phy.h
+++ b/include/generic-phy.h
@@ -185,6 +185,10 @@ struct phy_ops {
* Return: 0 if OK, or a negative error code
*/
int (*set_speed)(struct phy *phy, int speed);
+
+ unsigned long (*set_pll)(struct phy *phy, unsigned long rate);
+ int (*set_bus_width)(struct phy *phy, u32 bus_width);
+ long (*round_rate)(struct phy *phy, unsigned long rate);
};
/**
@@ -429,6 +433,12 @@ int generic_setup_phy(struct udevice *dev, struct phy *phy, int index);
*/
int generic_shutdown_phy(struct phy *phy);
+unsigned long generic_phy_set_pll(struct phy *phy, unsigned long rate);
+
+int generic_phy_set_bus_width(struct phy *phy, u32 bus_width);
+
+long generic_phy_round_rate(struct phy *phy, unsigned long rate);
+
#else /* CONFIG_PHY */
static inline int generic_phy_init(struct phy *phy)
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index 0dcfe258bc..e824ff7b9e 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -225,6 +225,54 @@ int generic_phy_get_by_name(struct udevice *dev, const char *phy_name,
return generic_phy_get_by_index(dev, index, phy);
}
+unsigned long generic_phy_set_pll(struct phy *phy, unsigned long rate)
+{
+ struct phy_ops const *ops;
+ int ret;
+
+ if (!generic_phy_valid(phy))
+ return 0;
+ ops = phy_dev_ops(phy->dev);
+ if (!ops->set_pll)
+ return 0;
+ ret = ops->set_pll(phy, rate);
+ if (ret)
+ dev_err(phy->dev, "PHY: Failed to set_pll %s: %d.\n",
+ phy->dev->name, ret);
+
+ return ret;
+}
+
+int generic_phy_set_bus_width(struct phy *phy, u32 bus_width)
+{
+ struct phy_ops const *ops;
+ int ret;
+
+ if (!generic_phy_valid(phy))
+ return 0;
+ ops = phy_dev_ops(phy->dev);
+ if (!ops->set_bus_width)
+ return 0;
+ ret = ops->set_bus_width(phy, bus_width);
+ if (ret)
+ dev_err(phy->dev, "PHY: Failed to set_bus_width %s: %d.\n",
+ phy->dev->name, ret);
+
+ return ret;
+}
+
+long generic_phy_round_rate(struct phy *phy, unsigned long rate)
+{
+ struct phy_ops const *ops;
+
+ if (!generic_phy_valid(phy))
+ return 0;
+ ops = phy_dev_ops(phy->dev);
+ if (!ops->round_rate)
+ return 0;
+ return ops->round_rate(phy, rate);
+}
+
int generic_phy_init(struct phy *phy)
{
struct phy_counts *counts;

View File

@ -0,0 +1,225 @@
From c6c14957e96c46f0f197f787f407f8c3c152c17a Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Sun, 19 Feb 2023 00:01:34 +0530
Subject: [PATCH] video: dw_hdmi: Add Vendor PHY handling
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/dw_hdmi.c | 29 +++++++++++++++++++++++++++-
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(-)
diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index c4fbb182944..ea12a094074 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,37 @@ 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;
+}
+
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;
+
+ /* 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;
diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
index e5f28132053..d03e8e493b7 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)
return -ETIMEDOUT;
}
+static const struct dw_hdmi_phy_ops dw_hdmi_meson_phy_ops = {
+ .phy_set = meson_dw_hdmi_phy_cfg,
+};
+
+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);
@@ -396,7 +405,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 3041360c6ed..b32139a8a6e 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 b75a1744896..e34f532cd68 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/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 19ed80b48a..8e4922c759 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,
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 +386,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 8acae3839fb..4ad8b39f84d 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);
};

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

@ -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,147 @@
diff --git a/configs/rk3318-box_defconfig b/configs/rk3318-box_defconfig
new file mode 100644
index 0000000000..d356b21ac6
--- /dev/null
+++ b/configs/rk3318-box_defconfig
@@ -0,0 +1,141 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_COUNTER_FREQUENCY=24000000
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_TEXT_BASE=0x200000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x300000
+CONFIG_SF_DEFAULT_SPEED=20000000
+CONFIG_ENV_OFFSET=0x3F8000
+CONFIG_DEFAULT_DEVICE_TREE="rk3318-box"
+CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_DM_RESET=y
+CONFIG_ROCKCHIP_RK3328=y
+CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y
+CONFIG_TPL_LIBCOMMON_SUPPORT=y
+CONFIG_TPL_LIBGENERIC_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC=y
+CONFIG_TARGET_BOX_RK3318=y
+CONFIG_SPL_STACK_R_ADDR=0x4000000
+CONFIG_SPL_STACK=0x400000
+CONFIG_TPL_SYS_MALLOC_F_LEN=0x800
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x4000
+CONFIG_PRE_CON_BUF_ADDR=0xf200000
+CONFIG_DEBUG_UART_BASE=0xFF130000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_SYS_LOAD_ADDR=0x800800
+CONFIG_DEBUG_UART=y
+CONFIG_LOCALVERSION="-armbian"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_BOOTDELAY=1
+CONFIG_USE_PREBOOT=y
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3318-box.dtb"
+CONFIG_LOGLEVEL=6
+CONFIG_SILENT_CONSOLE=y
+# CONFIG_SPL_SILENT_CONSOLE is not set
+# CONFIG_TPL_SILENT_CONSOLE is not set
+CONFIG_PRE_CONSOLE_BUFFER=y
+# CONFIG_SYS_DEVICE_NULLDEV is not set
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_R=y
+CONFIG_SPL_MAX_SIZE=0x40000
+CONFIG_SPL_PAD_TO=0x7f8000
+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
+CONFIG_SPL_BSS_START_ADDR=0x2000000
+CONFIG_SPL_BSS_MAX_SIZE=0x2000
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000
+CONFIG_SPL_ATF=y
+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
+CONFIG_TPL_SYS_MALLOC_SIMPLE=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPIO_READ=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_CMD_BTRFS=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_TPL_OF_PLATDATA=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SYS_MMC_ENV_DEV=1
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_TPL_DM=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_TPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_TPL_SYSCON=y
+CONFIG_BUTTON=y
+CONFIG_BUTTON_ADC=y
+CONFIG_BUTTON_GPIO=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MISC=y
+CONFIG_ROCKCHIP_EFUSE=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_ETH_PHY=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_RGMII=y
+CONFIG_MII=y
+CONFIG_RMII=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_NOP_PHY=y
+CONFIG_PHY_ROCKCHIP_INNO_HDMI=y
+CONFIG_PHY_ROCKCHIP_INNO_USB2=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_DM_PMIC=y
+# CONFIG_SPL_DM_PMIC is not set
+CONFIG_PMIC_RK8XX=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_TPL_RAM=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_SYS_NS16550_MEM32=y
+CONFIG_SYSRESET=y
+# CONFIG_TPL_SYSRESET is not set
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+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_DWC3=y
+CONFIG_USB_DWC3_GENERIC=y
+CONFIG_USB_KEYBOARD=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_VIDEO_SIMPLE=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_TPL_TINY_MEMSET=y
+CONFIG_ERRNO_STR=y

View File

@ -0,0 +1,730 @@
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index cf4f4ae8..3475d564 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -107,6 +107,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3308) += \
rk3308-roc-cc.dtb
dtb-$(CONFIG_ROCKCHIP_RK3328) += \
+ rk3318-box.dtb \
rk3328-evb.dtb \
rk3328-nanopi-r2-rev00.dtb \
rk3328-orangepi-r1-plus.dtb \
diff --git a/arch/arm/dts/rk3318-box.dts b/arch/arm/dts/rk3318-box.dts
new file mode 100644
index 00000000..d4678c7c
--- /dev/null
+++ b/arch/arm/dts/rk3318-box.dts
@@ -0,0 +1,648 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd
+ * Copyright (c) 2020 Armbian project (jock)
+ */
+
+/dts-v1/;
+#include "rk3328.dtsi"
+
+/ {
+ model = "Rockchip RK3318 BOX";
+ compatible = "rockchip,rk3318-box", "rockchip,rk3328-box", "rockchip,rk3328";
+
+ aliases {
+ mmc0 = &sdmmc;
+ mmc1 = &sdio;
+ mmc2 = &emmc;
+ mmc3 = &sdmmc_ext;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc_keys: adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 0>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-recovery {
+ label = "Recovery";
+ linux,code = <0x168>; /*KEY_VENDOR*/
+ press-threshold-microvolt = <17000>;
+ };
+ };
+
+ xin32k: xin32k {
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ clock-output-names = "xin32k";
+ #clock-cells = <0>;
+ };
+
+ gmac_clkin: gmac-clkin {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "gmac_clkin";
+ #clock-cells = <0x00>;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <0x01>;
+ #size-cells = <0x00>;
+
+ vcc_18: regulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vccio_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ vcc_io: regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "vccio_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+
+ vcc_phy: vcc-phy-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_phy";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vcc_sys: vcc-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc_sd: sdmmc-regulator {
+ compatible = "regulator-fixed";
+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0m1_pin>;
+ regulator-name = "vcc_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_io>;
+ };
+
+ /*
+ * USB3 vbus
+ */
+ vcc_host_vbus: vcc-host-vbus {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb30_host_drv>;
+ regulator-name = "vcc_host_vbus";
+ regulator-always-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_sys>;
+ };
+
+ /*
+ * USB2 OTG vbus
+ */
+ vcc_otg_vbus: vcc-otg-vbus {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb20_host_drv>;
+ regulator-name = "vcc_otg_vbus";
+ regulator-always-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vdd_arm: vdd-arm {
+ compatible = "pwm-regulator";
+ pwms = <&pwm0 0 5000 1>;
+ pwm-supply = <&vcc_sys>;
+ regulator-name = "vdd_arm";
+ regulator-init-microvolt = <1000000>;
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-ramp-delay = <12500>;
+ regulator-settling-time-up-us = <250>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ };
+
+ vdd_logic: vdd-log {
+ compatible = "pwm-regulator";
+ pwms = <&pwm1 0 5000 1>;
+ pwm-supply = <&vcc_sys>;
+ regulator-name = "vdd_log";
+ regulator-init-microvolt = <1000000>;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-ramp-delay = <12500>;
+ regulator-settling-time-up-us = <250>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&working_led>;
+
+ working {
+ gpios = <&gpio2 RK_PC7 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "default-on";
+ default-state = "on";
+ };
+
+ };
+
+ ir-receiver {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&ir_int>;
+ pinctrl-names = "default";
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_enable_h>;
+
+ /*
+ * On the module itself this is one of these (depending
+ * on the actual card populated):
+ * - SDIO_RESET_L_WL_REG_ON
+ * - PDN (power down when low)
+ */
+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
+ };
+
+ fd628_dev {
+ compatible = "fd628_dev";
+ fd628_gpio_clk = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>;
+ fd628_gpio_dat = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ };
+
+ analog-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,name = "ANALOG";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&codec>;
+ };
+ };
+
+ hdmi-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,mclk-fs = <128>;
+ simple-audio-card,name = "HDMI";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s0>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&hdmi>;
+ };
+ };
+
+};
+
+&codec {
+ status = "okay";
+ mute-gpios = <&grf_gpio 0 GPIO_ACTIVE_LOW>;
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_arm>;
+};
+
+/*
+&dmc {
+ center-supply = <&vdd_logic>;
+ status = "disabled";
+};
+*/
+
+&display_subsystem {
+ status = "okay";
+};
+
+&emmc {
+
+ supports-emmc;
+ no-sdio;
+ no-sd;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ disable-wp;
+ non-removable;
+ bus-width = <8>;
+ num-slots = <0x01>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
+
+ vmmc-supply = <&vcc_io>;
+ vqmmc-supply = <&vcc_18>;
+
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ card-detect-delay = <200>;
+ disable-wp;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>;
+ supports-sd;
+ vmmc-supply = <&vcc_sd>;
+ status = "okay";
+};
+
+&sdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ disable-wp;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ non-removable;
+ num-slots = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>;
+ supports-sdio;
+ status = "okay";
+
+ brcmf: wifi@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ brcm,drive-strength = <4>;
+ interrupt-parent = <&gpio1>;
+ interrupt-names = "host_wake";
+ interrupts = <RK_PC3 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio_host_wake>;
+ };
+
+};
+
+&sdmmc_ext {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ card-detect-delay = <200>;
+ disable-wp;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0ext_clk &sdmmc0ext_cmd &sdmmc0ext_dectn &sdmmc0ext_bus4>;
+ supports-sd;
+ vmmc-supply = <&vcc_sd>;
+ status = "okay";
+};
+
+&gmac2phy {
+ phy-supply = <&vcc_phy>;
+
+ phy-mode = "rmii";
+
+ clock_in_out = "output";
+ assigned-clocks = <&cru SCLK_MAC2PHY>;
+ assigned-clock-rate = <50000000>;
+ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>;
+ tx_delay = <0x30>;
+ rx_delay = <0x10>;
+
+ status = "okay";
+
+};
+
+&gpu {
+ status = "okay";
+ mali-supply = <&vdd_logic>;
+};
+
+/*
+&h265e {
+ status = "okay";
+};
+*/
+
+&h265e_mmu {
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+/*
+&spdif {
+ pinctrl-0 = <&spdifm0_tx>;
+ status = "okay";
+};
+
+&spdif_out {
+ status = "okay";
+};
+
+&spdif_sound {
+ status = "okay";
+};
+*/
+
+&hdmiphy {
+ status = "okay";
+};
+
+&i2s0 {
+ status = "okay";
+};
+
+&i2s1 {
+ status = "okay";
+};
+
+&io_domains {
+ status = "okay";
+
+ vccio1-supply = <&vcc_io>;
+ vccio2-supply = <&vcc_18>;
+ vccio3-supply = <&vcc_io>;
+ vccio4-supply = <&vcc_18>;
+ vccio5-supply = <&vcc_io>;
+ vccio6-supply = <&vcc_io>;
+ pmuio-supply = <&vcc_io>;
+};
+
+&pinctrl {
+ pinctrl-names = "default";
+ pinctrl-0 = <&clk_32k_out>;
+
+ clk_32k {
+ clk_32k_out: clk-32k-out {
+ rockchip,pins = <1 RK_PD4 1 &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ working_led: working-led {
+ rockchip,pins = <2 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none_2ma>;
+ };
+ };
+
+ ir {
+ ir_int: ir-int {
+ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ sdio-pwrseq {
+ wifi_enable_h: wifi-enable-h {
+ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none_4ma>;/*,
+ <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none_4ma>;*/
+ };
+ };
+
+ usb2 {
+ usb20_host_drv: usb20-host-drv {
+ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb3 {
+ usb30_host_drv: usb30-host-drv {
+ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wireless-bluetooth {
+ uart0_gpios: uart0-gpios {
+ rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wireless-wlan {
+ sdio_host_wake: sdio-host-wake {
+ rockchip,pins = <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+};
+
+/*
+&rkvdec {
+ status = "okay";
+ vcodec-supply = <&vdd_logic>;
+};
+*/
+
+&rkvdec_mmu {
+ status = "okay";
+};
+
+&threshold {
+ temperature = <80000>; /* millicelsius */
+};
+
+&target {
+ temperature = <95000>; /* millicelsius */
+};
+
+&soc_crit {
+ temperature = <100000>; /* millicelsius */
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <0>;
+ rockchip,hw-tshut-polarity = <0>;
+ status = "okay";
+};
+
+&uart0 {
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer &uart0_cts>;
+ status = "okay";
+
+ bluetooth {
+ compatbile = "brcm,bcm43341-bt";
+ max-speed = <1500000>;
+ shutdown-gpios = <&gpio1 RK_PC5 GPIO_ACTIVE_HIGH>;
+ interrupt-names = "host-wakeup";
+ interrupts = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
+ brcm,bt-pcm-int-params = [01 02 00 01 01];
+ };
+
+};
+
+&uart2 {
+ /delete-property/ dmas;
+ /delete-property/ dma-names;
+
+ status = "okay";
+};
+
+&u2phy {
+ status = "okay";
+
+ u2phy_host: host-port {
+ status = "okay";
+ };
+
+ u2phy_otg: otg-port {
+ status = "okay";
+ };
+};
+
+&usb20_otg {
+ dr_mode = "host";
+ status = "okay";
+};
+
+/*
+&u3phy {
+ vbus-supply = <&vcc_host_vbus>;
+ status = "okay";
+};
+
+&u3phy_utmi {
+ status = "okay";
+};
+
+&u3phy_pipe {
+ status = "okay";
+};
+*/
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+/*
+&usbdrd3 {
+ status = "okay";
+};
+
+&usbdrd_dwc3 {
+ dr_mode = "host";
+ status = "okay";
+};
+*/
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vpu {
+ status = "okay";
+ vcodec-supply = <&vdd_logic>;
+};
+
+&vpu_mmu {
+ status = "okay";
+};
+
+/*
+&vepu {
+ status = "okay";
+};
+*/
+
+&vepu_mmu {
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_18>;
+ status = "okay";
+};
+
+/*
+&rga {
+ status = "okay";
+};
+*/
+
+&pwm0 {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&cpu0_opp_table {
+
+ opp-1512000000 {
+ status = "disabled";
+ };
+
+};
+
+&hdmi_sound {
+ status = "okay";
+};
+
+&analog_sound {
+ status = "okay";
+};
diff --git a/arch/arm/dts/rk3318-box-u-boot.dtsi b/arch/arm/dts/rk3318-box-u-boot.dtsi
new file mode 100644
index 0000000000..ffe48d8932
--- /dev/null
+++ b/arch/arm/dts/rk3318-box-u-boot.dtsi
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020 Armbian project (jock)
+ */
+
+#include "rk3328-u-boot.dtsi"
+#include "rk3328-sdram-ddr3-666.dtsi"
+
+/*
+ * Remove the OP-TEE binary node from the binman assembly to avoid
+ * the relative u-boot warning. rk3318-box has not op-tee binary.
+ * The absolute path of the offending binary is:
+ * /binman/simple-bin/fit/images/@tee-SEQ/tee-os
+ *
+ * see rockchip-u-boot.dtsi for the binman mayhem
+ *
+ */
+&fit {
+ images {
+ /delete-node/ @tee-SEQ;
+ };
+};
+
+/ {
+ chosen {
+ u-boot,spl-boot-order = "same-as-spl", &sdmmc, &sdmmc_ext, &emmc;
+ };
+
+};
+
+/*
+&usb_host0_xhci {
+ vbus-supply = <&vcc_host_vbus>;
+ status = "okay";
+};
+*/
+
+&sdio {
+ status="disabled";
+};
+
+&pinctrl {
+
+ sdmmc0-1 {
+ sdmmc0m1_pwren: sdmmc0m1-pwren {
+ rockchip,pins = <0 RK_PD6 3 &pcfg_pull_up_4ma>;
+ };
+
+ sdmmc0m1_pin: sdmmc0m1-pin {
+ rockchip,pins = <0 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up_4ma>;
+ };
+ };
+
+};
+
+&vdd_arm {
+ regulator-init-microvolt = <1200000>;
+};

View File

@ -0,0 +1,212 @@
diff --git a/arch/arm/mach-rockchip/rk3328/Kconfig b/arch/arm/mach-rockchip/rk3328/Kconfig
index d13a1690..f2d8dab4 100644
--- a/arch/arm/mach-rockchip/rk3328/Kconfig
+++ b/arch/arm/mach-rockchip/rk3328/Kconfig
@@ -10,6 +10,13 @@ config TARGET_EVB_RK3328
with full function and phisical connectors support like
usb2.0 host ports, LVDS, JTAG, MAC, SDcard, HDMI, USB-2-serial...
+config TARGET_BOX_RK3318
+ bool "Generic RK3318 Box"
+ help
+ Generic RK3318/RK3328 Tvbox appliance,
+ with full function and phisical connectors support like
+ usb2.0 and usb3.0 ports, MAC, SDcard, HDMI, eMMC, WiFi, ...
+
endchoice
config ROCKCHIP_BOOT_MODE_REG
@@ -40,5 +47,6 @@ config TPL_STACK
default 0xff098000
source "board/rockchip/evb_rk3328/Kconfig"
+source "board/rockchip/rk3318_box/Kconfig"
endif
diff --git a/board/rockchip/rk3318_box/Kconfig b/board/rockchip/rk3318_box/Kconfig
new file mode 100644
index 00000000..4b146413
--- /dev/null
+++ b/board/rockchip/rk3318_box/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_BOX_RK3318
+
+config SYS_BOARD
+ default "rk3318_box"
+
+config SYS_VENDOR
+ default "rockchip"
+
+config SYS_CONFIG_NAME
+ default "rk3318-box"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+
+endif
diff --git a/board/rockchip/rk3318_box/MAINTAINERS b/board/rockchip/rk3318_box/MAINTAINERS
new file mode 100644
index 00000000..e7dd59ff
--- /dev/null
+++ b/board/rockchip/rk3318_box/MAINTAINERS
@@ -0,0 +1,26 @@
+EVB-RK3328
+M: Kever Yang <kever.yang@rock-chips.com>
+S: Maintained
+F: board/rockchip/evb_rk3328
+F: include/configs/evb_rk3328.h
+F: configs/evb-rk3328_defconfig
+
+ROC-RK3328-CC
+M: Loic Devulder <ldevulder@suse.com>
+M: Chen-Yu Tsai <wens@csie.org>
+S: Maintained
+F: configs/roc-cc-rk3328_defconfig
+F: arch/arm/dts/rk3328-roc-cc-u-boot.dtsi
+
+ROCK64-RK3328
+M: Matwey V. Kornilov <matwey.kornilov@gmail.com>
+S: Maintained
+F: configs/rock64-rk3328_defconfig
+F: arch/arm/dts/rk3328-rock64-u-boot.dtsi
+
+ROCKPIE-RK3328
+M: Banglang Huang <banglang.huang@foxmail.com>
+S: Maintained
+F: configs/rock-pi-e-rk3328_defconfig
+F: arch/arm/dts/rk3328-rock-pi-e.dts
+F: arch/arm/dts/rk3328-rock-pi-e-u-boot.dtsi
diff --git a/board/rockchip/rk3318_box/Makefile b/board/rockchip/rk3318_box/Makefile
new file mode 100644
index 00000000..5eba9dfb
--- /dev/null
+++ b/board/rockchip/rk3318_box/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2016 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += rk3318-box.o
diff --git a/board/rockchip/rk3318_box/README b/board/rockchip/rk3318_box/README
new file mode 100644
index 00000000..6cbb66a4
--- /dev/null
+++ b/board/rockchip/rk3318_box/README
@@ -0,0 +1,70 @@
+Introduction
+============
+
+RK3328 key features we might use in U-Boot:
+* CPU: ARMv8 64bit quad-core Cortex-A53
+* IRAM: 36KB
+* DRAM: 4GB-16MB dual-channel
+* eMMC: support eMMC 5.0/5.1, suport HS400, HS200, DDR50
+* SD/MMC: support SD 3.0, MMC 4.51
+* USB: USB2.0 EHCI host port *2
+* Display: RGB/HDMI/DP/MIPI/EDP
+
+evb key features:
+* regulator: pwm regulator for CPU B/L
+* PMIC: rk808
+* debug console: UART2
+
+In order to support Arm Trust Firmware(ATF), we need to use the
+miniloader from rockchip which:
+* do DRAM init
+* load and verify ATF image
+* load and verify U-Boot image
+
+Here is the step-by-step to boot to U-Boot on rk3328.
+
+Get the Source and prebuild binary
+==================================
+
+ > mkdir ~/evb_rk3328
+ > cd ~/evb_rk3328
+ > git clone https://github.com/ARM-software/arm-trusted-firmware.git
+ > git clone https://github.com/rockchip-linux/rkbin
+ > git clone https://github.com/rockchip-linux/rkflashtool
+
+Compile ATF
+===============
+
+ > cd arm-trusted-firmware
+ > make realclean
+ > make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3328 bl31
+
+Compile U-Boot
+==================
+
+ > cd ../u-boot
+ > make CROSS_COMPILE=aarch64-linux-gnu- evb-rk3328_defconfig all
+
+Compile rkflashtool
+=======================
+
+ > cd ../rkflashtool
+ > make
+
+Package image for miniloader
+================================
+ > cd ..
+ > cp arm-trusted-firmware/build/rk3328/release/bl31.bin rkbin/rk33
+ > ./rkbin/tools/trust_merger rkbin/tools/RK3328TRUST.ini
+ > ./rkbin/tools/loaderimage --pack --uboot u-boot/u-boot-dtb.bin uboot.img
+ > mkdir image
+ > mv trust.img ./image/
+ > mv uboot.img ./image/rk3328evb-uboot.bin
+
+Flash image
+===============
+Power on(or reset with RESET KEY) with MASKROM KEY preesed, and then:
+
+ > ./rkflashtool/rkflashloader rk3328evb
+
+You should be able to get U-Boot log message in console/UART2 now.
diff --git a/board/rockchip/rk3318_box/rk3318-box.c b/board/rockchip/rk3318_box/rk3318-box.c
new file mode 100644
index 00000000..779bc646
--- /dev/null
+++ b/board/rockchip/rk3318_box/rk3318-box.c
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ */
+
diff --git a/include/configs/rk3318-box.h b/include/configs/rk3318-box.h
new file mode 100644
index 0000000000..dfbf9d7177
--- /dev/null
+++ b/include/configs/rk3318-box.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __RK3318_BOX_H
+#define __RK3318_BOX_H
+
+#include <configs/rk3328_common.h>
+
+#undef BOOT_TARGETS
+
+#define BOOT_TARGETS "mmc1 mmc3 usb mmc0 pxe dhcp"
+
+#undef CFG_EXTRA_ENV_SETTINGS
+
+#define CFG_EXTRA_ENV_SETTINGS \
+ ENV_MEM_LAYOUT_SETTINGS \
+ "stdin=serial,usbkbd\0" \
+ "stdout=serial,vidconsole\0" \
+ "stderr=serial,vidconsole\0" \
+ "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
+ "fdt_high=0xffffffffffffffff\0" \
+ "initrd_high=0xffffffffffffffff\0" \
+ "boot_targets=" BOOT_TARGETS "\0"
+
+
+#endif

View File

@ -0,0 +1,213 @@
From 3b445a031cb98413cd34e6daf8306701b5d451d4 Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Mon, 20 Feb 2023 01:04:39 +0530
Subject: [PATCH] video: rockchip: Add rk3328 hdmi support
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/rockchip/Makefile | 1 +
drivers/video/rockchip/rk3328_hdmi.c | 141 +++++++++++++++++++++++++++
drivers/video/rockchip/rk_hdmi.h | 3 +
3 files changed, 145 insertions(+)
create mode 100644 drivers/video/rockchip/rk3328_hdmi.c
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 2a23a1a447f..ad954240afa 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -11,6 +11,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_RK3328) += rk3328_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
diff --git a/drivers/video/rockchip/rk3328_hdmi.c b/drivers/video/rockchip/rk3328_hdmi.c
new file mode 100644
index 0000000000..8643800f72
--- /dev/null
+++ b/drivers/video/rockchip/rk3328_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 <asm/arch-rockchip/grf_rk3328.h>
+#include "rk_hdmi.h"
+
+#define RK3328_IO_3V_DOMAIN (7 << (9 + 16))
+#define RK3328_IO_5V_DOMAIN ((7 << 9) | (3 << (9 + 16)))
+#define RK3328_IO_DDC_IN_MSK ((3 << 10) | (3 << (10 + 16)))
+#define RK3328_IO_CTRL_BY_HDMI ((1 << 13) | (1 << (13 + 16)))
+
+static int rk3328_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 rk3328_dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint pixclock)
+{
+ struct rk_hdmi_priv *priv = container_of(hdmi, struct rk_hdmi_priv, hdmi);
+ unsigned long rate;
+ int ret;
+
+ rate = generic_phy_round_rate(&priv->phy, pixclock);
+ if (rate < 0) {
+ printf("failed phy round rate (rate=%ld)\n", rate);
+ return ret;
+ }
+
+ generic_phy_set_bus_width(&priv->phy, 8);
+
+ ret = generic_phy_set_pll(&priv->phy, rate);
+ if (ret) {
+ printf("failed set phy pll (ret=%d)\n", ret);
+ return ret;
+ }
+
+ ret = generic_phy_power_on(&priv->phy);
+ if (ret) {
+ printf("failed to on hdmi phy (ret=%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void rk3328_dw_hdmi_setup_hpd(struct dw_hdmi *hdmi)
+{
+ struct rk_hdmi_priv *priv = container_of(hdmi, struct rk_hdmi_priv, hdmi);
+ struct rk3328_grf_regs *grf = priv->grf;
+
+ writel(RK3328_IO_DDC_IN_MSK, &grf->soc_con[2]);
+ writel(RK3328_IO_CTRL_BY_HDMI, &grf->soc_con[3]);
+}
+
+static void rk3328_dw_hdmi_read_hpd(struct dw_hdmi *hdmi, bool hpd_status)
+{
+ struct rk_hdmi_priv *priv = container_of(hdmi, struct rk_hdmi_priv, hdmi);
+ struct rk3328_grf_regs *grf = priv->grf;
+
+ if (hpd_status)
+ writel(RK3328_IO_5V_DOMAIN, &grf->soc_con[4]);
+ else
+ writel(RK3328_IO_3V_DOMAIN, &grf->soc_con[4]);
+}
+
+static const struct dw_hdmi_phy_ops dw_hdmi_rk3328_phy_ops = {
+ .phy_set = rk3328_dw_hdmi_phy_cfg,
+ .setup_hpd = rk3328_dw_hdmi_setup_hpd,
+ .read_hpd = rk3328_dw_hdmi_read_hpd,
+};
+
+static const struct dw_hdmi_plat_data dw_hdmi_rk3328_plat_data = {
+ .phy_force_vendor = true,
+ .phy_ops = &dw_hdmi_rk3328_phy_ops,
+};
+
+static int rk3328_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_rk3328_plat_data;
+
+ return 0;
+}
+
+static int rk3328_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 rk3328_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 rk3328_hdmi_ops = {
+ .read_edid = rk_hdmi_read_edid,
+ .enable = rk3328_hdmi_enable,
+};
+
+static const struct udevice_id rk3328_hdmi_ids[] = {
+ { .compatible = "rockchip,rk3328-dw-hdmi" },
+ { }
+};
+
+U_BOOT_DRIVER(rk3328_hdmi_rockchip) = {
+ .name = "rk3328_hdmi_rockchip",
+ .id = UCLASS_DISPLAY,
+ .of_match = rk3328_hdmi_ids,
+ .ops = &rk3328_hdmi_ops,
+ .of_to_plat = rk3328_hdmi_of_to_plat,
+ .probe = rk3328_hdmi_probe,
+ .priv_auto = sizeof(struct rk_hdmi_priv),
+ .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

@ -0,0 +1,339 @@
From 32a6e8629d11cfa79d33fa733d1b845e36eadaef Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Mon, 20 Feb 2023 00:58:55 +0530
Subject: [PATCH] video: rockchip: Add rk3328 vop support
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/rockchip/Makefile | 1 +
drivers/video/rockchip/rk3328_vop.c | 66 +++++++++++++++++++++++++++++
2 files changed, 67 insertions(+)
create mode 100644 drivers/video/rockchip/rk3328_vop.c
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 9aced5ef3f4..2a23a1a447f 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_RK3328) += rk3328_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
diff --git a/drivers/video/rockchip/rk3328_vop.c b/drivers/video/rockchip/rk3328_vop.c
new file mode 100644
index 0000000000..5275d65417
--- /dev/null
+++ b/drivers/video/rockchip/rk3328_vop.c
@@ -0,0 +1,111 @@
+// 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 rk3328_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 rk3328_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 rk3328_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 rk3328_driverdata = {
+ .dsp_offset = 0x490,
+ .win_offset = 0xd0,
+ .features = VOP_FEATURE_OUTPUT_10BIT,
+ .set_pin_polarity = rk3328_set_pin_polarity,
+};
+
+static const struct udevice_id rk3328_vop_ids[] = {
+ {
+ .compatible = "rockchip,rk3328-vop",
+ .data = (ulong)&rk3328_driverdata
+ },
+ { /* sentile */ }
+};
+
+static const struct video_ops rk3328_vop_ops = {
+};
+
+U_BOOT_DRIVER(rockchip_rk3328_vop) = {
+ .name = "rockchip_rk3328_vop",
+ .id = UCLASS_VIDEO,
+ .of_match = rk3328_vop_ids,
+ .ops = &rk3328_vop_ops,
+ .bind = rk_vop_bind,
+ .probe = rk3328_vop_probe,
+ .remove = rk3328_vop_remove,
+ .priv_auto = sizeof(struct rk_vop_priv),
+ .flags = DM_FLAG_OS_PREPARE
+};
From 192910962f05ea174e3f30cc1ef182981bf8ef71 Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Thu, 16 Feb 2023 22:48:09 +0530
Subject: [PATCH] ARM: dts: rk3328: Enable VOP for u-boot,dm-pre-reloc
Model: Firefly roc-rk3328-cc
DRAM: 1 GiB (effective 1022 MiB)
Video device 'vop@ff370000' cannot allocate frame buffer memory -ensure the device is set up before relocation
Error binding driver 'rockchip_rk3328_vop': -28
Some drivers failed to bind
initcall sequence 000000003ffcd5e8 failed at call 000000000021a5c4 (err=-28)
### ERROR ### Please RESET the board ###
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
arch/arm/dts/rk3328-u-boot.dtsi | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/rk3328-u-boot.dtsi b/arch/arm/dts/rk3328-u-boot.dtsi
index d4a7540a92c..bd6702dedc7 100644
--- a/arch/arm/dts/rk3328-u-boot.dtsi
+++ b/arch/arm/dts/rk3328-u-boot.dtsi
@@ -73,3 +73,7 @@
&spi0 {
u-boot,dm-pre-reloc;
};
+
+&vop {
+ u-boot,dm-pre-reloc;
+};
From ac6442b276b1aef478e1b701e3f4754d98ca61ab Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@amarulasolutions.com>
Date: Thu, 16 Feb 2023 10:48:48 +0530
Subject: [PATCH] clk: rockchip: rk3328: Add VOP clk support
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
.../include/asm/arch-rockchip/cru_rk3328.h | 34 ++++++++
drivers/clk/rockchip/clk_rk3328.c | 83 ++++++++++++++++++-
2 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3328.h b/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
index 226744d67d9..4ad1d33e056 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
@@ -62,6 +62,40 @@ check_member(rk3328_cru, sdmmc_ext_con[1], 0x39c);
enum apll_frequencies {
APLL_816_MHZ,
APLL_600_MHZ,
+
+ /* CRU_CLK_SEL37_CON */
+ ACLK_VIO_PLL_SEL_CPLL = 0,
+ ACLK_VIO_PLL_SEL_GPLL = 1,
+ ACLK_VIO_PLL_SEL_HDMIPHY = 2,
+ ACLK_VIO_PLL_SEL_USB480M = 3,
+ ACLK_VIO_PLL_SEL_SHIFT = 6,
+ ACLK_VIO_PLL_SEL_MASK = 3 << ACLK_VIO_PLL_SEL_SHIFT,
+ ACLK_VIO_DIV_CON_SHIFT = 0,
+ ACLK_VIO_DIV_CON_MASK = 0x1f << ACLK_VIO_DIV_CON_SHIFT,
+ HCLK_VIO_DIV_CON_SHIFT = 8,
+ HCLK_VIO_DIV_CON_MASK = 0x1f << HCLK_VIO_DIV_CON_SHIFT,
+
+ /* CRU_CLK_SEL39_CON */
+ ACLK_VOP_PLL_SEL_CPLL = 0,
+ ACLK_VOP_PLL_SEL_GPLL = 1,
+ ACLK_VOP_PLL_SEL_HDMIPHY = 2,
+ ACLK_VOP_PLL_SEL_USB480M = 3,
+ ACLK_VOP_PLL_SEL_SHIFT = 6,
+ ACLK_VOP_PLL_SEL_MASK = 3 << ACLK_VOP_PLL_SEL_SHIFT,
+ ACLK_VOP_DIV_CON_SHIFT = 0,
+ ACLK_VOP_DIV_CON_MASK = 0x1f << ACLK_VOP_DIV_CON_SHIFT,
+
+ /* CRU_CLK_SEL40_CON */
+ DCLK_LCDC_PLL_SEL_GPLL = 0,
+ DCLK_LCDC_PLL_SEL_CPLL = 1,
+ DCLK_LCDC_PLL_SEL_SHIFT = 0,
+ DCLK_LCDC_PLL_SEL_MASK = 1 << DCLK_LCDC_PLL_SEL_SHIFT,
+ DCLK_LCDC_SEL_HDMIPHY = 0,
+ DCLK_LCDC_SEL_PLL = 1,
+ DCLK_LCDC_SEL_SHIFT = 1,
+ DCLK_LCDC_SEL_MASK = 1 << DCLK_LCDC_SEL_SHIFT,
+ DCLK_LCDC_DIV_CON_SHIFT = 8,
+ DCLK_LCDC_DIV_CON_MASK = 0xFf << DCLK_LCDC_DIV_CON_SHIFT,
};
void rk3328_configure_cpu(struct rk3328_cru *cru,
diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index b825ff4cf83..195247d9e02 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -581,6 +581,81 @@ static ulong rk3328_spi_set_clk(struct rk3328_cru *cru, uint hz)
return rk3328_spi_get_clk(cru);
}
+#ifndef CONFIG_SPL_BUILD
+static ulong rk3328_vop_get_clk(struct rk3328_clk_priv *priv, ulong clk_id)
+{
+ struct rk3328_cru *cru = priv->cru;
+ u32 div, con, parent;
+
+ switch (clk_id) {
+ case ACLK_VOP_PRE:
+ con = readl(&cru->clksel_con[39]);
+ div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT;
+ parent = GPLL_HZ;
+ break;
+ case ACLK_VIO_PRE:
+ con = readl(&cru->clksel_con[37]);
+ div = (con & ACLK_VIO_DIV_CON_MASK) >> ACLK_VIO_DIV_CON_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 rk3328_vop_set_clk(struct rk3328_clk_priv *priv,
+ ulong clk_id, uint hz)
+{
+ struct rk3328_cru *cru = priv->cru;
+ int src_clk_div;
+ u32 con, parent;
+
+ src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+ assert(src_clk_div - 1 < 31);
+
+ switch (clk_id) {
+ 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 |
+ (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 |
+ (src_clk_div - 1) << ACLK_VIO_DIV_CON_SHIFT);
+ break;
+ case DCLK_LCDC:
+ con = readl(&cru->clksel_con[40]);
+ con = (con & DCLK_LCDC_SEL_MASK) >> DCLK_LCDC_SEL_SHIFT;
+ if (con) {
+ parent = readl(&cru->clksel_con[40]);
+ parent = (parent & DCLK_LCDC_PLL_SEL_MASK) >>
+ DCLK_LCDC_PLL_SEL_SHIFT;
+ if (parent)
+ src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+ else
+ src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+
+ rk_clrsetreg(&cru->clksel_con[40],
+ DCLK_LCDC_DIV_CON_MASK,
+ (src_clk_div - 1) <<
+ DCLK_LCDC_DIV_CON_SHIFT);
+ }
+ break;
+ default:
+ printf("%s: Unable to set vop clk#%ld\n", __func__, clk_id);
+ return -EINVAL;
+ }
+
+ return rk3328_vop_get_clk(priv, clk_id);
+}
+#endif
+
static ulong rk3328_clk_get_rate(struct clk *clk)
{
struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
@@ -649,7 +724,13 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
case SCLK_SPI:
ret = rk3328_spi_set_clk(priv->cru, rate);
break;
+#ifndef CONFIG_SPL_BUILD
case DCLK_LCDC:
+ case ACLK_VOP_PRE:
+ case ACLK_VIO_PRE:
+ rate = rk3328_vop_set_clk(priv, clk->id, rate);
+ break;
+#endif
case SCLK_PDM:
case SCLK_RTC32K:
case SCLK_UART0:
@@ -664,11 +745,9 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
case ACLK_PERI_PRE:
case HCLK_PERI:
case PCLK_PERI:
- case ACLK_VIO_PRE:
case HCLK_VIO_PRE:
case ACLK_RGA_PRE:
case SCLK_RGA:
- case ACLK_VOP_PRE:
case ACLK_RKVDEC_PRE:
case ACLK_RKVENC:
case ACLK_VPU_PRE:

View File

@ -0,0 +1,13 @@
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index cefe9d83..f7288203 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -440,6 +440,8 @@ static void dwc_otg_core_init(struct dwc2_priv *priv)
writel(usbcfg, &regs->gusbcfg);
+ mdelay(10);
+
/* Program the GAHBCFG Register. */
switch (readl(&regs->ghwcfg2) & DWC2_HWCFG2_ARCHITECTURE_MASK) {
case DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY:

View File

@ -0,0 +1,849 @@
diff --git a/arch/arm/dts/rk3229-evb.dts b/arch/arm/dts/rk3229-evb.dts
index 632cdc9bc3..f868524ae1 100644
--- a/arch/arm/dts/rk3229-evb.dts
+++ b/arch/arm/dts/rk3229-evb.dts
@@ -50,19 +50,25 @@
};
&gmac {
- assigned-clocks = <&cru SCLK_MAC_EXTCLK>, <&cru SCLK_MAC>;
- assigned-clock-parents = <&ext_gmac>, <&cru SCLK_MAC_EXTCLK>;
- clock_in_out = "input";
- phy-supply = <&vcc_phy>;
- phy-mode = "rgmii";
- pinctrl-names = "default";
- pinctrl-0 = <&rgmii_pins>;
- snps,reset-gpio = <&gpio2 RK_PD0 GPIO_ACTIVE_LOW>;
- snps,reset-active-low;
- snps,reset-delays-us = <0 10000 1000000>;
- tx_delay = <0x30>;
- rx_delay = <0x10>;
- status = "okay";
+ assigned-clocks = <&cru SCLK_MAC_SRC>;
+ assigned-clock-rates = <50000000>;
+ clock_in_out = "output";
+ phy-supply = <&vcc_phy>;
+ phy-mode = "rmii";
+ phy-handle = <&phy>;
+ status = "okay";
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy: phy@0 {
+ compatible = "ethernet-phy-id1234.d400", "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ phy-is-integrated;
+ };
+ };
};
&emmc {
diff --git a/arch/arm/dts/rk322x.dtsi b/arch/arm/dts/rk322x.dtsi
index 4a8be5dabb..3c2861f271 100644
--- a/arch/arm/dts/rk322x.dtsi
+++ b/arch/arm/dts/rk322x.dtsi
@@ -448,13 +448,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 c87c830716..15039c87be 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk322x.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk322x.h
@@ -12,6 +12,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/configs/evb-rk3229_defconfig b/configs/evb-rk3229_defconfig
index f8e648bbb4..5fd2bd3ba2 100644
--- a/configs/evb-rk3229_defconfig
+++ b/configs/evb-rk3229_defconfig
@@ -58,6 +58,8 @@ CONFIG_GMAC_ROCKCHIP=y
CONFIG_PHY=y
CONFIG_PINCTRL=y
CONFIG_RAM=y
+CONFIG_DM_RESET=y
+CONFIG_RESET_ROCKCHIP=y
CONFIG_SPL_RAM=y
CONFIG_TPL_RAM=y
CONFIG_BAUDRATE=1500000
diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig
index 5bbdc00214..19c09e4503 100644
--- a/configs/evb-rk3328_defconfig
+++ b/configs/evb-rk3328_defconfig
@@ -71,6 +71,8 @@ CONFIG_DM_REGULATOR_FIXED=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
CONFIG_RAM=y
+CONFIG_DM_RESET=y
+CONFIG_RESET_ROCKCHIP=y
CONFIG_SPL_RAM=y
CONFIG_TPL_RAM=y
CONFIG_BAUDRATE=1500000
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 ef33adbf29..c427e0438b 100644
--- a/drivers/clk/rockchip/clk_rk322x.c
+++ b/drivers/clk/rockchip/clk_rk322x.c
@@ -38,6 +38,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)
@@ -87,11 +88,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
@@ -164,7 +167,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 */
@@ -254,11 +258,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)
@@ -387,6 +390,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/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index 8e867c58df..ba2b34c626 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -93,6 +93,14 @@ enum {
PCLK_DBG_DIV_SHIFT = 0,
PCLK_DBG_DIV_MASK = 0xF << PCLK_DBG_DIV_SHIFT,
+ /* CLKSEL_CON26 */
+ GMAC2PHY_PLL_SEL_SHIFT = 7,
+ GMAC2PHY_PLL_SEL_MASK = 1 << GMAC2PHY_PLL_SEL_SHIFT,
+ GMAC2PHY_PLL_SEL_CPLL = 0,
+ GMAC2PHY_PLL_SEL_GPLL = 1,
+ GMAC2PHY_CLK_DIV_MASK = 0x1f,
+ GMAC2PHY_CLK_DIV_SHIFT = 0,
+
/* CLKSEL_CON27 */
GMAC2IO_PLL_SEL_SHIFT = 7,
GMAC2IO_PLL_SEL_MASK = 1 << GMAC2IO_PLL_SEL_SHIFT,
@@ -440,6 +448,39 @@ static ulong rk3328_gmac2io_set_clk(struct rk3328_cru *cru, ulong rate)
return ret;
}
+static ulong rk3328_gmac2phy_src_set_clk(struct rk3328_cru *cru, ulong rate)
+{
+ u32 con = readl(&cru->clksel_con[26]);
+ ulong pll_rate;
+ u8 div;
+
+ if ((con >> GMAC2PHY_PLL_SEL_SHIFT) & GMAC2PHY_PLL_SEL_GPLL)
+ pll_rate = GPLL_HZ;
+ else
+ pll_rate = CPLL_HZ;
+
+ div = DIV_ROUND_UP(pll_rate, rate) - 1;
+ if (div <= 0x1f)
+ rk_clrsetreg(&cru->clksel_con[26], GMAC2PHY_CLK_DIV_MASK,
+ div << GMAC2PHY_CLK_DIV_SHIFT);
+ else
+ debug("Unsupported div for gmac:%d\n", div);
+
+ return DIV_TO_RATE(pll_rate, div);
+}
+
+static ulong rk3328_gmac2phy_set_clk(struct rk3328_cru *cru, ulong rate)
+{
+ struct rk3328_grf_regs *grf;
+
+ grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ if (readl(&grf->mac_con[2]) & BIT(10))
+ /* An external clock will always generate the right rate... */
+ return rate;
+ else
+ return rk3328_gmac2phy_src_set_clk(cru, rate);
+}
+
static ulong rk3328_mmc_get_clk(struct rk3328_cru *cru, uint clk_id)
{
u32 div, con, con_id;
@@ -608,6 +649,12 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
case SCLK_MAC2IO:
ret = rk3328_gmac2io_set_clk(priv->cru, rate);
break;
+ case SCLK_MAC2PHY:
+ ret = rk3328_gmac2phy_set_clk(priv->cru, rate);
+ break;
+ case SCLK_MAC2PHY_SRC:
+ ret = rk3328_gmac2phy_src_set_clk(priv->cru, rate);
+ break;
case SCLK_PWM:
ret = rk3328_pwm_set_clk(priv->cru, rate);
break;
@@ -728,6 +775,43 @@ static int rk3328_gmac2io_ext_set_parent(struct clk *clk, struct clk *parent)
return -EINVAL;
}
+static int rk3328_gmac2phy_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct rk3328_grf_regs *grf;
+ const char *clock_output_name;
+ int ret;
+
+ grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+
+ /*
+ * If the requested parent is in the same clock-controller and the id
+ * is SCLK_MAC2PHY_SRC ("clk_mac2phy_src"), switch to the internal clock.
+ */
+ if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2PHY_SRC)) {
+ debug("%s: switching MAC CLK to SCLK_MAC2IO_PHY\n", __func__);
+ rk_clrreg(&grf->mac_con[2], BIT(10));
+ return 0;
+ }
+
+ /*
+ * Otherwise, we need to check the clock-output-names of the
+ * requested parent to see if the requested id is "phy_50m_out".
+ */
+ ret = dev_read_string_index(parent->dev, "clock-output-names",
+ parent->id, &clock_output_name);
+ if (ret < 0)
+ return -ENODATA;
+
+ /* If this is "phy_50m_out", switch to the external clock input */
+ if (!strcmp(clock_output_name, "phy_50m_out")) {
+ debug("%s: switching MAC CLK to PHY_50M_OUT\n", __func__);
+ rk_setreg(&grf->mac_con[2], BIT(10));
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent)
{
switch (clk->id) {
@@ -735,6 +819,8 @@ static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent)
return rk3328_gmac2io_set_parent(clk, parent);
case SCLK_MAC2IO_EXT:
return rk3328_gmac2io_ext_set_parent(clk, parent);
+ case SCLK_MAC2PHY:
+ return rk3328_gmac2phy_set_parent(clk, parent);
case DCLK_LCDC:
case SCLK_PDM:
case SCLK_RTC32K:
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index e152faf083..d3f6973043 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -9,6 +9,7 @@
#include <dm.h>
#include <clk.h>
#include <phy.h>
+#include <reset.h>
#include <syscon.h>
#include <asm/global_data.h>
#include <asm/io.h>
@@ -23,6 +24,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 "designware.h"
@@ -39,21 +41,29 @@ 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"))
@@ -61,6 +71,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);
@@ -74,7 +103,8 @@ static int gmac_rockchip_of_to_plat(struct udevice *dev)
return designware_eth_of_to_plat(dev);
}
-static int px30_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int px30_gmac_fix_rmii_speed(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv)
{
struct px30_grf *grf;
struct clk clk_speed;
@@ -115,7 +145,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;
@@ -148,7 +214,8 @@ static int rk3228_gmac_fix_mac_speed(struct dw_eth_dev *priv)
return 0;
}
-static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3288_gmac_fix_rgmii_speed(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv)
{
struct rk3288_grf *grf;
int clk;
@@ -174,7 +241,8 @@ static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv)
return 0;
}
-static int rk3308_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3308_gmac_fix_rmii_speed(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv)
{
struct rk3308_grf *grf;
struct clk clk_speed;
@@ -215,7 +283,43 @@ static int rk3308_gmac_fix_mac_speed(struct dw_eth_dev *priv)
return 0;
}
-static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3328_gmac_fix_rmii_speed(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv)
+{
+ struct rk3328_grf_regs *grf;
+ int clk;
+ enum {
+ RK3328_GMAC_RMII_CLK_MASK = BIT(7),
+ RK3328_GMAC_RMII_CLK_2_5M = 0,
+ RK3328_GMAC_RMII_CLK_25M = BIT(7),
+
+ RK3328_GMAC_RMII_SPEED_MASK = BIT(2),
+ RK3328_GMAC_RMII_SPEED_10 = 0,
+ RK3328_GMAC_RMII_SPEED_100 = BIT(2),
+ };
+
+ switch (priv->phydev->speed) {
+ case 10:
+ clk = RK3328_GMAC_RMII_CLK_2_5M | RK3328_GMAC_RMII_SPEED_10;
+ break;
+ case 100:
+ clk = RK3328_GMAC_RMII_CLK_25M | RK3328_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(pdata->integrated_phy ? &grf->mac_con[2] : &grf->mac_con[1],
+ RK3328_GMAC_RMII_CLK_MASK | RK3328_GMAC_RMII_SPEED_MASK,
+ clk);
+
+ return 0;
+}
+
+static int rk3328_gmac_fix_rgmii_speed(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv)
{
struct rk3328_grf_regs *grf;
int clk;
@@ -248,7 +352,8 @@ static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv)
return 0;
}
-static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3368_gmac_fix_rgmii_speed(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv)
{
struct rk3368_grf *grf;
int clk;
@@ -280,7 +385,8 @@ static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv)
return 0;
}
-static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3399_gmac_fix_rgmii_speed(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv)
{
struct rk3399_grf_regs *grf;
int clk;
@@ -306,7 +412,8 @@ static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv)
return 0;
}
-static int rv1108_set_rmii_speed(struct dw_eth_dev *priv)
+static int rv1108_gmac_fix_rmii_speed(struct gmac_rockchip_plat *pdata,
+ struct dw_eth_dev *priv)
{
struct rv1108_grf *grf;
int clk, speed;
@@ -357,6 +464,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;
@@ -435,6 +564,25 @@ static void rk3308_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata)
RK3308_GMAC_PHY_INTF_SEL_RMII);
}
+static void rk3328_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata)
+{
+ struct rk3328_grf_regs *grf;
+ enum {
+ RK3328_RMII_MODE_MASK = BIT(9),
+ RK3328_RMII_MODE = BIT(9),
+
+ RK3328_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4),
+ RK3328_GMAC_PHY_INTF_SEL_RMII = BIT(6),
+ };
+
+ grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ rk_clrsetreg(pdata->integrated_phy ? &grf->mac_con[2] : &grf->mac_con[1],
+ RK3328_RMII_MODE_MASK |
+ RK3328_GMAC_PHY_INTF_SEL_MASK,
+ RK3328_GMAC_PHY_INTF_SEL_RMII |
+ RK3328_RMII_MODE);
+}
+
static void rk3328_gmac_set_to_rgmii(struct gmac_rockchip_plat *pdata)
{
struct rk3328_grf_regs *grf;
@@ -550,6 +698,126 @@ 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 void rk3328_gmac_integrated_phy_powerup(struct gmac_rockchip_plat *pdata)
+{
+ struct rk3328_grf_regs *grf;
+ enum {
+ RK3328_GRF_CON_RMII_MODE_MASK = BIT(9),
+ RK3328_GRF_CON_RMII_MODE = BIT(9),
+ };
+ enum {
+ RK3328_MACPHY_CFG_CLK_50M_MASK = BIT(14),
+ RK3328_MACPHY_CFG_CLK_50M = BIT(14),
+
+ RK3328_MACPHY_RMII_MODE_MASK = GENMASK(7, 6),
+ RK3328_MACPHY_RMII_MODE = BIT(6),
+
+ RK3328_MACPHY_ENABLE_MASK = BIT(0),
+ RK3328_MACPHY_DISENABLE = 0,
+ RK3328_MACPHY_ENABLE = BIT(0),
+ };
+ enum {
+ RK3328_RK_GRF_CON2_MACPHY_ID_MASK = GENMASK(6, 0),
+ RK3328_RK_GRF_CON2_MACPHY_ID = 0x1234,
+ };
+ enum {
+ RK3328_RK_GRF_CON3_MACPHY_ID_MASK = GENMASK(5, 0),
+ RK3328_RK_GRF_CON3_MACPHY_ID = 0x35,
+ };
+
+ grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ rk_clrsetreg(&grf->macphy_con[1],
+ RK3328_GRF_CON_RMII_MODE_MASK,
+ RK3328_GRF_CON_RMII_MODE);
+
+ rk_clrsetreg(&grf->macphy_con[2],
+ RK3328_RK_GRF_CON2_MACPHY_ID_MASK,
+ RK3328_RK_GRF_CON2_MACPHY_ID);
+
+ rk_clrsetreg(&grf->macphy_con[3],
+ RK3328_RK_GRF_CON3_MACPHY_ID_MASK,
+ RK3328_RK_GRF_CON3_MACPHY_ID);
+
+ /* disabled before trying to reset it */
+ rk_clrsetreg(&grf->macphy_con[0],
+ RK3328_MACPHY_CFG_CLK_50M_MASK |
+ RK3328_MACPHY_RMII_MODE_MASK |
+ RK3328_MACPHY_ENABLE_MASK,
+ RK3328_MACPHY_CFG_CLK_50M |
+ RK3328_MACPHY_RMII_MODE |
+ RK3328_MACPHY_DISENABLE);
+
+ reset_assert(&pdata->phy_reset);
+ udelay(10);
+ reset_deassert(&pdata->phy_reset);
+ udelay(10);
+
+ rk_clrsetreg(&grf->macphy_con[0],
+ RK3328_MACPHY_ENABLE_MASK,
+ RK3328_MACPHY_ENABLE);
+ udelay(30 * 1000);
+}
+
static int gmac_rockchip_probe(struct udevice *dev)
{
struct gmac_rockchip_plat *pdata = dev_get_plat(dev);
@@ -569,6 +837,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 */
@@ -652,7 +923,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;
}
@@ -661,18 +932,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;
@@ -690,42 +976,48 @@ const struct eth_ops gmac_rockchip_eth_ops = {
};
const struct rk_gmac_ops px30_gmac_ops = {
- .fix_mac_speed = px30_gmac_fix_mac_speed,
+ .fix_rmii_speed = px30_gmac_fix_rmii_speed,
.set_to_rmii = px30_gmac_set_to_rmii,
};
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 = {
- .fix_mac_speed = rk3288_gmac_fix_mac_speed,
+ .fix_rgmii_speed = rk3288_gmac_fix_rgmii_speed,
.set_to_rgmii = rk3288_gmac_set_to_rgmii,
};
const struct rk_gmac_ops rk3308_gmac_ops = {
- .fix_mac_speed = rk3308_gmac_fix_mac_speed,
+ .fix_rmii_speed = rk3308_gmac_fix_rmii_speed,
.set_to_rmii = rk3308_gmac_set_to_rmii,
};
const struct rk_gmac_ops rk3328_gmac_ops = {
- .fix_mac_speed = rk3328_gmac_fix_mac_speed,
+ .fix_rmii_speed = rk3328_gmac_fix_rmii_speed,
+ .fix_rgmii_speed = rk3328_gmac_fix_rgmii_speed,
+ .set_to_rmii = rk3328_gmac_set_to_rmii,
.set_to_rgmii = rk3328_gmac_set_to_rgmii,
+ .integrated_phy_powerup = rk3328_gmac_integrated_phy_powerup,
};
const struct rk_gmac_ops rk3368_gmac_ops = {
- .fix_mac_speed = rk3368_gmac_fix_mac_speed,
+ .fix_rgmii_speed = rk3368_gmac_fix_rgmii_speed,
.set_to_rgmii = rk3368_gmac_set_to_rgmii,
};
const struct rk_gmac_ops rk3399_gmac_ops = {
- .fix_mac_speed = rk3399_gmac_fix_mac_speed,
+ .fix_rgmii_speed = rk3399_gmac_fix_rgmii_speed,
.set_to_rgmii = rk3399_gmac_set_to_rgmii,
};
const struct rk_gmac_ops rv1108_gmac_ops = {
- .fix_mac_speed = rv1108_set_rmii_speed,
+ .fix_rmii_speed = rv1108_gmac_fix_rmii_speed,
.set_to_rmii = rv1108_gmac_set_to_rmii,
};
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index ae9fe9da..92514af1 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -891,7 +891,7 @@ static int gmac_rockchip_probe(struct udevice *dev)
if (!pdata->clock_input) {
rate = clk_set_rate(&clk, 50000000);
- if (rate != 50000000)
+ if (rate != 50000000 && rate != 49500000)
return -EINVAL;
}
break;

View File

@ -0,0 +1,46 @@
From 91b83f2920631e3104fd5691bde107e39a98feee Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Fri, 5 Nov 2021 16:03:11 +0000
Subject: [PATCH 1/2] rk3328: resets for mmc controllers
---
arch/arm/dts/rk3328.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/dts/rk3328.dtsi b/arch/arm/dts/rk3328.dtsi
index 945387e5..3314d5e4 100644
--- a/arch/arm/dts/rk3328.dtsi
+++ b/arch/arm/dts/rk3328.dtsi
@@ -859,6 +859,8 @@
clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
<&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ resets = <&cru SRST_MMC0>;
+ reset-names = "reset";
fifo-depth = <0x100>;
max-frequency = <150000000>;
status = "disabled";
@@ -871,6 +873,8 @@
clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
<&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ resets = <&cru SRST_SDIO>;
+ reset-names = "reset";
fifo-depth = <0x100>;
max-frequency = <150000000>;
status = "disabled";
@@ -883,8 +887,11 @@
clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
<&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ resets = <&cru SRST_EMMC>;
+ reset-names = "reset";
fifo-depth = <0x100>;
max-frequency = <150000000>;
+
status = "disabled";
};
--
2.30.2

View File

@ -0,0 +1,37 @@
From 073b28838387a4f7c5947d7a3f07d326f13b72f4 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Fri, 5 Nov 2021 16:03:53 +0000
Subject: [PATCH 2/2] rk3328: sdmmc_ext node
---
arch/arm/dts/rk3328.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm/dts/rk3328.dtsi b/arch/arm/dts/rk3328.dtsi
index 3314d5e4..a1fedc56 100644
--- a/arch/arm/dts/rk3328.dtsi
+++ b/arch/arm/dts/rk3328.dtsi
@@ -895,6 +895,20 @@
status = "disabled";
};
+ sdmmc_ext: dwmmc@ff5f0000 {
+ compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc";
+ reg = <0x0 0xff5f0000 0x0 0x4000>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru HCLK_SDMMC_EXT>, <&cru SCLK_SDMMC_EXT>,
+ <&cru SCLK_SDMMC_EXT_DRV>, <&cru SCLK_SDMMC_EXT_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ fifo-depth = <0x100>;
+ max-frequency = <150000000>;
+ resets = <&cru SRST_SDMMCEXT>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
gmac2io: ethernet@ff540000 {
compatible = "rockchip,rk3328-gmac";
reg = <0x0 0xff540000 0x0 0x10000>;
--
2.30.2