diff --git a/config/boards/rk3318-box.tvb b/config/boards/rk3318-box.tvb index e718ed9fa2..add4e4049d 100644 --- a/config/boards/rk3318-box.tvb +++ b/config/boards/rk3318-box.tvb @@ -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" diff --git a/patch/u-boot/v2024.01/board_rk3318-box/general-add-inno-hdmi-phy.patch b/patch/u-boot/v2024.01/board_rk3318-box/general-add-inno-hdmi-phy.patch new file mode 100644 index 0000000000..d9a818f734 --- /dev/null +++ b/patch/u-boot/v2024.01/board_rk3318-box/general-add-inno-hdmi-phy.patch @@ -0,0 +1,784 @@ +From 42a891d30cd2c4c00ee674738128c03277d2d5f8 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Thu, 16 Feb 2023 21:59:42 +0530 +Subject: [PATCH] phy: rockchip: Add Rockchip INNO HDMI PHY driver + +Signed-off-by: Jagan Teki +Signed-off-by: Jagan Teki +--- + 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 ++#include ++#include ++#include ++#include ++#include ++ ++#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), ++}; diff --git a/patch/u-boot/v2024.01/board_rk3318-box/general-add-phy-ops.patch b/patch/u-boot/v2024.01/board_rk3318-box/general-add-phy-ops.patch new file mode 100644 index 0000000000..2d4f7005fc --- /dev/null +++ b/patch/u-boot/v2024.01/board_rk3318-box/general-add-phy-ops.patch @@ -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; diff --git a/patch/u-boot/v2024.01/board_rk3318-box/general-hdmi-vendor-phy-handling.patch b/patch/u-boot/v2024.01/board_rk3318-box/general-hdmi-vendor-phy-handling.patch new file mode 100644 index 0000000000..d7255025e5 --- /dev/null +++ b/patch/u-boot/v2024.01/board_rk3318-box/general-hdmi-vendor-phy-handling.patch @@ -0,0 +1,225 @@ +From c6c14957e96c46f0f197f787f407f8c3c152c17a Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Sun, 19 Feb 2023 00:01:34 +0530 +Subject: [PATCH] video: dw_hdmi: Add Vendor PHY handling + +Signed-off-by: Jagan Teki +--- + drivers/video/dw_hdmi.c | 29 +++++++++++++++++++++++++++- + drivers/video/meson/meson_dw_hdmi.c | 11 ++++++++++- + drivers/video/rockchip/rk3399_hdmi.c | 8 +++++++- + drivers/video/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); + }; diff --git a/patch/u-boot/v2024.01/board_rk3318-box/general-hpd-enhancements.patch b/patch/u-boot/v2024.01/board_rk3318-box/general-hpd-enhancements.patch new file mode 100644 index 0000000000..8c45007506 --- /dev/null +++ b/patch/u-boot/v2024.01/board_rk3318-box/general-hpd-enhancements.patch @@ -0,0 +1,193 @@ +From d2804380b05b4e8e6557ce7239a1680853dd5258 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Sat, 18 Feb 2023 00:30:30 +0530 +Subject: [PATCH] video: rockchip: hdmi: Detect hpd after controller init + +Signed-off-by: Jagan Teki +--- + 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 +Date: Sun, 19 Feb 2023 00:20:52 +0530 +Subject: [PATCH] video: dw_hdmi: Simplify HPD detection + +Signed-off-by: Jagan Teki +--- + 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 +Date: Sun, 19 Feb 2023 00:30:37 +0530 +Subject: [PATCH] video: dw_hdmi: Add read_hpd hook + +Signed-off-by: Jagan Teki +--- + 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 +Date: Sun, 19 Feb 2023 00:33:18 +0530 +Subject: [PATCH] video: dw_hdmi: Add setup_hpd hook + +Signed-off-by: Jagan Teki +--- + 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 { diff --git a/patch/u-boot/v2024.01/board_rk3318-box/general-rockchip-vop-enhancements.patch b/patch/u-boot/v2024.01/board_rk3318-box/general-rockchip-vop-enhancements.patch new file mode 100644 index 0000000000..98e7393287 --- /dev/null +++ b/patch/u-boot/v2024.01/board_rk3318-box/general-rockchip-vop-enhancements.patch @@ -0,0 +1,242 @@ +From dc0ea12fdeb6843839ee1a182166bc2506fa0ec7 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Sun, 19 Feb 2023 00:47:19 +0530 +Subject: [PATCH] video: rockchip: vop: Simplify rkvop_enable + +Signed-off-by: Jagan Teki +--- + 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 +Date: Sun, 19 Feb 2023 00:53:06 +0530 +Subject: [PATCH] video: rockchip: vop: Add win offset support + +Signed-off-by: Jagan Teki +--- + 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), +- ®s->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), +- ®s->win0_dsp_st); ++ &win_regs->win0_dsp_st); + + writel(V_DSP_WIDTH(hactive - 1) | + V_DSP_HEIGHT(vactive - 1), +- ®s->win0_dsp_info); ++ &win_regs->win0_dsp_info); + +- clrsetbits_le32(®s->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), ®s->win0_vir); ++ writel(V_RGB565_VIRWIDTH(hactive), &win_regs->win0_vir); + break; + case 24: + rgb_mode = RGB888; +- writel(V_RGB888_VIRWIDTH(hactive), ®s->win0_vir); ++ writel(V_RGB888_VIRWIDTH(hactive), &win_regs->win0_vir); + break; + case 32: + default: + rgb_mode = ARGB8888; +- writel(V_ARGB888_VIRWIDTH(hactive), ®s->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(®s->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, ®s->win0_yrgb_mst); ++ writel(fbbase, &win_regs->win0_yrgb_mst); + writel(0x01, ®s->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 +Date: Mon, 20 Feb 2023 00:52:32 +0530 +Subject: [PATCH] video: rockchip: vop: Add dsp offset support + +Signed-off-by: Jagan Teki +--- + 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), +- ®s->dsp_htotal_hs_end); ++ &dsp_regs->dsp_htotal_hs_end); + + writel(V_HEAP(hsync_len + hback_porch + hactive) | + V_HASP(hsync_len + hback_porch), +- ®s->dsp_hact_st_end); ++ &dsp_regs->dsp_hact_st_end); + + writel(V_VSYNC(vsync_len) | + V_VERPRD(vsync_len + vback_porch + vactive + vfront_porch), +- ®s->dsp_vtotal_vs_end); ++ &dsp_regs->dsp_vtotal_vs_end); + + writel(V_VAEP(vsync_len + vback_porch + vactive)| + V_VASP(vsync_len + vback_porch), +- ®s->dsp_vact_st_end); ++ &dsp_regs->dsp_vact_st_end); + + writel(V_HEAP(hsync_len + hback_porch + hactive) | + V_HASP(hsync_len + hback_porch), +- ®s->post_dsp_hact_info); ++ &dsp_regs->post_dsp_hact_info); + + writel(V_VAEP(vsync_len + vback_porch + vactive)| + V_VASP(vsync_len + vback_porch), +- ®s->post_dsp_vact_info); ++ &dsp_regs->post_dsp_vact_info); + + writel(0x01, ®s->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; diff --git a/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-defconfig.patch b/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-defconfig.patch new file mode 100644 index 0000000000..0b16d01552 --- /dev/null +++ b/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-defconfig.patch @@ -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 diff --git a/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-dts.patch b/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-dts.patch new file mode 100644 index 0000000000..069e2f0d5e --- /dev/null +++ b/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-dts.patch @@ -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 = ; ++ 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>; ++}; diff --git a/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-makefile.patch b/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-makefile.patch new file mode 100644 index 0000000000..ae10dc2b40 --- /dev/null +++ b/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-makefile.patch @@ -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 ++S: Maintained ++F: board/rockchip/evb_rk3328 ++F: include/configs/evb_rk3328.h ++F: configs/evb-rk3328_defconfig ++ ++ROC-RK3328-CC ++M: Loic Devulder ++M: Chen-Yu Tsai ++S: Maintained ++F: configs/roc-cc-rk3328_defconfig ++F: arch/arm/dts/rk3328-roc-cc-u-boot.dtsi ++ ++ROCK64-RK3328 ++M: Matwey V. Kornilov ++S: Maintained ++F: configs/rock64-rk3328_defconfig ++F: arch/arm/dts/rk3328-rock64-u-boot.dtsi ++ ++ROCKPIE-RK3328 ++M: Banglang Huang ++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 ++ ++#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 diff --git a/patch/u-boot/v2024.01/board_rk3318-box/rk3328-hdmi-driver.patch b/patch/u-boot/v2024.01/board_rk3318-box/rk3328-hdmi-driver.patch new file mode 100644 index 0000000000..c9793b4d5f --- /dev/null +++ b/patch/u-boot/v2024.01/board_rk3318-box/rk3328-hdmi-driver.patch @@ -0,0 +1,213 @@ +From 3b445a031cb98413cd34e6daf8306701b5d451d4 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Mon, 20 Feb 2023 01:04:39 +0530 +Subject: [PATCH] video: rockchip: Add rk3328 hdmi support + +Signed-off-by: Jagan Teki +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ++ + struct rkhdmi_driverdata { + /* configuration */ + u8 i2c_clk_high; +@@ -19,6 +21,7 @@ struct rkhdmi_driverdata { + + struct rk_hdmi_priv { + struct dw_hdmi hdmi; ++ struct phy phy; + void *grf; + }; + diff --git a/patch/u-boot/v2024.01/board_rk3318-box/rk3328-vop-driver.patch b/patch/u-boot/v2024.01/board_rk3318-box/rk3328-vop-driver.patch new file mode 100644 index 0000000000..f32474315a --- /dev/null +++ b/patch/u-boot/v2024.01/board_rk3318-box/rk3328-vop-driver.patch @@ -0,0 +1,339 @@ +From 32a6e8629d11cfa79d33fa733d1b845e36eadaef Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Mon, 20 Feb 2023 00:58:55 +0530 +Subject: [PATCH] video: rockchip: Add rk3328 vop support + +Signed-off-by: Jagan Teki +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#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(®s->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(®s->sys_ctrl, V_STANDBY_EN(1)); ++ clrsetbits_le32(®s->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 +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 +--- + 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 +Date: Thu, 16 Feb 2023 10:48:48 +0530 +Subject: [PATCH] clk: rockchip: rk3328: Add VOP clk support + +Signed-off-by: Jagan Teki +--- + .../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: diff --git a/patch/u-boot/v2024.01/general-dwc-otg-usb-fix.patch b/patch/u-boot/v2024.01/general-dwc-otg-usb-fix.patch new file mode 100644 index 0000000000..dcfbaea5ad --- /dev/null +++ b/patch/u-boot/v2024.01/general-dwc-otg-usb-fix.patch @@ -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, ®s->gusbcfg); + ++ mdelay(10); ++ + /* Program the GAHBCFG Register. */ + switch (readl(®s->ghwcfg2) & DWC2_HWCFG2_ARCHITECTURE_MASK) { + case DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY: diff --git a/patch/u-boot/v2024.01/general-support-rmii-integrated-phy.patch b/patch/u-boot/v2024.01/general-support-rmii-integrated-phy.patch new file mode 100644 index 0000000000..97ca6684ae --- /dev/null +++ b/patch/u-boot/v2024.01/general-support-rmii-integrated-phy.patch @@ -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 + #include + #include ++#include + #include + #include + #include +@@ -23,6 +24,8 @@ + #include + #include + #include ++#include ++#include + #include + #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; diff --git a/patch/u-boot/v2024.01/rk3328-resets-for-mmc-controllers.patch b/patch/u-boot/v2024.01/rk3328-resets-for-mmc-controllers.patch new file mode 100644 index 0000000000..c8530a9bef --- /dev/null +++ b/patch/u-boot/v2024.01/rk3328-resets-for-mmc-controllers.patch @@ -0,0 +1,46 @@ +From 91b83f2920631e3104fd5691bde107e39a98feee Mon Sep 17 00:00:00 2001 +From: Paolo Sabatino +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 + diff --git a/patch/u-boot/v2024.01/rk3328-sdmmc_ext-node.patch b/patch/u-boot/v2024.01/rk3328-sdmmc_ext-node.patch new file mode 100644 index 0000000000..f8d2228ffc --- /dev/null +++ b/patch/u-boot/v2024.01/rk3328-sdmmc_ext-node.patch @@ -0,0 +1,37 @@ +From 073b28838387a4f7c5947d7a3f07d326f13b72f4 Mon Sep 17 00:00:00 2001 +From: Paolo Sabatino +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 = ; ++ 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 +