diff --git a/target/linux/rockchip/armv8/config-5.18 b/target/linux/rockchip/armv8/config-5.18 index e0232eb9b..1136c502c 100644 --- a/target/linux/rockchip/armv8/config-5.18 +++ b/target/linux/rockchip/armv8/config-5.18 @@ -391,6 +391,7 @@ CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_MSI_IOMMU=y CONFIG_IRQ_TIME_ACCOUNTING=y CONFIG_IRQ_WORK=y +CONFIG_JLSEMI_JL2XX1_PHY=y CONFIG_JBD2=y CONFIG_JFFS2_ZLIB=y CONFIG_JUMP_LABEL=y diff --git a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-doornet1.dts b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-doornet1.dts index 26cd28f62..6f9cf81f8 100644 --- a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-doornet1.dts +++ b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-doornet1.dts @@ -7,6 +7,7 @@ #include #include +#include "rk3328-dram-nanopi2-timing.dtsi" #include "rk3328.dtsi" / { @@ -58,6 +59,72 @@ enable-active-high; }; + dmc: dmc { + compatible = "rockchip,rk3328-dmc"; + devfreq-events = <&dfi>; + center-supply = <&vdd_log>; + clocks = <&cru SCLK_DDRCLK>; + clock-names = "dmc_clk"; + operating-points-v2 = <&dmc_opp_table>; + ddr_timing = <&ddr_timing>; + upthreshold = <40>; + downdifferential = <20>; + auto-min-freq = <786000>; + auto-freq-en = <1>; + #cooling-cells = <2>; + status = "okay"; + + ddr_power_model: ddr_power_model { + compatible = "ddr_power_model"; + dynamic-power-coefficient = <120>; + static-power-coefficient = <200>; + ts = <32000 4700 (-80) 2>; + thermal-zone = "soc-thermal"; + }; + }; + + dmc_opp_table: dmc-opp-table { + compatible = "operating-points-v2"; + + rockchip,leakage-voltage-sel = < + 1 10 0 + 11 254 1 + >; + nvmem-cells = <&logic_leakage>; + nvmem-cell-names = "ddr_leakage"; + + opp-786000000 { + opp-hz = /bits/ 64 <786000000>; + opp-microvolt = <1075000>; + opp-microvolt-L0 = <1075000>; + opp-microvolt-L1 = <1050000>; + }; + opp-798000000 { + opp-hz = /bits/ 64 <798000000>; + opp-microvolt = <1075000>; + opp-microvolt-L0 = <1075000>; + opp-microvolt-L1 = <1050000>; + }; + opp-840000000 { + opp-hz = /bits/ 64 <840000000>; + opp-microvolt = <1075000>; + opp-microvolt-L0 = <1075000>; + opp-microvolt-L1 = <1050000>; + }; + opp-924000000 { + opp-hz = /bits/ 64 <924000000>; + opp-microvolt = <1100000>; + opp-microvolt-L0 = <1100000>; + opp-microvolt-L1 = <1075000>; + }; + opp-1056000000 { + opp-hz = /bits/ 64 <1056000000>; + opp-microvolt = <1175000>; + opp-microvolt-L0 = <1175000>; + opp-microvolt-L1 = <1150000>; + }; + }; + leds { compatible = "gpio-leds"; pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; @@ -140,6 +207,10 @@ cpu-supply = <&vdd_arm>; }; +&dfi { + status = "okay"; +}; + &gmac2io { assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; diff --git a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts index 5826d7799..ee37573d6 100644 --- a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts +++ b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts @@ -42,6 +42,21 @@ status = "okay"; }; +&dmc_opp_table { + opp-1056000000 { + status = "disabled"; + }; + opp-924000000 { + status = "disabled"; + }; + opp-840000000 { + status = "disabled"; + }; + opp-798000000 { + status = "disabled"; + }; +}; + &sys_led { label = "orangepi-r1-plus-lts:red:sys"; }; diff --git a/target/linux/rockchip/patches-5.18/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch b/target/linux/rockchip/patches-5.18/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch new file mode 100644 index 000000000..8eea25381 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch @@ -0,0 +1,50 @@ +From e5b5361651940ff5c0c1784dfd0130abec7ab535 Mon Sep 17 00:00:00 2001 +From: wevsty +Date: Mon, 24 Aug 2020 02:27:11 +0800 +Subject: [PATCH] arm64: dts: rockchip: add hardware random number generator + for RK3328 and RK3399 + +Adding Hardware Random Number Generator Resources to the RK3328 and RK3399. + +Signed-off-by: wevsty +--- + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -279,6 +279,17 @@ + status = "disabled"; + }; + ++ rng: rng@ff060000 { ++ compatible = "rockchip,cryptov1-rng"; ++ reg = <0x0 0xff060000 0x0 0x4000>; ++ ++ clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO_SLV>; ++ clock-names = "clk_crypto", "hclk_crypto"; ++ assigned-clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO_SLV>; ++ assigned-clock-rates = <150000000>, <100000000>; ++ status = "disabled"; ++ }; ++ + grf: syscon@ff100000 { + compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd"; + reg = <0x0 0xff100000 0x0 0x1000>; +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1937,6 +1937,16 @@ + }; + }; + ++ rng: rng@ff8b8000 { ++ compatible = "rockchip,cryptov1-rng"; ++ reg = <0x0 0xff8b8000 0x0 0x1000>; ++ clocks = <&cru SCLK_CRYPTO1>, <&cru HCLK_S_CRYPTO1>; ++ clock-names = "clk_crypto", "hclk_crypto"; ++ assigned-clocks = <&cru SCLK_CRYPTO1>, <&cru HCLK_S_CRYPTO1>; ++ assigned-clock-rates = <150000000>, <100000000>; ++ status = "okay"; ++ }; ++ + gpu: gpu@ff9a0000 { + compatible = "rockchip,rk3399-mali", "arm,mali-t860"; + reg = <0x0 0xff9a0000 0x0 0x10000>; diff --git a/target/linux/rockchip/patches-5.18/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch b/target/linux/rockchip/patches-5.18/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch new file mode 100644 index 000000000..ef06b0d59 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch @@ -0,0 +1,44 @@ +From fcd9629c05f373771e85920e1c1d0ab252617878 Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 13:53:25 +0800 +Subject: [PATCH] PM / devfreq: rockchip: add devfreq driver for rk3328 dmc + +Signed-off-by: hmz007 +--- + drivers/devfreq/Kconfig | 18 +- + drivers/devfreq/Makefile | 1 + + drivers/devfreq/rk3328_dmc.c | 846 +++++++++++++++++++++++++++++++++++ + 3 files changed, 862 insertions(+), 3 deletions(-) + create mode 100644 drivers/devfreq/rk3328_dmc.c + +--- a/drivers/devfreq/Kconfig ++++ b/drivers/devfreq/Kconfig +@@ -120,6 +120,18 @@ config ARM_TEGRA_DEVFREQ + It reads ACTMON counters of memory controllers and adjusts the + operating frequencies and voltages with OPP support. + ++config ARM_RK3328_DMC_DEVFREQ ++ tristate "ARM RK3328 DMC DEVFREQ Driver" ++ depends on ARCH_ROCKCHIP ++ select DEVFREQ_EVENT_ROCKCHIP_DFI ++ select DEVFREQ_GOV_SIMPLE_ONDEMAND ++ select PM_DEVFREQ_EVENT ++ select PM_OPP ++ help ++ This adds the DEVFREQ driver for the RK3328 DMC(Dynamic Memory Controller). ++ It sets the frequency for the memory controller and reads the usage counts ++ from hardware. ++ + config ARM_RK3399_DMC_DEVFREQ + tristate "ARM RK3399 DMC DEVFREQ Driver" + depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \ +--- a/drivers/devfreq/Makefile ++++ b/drivers/devfreq/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += gov + obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o + obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.o + obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o ++obj-$(CONFIG_ARM_RK3328_DMC_DEVFREQ) += rk3328_dmc.o + obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o + obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o + diff --git a/target/linux/rockchip/patches-5.18/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch b/target/linux/rockchip/patches-5.18/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch new file mode 100644 index 000000000..0408a0a73 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch @@ -0,0 +1,210 @@ +From ce6d3614888e6358466f0e84e248177a6bca5258 Mon Sep 17 00:00:00 2001 +From: Tang Yun ping +Date: Thu, 4 May 2017 20:49:58 +0800 +Subject: [PATCH] clk: rockchip: support setting ddr clock via SIP Version 2 + APIs + +commit 764e893ee82321938fc6f4349e9e7caf06a04410 rockchip. + +Signed-off-by: Tang Yun ping +Signed-off-by: hmz007 +--- + drivers/clk/rockchip/clk-ddr.c | 130 ++++++++++++++++++++++++++++ + drivers/clk/rockchip/clk-rk3328.c | 7 +- + drivers/clk/rockchip/clk.h | 3 +- + include/soc/rockchip/rockchip_sip.h | 11 +++ + 4 files changed, 147 insertions(+), 4 deletions(-) + +--- a/drivers/clk/rockchip/clk-ddr.c ++++ b/drivers/clk/rockchip/clk-ddr.c +@@ -87,6 +87,133 @@ static const struct clk_ops rockchip_ddr + .get_parent = rockchip_ddrclk_get_parent, + }; + ++/* See v4.4/include/dt-bindings/display/rk_fb.h */ ++#define SCREEN_NULL 0 ++#define SCREEN_HDMI 6 ++ ++static inline int rk_drm_get_lcdc_type(void) ++{ ++ return SCREEN_NULL; ++} ++ ++struct share_params { ++ u32 hz; ++ u32 lcdc_type; ++ u32 vop; ++ u32 vop_dclk_mode; ++ u32 sr_idle_en; ++ u32 addr_mcu_el3; ++ /* ++ * 1: need to wait flag1 ++ * 0: never wait flag1 ++ */ ++ u32 wait_flag1; ++ /* ++ * 1: need to wait flag1 ++ * 0: never wait flag1 ++ */ ++ u32 wait_flag0; ++ u32 complt_hwirq; ++ /* if need, add parameter after */ ++}; ++ ++struct rockchip_ddrclk_data { ++ u32 inited_flag; ++ void __iomem *share_memory; ++}; ++ ++static struct rockchip_ddrclk_data ddr_data; ++ ++static void rockchip_ddrclk_data_init(void) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_SHARE_MEM, ++ 1, SHARE_PAGE_TYPE_DDR, 0, ++ 0, 0, 0, 0, &res); ++ ++ if (!res.a0) { ++ ddr_data.share_memory = (void __iomem *)ioremap(res.a1, 1<<12); ++ ddr_data.inited_flag = 1; ++ } ++} ++ ++static int rockchip_ddrclk_sip_set_rate_v2(struct clk_hw *hw, ++ unsigned long drate, ++ unsigned long prate) ++{ ++ struct share_params *p; ++ struct arm_smccc_res res; ++ ++ if (!ddr_data.inited_flag) ++ rockchip_ddrclk_data_init(); ++ ++ p = (struct share_params *)ddr_data.share_memory; ++ ++ p->hz = drate; ++ p->lcdc_type = rk_drm_get_lcdc_type(); ++ p->wait_flag1 = 1; ++ p->wait_flag0 = 1; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE, ++ 0, 0, 0, 0, &res); ++ ++ if ((int)res.a1 == -6) { ++ pr_err("%s: timeout, drate = %lumhz\n", __func__, drate/1000000); ++ /* TODO: rockchip_dmcfreq_wait_complete(); */ ++ } ++ ++ return res.a0; ++} ++ ++static unsigned long rockchip_ddrclk_sip_recalc_rate_v2 ++ (struct clk_hw *hw, unsigned long parent_rate) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE, ++ 0, 0, 0, 0, &res); ++ if (!res.a0) ++ return res.a1; ++ else ++ return 0; ++} ++ ++static long rockchip_ddrclk_sip_round_rate_v2(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long *prate) ++{ ++ struct share_params *p; ++ struct arm_smccc_res res; ++ ++ if (!ddr_data.inited_flag) ++ rockchip_ddrclk_data_init(); ++ ++ p = (struct share_params *)ddr_data.share_memory; ++ ++ p->hz = rate; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE, ++ 0, 0, 0, 0, &res); ++ if (!res.a0) ++ return res.a1; ++ else ++ return 0; ++} ++ ++static const struct clk_ops rockchip_ddrclk_sip_ops_v2 = { ++ .recalc_rate = rockchip_ddrclk_sip_recalc_rate_v2, ++ .set_rate = rockchip_ddrclk_sip_set_rate_v2, ++ .round_rate = rockchip_ddrclk_sip_round_rate_v2, ++ .get_parent = rockchip_ddrclk_get_parent, ++}; ++ + struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, + const char *const *parent_names, + u8 num_parents, int mux_offset, +@@ -114,6 +241,9 @@ struct clk *rockchip_clk_register_ddrclk + case ROCKCHIP_DDRCLK_SIP: + init.ops = &rockchip_ddrclk_sip_ops; + break; ++ case ROCKCHIP_DDRCLK_SIP_V2: ++ init.ops = &rockchip_ddrclk_sip_ops_v2; ++ break; + default: + pr_err("%s: unsupported ddrclk type %d\n", __func__, ddr_flag); + kfree(ddrclk); +--- a/drivers/clk/rockchip/clk-rk3328.c ++++ b/drivers/clk/rockchip/clk-rk3328.c +@@ -315,9 +315,10 @@ static struct rockchip_clk_branch rk3328 + RK3328_CLKGATE_CON(14), 1, GFLAGS), + + /* PD_DDR */ +- COMPOSITE(0, "clk_ddr", mux_ddrphy_p, CLK_IGNORE_UNUSED, +- RK3328_CLKSEL_CON(3), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, +- RK3328_CLKGATE_CON(0), 4, GFLAGS), ++ COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0, ++ RK3328_CLKSEL_CON(3), 8, 2, 0, 3, ++ ROCKCHIP_DDRCLK_SIP_V2), ++ + GATE(0, "clk_ddrmsch", "clk_ddr", CLK_IGNORE_UNUSED, + RK3328_CLKGATE_CON(18), 6, GFLAGS), + GATE(0, "clk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED, +--- a/drivers/clk/rockchip/clk.h ++++ b/drivers/clk/rockchip/clk.h +@@ -399,7 +399,8 @@ struct clk *rockchip_clk_register_mmc(co + * DDRCLK flags, including method of setting the rate + * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate. + */ +-#define ROCKCHIP_DDRCLK_SIP BIT(0) ++#define ROCKCHIP_DDRCLK_SIP 0x01 ++#define ROCKCHIP_DDRCLK_SIP_V2 0x03 + + struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, + const char *const *parent_names, +--- a/include/soc/rockchip/rockchip_sip.h ++++ b/include/soc/rockchip/rockchip_sip.h +@@ -16,5 +16,16 @@ + #define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06 + #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07 + #define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08 ++#define ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION 0x08 ++ ++#define ROCKCHIP_SIP_SHARE_MEM 0x82000009 ++ ++/* Share mem page types */ ++typedef enum { ++ SHARE_PAGE_TYPE_INVALID = 0, ++ SHARE_PAGE_TYPE_UARTDBG, ++ SHARE_PAGE_TYPE_DDR, ++ SHARE_PAGE_TYPE_MAX, ++} share_page_type_t; + + #endif diff --git a/target/linux/rockchip/patches-5.18/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch b/target/linux/rockchip/patches-5.18/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch new file mode 100644 index 000000000..283e4abd2 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch @@ -0,0 +1,662 @@ +From 4db93c6dad0c71750b86163df2fdb21c35f00d9a Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 12:49:48 +0800 +Subject: [PATCH] PM / devfreq: rockchip-dfi: add more soc support + +Signed-off-by: hmz007 +--- + drivers/devfreq/event/rockchip-dfi.c | 554 ++++++++++++++++++++++++--- + 1 file changed, 505 insertions(+), 49 deletions(-) + +--- a/drivers/devfreq/event/rockchip-dfi.c ++++ b/drivers/devfreq/event/rockchip-dfi.c +@@ -18,25 +18,66 @@ + #include + #include + +-#include +- +-#define RK3399_DMC_NUM_CH 2 ++#define PX30_PMUGRF_OS_REG2 0x208 + ++#define RK3128_GRF_SOC_CON0 0x140 ++#define RK3128_GRF_OS_REG1 0x1cc ++#define RK3128_GRF_DFI_WRNUM 0x220 ++#define RK3128_GRF_DFI_RDNUM 0x224 ++#define RK3128_GRF_DFI_TIMERVAL 0x22c ++#define RK3128_DDR_MONITOR_EN ((1 << (16 + 6)) + (1 << 6)) ++#define RK3128_DDR_MONITOR_DISB ((1 << (16 + 6)) + (0 << 6)) ++ ++#define RK3288_PMU_SYS_REG2 0x9c ++#define RK3288_GRF_SOC_CON4 0x254 ++#define RK3288_GRF_SOC_STATUS(n) (0x280 + (n) * 4) ++#define RK3288_DFI_EN (0x30003 << 14) ++#define RK3288_DFI_DIS (0x30000 << 14) ++#define RK3288_LPDDR_SEL (0x10001 << 13) ++#define RK3288_DDR3_SEL (0x10000 << 13) ++ ++#define RK3328_GRF_OS_REG2 0x5d0 ++ ++#define RK3368_GRF_DDRC0_CON0 0x600 ++#define RK3368_GRF_SOC_STATUS5 0x494 ++#define RK3368_GRF_SOC_STATUS6 0x498 ++#define RK3368_GRF_SOC_STATUS8 0x4a0 ++#define RK3368_GRF_SOC_STATUS9 0x4a4 ++#define RK3368_GRF_SOC_STATUS10 0x4a8 ++#define RK3368_DFI_EN (0x30003 << 5) ++#define RK3368_DFI_DIS (0x30000 << 5) ++ ++#define MAX_DMC_NUM_CH 2 ++#define READ_DRAMTYPE_INFO(n) (((n) >> 13) & 0x7) ++#define READ_CH_INFO(n) (((n) >> 28) & 0x3) + /* DDRMON_CTRL */ +-#define DDRMON_CTRL 0x04 +-#define CLR_DDRMON_CTRL (0x1f0000 << 0) +-#define LPDDR4_EN (0x10001 << 4) +-#define HARDWARE_EN (0x10001 << 3) +-#define LPDDR3_EN (0x10001 << 2) +-#define SOFTWARE_EN (0x10001 << 1) +-#define SOFTWARE_DIS (0x10000 << 1) +-#define TIME_CNT_EN (0x10001 << 0) ++#define DDRMON_CTRL 0x04 ++#define CLR_DDRMON_CTRL (0x3f0000 << 0) ++#define DDR4_EN (0x10001 << 5) ++#define LPDDR4_EN (0x10001 << 4) ++#define HARDWARE_EN (0x10001 << 3) ++#define LPDDR2_3_EN (0x10001 << 2) ++#define SOFTWARE_EN (0x10001 << 1) ++#define SOFTWARE_DIS (0x10000 << 1) ++#define TIME_CNT_EN (0x10001 << 0) + + #define DDRMON_CH0_COUNT_NUM 0x28 + #define DDRMON_CH0_DFI_ACCESS_NUM 0x2c + #define DDRMON_CH1_COUNT_NUM 0x3c + #define DDRMON_CH1_DFI_ACCESS_NUM 0x40 + ++/* pmu grf */ ++#define PMUGRF_OS_REG2 0x308 ++ ++enum { ++ DDR4 = 0, ++ DDR3 = 3, ++ LPDDR2 = 5, ++ LPDDR3 = 6, ++ LPDDR4 = 7, ++ UNUSED = 0xFF ++}; ++ + struct dmc_usage { + u32 access; + u32 total; +@@ -50,33 +91,261 @@ struct dmc_usage { + struct rockchip_dfi { + struct devfreq_event_dev *edev; + struct devfreq_event_desc *desc; +- struct dmc_usage ch_usage[RK3399_DMC_NUM_CH]; ++ struct dmc_usage ch_usage[MAX_DMC_NUM_CH]; + struct device *dev; + void __iomem *regs; + struct regmap *regmap_pmu; ++ struct regmap *regmap_grf; ++ struct regmap *regmap_pmugrf; + struct clk *clk; ++ u32 dram_type; ++ /* ++ * available mask, 1: available, 0: not available ++ * each bit represent a channel ++ */ ++ u32 ch_msk; ++}; ++ ++static void rk3128_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, ++ RK3128_GRF_SOC_CON0, ++ RK3128_DDR_MONITOR_EN); ++} ++ ++static void rk3128_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, ++ RK3128_GRF_SOC_CON0, ++ RK3128_DDR_MONITOR_DISB); ++} ++ ++static int rk3128_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3128_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3128_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3128_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3128_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3128_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ unsigned long flags; ++ u32 dfi_wr, dfi_rd, dfi_timer; ++ ++ local_irq_save(flags); ++ ++ rk3128_dfi_stop_hardware_counter(edev); ++ ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_WRNUM, &dfi_wr); ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_RDNUM, &dfi_rd); ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_TIMERVAL, &dfi_timer); ++ ++ edata->load_count = (dfi_wr + dfi_rd) * 4; ++ edata->total_count = dfi_timer; ++ ++ rk3128_dfi_start_hardware_counter(edev); ++ ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3128_dfi_ops = { ++ .disable = rk3128_dfi_disable, ++ .enable = rk3128_dfi_enable, ++ .get_event = rk3128_dfi_get_event, ++ .set_event = rk3128_dfi_set_event, ++}; ++ ++static void rk3288_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_EN); ++} ++ ++static void rk3288_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_DIS); ++} ++ ++static int rk3288_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3288_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3288_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3288_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3288_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3288_dfi_get_busier_ch(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ u32 tmp, max = 0; ++ u32 i, busier_ch = 0; ++ u32 rd_count, wr_count, total_count; ++ ++ rk3288_dfi_stop_hardware_counter(edev); ++ ++ /* Find out which channel is busier */ ++ for (i = 0; i < MAX_DMC_NUM_CH; i++) { ++ if (!(info->ch_msk & BIT(i))) ++ continue; ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(11 + i * 4), &wr_count); ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(12 + i * 4), &rd_count); ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(14 + i * 4), &total_count); ++ info->ch_usage[i].access = (wr_count + rd_count) * 4; ++ info->ch_usage[i].total = total_count; ++ tmp = info->ch_usage[i].access; ++ if (tmp > max) { ++ busier_ch = i; ++ max = tmp; ++ } ++ } ++ rk3288_dfi_start_hardware_counter(edev); ++ ++ return busier_ch; ++} ++ ++static int rk3288_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ int busier_ch; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ busier_ch = rk3288_dfi_get_busier_ch(edev); ++ local_irq_restore(flags); ++ ++ edata->load_count = info->ch_usage[busier_ch].access; ++ edata->total_count = info->ch_usage[busier_ch].total; ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3288_dfi_ops = { ++ .disable = rk3288_dfi_disable, ++ .enable = rk3288_dfi_enable, ++ .get_event = rk3288_dfi_get_event, ++ .set_event = rk3288_dfi_set_event, ++}; ++ ++static void rk3368_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_EN); ++} ++ ++static void rk3368_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_DIS); ++} ++ ++static int rk3368_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3368_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3368_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3368_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3368_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3368_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ unsigned long flags; ++ u32 dfi0_wr, dfi0_rd, dfi1_wr, dfi1_rd, dfi_timer; ++ ++ local_irq_save(flags); ++ ++ rk3368_dfi_stop_hardware_counter(edev); ++ ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS5, &dfi0_wr); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS6, &dfi0_rd); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS9, &dfi1_wr); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS10, &dfi1_rd); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS8, &dfi_timer); ++ ++ edata->load_count = (dfi0_wr + dfi0_rd + dfi1_wr + dfi1_rd) * 2; ++ edata->total_count = dfi_timer; ++ ++ rk3368_dfi_start_hardware_counter(edev); ++ ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3368_dfi_ops = { ++ .disable = rk3368_dfi_disable, ++ .enable = rk3368_dfi_enable, ++ .get_event = rk3368_dfi_get_event, ++ .set_event = rk3368_dfi_set_event, + }; + + static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev) + { + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + void __iomem *dfi_regs = info->regs; +- u32 val; +- u32 ddr_type; +- +- /* get ddr type */ +- regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); +- ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) & +- RK3399_PMUGRF_DDRTYPE_MASK; + + /* clear DDRMON_CTRL setting */ + writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL); + + /* set ddr type to dfi */ +- if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3) +- writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL); +- else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4) ++ if (info->dram_type == LPDDR3 || info->dram_type == LPDDR2) ++ writel_relaxed(LPDDR2_3_EN, dfi_regs + DDRMON_CTRL); ++ else if (info->dram_type == LPDDR4) + writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL); ++ else if (info->dram_type == DDR4) ++ writel_relaxed(DDR4_EN, dfi_regs + DDRMON_CTRL); + + /* enable count, use software mode */ + writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL); +@@ -100,12 +369,22 @@ static int rockchip_dfi_get_busier_ch(st + rockchip_dfi_stop_hardware_counter(edev); + + /* Find out which channel is busier */ +- for (i = 0; i < RK3399_DMC_NUM_CH; i++) { +- info->ch_usage[i].access = readl_relaxed(dfi_regs + +- DDRMON_CH0_DFI_ACCESS_NUM + i * 20) * 4; ++ for (i = 0; i < MAX_DMC_NUM_CH; i++) { ++ if (!(info->ch_msk & BIT(i))) ++ continue; ++ + info->ch_usage[i].total = readl_relaxed(dfi_regs + + DDRMON_CH0_COUNT_NUM + i * 20); +- tmp = info->ch_usage[i].access; ++ ++ /* LPDDR4 BL = 16,other DDR type BL = 8 */ ++ tmp = readl_relaxed(dfi_regs + ++ DDRMON_CH0_DFI_ACCESS_NUM + i * 20); ++ if (info->dram_type == LPDDR4) ++ tmp *= 8; ++ else ++ tmp *= 4; ++ info->ch_usage[i].access = tmp; ++ + if (tmp > max) { + busier_ch = i; + max = tmp; +@@ -121,7 +400,8 @@ static int rockchip_dfi_disable(struct d + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + + rockchip_dfi_stop_hardware_counter(edev); +- clk_disable_unprepare(info->clk); ++ if (info->clk) ++ clk_disable_unprepare(info->clk); + + return 0; + } +@@ -131,10 +411,13 @@ static int rockchip_dfi_enable(struct de + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + int ret; + +- ret = clk_prepare_enable(info->clk); +- if (ret) { +- dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret); +- return ret; ++ if (info->clk) { ++ ret = clk_prepare_enable(info->clk); ++ if (ret) { ++ dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ++ ret); ++ return ret; ++ } + } + + rockchip_dfi_start_hardware_counter(edev); +@@ -151,8 +434,11 @@ static int rockchip_dfi_get_event(struct + { + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + int busier_ch; ++ unsigned long flags; + ++ local_irq_save(flags); + busier_ch = rockchip_dfi_get_busier_ch(edev); ++ local_irq_restore(flags); + + edata->load_count = info->ch_usage[busier_ch].access; + edata->total_count = info->ch_usage[busier_ch].total; +@@ -167,22 +453,116 @@ static const struct devfreq_event_ops ro + .set_event = rockchip_dfi_set_event, + }; + +-static const struct of_device_id rockchip_dfi_id_match[] = { +- { .compatible = "rockchip,rk3399-dfi" }, +- { }, +-}; +-MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match); ++static __init int px30_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ struct resource *res; ++ u32 val; + +-static int rockchip_dfi_probe(struct platform_device *pdev) ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ data->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(data->regs)) ++ return PTR_ERR(data->regs); ++ ++ node = of_parse_phandle(np, "rockchip,pmugrf", 0); ++ if (node) { ++ data->regmap_pmugrf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_pmugrf)) ++ return PTR_ERR(data->regmap_pmugrf); ++ } ++ ++ regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = 1; ++ data->clk = NULL; ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3128_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) + { +- struct device *dev = &pdev->dev; +- struct rockchip_dfi *data; +- struct devfreq_event_desc *desc; + struct device_node *np = pdev->dev.of_node, *node; + +- data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL); +- if (!data) +- return -ENOMEM; ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ desc->ops = &rk3128_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3288_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ u32 val; ++ ++ node = of_parse_phandle(np, "rockchip,pmu", 0); ++ if (node) { ++ data->regmap_pmu = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_pmu)) ++ return PTR_ERR(data->regmap_pmu); ++ } ++ ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ regmap_read(data->regmap_pmu, RK3288_PMU_SYS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = READ_CH_INFO(val); ++ ++ if (data->dram_type == DDR3) ++ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, ++ RK3288_DDR3_SEL); ++ else ++ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, ++ RK3288_LPDDR_SEL); ++ ++ desc->ops = &rk3288_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3368_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device *dev = &pdev->dev; ++ ++ if (!dev->parent || !dev->parent->of_node) ++ return -EINVAL; ++ ++ data->regmap_grf = syscon_node_to_regmap(dev->parent->of_node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ ++ desc->ops = &rk3368_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rockchip_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = pdev->dev.of_node, *node; ++ u32 val; + + data->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(data->regs)) +@@ -202,21 +582,97 @@ static int rockchip_dfi_probe(struct pla + if (IS_ERR(data->regmap_pmu)) + return PTR_ERR(data->regmap_pmu); + } +- data->dev = dev; ++ ++ regmap_read(data->regmap_pmu, PMUGRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = READ_CH_INFO(val); ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3328_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ struct resource *res; ++ u32 val; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ data->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(data->regs)) ++ return PTR_ERR(data->regs); ++ ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ regmap_read(data->regmap_grf, RK3328_GRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = 1; ++ data->clk = NULL; ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static const struct of_device_id rockchip_dfi_id_match[] = { ++ { .compatible = "rockchip,px30-dfi", .data = px30_dfi_init }, ++ { .compatible = "rockchip,rk1808-dfi", .data = px30_dfi_init }, ++ { .compatible = "rockchip,rk3128-dfi", .data = rk3128_dfi_init }, ++ { .compatible = "rockchip,rk3288-dfi", .data = rk3288_dfi_init }, ++ { .compatible = "rockchip,rk3328-dfi", .data = rk3328_dfi_init }, ++ { .compatible = "rockchip,rk3368-dfi", .data = rk3368_dfi_init }, ++ { .compatible = "rockchip,rk3399-dfi", .data = rockchip_dfi_init }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match); ++ ++static int rockchip_dfi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rockchip_dfi *data; ++ struct devfreq_event_desc *desc; ++ struct device_node *np = pdev->dev.of_node; ++ const struct of_device_id *match; ++ int (*init)(struct platform_device *pdev, struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc); ++ ++ data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; + + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + +- desc->ops = &rockchip_dfi_ops; ++ match = of_match_node(rockchip_dfi_id_match, pdev->dev.of_node); ++ if (match) { ++ init = match->data; ++ if (init) { ++ if (init(pdev, data, desc)) ++ return -EINVAL; ++ } else { ++ return 0; ++ } ++ } else { ++ return 0; ++ } ++ + desc->driver_data = data; + desc->name = np->name; + data->desc = desc; ++ data->dev = dev; + +- data->edev = devm_devfreq_event_add_edev(&pdev->dev, desc); ++ data->edev = devm_devfreq_event_add_edev(dev, desc); + if (IS_ERR(data->edev)) { +- dev_err(&pdev->dev, +- "failed to add devfreq-event device\n"); ++ dev_err(dev, "failed to add devfreq-event device\n"); + return PTR_ERR(data->edev); + } + diff --git a/target/linux/rockchip/patches-5.18/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch b/target/linux/rockchip/patches-5.18/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch new file mode 100644 index 000000000..d9c5f944d --- /dev/null +++ b/target/linux/rockchip/patches-5.18/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch @@ -0,0 +1,27 @@ +From f9ae6e992d3d9e80357fee7d65ba0fe2dd37ae1f Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 14:21:51 +0800 +Subject: [PATCH] arm64: dts: rockchip: rk3328: add dfi node + +Signed-off-by: hmz007 +[adjusted commit title] +Signed-off-by: Tianling Shen +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 7 +++++++ + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -1010,6 +1010,13 @@ + status = "disabled"; + }; + ++ dfi: dfi@ff790000 { ++ reg = <0x00 0xff790000 0x00 0x400>; ++ compatible = "rockchip,rk3328-dfi"; ++ rockchip,grf = <&grf>; ++ status = "disabled"; ++ }; ++ + gic: interrupt-controller@ff811000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; diff --git a/target/linux/rockchip/patches-5.18/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch b/target/linux/rockchip/patches-5.18/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch new file mode 100644 index 000000000..f195f2aa3 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch @@ -0,0 +1,126 @@ +From f9ae6e992d3d9e80357fee7d65ba0fe2dd37ae1f Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 14:21:51 +0800 +Subject: [PATCH] arm64: dts: nanopi-r2: add rk3328-dmc relate node + +Signed-off-by: hmz007 +--- + .../rockchip/rk3328-dram-default-timing.dtsi | 311 ++++++++++++++++++ + .../dts/rockchip/rk3328-nanopi-r2-common.dtsi | 85 ++++- + include/dt-bindings/clock/rockchip-ddr.h | 63 ++++ + include/dt-bindings/memory/rk3328-dram.h | 159 +++++++++ + 4 files changed, 617 insertions(+), 1 deletion(-) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi + create mode 100644 include/dt-bindings/clock/rockchip-ddr.h + create mode 100644 include/dt-bindings/memory/rk3328-dram.h + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -7,6 +7,7 @@ + + #include + #include ++#include "rk3328-dram-nanopi2-timing.dtsi" + #include "rk3328.dtsi" + + / { +@@ -119,6 +120,72 @@ + regulator-boot-on; + vin-supply = <&vdd_5v>; + }; ++ ++ dmc: dmc { ++ compatible = "rockchip,rk3328-dmc"; ++ devfreq-events = <&dfi>; ++ center-supply = <&vdd_log>; ++ clocks = <&cru SCLK_DDRCLK>; ++ clock-names = "dmc_clk"; ++ operating-points-v2 = <&dmc_opp_table>; ++ ddr_timing = <&ddr_timing>; ++ upthreshold = <40>; ++ downdifferential = <20>; ++ auto-min-freq = <786000>; ++ auto-freq-en = <0>; ++ #cooling-cells = <2>; ++ status = "okay"; ++ ++ ddr_power_model: ddr_power_model { ++ compatible = "ddr_power_model"; ++ dynamic-power-coefficient = <120>; ++ static-power-coefficient = <200>; ++ ts = <32000 4700 (-80) 2>; ++ thermal-zone = "soc-thermal"; ++ }; ++ }; ++ ++ dmc_opp_table: dmc-opp-table { ++ compatible = "operating-points-v2"; ++ ++ rockchip,leakage-voltage-sel = < ++ 1 10 0 ++ 11 254 1 ++ >; ++ nvmem-cells = <&logic_leakage>; ++ nvmem-cell-names = "ddr_leakage"; ++ ++ opp-786000000 { ++ opp-hz = /bits/ 64 <786000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-798000000 { ++ opp-hz = /bits/ 64 <798000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-840000000 { ++ opp-hz = /bits/ 64 <840000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-924000000 { ++ opp-hz = /bits/ 64 <924000000>; ++ opp-microvolt = <1100000>; ++ opp-microvolt-L0 = <1100000>; ++ opp-microvolt-L1 = <1075000>; ++ }; ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-microvolt = <1175000>; ++ opp-microvolt-L0 = <1175000>; ++ opp-microvolt-L1 = <1150000>; ++ }; ++ }; + }; + + &cpu0 { +@@ -137,6 +204,10 @@ + cpu-supply = <&vdd_arm>; + }; + ++&dfi { ++ status = "okay"; ++}; ++ + &display_subsystem { + status = "disabled"; + }; +@@ -206,6 +277,7 @@ + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; ++ regulator-init-microvolt = <1075000>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; +@@ -220,6 +292,7 @@ + regulator-name = "vdd_arm"; + regulator-always-on; + regulator-boot-on; ++ regulator-init-microvolt = <1225000>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; diff --git a/target/linux/rockchip/patches-5.18/808-drv-net-phy-add-JLSemi-jl2xxx-driver.patch b/target/linux/rockchip/patches-5.18/808-drv-net-phy-add-JLSemi-jl2xxx-driver.patch new file mode 100644 index 000000000..e2fb70694 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/808-drv-net-phy-add-JLSemi-jl2xxx-driver.patch @@ -0,0 +1,702 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -260,6 +260,11 @@ config INTEL_XWAY_PHY + PEF 7061, PEF 7071 and PEF 7072 or integrated into the Intel + SoCs xRX200, xRX300, xRX330, xRX350 and xRX550. + ++config JLSEMI_JL2XX1_PHY ++ tristate "JLSemi JL2XX1 PHYs" ++ help ++ Currently supports the JLSemi jl2xx1 PHYs. ++ + config LSI_ET1011C_PHY + tristate "LSI ET1011C PHY" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -72,6 +72,8 @@ obj-$(CONFIG_DP83TC811_PHY) += dp83tc811 + obj-$(CONFIG_FIXED_PHY) += fixed_phy.o + obj-$(CONFIG_ICPLUS_PHY) += icplus.o + obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o ++obj-$(CONFIG_JLSEMI_JL2XX1_PHY) += jl2xx1.o ++jl2xx1-objs := jl2xxx.o jl2xxx-core.o + obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o + obj-$(CONFIG_LXT_PHY) += lxt.o + obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o +--- /dev/null ++++ b/drivers/net/phy/jl2xxx-core.c +@@ -0,0 +1,438 @@ ++/* ++ * Copyright (C) 2021 JLSemi Corporation ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++#include "jl2xxx-core.h" ++#include ++#include ++#include ++#include ++ ++#define RGMII_CTRL_PAGE 171 ++#define RGMII_CTRL_REG 17 ++#define RGMII_TX_SW_RSTN BIT(14) ++#define RGMII_ERR_STAS BIT(3) ++#define RGMII_TX_CTR_EN BIT(1) ++ ++#define RGMII_STATUS_PAGE 166 ++#define RGMII_STATUS_REG 18 ++ ++#define BASIC_PAGE 0 ++#define BMCR_REG 0 ++#define SOFT_RESET BIT(15) ++#define SPEED_LSB BIT(13) ++#define AUTONEG_EN BIT(12) ++#define SPEED_MSB BIT(6) ++ ++#define DIG_PAGE 201 ++#define DIG_REG 17 ++#define CLK_10M_EN BIT(15) ++#define DAC_OUT_SEL_MSB BIT(1) ++#define DAC_OUT_SEL_LSB BIT(0) ++ ++/************************* Configuration section *************************/ ++ ++ ++/************************* JLSemi iteration code *************************/ ++ ++/* Patch for version: def2 */ ++uint32_t init_data[] = { ++ 0x1f00a0, 0x1903f3, 0x1f0012, 0x150100, 0x1f00ad, 0x100000, 0x11e0c6, 0x1f00a0, 0x1903fb, 0x1903fb, ++ 0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb, 0x1f00ad, 0x110000, 0x120400, 0x130093, ++ 0x140000, 0x150193, 0x160000, 0x170213, 0x180000, 0x12040c, 0x130293, 0x140000, 0x150313, 0x160000, ++ 0x170393, 0x180000, 0x120418, 0x130413, 0x140000, 0x150493, 0x160000, 0x170513, 0x180000, 0x120424, ++ 0x130593, 0x140000, 0x150613, 0x160000, 0x170693, 0x180000, 0x120430, 0x130713, 0x140000, 0x150793, ++ 0x160000, 0x171137, 0x180000, 0x12043c, 0x13006f, 0x140060, 0x15a001, 0x160113, 0x17fd41, 0x18d026, ++ 0x120448, 0x13d406, 0x14d222, 0x1517b7, 0x160800, 0x17aa23, 0x189407, 0x120454, 0x130713, 0x1430f0, ++ 0x1567b7, 0x160800, 0x17a423, 0x1846e7, 0x120460, 0x13a703, 0x14a587, 0x156685, 0x168f55, 0x17ac23, ++ 0x18a4e7, 0x12046c, 0x1367b9, 0x145737, 0x150800, 0x168793, 0x17ef27, 0x182023, 0x120478, 0x1374f7, ++ 0x1407b7, 0x150800, 0x165bfc, 0x17d493, 0x180037, 0x120484, 0x13f493, 0x141f04, 0x15f793, 0x1607f7, ++ 0x178fc5, 0x18c03e, 0x120490, 0x134702, 0x140793, 0x150210, 0x160763, 0x1700f7, 0x180793, 0x12049c, ++ 0x130270, 0x140c63, 0x1530f7, 0x16a001, 0x1707b7, 0x180002, 0x1204a8, 0x138793, 0x146967, 0x15c83e, ++ 0x1617b7, 0x170002, 0x188793, 0x1204b4, 0x13e567, 0x14c43e, 0x1537b7, 0x160002, 0x178793, 0x186867, ++ 0x1204c0, 0x13c23e, 0x1447b7, 0x150002, 0x168793, 0x17e9a7, 0x1866b7, 0x1204cc, 0x130800, 0x14ca3e, ++ 0x15a783, 0x166d86, 0x1775c1, 0x188713, 0x1204d8, 0x130ff5, 0x148ff9, 0x156735, 0x160713, 0x178007, ++ 0x188fd9, 0x1204e4, 0x13ac23, 0x146cf6, 0x15a783, 0x1665c6, 0x175737, 0x180800, 0x1204f0, 0x136611, ++ 0x14f793, 0x15f0f7, 0x16e793, 0x170807, 0x18ae23, 0x1204fc, 0x1364f6, 0x142783, 0x155c47, 0x169bf5, ++ 0x172223, 0x185cf7, 0x120508, 0x13a703, 0x14f5c6, 0x158f51, 0x16ae23, 0x17f4e6, 0x180737, 0x120514, ++ 0x130809, 0x14433c, 0x158fd1, 0x16c33c, 0x170637, 0x180800, 0x120520, 0x134a74, 0x14679d, 0x158793, ++ 0x160e07, 0x179ae1, 0x18e693, 0x12052c, 0x130036, 0x14ca74, 0x154678, 0x1676e1, 0x178693, 0x185006, ++ 0x120538, 0x138ff9, 0x148fd5, 0x1507c2, 0x168f6d, 0x1783c1, 0x188fd9, 0x120544, 0x13c67c, 0x140713, ++ 0x151000, 0x160793, 0x170000, 0x189c23, 0x120550, 0x1324e7, 0x140713, 0x151010, 0x169123, 0x1726e7, ++ 0x18470d, 0x12055c, 0x13c63a, 0x144702, 0x158d23, 0x162407, 0x17a223, 0x182607, 0x120568, 0x130793, ++ 0x140270, 0x150413, 0x160000, 0x171463, 0x1800f7, 0x120574, 0x134789, 0x14c63e, 0x154709, 0x16cc3a, ++ 0x174702, 0x180793, 0x120580, 0x130270, 0x141463, 0x1500f7, 0x16478d, 0x17cc3e, 0x180513, 0x12058c, ++ 0x130000, 0x144792, 0x154581, 0x164485, 0x179782, 0x184018, 0x120598, 0x131775, 0x14e563, 0x1502e4, ++ 0x162703, 0x170a04, 0x181163, 0x1205a4, 0x130297, 0x144818, 0x150563, 0x160097, 0x1747a2, 0x18c804, ++ 0x1205b0, 0x139782, 0x1466b7, 0x150800, 0x16a703, 0x174c46, 0x189b71, 0x1205bc, 0x136713, 0x140027, ++ 0x15a223, 0x164ce6, 0x174783, 0x180fd4, 0x1205c8, 0x13c7b9, 0x142683, 0x151004, 0x164745, 0x179763, ++ 0x1820e6, 0x1205d4, 0x133737, 0x140822, 0x152683, 0x163007, 0x177645, 0x18167d, 0x1205e0, 0x138ef1, ++ 0x142023, 0x1530d7, 0x162683, 0x172807, 0x18e693, 0x1205ec, 0x131006, 0x142023, 0x1528d7, 0x162683, ++ 0x173807, 0x18e693, 0x1205f8, 0x131006, 0x142023, 0x1538d7, 0x162683, 0x174007, 0x18e693, 0x120604, ++ 0x131006, 0x142023, 0x1540d7, 0x162683, 0x174807, 0x18e693, 0x120610, 0x131006, 0x142023, 0x1548d7, ++ 0x1656b7, 0x170800, 0x18a703, 0x12061c, 0x133486, 0x14830d, 0x158b05, 0x16cf01, 0x17a703, 0x185c46, ++ 0x120628, 0x137671, 0x14167d, 0x158f71, 0x166611, 0x17a223, 0x185ce6, 0x120634, 0x138f51, 0x14a223, ++ 0x155ce6, 0x162703, 0x171084, 0x1846b2, 0x120640, 0x131c63, 0x1402d7, 0x153737, 0x160822, 0x172683, ++ 0x182807, 0x12064c, 0x13e693, 0x140016, 0x152023, 0x1628d7, 0x172683, 0x183807, 0x120658, 0x13e693, ++ 0x140016, 0x152023, 0x1638d7, 0x172683, 0x184007, 0x120664, 0x13e693, 0x140016, 0x152023, 0x1640d7, ++ 0x172683, 0x184807, 0x120670, 0x13e693, 0x140016, 0x152023, 0x1648d7, 0x172703, 0x181004, 0x12067c, ++ 0x1346b2, 0x149c63, 0x151ae6, 0x160737, 0x170800, 0x184b78, 0x120688, 0x130693, 0x140ff0, 0x15463d, ++ 0x168b1d, 0x17ce3a, 0x1852b7, 0x120694, 0x130800, 0x144701, 0x154389, 0x16408d, 0x174311, 0x180537, ++ 0x1206a0, 0x130820, 0x141593, 0x150077, 0x1695aa, 0x17418c, 0x184572, 0x1206ac, 0x1305c2, 0x1481c1, ++ 0x1581a9, 0x167763, 0x1700b5, 0x189533, 0x1206b8, 0x1300e4, 0x144513, 0x15fff5, 0x168e69, 0x170537, ++ 0x180800, 0x1206c4, 0x134568, 0x148121, 0x15893d, 0x167463, 0x1702b5, 0x18a583, 0x1206d0, 0x1306c2, ++ 0x140763, 0x151277, 0x160a63, 0x171217, 0x1805c2, 0x1206dc, 0x1381c1, 0x14818d, 0x150d63, 0x161097, ++ 0x178985, 0x180586, 0x1206e8, 0x1395b3, 0x1400b4, 0x15c593, 0x16fff5, 0x178eed, 0x180705, 0x1206f4, ++ 0x1315e3, 0x14fa67, 0x1535b7, 0x160822, 0x17a703, 0x183005, 0x120700, 0x13757d, 0x148a3d, 0x150513, ++ 0x160ff5, 0x178f69, 0x180622, 0x12070c, 0x138e59, 0x14a023, 0x1530c5, 0x168637, 0x170800, 0x185a38, ++ 0x120718, 0x1375c1, 0x14f693, 0x150ff6, 0x168593, 0x170ff5, 0x188f6d, 0x120724, 0x1306a2, 0x148ed9, ++ 0x15da34, 0x164682, 0x170713, 0x180210, 0x120730, 0x139163, 0x140ee6, 0x154711, 0x16e391, 0x17471d, ++ 0x182023, 0x12073c, 0x1310e4, 0x142683, 0x150a04, 0x16471d, 0x179e63, 0x1800e6, 0x120748, 0x136737, ++ 0x140800, 0x152703, 0x164cc7, 0x170693, 0x184000, 0x120754, 0x137713, 0x144807, 0x151463, 0x1600d7, ++ 0x172223, 0x180e04, 0x120760, 0x134018, 0x141163, 0x150497, 0x165703, 0x1700c4, 0x181793, 0x12076c, ++ 0x130117, 0x14db63, 0x150207, 0x168737, 0x170800, 0x184778, 0x120778, 0x137713, 0x140807, 0x15e705, ++ 0x160513, 0x170000, 0x184792, 0x120784, 0x134581, 0x149782, 0x1547a2, 0x164711, 0x17c818, 0x18c004, ++ 0x120790, 0x130d23, 0x140094, 0x150ca3, 0x160004, 0x179782, 0x1856b7, 0x12079c, 0x130800, 0x1442b8, ++ 0x159b71, 0x16c2b8, 0x170513, 0x180000, 0x1207a8, 0x1347d2, 0x149782, 0x154703, 0x162684, 0x1703e3, ++ 0x18de07, 0x1207b4, 0x13bbd9, 0x1407b7, 0x150002, 0x168793, 0x1765c7, 0x18c83e, 0x1207c0, 0x1327b7, ++ 0x140002, 0x158793, 0x16dae7, 0x17c43e, 0x1847b7, 0x1207cc, 0x130002, 0x148793, 0x151427, 0x16c23e, ++ 0x1757b7, 0x180002, 0x1207d8, 0x138793, 0x149867, 0x15b1fd, 0x162683, 0x171504, 0x184709, 0x1207e4, ++ 0x1399e3, 0x14e2e6, 0x1536b7, 0x160822, 0x17a703, 0x183006, 0x1207f0, 0x13663d, 0x148f51, 0x15a023, ++ 0x1630e6, 0x17bd39, 0x18c593, 0x1207fc, 0x130015, 0x14b5dd, 0x158991, 0x1635b3, 0x1700b0, 0x180589, ++ 0x120808, 0x13bdf9, 0x148991, 0x15b593, 0x160015, 0x17bfdd, 0x180737, 0x120814, 0x130800, 0x144f28, ++ 0x15cf89, 0x1647c2, 0x17893d, 0x189782, 0x120820, 0x1347e2, 0x140713, 0x151000, 0x162223, 0x1710e4, ++ 0x182423, 0x12082c, 0x1310f4, 0x14474d, 0x15b729, 0x168111, 0x17b7dd, 0x1814e3, 0x120838, 0x13f097, ++ 0x140737, 0x150800, 0x164770, 0x171713, 0x180106, 0x120844, 0x135d63, 0x140607, 0x1585b7, 0x160800, ++ 0x17a683, 0x180d05, 0x120850, 0x1372c5, 0x147313, 0x1500f6, 0x1612fd, 0x17a703, 0x180d45, 0x12085c, ++ 0x131513, 0x1400c3, 0x15f6b3, 0x160056, 0x178ec9, 0x18757d, 0x120868, 0x130393, 0x140ff5, 0x151293, ++ 0x160083, 0x17f6b3, 0x180076, 0x120874, 0x139b41, 0x148211, 0x15e2b3, 0x160056, 0x171093, 0x180043, ++ 0x120880, 0x137693, 0x140016, 0x156333, 0x160067, 0x170613, 0x187ff5, 0x12088c, 0x139713, 0x1400b6, ++ 0x157633, 0x1600c3, 0x178e59, 0x189513, 0x120898, 0x1300a6, 0x147613, 0x159ff6, 0x169713, 0x170096, ++ 0x188e49, 0x1208a4, 0x13f293, 0x14f0f2, 0x158e59, 0x16e2b3, 0x170012, 0x1806a2, 0x1208b0, 0x137613, ++ 0x14eff6, 0x158e55, 0x16a823, 0x170c55, 0x18aa23, 0x1208bc, 0x130cc5, 0x1480e3, 0x15e807, 0x1646b7, ++ 0x170822, 0x18a703, 0x1208c8, 0x13f006, 0x149b61, 0x156713, 0x160027, 0x17a023, 0x18f0e6, 0x1208d4, ++ 0x13b5ad, 0x140000, 0x150000, 0x160000, 0x170000, 0x180000, 0x110000, 0x120400, 0x104000, 0x1f0000, ++}; ++ ++int jl2xxx_pre_init(struct phy_device *phydev) ++{ ++ int i, j; ++ int regaddr, val; ++ int length = sizeof(init_data)/sizeof(init_data[0]); ++ ++ for (i = 0; i < length; i++) { ++ regaddr = ((init_data[i] >> 16) & 0xff); ++ val = (init_data[i] & 0xffff); ++ phy_write(phydev, regaddr, val); ++ if (regaddr == 0x18) { ++ phy_write(phydev, 0x10, 0x8006); ++ for (j = 0; j < 8; j++) { ++ if (phy_read(phydev, 0x10) == 0) { ++ break; ++ } ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++int enable_wol(struct phy_device *phydev) ++{ ++ jlsemi_set_bits(phydev, WOL_CTL_PAGE, ++ WOL_CTL_REG, WOL_EN); ++ ++ jlsemi_clear_bits(phydev, WOL_CTL_STAS_PAGE, ++ WOL_CTL_STAS_REG, WOL_CTL_EN); ++ ++ return 0; ++} ++ ++int disable_wol(struct phy_device *phydev) ++{ ++ jlsemi_clear_bits(phydev, WOL_CTL_PAGE, ++ WOL_CTL_REG, WOL_EN); ++ ++ jlsemi_set_bits(phydev, BASIC_PAGE, BMCR_REG, SOFT_RESET); ++ /* wait soft reset complete*/ ++ msleep(20); ++ ++ return 0; ++} ++ ++int setup_wol_low_polarity(struct phy_device *phydev) ++{ ++ jlsemi_clear_bits(phydev, WOL_CTL_STAS_PAGE, ++ WOL_CTL_STAS_REG, WOL_POLARITY); ++ return 0; ++} ++ ++int setup_wol_high_polarity(struct phy_device *phydev) ++{ ++ jlsemi_set_bits(phydev, WOL_CTL_STAS_PAGE, ++ WOL_CTL_STAS_REG, WOL_POLARITY); ++ return 0; ++} ++ ++int clear_wol_event(struct phy_device *phydev) ++{ ++ jlsemi_set_bits(phydev, WOL_CTL_STAS_PAGE, ++ WOL_CTL_STAS_REG, WOL_EVENT); ++ ++ jlsemi_clear_bits(phydev, WOL_CTL_STAS_PAGE, ++ WOL_CTL_STAS_REG, WOL_EVENT); ++ return 0; ++} ++ ++int store_mac_addr(struct phy_device *phydev) ++{ ++ int err; ++ ++ jlsemi_write_page(phydev, WOL_CTL_STAS_PAGE); ++ ++ /* Store the device address for the magic packet */ ++ err = phy_write(phydev, WOL_MAC_ADDR2_REG, ++ ((phydev->attached_dev->dev_addr[0] << 8) | ++ phydev->attached_dev->dev_addr[1])); ++ if (err < 0) ++ return err; ++ err = phy_write(phydev, WOL_MAC_ADDR1_REG, ++ ((phydev->attached_dev->dev_addr[2] << 8) | ++ phydev->attached_dev->dev_addr[3])); ++ if (err < 0) ++ return err; ++ err = phy_write(phydev, WOL_MAC_ADDR0_REG, ++ ((phydev->attached_dev->dev_addr[4] << 8) | ++ phydev->attached_dev->dev_addr[5])); ++ if (err < 0) ++ return err; ++ ++ /* change page to 0 */ ++ jlsemi_write_page(phydev, BASIC_PAGE); ++ ++ return 0; ++} ++ ++int config_phy_info(struct phy_device *phydev, ++ struct jl2xx1_priv *jl2xx1) ++{ ++ int val, major, minor; ++ ++ val = phy_read(phydev, 29); ++ if (val < 0) ++ return val; ++ ++ major = (val >> 7) & 0x1f; ++ minor = (val >> 0) & 0x7f; ++ /* major enlarge 10 */ ++ jl2xx1->sw_info = major * 10 + minor; ++ ++ return 0; ++} ++ ++/********************** Convenience function for phy **********************/ ++ ++/** ++ * jlsemi_write_page() - write the page register ++ * @phydev: a pointer to a &struct phy_device ++ * @page: page values ++ */ ++int jlsemi_write_page(struct phy_device *phydev, int page) ++{ ++ return phy_write(phydev, MII_JLSEMI_PHY_PAGE, page); ++} ++ ++/** ++ * jlsemi_read_page() - write the page register ++ * @phydev: a pointer to a &struct phy_device ++ * ++ * Return: get page values at present ++ */ ++int jlsemi_read_page(struct phy_device *phydev) ++{ ++ return phy_read(phydev, MII_JLSEMI_PHY_PAGE); ++} ++ ++/** ++ * __jlsemi_save_page() - save the page value ++ *@phydev: a pointer to a &struct phy_device ++ * ++ * Return: save page value ++ */ ++static inline int __jlsemi_save_page(struct phy_device *phydev) ++{ ++ return jlsemi_read_page(phydev); ++} ++ ++/** ++ * __jlsemi_select_page() - restore the page register ++ * @phydev: a pointer to a &struct phy_device ++ * @page: the page ++ * ++ * Return: ++ * @oldpgae: this is last page value ++ * @ret: if page is change it will return new page value ++ */ ++static inline int __jlsemi_select_page(struct phy_device *phydev, int page) ++{ ++ int ret, oldpage; ++ ++ oldpage = ret = __jlsemi_save_page(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (oldpage != page) { ++ ret = jlsemi_write_page(phydev, page); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return oldpage; ++} ++ ++/** ++ * __jlsemi_restore_page() - restore the page register ++ * @phydev: a pointer to a &struct phy_device ++ * @oldpage: the old page, return value from __jlsemi_save_page() or ++ * __jlsemi_select_page() ++ * @ret: operation's return code ++ * ++ * Returns: ++ * @oldpage if it was a negative value, otherwise ++ * @ret if it was a negative errno value, otherwise ++ * phy_write_page()'s negative value if it were in error, otherwise ++ * @ret ++ */ ++static inline int __jlsemi_restore_page(struct phy_device *phydev, ++ int oldpage, int ret) ++{ ++ int r; ++ ++ if (oldpage >= 0) { ++ r = jlsemi_write_page(phydev, oldpage); ++ ++ /* Propagate the operation return code if the page write ++ * was successful. ++ */ ++ if (ret >= 0 && r < 0) ++ ret = r; ++ } else { ++ /* Propagate the phy page selection error code */ ++ ret = oldpage; ++ } ++ ++ return ret; ++} ++ ++/** ++ * __jlsemi_modify_reg() - Convenience function for modifying a PHY register ++ * @phydev: a pointer to a &struct phy_device ++ * @regnum: register number ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ * ++ * Returns negative errno, 0 if there was no change, and 1 in case of change ++ */ ++static inline int __jlsemi_modify_reg(struct phy_device *phydev, ++ u32 regnum, u16 mask, u16 set) ++{ ++ int newval, ret; ++ ++ ret = phy_read(phydev, regnum); ++ if (ret < 0) ++ return ret; ++ ++ newval = (ret & ~mask) | set; ++ if (newval == ret) ++ return 0; ++ ++ ret = phy_write(phydev, regnum, newval); ++ ++ return ret < 0 ? ret : 1; ++} ++ ++/** ++ * jlsemi_modify_paged_reg() - Function for modifying a paged register ++ * @phydev: a pointer to a &struct phy_device ++ * @page: the page for the phy ++ * @regnum: register number ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ * ++ * Returns negative errno, 0 if there was no change, and 1 in case of change ++ */ ++int jlsemi_modify_paged_reg(struct phy_device *phydev, ++ int page, u32 regnum, ++ u16 mask, u16 set) ++{ ++ int ret = 0, oldpage; ++ ++ oldpage = __jlsemi_select_page(phydev, page); ++ if (oldpage >= 0) ++ ret = __jlsemi_modify_reg(phydev, regnum, mask, set); ++ ++ return __jlsemi_restore_page(phydev, oldpage, ret); ++} ++ ++/** ++ * jlsemi_set_bits() - Convenience function for setting bits in a PHY register ++ * @phydev: a pointer to a &struct phy_device ++ * @page: the page for the phy ++ * @regnum: register number to write ++ * @val: bits to set ++ */ ++int jlsemi_set_bits(struct phy_device *phydev, ++ int page, u32 regnum, u16 val) ++{ ++ return jlsemi_modify_paged_reg(phydev, page, regnum, 0, val); ++} ++ ++/** ++ * jlsemi_clear_bits - Convenience function for clearing bits in a PHY register ++ * @phydev: the phy_device struct ++ * @page: the page for the phy ++ * @regnum: register number to write ++ * @val: bits to clear ++ */ ++int jlsemi_clear_bits(struct phy_device *phydev, ++ int page, u32 regnum, u16 val) ++{ ++ return jlsemi_modify_paged_reg(phydev, page, regnum, val, 0); ++} ++ ++/** ++ * jlsemi_get_bit() - Convenience function for setting bits in a PHY register ++ * @phydev: a pointer to a &struct phy_device ++ * @page: the page for the phy ++ * @regnum: register number to write ++ * @val: bit to get ++ * ++ * Note: ++ * you only get one bit at meanwhile ++ * ++ */ ++int jlsemi_get_bit(struct phy_device *phydev, ++ int page, u32 regnum, u16 val) ++{ ++ int ret = 0, oldpage; ++ ++ oldpage = __jlsemi_select_page(phydev, page); ++ if (oldpage >= 0) ++ { ++ ret = phy_read(phydev, regnum); ++ if (ret < 0) ++ return ret; ++ ret = ((ret & val) == val) ? 1 : 0; ++ } ++ ++ return __jlsemi_restore_page(phydev, oldpage, ret); ++} +--- /dev/null ++++ b/drivers/net/phy/jl2xxx-core.h +@@ -0,0 +1,104 @@ ++/* ++ * Copyright (C) 2021 JLSemi Corporation ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++#ifndef _JLSEMI_CORE_H ++#define _JLSEMI_CORE_H ++ ++#include ++#include ++#include ++ ++#define JL2XX1_PHY_ID 0x937c4030 ++#define JLSEMI_PHY_ID_MASK 0xfffffff0 ++ ++#define JL2101_PHY_ID 0x937c4032 ++ ++#define MII_JLSEMI_PHY_PAGE 0x1f ++ ++#define WOL_CTL_PAGE 18 ++#define WOL_CTL_REG 21 ++#define WOL_CTL_STAS_PAGE 4608 ++#define WOL_CTL_STAS_REG 16 ++#define WOL_MAC_ADDR2_REG 17 ++#define WOL_MAC_ADDR1_REG 18 ++#define WOL_MAC_ADDR0_REG 19 ++#define WOL_EVENT BIT(1) ++#define WOL_POLARITY BIT(14) ++#define WOL_EN BIT(6) ++#define WOL_CTL_EN BIT(15) ++ ++ ++/************************* Configuration section *************************/ ++ ++#define JLSEMI_WOL_EN 0 ++ ++ ++/************************* JLSemi iteration code *************************/ ++struct jl2xx1_priv { ++ u16 sw_info; ++}; ++ ++int jl2xxx_pre_init(struct phy_device *phydev); ++ ++int config_phy_info(struct phy_device *phydev, ++ struct jl2xx1_priv *jl2xx1); ++ ++int check_rgmii(struct phy_device *phydev); ++ ++int dis_rgmii_tx_ctrl(struct phy_device *phydev); ++ ++int config_suspend(struct phy_device *phydev); ++ ++int config_resume(struct phy_device *phydev); ++ ++int enable_wol(struct phy_device *phydev); ++ ++int disable_wol(struct phy_device *phydev); ++ ++int setup_wol_low_polarity(struct phy_device *phydev); ++ ++int setup_wol_high_polarity(struct phy_device *phydev); ++ ++int clear_wol_event(struct phy_device *phydev); ++ ++int store_mac_addr(struct phy_device *phydev); ++ ++int software_version(struct phy_device *phydev); ++ ++ ++/********************** Convenience function for phy **********************/ ++ ++/* Notice: You should change page 0 when you When you call it after*/ ++int jlsemi_write_page(struct phy_device *phydev, int page); ++ ++int jlsemi_read_page(struct phy_device *phydev); ++ ++int jlsemi_modify_paged_reg(struct phy_device *phydev, ++ int page, u32 regnum, ++ u16 mask, u16 set); ++ ++int jlsemi_set_bits(struct phy_device *phydev, ++ int page, u32 regnum, u16 val); ++ ++int jlsemi_clear_bits(struct phy_device *phydev, ++ int page, u32 regnum, u16 val); ++ ++int jlsemi_get_bit(struct phy_device *phydev, ++ int page, u32 regnum, u16 val); ++ ++int jlsemi_drivers_register(struct phy_driver *phydrvs, int size); ++ ++void jlsemi_drivers_unregister(struct phy_driver *phydrvs, int size); ++ ++#endif /* _JLSEMI_CORE_H */ ++ +--- /dev/null ++++ b/drivers/net/phy/jl2xxx.c +@@ -0,0 +1,126 @@ ++/* ++ * drivers/net/phy/jlsemi.c ++ * ++ * Driver for JLSemi PHYs ++ * ++ * Author: Gangqiao Kuang ++ * ++ * Copyright (c) 2021 JingLue Semiconductor, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++#include "jl2xxx-core.h" ++#include ++#include ++#include ++ ++ ++MODULE_DESCRIPTION("JLSemi PHY driver"); ++MODULE_AUTHOR("Gangqiao Kuang"); ++MODULE_LICENSE("GPL"); ++ ++static int jlsemi_probe(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = jl2xxx_pre_init(phydev); ++ ++ /* wait load complete*/ ++ msleep(20); ++ ++ return (err < 0) ? err : 0; ++} ++ ++#if JLSEMI_WOL_EN ++static void jlsemi_get_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int wol_en; ++ ++ wol->supported = WAKE_MAGIC; ++ wol->wolopts = 0; ++ ++ wol_en = jlsemi_get_bit(phydev, WOL_CTL_PAGE, ++ WOL_CTL_REG, WOL_EN); ++ ++ if (wol_en) ++ wol->wolopts |= WAKE_MAGIC; ++} ++ ++static int jlsemi_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int err; ++ ++ if (wol->wolopts & WAKE_MAGIC) { ++ err = enable_wol(phydev); ++ if (err < 0) ++ return err; ++ ++ err = clear_wol_event(phydev); ++ if (err < 0) ++ return err; ++ ++ err = setup_wol_high_polarity(phydev); ++ if (err < 0) ++ return err; ++ ++ err = store_mac_addr(phydev); ++ if (err < 0) ++ return err; ++ } else { ++ err = disable_wol(phydev); ++ if (err < 0) ++ return err; ++ ++ err = setup_wol_high_polarity(phydev); ++ if (err < 0) ++ return err; ++ ++ err = clear_wol_event(phydev); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++#endif ++ ++static struct phy_driver jlsemi_driver[] = { ++ { ++ PHY_ID_MATCH_EXACT(JL2101_PHY_ID), ++ .name = "JL2101 Gigabit Ethernet", ++ /* PHY_BASIC_FEATURES */ ++ .features = PHY_GBIT_FEATURES, ++ .probe = jlsemi_probe, ++ #if JLSEMI_WOL_EN ++ .get_wol = jlsemi_get_wol, ++ .set_wol = jlsemi_set_wol, ++ #endif ++ }, ++ { ++ PHY_ID_MATCH_MODEL(JL2XX1_PHY_ID), ++ .name = "JL2xx1 Gigabit Ethernet", ++ /* PHY_BASIC_FEATURES */ ++ .features = PHY_GBIT_FEATURES, ++ .probe = jlsemi_probe, ++ #if JLSEMI_WOL_EN ++ .get_wol = jlsemi_get_wol, ++ .set_wol = jlsemi_set_wol, ++ #endif ++ }, ++}; ++ ++module_phy_driver(jlsemi_driver); ++ ++static struct mdio_device_id __maybe_unused jlsemi_tbl[] = { ++ { PHY_ID_MATCH_EXACT(JL2101_PHY_ID) }, ++ { PHY_ID_MATCH_MODEL(JL2XX1_PHY_ID) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, jlsemi_tbl); diff --git a/target/linux/rockchip/patches-5.18/902-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch b/target/linux/rockchip/patches-5.18/902-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch new file mode 100644 index 000000000..e7c6cb93f --- /dev/null +++ b/target/linux/rockchip/patches-5.18/902-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Leonidas P. Papadakos +Date: Fri, 1 Mar 2019 21:55:53 +0200 +Subject: [PATCH v2] arm64: dts: rockchip: add more cpu operating points for + RK3328 + +This allows for greater max frequency on rk3328 boards, +increasing performance. + +It has been included in Armbian (a linux distibution for ARM boards) +for a while now without any reported issues + +https://github.com/armbian/build/blob/master/patch/kernel/rockchip64-default/enable-1392mhz-opp.patch +https://github.com/armbian/build/blob/master/patch/kernel/rockchip64-default/enable-1512mhz-opp.patch + +Signed-off-by: Leonidas P. Papadakos +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 15 +++++++++++++++ + 1 files changed, 15 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -140,6 +140,21 @@ opp-1296000000 { + opp-microvolt = <1300000>; + clock-latency-ns = <40000>; + }; ++ opp-1392000000 { ++ opp-hz = /bits/ 64 <1392000000>; ++ opp-microvolt = <1350000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <1400000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <1450000>; ++ clock-latency-ns = <40000>; ++ }; + }; + + analog_sound: analog-sound {