rockchip: backport pending driver/dts updates for rk3528
authorTianling Shen <[email protected]>
Sat, 11 Oct 2025 09:04:07 +0000 (17:04 +0800)
committerHauke Mehrtens <[email protected]>
Sat, 15 Nov 2025 18:56:27 +0000 (19:56 +0100)
Backport pending nvmem/thermal/usb updates for rk3528.
These patches are not merged by upstream yet but worthy to have here.

Signed-off-by: Tianling Shen <[email protected]>
Link: https://github.com/openwrt/openwrt/pull/20375
Signed-off-by: Hauke Mehrtens <[email protected]>
12 files changed:
target/linux/rockchip/patches-6.12/160-01-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-handling.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/160-02-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/160-03-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/160-04-phy-rockchip-naneng-combphy-Fix-PCIe-L1ss-support.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/161-01-thermal-rockchip-Change-to-use-bulk-clks.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/161-02-thermal-rockchip-Add-support-for-RK3528.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/162-01-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/162-02-nvmem-rockchip-otp-Add-support-for-RK3568.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/162-03-nvmem-rockchip-otp-Add-support-for-RK3528.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/163-01-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/163-02-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/163-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch [new file with mode: 0644]

diff --git a/target/linux/rockchip/patches-6.12/160-01-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-handling.patch b/target/linux/rockchip/patches-6.12/160-01-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-handling.patch
new file mode 100644 (file)
index 0000000..98d0b2c
--- /dev/null
@@ -0,0 +1,218 @@
+From 4e7d472b61625804f585035a54364a6620bf803a Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <[email protected]>
+Date: Wed, 23 Jul 2025 12:23:00 +0000
+Subject: [PATCH] phy: rockchip: inno-usb2: Simplify rockchip,usbgrf handling
+
+The logic to decide if usbgrf or grf should be used is more complex than
+it needs to be. For RK3568, RV1108 and soon RK3528 we can assign the
+rockchip,usbgrf regmap directly to grf instead of doing a usbgrf and grf
+dance.
+
+Simplify the code to only use the grf regmap and handle the logic of
+what regmap should be used in driver probe instead.
+
+The only expected change from this is that RK3528 can be supported
+because of an addition of a of_property_present() check.
+
+Signed-off-by: Jonas Karlman <[email protected]>
+---
+ drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 68 +++++--------------
+ 1 file changed, 18 insertions(+), 50 deletions(-)
+
+--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+@@ -228,7 +228,6 @@ struct rockchip_usb2phy_port {
+  * struct rockchip_usb2phy - usb2.0 phy driver data.
+  * @dev: pointer to device.
+  * @grf: General Register Files regmap.
+- * @usbgrf: USB General Register Files regmap.
+  * @clks: array of phy input clocks.
+  * @clk480m: clock struct of phy output clk.
+  * @clk480m_hw: clock struct of phy output clk management.
+@@ -246,7 +245,6 @@ struct rockchip_usb2phy_port {
+ struct rockchip_usb2phy {
+       struct device   *dev;
+       struct regmap   *grf;
+-      struct regmap   *usbgrf;
+       struct clk_bulk_data    *clks;
+       struct clk      *clk480m;
+       struct clk_hw   clk480m_hw;
+@@ -261,11 +259,6 @@ struct rockchip_usb2phy {
+       struct rockchip_usb2phy_port    ports[USB2PHY_NUM_PORTS];
+ };
+-static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy)
+-{
+-      return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf;
+-}
+-
+ static inline int property_enable(struct regmap *base,
+                                 const struct usb2phy_reg *reg, bool en)
+ {
+@@ -323,12 +316,11 @@ static int rockchip_usb2phy_clk480m_prep
+ {
+       struct rockchip_usb2phy *rphy =
+               container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+-      struct regmap *base = get_reg_base(rphy);
+       int ret;
+       /* turn on 480m clk output if it is off */
+-      if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
+-              ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
++      if (!property_enabled(rphy->grf, &rphy->phy_cfg->clkout_ctl)) {
++              ret = property_enable(rphy->grf, &rphy->phy_cfg->clkout_ctl, true);
+               if (ret)
+                       return ret;
+@@ -343,19 +335,17 @@ static void rockchip_usb2phy_clk480m_unp
+ {
+       struct rockchip_usb2phy *rphy =
+               container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+-      struct regmap *base = get_reg_base(rphy);
+       /* turn off 480m clk output */
+-      property_enable(base, &rphy->phy_cfg->clkout_ctl, false);
++      property_enable(rphy->grf, &rphy->phy_cfg->clkout_ctl, false);
+ }
+ static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
+ {
+       struct rockchip_usb2phy *rphy =
+               container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+-      struct regmap *base = get_reg_base(rphy);
+-      return property_enabled(base, &rphy->phy_cfg->clkout_ctl);
++      return property_enabled(rphy->grf, &rphy->phy_cfg->clkout_ctl);
+ }
+ static unsigned long
+@@ -577,7 +567,6 @@ static int rockchip_usb2phy_power_on(str
+ {
+       struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
+-      struct regmap *base = get_reg_base(rphy);
+       int ret;
+       dev_dbg(&rport->phy->dev, "port power on\n");
+@@ -589,7 +578,7 @@ static int rockchip_usb2phy_power_on(str
+       if (ret)
+               return ret;
+-      ret = property_enable(base, &rport->port_cfg->phy_sus, false);
++      ret = property_enable(rphy->grf, &rport->port_cfg->phy_sus, false);
+       if (ret) {
+               clk_disable_unprepare(rphy->clk480m);
+               return ret;
+@@ -618,7 +607,6 @@ static int rockchip_usb2phy_power_off(st
+ {
+       struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
+-      struct regmap *base = get_reg_base(rphy);
+       int ret;
+       dev_dbg(&rport->phy->dev, "port power off\n");
+@@ -626,7 +614,7 @@ static int rockchip_usb2phy_power_off(st
+       if (rport->suspended)
+               return 0;
+-      ret = property_enable(base, &rport->port_cfg->phy_sus, true);
++      ret = property_enable(rphy->grf, &rport->port_cfg->phy_sus, true);
+       if (ret)
+               return ret;
+@@ -790,28 +778,22 @@ static const char *chg_to_string(enum po
+ static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
+                                   bool en)
+ {
+-      struct regmap *base = get_reg_base(rphy);
+-
+-      property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
+-      property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en);
++      property_enable(rphy->grf, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
++      property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idp_src_en, en);
+ }
+ static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
+                                           bool en)
+ {
+-      struct regmap *base = get_reg_base(rphy);
+-
+-      property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en);
+-      property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en);
++      property_enable(rphy->grf, &rphy->phy_cfg->chg_det.vdp_src_en, en);
++      property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idm_sink_en, en);
+ }
+ static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
+                                             bool en)
+ {
+-      struct regmap *base = get_reg_base(rphy);
+-
+-      property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en);
+-      property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en);
++      property_enable(rphy->grf, &rphy->phy_cfg->chg_det.vdm_src_en, en);
++      property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idp_sink_en, en);
+ }
+ #define CHG_DCD_POLL_TIME     (100 * HZ / 1000)
+@@ -823,7 +805,6 @@ static void rockchip_chg_detect_work(str
+       struct rockchip_usb2phy_port *rport =
+               container_of(work, struct rockchip_usb2phy_port, chg_work.work);
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
+-      struct regmap *base = get_reg_base(rphy);
+       bool is_dcd, tmout, vout;
+       unsigned long delay;
+@@ -834,7 +815,7 @@ static void rockchip_chg_detect_work(str
+               if (!rport->suspended)
+                       rockchip_usb2phy_power_off(rport->phy);
+               /* put the controller in non-driving mode */
+-              property_enable(base, &rphy->phy_cfg->chg_det.opmode, false);
++              property_enable(rphy->grf, &rphy->phy_cfg->chg_det.opmode, false);
+               /* Start DCD processing stage 1 */
+               rockchip_chg_enable_dcd(rphy, true);
+               rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
+@@ -897,7 +878,7 @@ static void rockchip_chg_detect_work(str
+               fallthrough;
+       case USB_CHG_STATE_DETECTED:
+               /* put the controller in normal mode */
+-              property_enable(base, &rphy->phy_cfg->chg_det.opmode, true);
++              property_enable(rphy->grf, &rphy->phy_cfg->chg_det.opmode, true);
+               rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
+               dev_dbg(&rport->phy->dev, "charger = %s\n",
+                        chg_to_string(rphy->chg_type));
+@@ -1352,29 +1333,14 @@ static int rockchip_usb2phy_probe(struct
+       if (!rphy)
+               return -ENOMEM;
+-      if (!dev->parent || !dev->parent->of_node) {
++      if (!dev->parent || !dev->parent->of_node ||
++          of_property_present(np, "rockchip,usbgrf")) {
+               rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf");
+-              if (IS_ERR(rphy->grf)) {
+-                      dev_err(dev, "failed to locate usbgrf\n");
+-                      return PTR_ERR(rphy->grf);
+-              }
+-      }
+-
+-      else {
+-              rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
+-              if (IS_ERR(rphy->grf))
+-                      return PTR_ERR(rphy->grf);
+-      }
+-
+-      if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) {
+-              rphy->usbgrf =
+-                      syscon_regmap_lookup_by_phandle(dev->of_node,
+-                                                      "rockchip,usbgrf");
+-              if (IS_ERR(rphy->usbgrf))
+-                      return PTR_ERR(rphy->usbgrf);
+       } else {
+-              rphy->usbgrf = NULL;
++              rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
+       }
++      if (IS_ERR(rphy->grf))
++              return PTR_ERR(rphy->grf);
+       if (of_property_read_u32_index(np, "reg", 0, &reg)) {
+               dev_err(dev, "the reg property is not assigned in %pOFn node\n",
diff --git a/target/linux/rockchip/patches-6.12/160-02-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch b/target/linux/rockchip/patches-6.12/160-02-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch
new file mode 100644 (file)
index 0000000..eeb79f5
--- /dev/null
@@ -0,0 +1,123 @@
+From 6b767459cf9295f10ee95b8ab78fbce5991132ed Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <[email protected]>
+Date: Wed, 23 Jul 2025 12:23:02 +0000
+Subject: [PATCH] phy: rockchip: inno-usb2: Add clkout_ctl_phy support
+
+The 480m clk is controlled using regs in the PHY address space and not
+in the USB GRF address space on e.g. RK3528 and RK3506.
+
+Add a clkout_ctl_phy usb2phy_reg to handle enable/disable of the 480m
+clk on these SoCs.
+
+Signed-off-by: Jonas Karlman <[email protected]>
+---
+ drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 47 +++++++++++++++----
+ 1 file changed, 38 insertions(+), 9 deletions(-)
+
+--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+@@ -179,6 +179,7 @@ struct rockchip_usb2phy_cfg {
+       unsigned int    num_ports;
+       int (*phy_tuning)(struct rockchip_usb2phy *rphy);
+       struct usb2phy_reg      clkout_ctl;
++      struct usb2phy_reg      clkout_ctl_phy;
+       const struct rockchip_usb2phy_port_cfg  port_cfgs[USB2PHY_NUM_PORTS];
+       const struct rockchip_chg_det_reg       chg_det;
+ };
+@@ -228,6 +229,7 @@ struct rockchip_usb2phy_port {
+  * struct rockchip_usb2phy - usb2.0 phy driver data.
+  * @dev: pointer to device.
+  * @grf: General Register Files regmap.
++ * @phy_base: USB PHY regmap.
+  * @clks: array of phy input clocks.
+  * @clk480m: clock struct of phy output clk.
+  * @clk480m_hw: clock struct of phy output clk management.
+@@ -245,6 +247,7 @@ struct rockchip_usb2phy_port {
+ struct rockchip_usb2phy {
+       struct device   *dev;
+       struct regmap   *grf;
++      struct regmap   *phy_base;
+       struct clk_bulk_data    *clks;
+       struct clk      *clk480m;
+       struct clk_hw   clk480m_hw;
+@@ -312,15 +315,33 @@ static void rockchip_usb2phy_clk_bulk_di
+       clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks);
+ }
+-static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
++static void
++rockchip_usb2phy_clk480m_clkout_ctl(struct clk_hw *hw, struct regmap **base,
++                                  const struct usb2phy_reg **clkout_ctl)
+ {
+       struct rockchip_usb2phy *rphy =
+               container_of(hw, struct rockchip_usb2phy, clk480m_hw);
++
++      if (rphy->phy_cfg->clkout_ctl_phy.enable) {
++              *base = rphy->phy_base;
++              *clkout_ctl = &rphy->phy_cfg->clkout_ctl_phy;
++      } else {
++              *base = rphy->grf;
++              *clkout_ctl = &rphy->phy_cfg->clkout_ctl;
++      }
++}
++
++static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
++{
++      const struct usb2phy_reg *clkout_ctl;
++      struct regmap *base;
+       int ret;
++      rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
++
+       /* turn on 480m clk output if it is off */
+-      if (!property_enabled(rphy->grf, &rphy->phy_cfg->clkout_ctl)) {
+-              ret = property_enable(rphy->grf, &rphy->phy_cfg->clkout_ctl, true);
++      if (!property_enabled(base, clkout_ctl)) {
++              ret = property_enable(base, clkout_ctl, true);
+               if (ret)
+                       return ret;
+@@ -333,19 +354,23 @@ static int rockchip_usb2phy_clk480m_prep
+ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
+ {
+-      struct rockchip_usb2phy *rphy =
+-              container_of(hw, struct rockchip_usb2phy, clk480m_hw);
++      const struct usb2phy_reg *clkout_ctl;
++      struct regmap *base;
++
++      rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
+       /* turn off 480m clk output */
+-      property_enable(rphy->grf, &rphy->phy_cfg->clkout_ctl, false);
++      property_enable(base, clkout_ctl, false);
+ }
+ static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
+ {
+-      struct rockchip_usb2phy *rphy =
+-              container_of(hw, struct rockchip_usb2phy, clk480m_hw);
++      const struct usb2phy_reg *clkout_ctl;
++      struct regmap *base;
++
++      rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
+-      return property_enabled(rphy->grf, &rphy->phy_cfg->clkout_ctl);
++      return property_enabled(base, clkout_ctl);
+ }
+ static unsigned long
+@@ -1335,9 +1360,13 @@ static int rockchip_usb2phy_probe(struct
+       if (!dev->parent || !dev->parent->of_node ||
+           of_property_present(np, "rockchip,usbgrf")) {
++              rphy->phy_base = device_node_to_regmap(np);
++              if (IS_ERR(rphy->phy_base))
++                      return PTR_ERR(rphy->phy_base);
+               rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf");
+       } else {
+               rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
++              rphy->phy_base = rphy->grf;
+       }
+       if (IS_ERR(rphy->grf))
+               return PTR_ERR(rphy->grf);
diff --git a/target/linux/rockchip/patches-6.12/160-03-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch b/target/linux/rockchip/patches-6.12/160-03-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch
new file mode 100644 (file)
index 0000000..1a77cbf
--- /dev/null
@@ -0,0 +1,125 @@
+From 8faac4ef6206a1c771e1c016e205dcee8164d618 Mon Sep 17 00:00:00 2001
+From: Jianwei Zheng <[email protected]>
+Date: Wed, 23 Jul 2025 12:23:03 +0000
+Subject: [PATCH] phy: rockchip: inno-usb2: Add support for RK3528
+
+The RK3528 has a single USB2PHY with a otg and host port.
+
+Add support for the RK3528 variant of USB2PHY.
+
+PHY tuning for RK3528:
+
+- Turn off differential receiver in suspend mode to save power
+  consumption.
+
+- Set HS eye-height to 400mV instead of default 450mV.
+
+- Choose the Tx fs/ls data as linestate from TX driver for otg port
+  which uses dwc3 controller to improve fs/ls devices compatibility with
+  long cables.
+
+This is based on vendor kernel linux-stan-6.1-rkr5 tag.
+
+Signed-off-by: Jianwei Zheng <[email protected]>
+Signed-off-by: Jonas Karlman <[email protected]>
+---
+ drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 74 +++++++++++++++++++
+ 1 file changed, 74 insertions(+)
+
+--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+@@ -1519,6 +1519,28 @@ static int rk3128_usb2phy_tuning(struct
+                               BIT(2) << BIT_WRITEABLE_SHIFT | 0);
+ }
++static int rk3528_usb2phy_tuning(struct rockchip_usb2phy *rphy)
++{
++      int ret = 0;
++
++      /* Turn off otg port differential receiver in suspend mode */
++      ret |= regmap_write(rphy->phy_base, 0x30, BIT(18) | 0x0000);
++
++      /* Turn off host port differential receiver in suspend mode */
++      ret |= regmap_write(rphy->phy_base, 0x430, BIT(18) | 0x0000);
++
++      /* Set otg port HS eye height to 400mv (default is 450mv) */
++      ret |= regmap_write(rphy->phy_base, 0x30, GENMASK(22, 20) | 0x0000);
++
++      /* Set host port HS eye height to 400mv (default is 450mv) */
++      ret |= regmap_write(rphy->phy_base, 0x430, GENMASK(22, 20) | 0x0000);
++
++      /* Choose the Tx fs/ls data as linestate from TX driver for otg port */
++      ret |= regmap_write(rphy->phy_base, 0x94, GENMASK(22, 19) | 0x0018);
++
++      return ret;
++}
++
+ static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy)
+ {
+       int ret;
+@@ -1901,6 +1923,57 @@ static const struct rockchip_usb2phy_cfg
+       { /* sentinel */ }
+ };
++static const struct rockchip_usb2phy_cfg rk3528_phy_cfgs[] = {
++      {
++              .reg = 0xffdf0000,
++              .num_ports      = 2,
++              .phy_tuning     = rk3528_usb2phy_tuning,
++              .clkout_ctl_phy = { 0x041c, 7, 2, 0, 0x27 },
++              .port_cfgs      = {
++                      [USB2PHY_PORT_OTG] = {
++                              .phy_sus        = { 0x004c, 8, 0, 0, 0x1d1 },
++                              .bvalid_det_en  = { 0x0074, 3, 2, 0, 3 },
++                              .bvalid_det_st  = { 0x0078, 3, 2, 0, 3 },
++                              .bvalid_det_clr = { 0x007c, 3, 2, 0, 3 },
++                              .idfall_det_en  = { 0x0074, 5, 5, 0, 1 },
++                              .idfall_det_st  = { 0x0078, 5, 5, 0, 1 },
++                              .idfall_det_clr = { 0x007c, 5, 5, 0, 1 },
++                              .idrise_det_en  = { 0x0074, 4, 4, 0, 1 },
++                              .idrise_det_st  = { 0x0078, 4, 4, 0, 1 },
++                              .idrise_det_clr = { 0x007c, 4, 4, 0, 1 },
++                              .ls_det_en      = { 0x0074, 0, 0, 0, 1 },
++                              .ls_det_st      = { 0x0078, 0, 0, 0, 1 },
++                              .ls_det_clr     = { 0x007c, 0, 0, 0, 1 },
++                              .utmi_avalid    = { 0x006c, 1, 1, 0, 1 },
++                              .utmi_bvalid    = { 0x006c, 0, 0, 0, 1 },
++                              .utmi_id        = { 0x006c, 6, 6, 0, 1 },
++                              .utmi_ls        = { 0x006c, 5, 4, 0, 1 },
++                      },
++                      [USB2PHY_PORT_HOST] = {
++                              .phy_sus        = { 0x005c, 8, 0, 0x1d2, 0x1d1 },
++                              .ls_det_en      = { 0x0090, 0, 0, 0, 1 },
++                              .ls_det_st      = { 0x0094, 0, 0, 0, 1 },
++                              .ls_det_clr     = { 0x0098, 0, 0, 0, 1 },
++                              .utmi_ls        = { 0x006c, 13, 12, 0, 1 },
++                              .utmi_hstdet    = { 0x006c, 15, 15, 0, 1 },
++                      }
++              },
++              .chg_det = {
++                      .opmode         = { 0x004c, 3, 0, 5, 1 },
++                      .cp_det         = { 0x006c, 19, 19, 0, 1 },
++                      .dcp_det        = { 0x006c, 18, 18, 0, 1 },
++                      .dp_det         = { 0x006c, 20, 20, 0, 1 },
++                      .idm_sink_en    = { 0x0058, 1, 1, 0, 1 },
++                      .idp_sink_en    = { 0x0058, 0, 0, 0, 1 },
++                      .idp_src_en     = { 0x0058, 2, 2, 0, 1 },
++                      .rdm_pdwn_en    = { 0x0058, 3, 3, 0, 1 },
++                      .vdm_src_en     = { 0x0058, 5, 5, 0, 1 },
++                      .vdp_src_en     = { 0x0058, 4, 4, 0, 1 },
++              },
++      },
++      { /* sentinel */ }
++};
++
+ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = {
+       {
+               .reg = 0xfe8a0000,
+@@ -2219,6 +2292,7 @@ static const struct of_device_id rockchi
+       { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
+       { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
+       { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
++      { .compatible = "rockchip,rk3528-usb2phy", .data = &rk3528_phy_cfgs },
+       { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
+       { .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs },
+       { .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
diff --git a/target/linux/rockchip/patches-6.12/160-04-phy-rockchip-naneng-combphy-Fix-PCIe-L1ss-support.patch b/target/linux/rockchip/patches-6.12/160-04-phy-rockchip-naneng-combphy-Fix-PCIe-L1ss-support.patch
new file mode 100644 (file)
index 0000000..4a55a2d
--- /dev/null
@@ -0,0 +1,45 @@
+From: Shawn Lin <[email protected]>
+To: Vinod Koul <[email protected]>
+Cc: Kishon Vijay Abraham I <[email protected]>,
+       Heiko Stuebner <[email protected]>, Yao Zi <[email protected]>,
+       [email protected],
+       [email protected],
+       Shawn Lin <[email protected]>
+Subject: [PATCH] phy: rockchip: naneng-combphy: Fix PCIe L1ss support
+Date: Thu, 13 Nov 2025 11:00:28 +0800  [thread overview]
+Message-ID: <[email protected]> (raw)
+
+Need to control the delay PLL turnoff time if PCIe works on
+L1 PM substates.
+
+Fixes: bbcca4fac873 ("phy: rockchip: naneng-combphy: Add RK3528 support")
+Signed-off-by: Shawn Lin <[email protected]>
+---
+
+ drivers/phy/rockchip/phy-rockchip-naneng-combphy.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
++++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
+@@ -21,6 +21,9 @@
+ #define REF_CLOCK_100MHz              (100 * HZ_PER_MHZ)
+ /* RK3528 COMBO PHY REG */
++#define RK3528_PHYREG5                                0x14
++#define RK3528_PHYREG5_GATE_TX_PCK_SEL                BIT(3)
++#define RK3528_PHYREG5_GATE_TX_PCK_DLY_PLL_OFF        BIT(3)
+ #define RK3528_PHYREG6                                0x18
+ #define RK3528_PHYREG6_PLL_KVCO                       GENMASK(12, 10)
+ #define RK3528_PHYREG6_PLL_KVCO_VALUE         0x2
+@@ -504,6 +507,11 @@ static int rk3528_combphy_cfg(struct roc
+       case REF_CLOCK_100MHz:
+               rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
+               if (priv->type == PHY_TYPE_PCIE) {
++                      /* Gate_tx_pck_sel length select for L1ss support */
++                      rockchip_combphy_updatel(priv, RK3528_PHYREG5_GATE_TX_PCK_SEL,
++                                               RK3528_PHYREG5_GATE_TX_PCK_DLY_PLL_OFF,
++                                               RK3528_PHYREG5);
++
+                       /* PLL KVCO tuning fine */
+                       val = FIELD_PREP(RK3528_PHYREG6_PLL_KVCO, RK3528_PHYREG6_PLL_KVCO_VALUE);
+                       rockchip_combphy_updatel(priv, RK3528_PHYREG6_PLL_KVCO, val,
diff --git a/target/linux/rockchip/patches-6.12/161-01-thermal-rockchip-Change-to-use-bulk-clks.patch b/target/linux/rockchip/patches-6.12/161-01-thermal-rockchip-Change-to-use-bulk-clks.patch
new file mode 100644 (file)
index 0000000..a18b9a0
--- /dev/null
@@ -0,0 +1,83 @@
+From 8d3a5547b908e371998376be106fe2b5cd6aacd4 Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <[email protected]>
+Date: Thu, 13 Mar 2025 17:49:33 +0000
+Subject: [PATCH] thermal: rockchip: Change to use bulk clks
+
+Signed-off-by: Jonas Karlman <[email protected]>
+---
+ drivers/thermal/rockchip_thermal.c | 33 ++++++++++--------------------
+ 1 file changed, 11 insertions(+), 22 deletions(-)
+
+--- a/drivers/thermal/rockchip_thermal.c
++++ b/drivers/thermal/rockchip_thermal.c
+@@ -140,8 +140,8 @@ struct rockchip_thermal_sensor {
+  * @pdev: platform device of thermal
+  * @reset: the reset controller of tsadc
+  * @sensors: array of thermal sensors
+- * @clk: the controller clock is divided by the exteral 24MHz
+- * @pclk: the advanced peripherals bus clock
++ * @clks: array of clks, e.g. controller and advanced peripherals bus clock
++ * @num_clks: the number of clks
+  * @grf: the general register file will be used to do static set by software
+  * @regs: the base address of tsadc controller
+  * @trim_base: major component of sensor trim value, in Celsius
+@@ -159,8 +159,8 @@ struct rockchip_thermal_data {
+       struct rockchip_thermal_sensor *sensors;
+-      struct clk *clk;
+-      struct clk *pclk;
++      struct clk_bulk_data *clks;
++      int num_clks;
+       struct regmap *grf;
+       void __iomem *regs;
+@@ -1741,15 +1741,11 @@ static int rockchip_thermal_probe(struct
+               return dev_err_probe(&pdev->dev, PTR_ERR(thermal->reset),
+                                    "failed to get tsadc reset.\n");
+-      thermal->clk = devm_clk_get_enabled(&pdev->dev, "tsadc");
+-      if (IS_ERR(thermal->clk))
+-              return dev_err_probe(&pdev->dev, PTR_ERR(thermal->clk),
+-                                   "failed to get tsadc clock.\n");
+-
+-      thermal->pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk");
+-      if (IS_ERR(thermal->pclk))
+-              return dev_err_probe(&pdev->dev, PTR_ERR(thermal->pclk),
+-                                   "failed to get apb_pclk clock.\n");
++      thermal->num_clks = devm_clk_bulk_get_all_enabled(&pdev->dev,
++                                                        &thermal->clks);
++      if (thermal->num_clks < 0)
++              return dev_err_probe(&pdev->dev, thermal->num_clks,
++                                   "failed to get clocks.\n");
+       rockchip_thermal_reset_controller(thermal->reset);
+@@ -1831,8 +1827,7 @@ static int __maybe_unused rockchip_therm
+       thermal->chip->control(thermal->regs, false);
+-      clk_disable(thermal->pclk);
+-      clk_disable(thermal->clk);
++      clk_bulk_disable(thermal->num_clks, thermal->clks);
+       pinctrl_pm_select_sleep_state(dev);
+@@ -1848,16 +1843,10 @@ static int __maybe_unused rockchip_therm
+       int error;
+       int i;
+-      error = clk_enable(thermal->clk);
++      error = clk_bulk_enable(thermal->num_clks, thermal->clks);
+       if (error)
+               return error;
+-      error = clk_enable(thermal->pclk);
+-      if (error) {
+-              clk_disable(thermal->clk);
+-              return error;
+-      }
+-
+       rockchip_thermal_reset_controller(thermal->reset);
+       tsadc->initialize(thermal->grf, thermal->regs, thermal->tshut_polarity);
diff --git a/target/linux/rockchip/patches-6.12/161-02-thermal-rockchip-Add-support-for-RK3528.patch b/target/linux/rockchip/patches-6.12/161-02-thermal-rockchip-Add-support-for-RK3528.patch
new file mode 100644 (file)
index 0000000..cf070b7
--- /dev/null
@@ -0,0 +1,199 @@
+From ddd86340a007963e8e893555d64f66b63a174ff7 Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <[email protected]>
+Date: Thu, 13 Mar 2025 22:51:45 +0000
+Subject: [PATCH] thermal: rockchip: Add support for RK3528
+
+Signed-off-by: Jonas Karlman <[email protected]>
+---
+ drivers/thermal/rockchip_thermal.c | 117 +++++++++++++++++++++++++++++
+ 1 file changed, 117 insertions(+)
+
+--- a/drivers/thermal/rockchip_thermal.c
++++ b/drivers/thermal/rockchip_thermal.c
+@@ -206,6 +206,7 @@ struct rockchip_thermal_data {
+ #define TSADCV2_AUTO_PERIOD_HT                        0x6c
+ #define TSADCV3_AUTO_PERIOD                   0x154
+ #define TSADCV3_AUTO_PERIOD_HT                        0x158
++#define TSADCV9_Q_MAX                         0x210
+ #define TSADCV2_AUTO_EN                               BIT(0)
+ #define TSADCV2_AUTO_EN_MASK                  BIT(16)
+@@ -216,6 +217,7 @@ struct rockchip_thermal_data {
+ #define TSADCV2_AUTO_TSHUT_POLARITY_MASK      BIT(24)
+ #define TSADCV3_AUTO_Q_SEL_EN                 BIT(1)
++#define TSADCV3_AUTO_Q_SEL_EN_MASK            BIT(17)
+ #define TSADCV2_INT_SRC_EN(chn)                       BIT(chn)
+ #define TSADCV2_INT_SRC_EN_MASK(chn)          BIT(16 + (chn))
+@@ -229,6 +231,7 @@ struct rockchip_thermal_data {
+ #define TSADCV2_DATA_MASK                     0xfff
+ #define TSADCV3_DATA_MASK                     0x3ff
+ #define TSADCV4_DATA_MASK                     0x1ff
++#define TSADCV5_DATA_MASK                     0x7ff
+ #define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT      4
+ #define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT    4
+@@ -241,6 +244,9 @@ struct rockchip_thermal_data {
+ #define TSADCV5_AUTO_PERIOD_HT_TIME           1622 /* 2.5ms */
+ #define TSADCV6_AUTO_PERIOD_TIME              5000 /* 2.5ms */
+ #define TSADCV6_AUTO_PERIOD_HT_TIME           5000 /* 2.5ms */
++#define TSADCV7_AUTO_PERIOD_TIME              3000 /* 2.5ms */
++#define TSADCV7_AUTO_PERIOD_HT_TIME           3000 /* 2.5ms */
++#define TSADCV3_Q_MAX_VAL                     0x7ff /* 11bit 2047 */
+ #define TSADCV2_USER_INTER_PD_SOC             0x340 /* 13 clocks */
+ #define TSADCV5_USER_INTER_PD_SOC             0xfc0 /* 97us, at least 90us */
+@@ -251,6 +257,8 @@ struct rockchip_thermal_data {
+ #define PX30_GRF_SOC_CON2                     0x0408
++#define RK3528_GRF_TSADC_CON                  0x0030
++
+ #define RK3568_GRF_TSADC_CON                  0x0600
+ #define RK3568_GRF_TSADC_ANA_REG0             (0x10001 << 0)
+ #define RK3568_GRF_TSADC_ANA_REG1             (0x10001 << 1)
+@@ -522,6 +530,45 @@ static const struct tsadc_table rk3399_c
+       {TSADCV3_DATA_MASK, 125000},
+ };
++static const struct tsadc_table rk3528_code_table[] = {
++      {0, -40000},
++      {1410, -40000},
++      {1419, -35000},
++      {1428, -30000},
++      {1436, -25000},
++      {1445, -20000},
++      {1454, -15000},
++      {1463, -10000},
++      {1471, -5000},
++      {1480, 0},
++      {1489, 5000},
++      {1498, 10000},
++      {1506, 15000},
++      {1515, 20000},
++      {1524, 25000},
++      {1533, 30000},
++      {1541, 35000},
++      {1550, 40000},
++      {1558, 45000},
++      {1567, 50000},
++      {1575, 55000},
++      {1584, 60000},
++      {1593, 65000},
++      {1602, 70000},
++      {1610, 75000},
++      {1619, 80000},
++      {1628, 85000},
++      {1637, 90000},
++      {1646, 95000},
++      {1654, 100000},
++      {1663, 105000},
++      {1672, 110000},
++      {1680, 115000},
++      {1689, 120000},
++      {1697, 125000},
++      {TSADCV5_DATA_MASK, 125000},
++};
++
+ static const struct tsadc_table rk3568_code_table[] = {
+       {0, -40000},
+       {1584, -40000},
+@@ -859,6 +906,40 @@ static void rk_tsadcv8_initialize(struct
+                              regs + TSADCV2_AUTO_CON);
+ }
++static void rk_tsadcv11_initialize(struct regmap *grf, void __iomem *regs,
++                                 enum tshut_polarity tshut_polarity)
++{
++      writel_relaxed(TSADCV7_AUTO_PERIOD_TIME,
++                     regs + TSADCV3_AUTO_PERIOD);
++      writel_relaxed(TSADCV7_AUTO_PERIOD_HT_TIME,
++                     regs + TSADCV3_AUTO_PERIOD_HT);
++      writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
++                     regs + TSADCV3_HIGHT_INT_DEBOUNCE);
++      writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
++                     regs + TSADCV3_HIGHT_TSHUT_DEBOUNCE);
++      writel_relaxed(TSADCV3_Q_MAX_VAL,
++                     regs + TSADCV9_Q_MAX);
++      writel_relaxed(TSADCV3_AUTO_Q_SEL_EN | TSADCV3_AUTO_Q_SEL_EN_MASK,
++                     regs + TSADCV2_AUTO_CON);
++
++      if (tshut_polarity == TSHUT_HIGH_ACTIVE)
++              writel_relaxed(TSADCV2_AUTO_TSHUT_POLARITY_HIGH |
++                             TSADCV2_AUTO_TSHUT_POLARITY_MASK,
++                             regs + TSADCV2_AUTO_CON);
++      else
++              writel_relaxed(TSADCV2_AUTO_TSHUT_POLARITY_MASK,
++                             regs + TSADCV2_AUTO_CON);
++
++      if (!IS_ERR(grf)) {
++              regmap_write(grf, RK3528_GRF_TSADC_CON, RK3568_GRF_TSADC_TSEN);
++              udelay(15);
++              regmap_write(grf, RK3528_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG0);
++              regmap_write(grf, RK3528_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG1);
++              regmap_write(grf, RK3528_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG2);
++              usleep_range(100, 200);
++      }
++}
++
+ static void rk_tsadcv2_irq_ack(void __iomem *regs)
+ {
+       u32 val;
+@@ -1094,6 +1175,15 @@ static int rk_tsadcv2_get_trim_code(cons
+       return code - base_code;
+ }
++static int rk_tsadcv3_get_trim_code(const struct chip_tsadc_table *table,
++                                  int code, int trim_base, int trim_base_frac)
++{
++      int temp = trim_base * 1000 + trim_base_frac * 100;
++      u32 base_code = rk_tsadcv2_temp_to_code(table, temp);
++
++      return (TSADCV3_Q_MAX_VAL - code) - base_code;
++}
++
+ static const struct rockchip_tsadc_chip px30_tsadc_data = {
+       /* cpu, gpu */
+       .chn_offset = 0,
+@@ -1292,6 +1382,29 @@ static const struct rockchip_tsadc_chip
+       },
+ };
++static const struct rockchip_tsadc_chip rk3528_tsadc_data = {
++      /* soc */
++      .chn_offset = 0,
++      .chn_num = 1, /* one channel for tsadc */
++      .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
++      .tshut_temp = 95000,
++      .initialize = rk_tsadcv11_initialize,
++      .irq_ack = rk_tsadcv4_irq_ack,
++      .control = rk_tsadcv4_control,
++      .get_temp = rk_tsadcv4_get_temp,
++      .set_alarm_temp = rk_tsadcv3_alarm_temp,
++      .set_tshut_temp = rk_tsadcv3_tshut_temp,
++      .set_tshut_mode = rk_tsadcv4_tshut_mode,
++      .get_trim_code = rk_tsadcv3_get_trim_code,
++      .trim_slope = 574,
++      .table = {
++              .id = rk3528_code_table,
++              .length = ARRAY_SIZE(rk3528_code_table),
++              .data_mask = TSADCV5_DATA_MASK,
++              .mode = ADC_INCREMENT,
++      },
++};
++
+ static const struct rockchip_tsadc_chip rk3568_tsadc_data = {
+       /* cpu, gpu */
+       .chn_offset = 0,
+@@ -1396,6 +1509,10 @@ static const struct of_device_id of_rock
+               .data = (void *)&rk3399_tsadc_data,
+       },
+       {
++              .compatible = "rockchip,rk3528-tsadc",
++              .data = (void *)&rk3528_tsadc_data,
++      },
++      {
+               .compatible = "rockchip,rk3568-tsadc",
+               .data = (void *)&rk3568_tsadc_data,
+       },
diff --git a/target/linux/rockchip/patches-6.12/162-01-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch b/target/linux/rockchip/patches-6.12/162-01-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch
new file mode 100644 (file)
index 0000000..c339e61
--- /dev/null
@@ -0,0 +1,172 @@
+From 7f6f8fc3ee62f6eb633320c7989d4ba502787e3c Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <[email protected]>
+Date: Sun, 16 Mar 2025 19:18:58 +0000
+Subject: [PATCH] nvmem: rockchip-otp: Handle internal word_size in main
+ reg_read op
+
+Rockchip SoCs RK3576 and RK3588 read data from the OTP using 32-bit
+words instead of normal 8-bit bytes. Similar RK3506, RK3528, RK3562 and
+RK3568 will read data from OTP using 16-bit words.
+
+The nvmem core stride and word_size cannot fully be used as cells is not
+always aligned. Continue to report a stride=1 and word_size=1 in
+nvmem_config and instead handle use of SoC specific word_size internally
+in the driver.
+
+Move current SoC specific word_size handling from the RK3588 read_reg
+operation to the main read_reg operation to help simplify the SoC
+specific read_reg operation and allow code reuse in a future RK3568
+reg_read operation.
+
+Signed-off-by: Jonas Karlman <[email protected]>
+Reviewed-by: Heiko Stuebner <[email protected]>
+Tested-by: Heiko Stuebner <[email protected]>
+---
+ drivers/nvmem/rockchip-otp.c | 72 ++++++++++++++++++++----------------
+ 1 file changed, 40 insertions(+), 32 deletions(-)
+
+--- a/drivers/nvmem/rockchip-otp.c
++++ b/drivers/nvmem/rockchip-otp.c
+@@ -59,7 +59,6 @@
+ #define RK3588_OTPC_AUTO_EN           0x08
+ #define RK3588_OTPC_INT_ST            0x84
+ #define RK3588_OTPC_DOUT0             0x20
+-#define RK3588_NBYTES                 4
+ #define RK3588_BURST_NUM              1
+ #define RK3588_BURST_SHIFT            8
+ #define RK3588_ADDR_SHIFT             16
+@@ -69,6 +68,7 @@
+ struct rockchip_data {
+       int size;
+       int read_offset;
++      int word_size;
+       const char * const *clks;
+       int num_clks;
+       nvmem_reg_read_t reg_read;
+@@ -185,48 +185,28 @@ read_end:
+ }
+ static int rk3588_otp_read(void *context, unsigned int offset,
+-                         void *val, size_t bytes)
++                         void *val, size_t count)
+ {
+       struct rockchip_otp *otp = context;
+-      unsigned int addr_start, addr_end, addr_len;
+-      int ret, i = 0;
+-      u32 data;
+-      u8 *buf;
+-
+-      addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES;
+-      addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES;
+-      addr_len = addr_end - addr_start;
+-      addr_start += otp->data->read_offset / RK3588_NBYTES;
+-
+-      buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL);
+-      if (!buf)
+-              return -ENOMEM;
++      u32 *buf = val;
++      int ret;
+-      while (addr_len--) {
+-              writel((addr_start << RK3588_ADDR_SHIFT) |
++      while (count--) {
++              writel((offset++ << RK3588_ADDR_SHIFT) |
+                      (RK3588_BURST_NUM << RK3588_BURST_SHIFT),
+                      otp->base + RK3588_OTPC_AUTO_CTRL);
+               writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN);
+               ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST,
+                                              RK3588_RD_DONE);
+-              if (ret < 0) {
++              if (ret) {
+                       dev_err(otp->dev, "timeout during read setup\n");
+-                      goto read_end;
++                      return ret;
+               }
+-              data = readl(otp->base + RK3588_OTPC_DOUT0);
+-              memcpy(&buf[i], &data, RK3588_NBYTES);
+-
+-              i += RK3588_NBYTES;
+-              addr_start++;
++              *buf++ = readl(otp->base + RK3588_OTPC_DOUT0);
+       }
+-      memcpy(val, buf + offset % RK3588_NBYTES, bytes);
+-
+-read_end:
+-      kfree(buf);
+-
+       return ret;
+ }
+@@ -234,7 +214,7 @@ static int rockchip_otp_read(void *conte
+                            void *val, size_t bytes)
+ {
+       struct rockchip_otp *otp = context;
+-      int ret;
++      int ret, word_size;
+       if (!otp->data || !otp->data->reg_read)
+               return -EINVAL;
+@@ -245,8 +225,34 @@ static int rockchip_otp_read(void *conte
+               return ret;
+       }
+-      ret = otp->data->reg_read(context, offset, val, bytes);
++      offset += otp->data->read_offset;
++      word_size = otp->data->word_size;
++
++      if (word_size > 1) {
++              unsigned int addr_start, addr_end;
++              size_t count;
++              u8 *buf;
++
++              addr_start = offset / word_size;
++              addr_end = DIV_ROUND_UP(offset + bytes, word_size);
++              count = addr_end - addr_start;
++
++              buf = kzalloc(array_size(count, word_size), GFP_KERNEL);
++              if (!buf) {
++                      ret = -ENOMEM;
++                      goto err;
++              }
++
++              ret = otp->data->reg_read(context, addr_start, buf, count);
++              if (!ret)
++                      memcpy(val, buf + (offset % word_size), bytes);
++
++              kfree(buf);
++      } else {
++              ret = otp->data->reg_read(context, offset, val, bytes);
++      }
++err:
+       clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks);
+       return ret;
+@@ -259,7 +265,7 @@ static struct nvmem_config otp_config =
+       .type = NVMEM_TYPE_OTP,
+       .read_only = true,
+       .stride = 1,
+-      .word_size = 1,
++      .word_size = sizeof(u8),
+       .reg_read = rockchip_otp_read,
+ };
+@@ -277,6 +283,7 @@ static const struct rockchip_data px30_d
+ static const struct rockchip_data rk3576_data = {
+       .size = 0x100,
+       .read_offset = 0x700,
++      .word_size = sizeof(u32),
+       .clks = px30_otp_clocks,
+       .num_clks = ARRAY_SIZE(px30_otp_clocks),
+       .reg_read = rk3588_otp_read,
+@@ -289,6 +296,7 @@ static const char * const rk3588_otp_clo
+ static const struct rockchip_data rk3588_data = {
+       .size = 0x400,
+       .read_offset = 0xc00,
++      .word_size = sizeof(u32),
+       .clks = rk3588_otp_clocks,
+       .num_clks = ARRAY_SIZE(rk3588_otp_clocks),
+       .reg_read = rk3588_otp_read,
diff --git a/target/linux/rockchip/patches-6.12/162-02-nvmem-rockchip-otp-Add-support-for-RK3568.patch b/target/linux/rockchip/patches-6.12/162-02-nvmem-rockchip-otp-Add-support-for-RK3568.patch
new file mode 100644 (file)
index 0000000..98c3a31
--- /dev/null
@@ -0,0 +1,115 @@
+From 24ddbf99c76a352cc1931ccb5118bca0656034b8 Mon Sep 17 00:00:00 2001
+From: Finley Xiao <[email protected]>
+Date: Tue, 15 Apr 2025 18:32:02 +0800
+Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3568
+
+This adds the necessary data for handling otp the rk3568.
+
+Signed-off-by: Finley Xiao <[email protected]>
+Signed-off-by: Kever Yang <[email protected]>
+Reviewed-by: Heiko Stuebner <[email protected]>
+Tested-by: Heiko Stuebner <[email protected]>
+Signed-off-by: Jonas Karlman <[email protected]>
+---
+ drivers/nvmem/rockchip-otp.c | 69 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 69 insertions(+)
+
+--- a/drivers/nvmem/rockchip-otp.c
++++ b/drivers/nvmem/rockchip-otp.c
+@@ -27,6 +27,7 @@
+ #define OTPC_USER_CTRL                        0x0100
+ #define OTPC_USER_ADDR                        0x0104
+ #define OTPC_USER_ENABLE              0x0108
++#define OTPC_USER_QP                  0x0120
+ #define OTPC_USER_Q                   0x0124
+ #define OTPC_INT_STATUS                       0x0304
+ #define OTPC_SBPI_CMD0_OFFSET         0x1000
+@@ -184,6 +185,58 @@ read_end:
+       return ret;
+ }
++static int rk3568_otp_read(void *context, unsigned int offset, void *val,
++                         size_t count)
++{
++      struct rockchip_otp *otp = context;
++      u16 *buf = val;
++      u32 otp_qp;
++      int ret;
++
++      ret = rockchip_otp_reset(otp);
++      if (ret) {
++              dev_err(otp->dev, "failed to reset otp phy\n");
++              return ret;
++      }
++
++      ret = rockchip_otp_ecc_enable(otp, true);
++      if (ret) {
++              dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
++              return ret;
++      }
++
++      writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
++      udelay(5);
++
++      while (count--) {
++              writel(offset++ | OTPC_USER_ADDR_MASK,
++                     otp->base + OTPC_USER_ADDR);
++              writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
++                     otp->base + OTPC_USER_ENABLE);
++
++              ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS,
++                                             OTPC_USER_DONE);
++              if (ret) {
++                      dev_err(otp->dev, "timeout during read setup\n");
++                      goto read_end;
++              }
++
++              otp_qp = readl(otp->base + OTPC_USER_QP);
++              if (((otp_qp & 0xc0) == 0xc0) || (otp_qp & 0x20)) {
++                      ret = -EIO;
++                      dev_err(otp->dev, "ecc check error during read setup\n");
++                      goto read_end;
++              }
++
++              *buf++ = readl(otp->base + OTPC_USER_Q);
++      }
++
++read_end:
++      writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
++
++      return ret;
++}
++
+ static int rk3588_otp_read(void *context, unsigned int offset,
+                          void *val, size_t count)
+ {
+@@ -280,6 +333,18 @@ static const struct rockchip_data px30_d
+       .reg_read = px30_otp_read,
+ };
++static const char * const rk3568_otp_clocks[] = {
++      "otp", "apb_pclk", "phy", "sbpi",
++};
++
++static const struct rockchip_data rk3568_data = {
++      .size = 0x80,
++      .word_size = sizeof(u16),
++      .clks = rk3568_otp_clocks,
++      .num_clks = ARRAY_SIZE(rk3568_otp_clocks),
++      .reg_read = rk3568_otp_read,
++};
++
+ static const struct rockchip_data rk3576_data = {
+       .size = 0x100,
+       .read_offset = 0x700,
+@@ -312,6 +377,10 @@ static const struct of_device_id rockchi
+               .data = &px30_data,
+       },
+       {
++              .compatible = "rockchip,rk3568-otp",
++              .data = &rk3568_data,
++      },
++      {
+               .compatible = "rockchip,rk3576-otp",
+               .data = &rk3576_data,
+       },
diff --git a/target/linux/rockchip/patches-6.12/162-03-nvmem-rockchip-otp-Add-support-for-RK3528.patch b/target/linux/rockchip/patches-6.12/162-03-nvmem-rockchip-otp-Add-support-for-RK3528.patch
new file mode 100644 (file)
index 0000000..eed7271
--- /dev/null
@@ -0,0 +1,45 @@
+From 249b07e24d3d1d47b7ec23d5f09a56837b66d7f5 Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <[email protected]>
+Date: Sun, 16 Mar 2025 00:05:45 +0000
+Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3528
+
+Add support for the OTP controller in RK3528. The OTPC is similar to the
+OTPC in RK3562 and RK3568, exept for a missing phy clock and reset.
+
+Signed-off-by: Jonas Karlman <[email protected]>
+---
+ drivers/nvmem/rockchip-otp.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/nvmem/rockchip-otp.c
++++ b/drivers/nvmem/rockchip-otp.c
+@@ -333,6 +333,18 @@ static const struct rockchip_data px30_d
+       .reg_read = px30_otp_read,
+ };
++static const char * const rk3528_otp_clocks[] = {
++      "otp", "apb_pclk", "sbpi",
++};
++
++static const struct rockchip_data rk3528_data = {
++      .size = 0x80,
++      .word_size = sizeof(u16),
++      .clks = rk3528_otp_clocks,
++      .num_clks = ARRAY_SIZE(rk3528_otp_clocks),
++      .reg_read = rk3568_otp_read,
++};
++
+ static const char * const rk3568_otp_clocks[] = {
+       "otp", "apb_pclk", "phy", "sbpi",
+ };
+@@ -377,6 +389,10 @@ static const struct of_device_id rockchi
+               .data = &px30_data,
+       },
+       {
++              .compatible = "rockchip,rk3528-otp",
++              .data = &rk3528_data,
++      },
++      {
+               .compatible = "rockchip,rk3568-otp",
+               .data = &rk3568_data,
+       },
diff --git a/target/linux/rockchip/patches-6.12/163-01-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch b/target/linux/rockchip/patches-6.12/163-01-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch
new file mode 100644 (file)
index 0000000..ebd710c
--- /dev/null
@@ -0,0 +1,71 @@
+From 8a50a4471e4b0db33a74c01229a7ad386918344b Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <[email protected]>
+Date: Sun, 16 Mar 2025 00:06:43 +0000
+Subject: [PATCH] arm64: dts: rockchip: Enable OTP controller for RK3528
+
+Enable the One Time Programmable Controller (OTPC) in RK3528 and add
+an initial nvmem fixed layout.
+
+Signed-off-by: Jonas Karlman <[email protected]>
+---
+ arch/arm64/boot/dts/rockchip/rk3528.dtsi | 49 ++++++++++++++++++++++++
+ 1 file changed, 49 insertions(+)
+
+--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+@@ -1190,6 +1190,55 @@
+                       status = "disabled";
+               };
++              otp: nvmem@ffce0000 {
++                      compatible = "rockchip,rk3528-otp";
++                      reg = <0x0 0xffce0000 0x0 0x4000>;
++                      clocks = <&cru CLK_USER_OTPC_NS>,
++                               <&cru PCLK_OTPC_NS>,
++                               <&cru CLK_SBPI_OTPC_NS>;
++                      clock-names = "otp", "apb_pclk", "sbpi";
++                      resets = <&cru SRST_USER_OTPC_NS>,
++                               <&cru SRST_P_OTPC_NS>,
++                               <&cru SRST_SBPI_OTPC_NS>;
++                      reset-names = "otp", "apb", "sbpi";
++
++                      nvmem-layout {
++                              compatible = "fixed-layout";
++                              #address-cells = <1>;
++                              #size-cells = <1>;
++
++                              cpu_code: cpu-code@2 {
++                                      reg = <0x02 0x2>;
++                              };
++
++                              otp_cpu_version: cpu-version@8 {
++                                      reg = <0x08 0x1>;
++                                      bits = <3 3>;
++                              };
++
++                              otp_id: id@a {
++                                      reg = <0x0a 0x10>;
++                              };
++
++                              cpu_leakage: cpu-leakage@1a {
++                                      reg = <0x1a 0x1>;
++                              };
++
++                              logic_leakage: logic-leakage@1b {
++                                      reg = <0x1b 0x1>;
++                              };
++
++                              gpu_leakage: gpu-leakage@1c {
++                                      reg = <0x1c 0x1>;
++                              };
++
++                              tsadc_trim: tsadc-trim@44 {
++                                      reg = <0x44 0x2>;
++                                      bits = <0 10>;
++                              };
++                      };
++              };
++
+               dmac: dma-controller@ffd60000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0x0 0xffd60000 0x0 0x4000>;
diff --git a/target/linux/rockchip/patches-6.12/163-02-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch b/target/linux/rockchip/patches-6.12/163-02-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch
new file mode 100644 (file)
index 0000000..041cb4f
--- /dev/null
@@ -0,0 +1,117 @@
+From a41519d8b438adc154debd433c3a1436ebb93a10 Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <[email protected]>
+Date: Wed, 23 Jul 2025 12:23:05 +0000
+Subject: [PATCH] arm64: dts: rockchip: Add USB nodes for RK3528
+
+Rockchip RK3528 has one USB 3.0 DWC3 controller, a USB 2.0 EHCI/OHCI
+controller and uses a USB2PHY for USB 2.0. The DWC3 controller may also
+use the Naneng Combo PHY for USB3.
+
+Add device tree nodes to describe these USB controllers along with the
+USB 2.0 PHYs.
+
+Signed-off-by: Jonas Karlman <[email protected]>
+---
+ arch/arm64/boot/dts/rockchip/rk3528.dtsi | 77 ++++++++++++++++++++++++
+ 1 file changed, 77 insertions(+)
+
+--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+@@ -336,6 +336,30 @@
+                       };
+               };
++              usb_host0_xhci: usb@fe500000 {
++                      compatible = "rockchip,rk3528-dwc3", "snps,dwc3";
++                      reg = <0x0 0xfe500000 0x0 0x400000>;
++                      clocks = <&cru CLK_REF_USB3OTG>,
++                               <&cru CLK_SUSPEND_USB3OTG>,
++                               <&cru ACLK_USB3OTG>;
++                      clock-names = "ref_clk", "suspend_clk", "bus_clk";
++                      interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
++                      power-domains = <&power RK3528_PD_VPU>;
++                      resets = <&cru SRST_A_USB3OTG>;
++                      dr_mode = "otg";
++                      phy_type = "utmi_wide";
++                      snps,dis_enblslpm_quirk;
++                      snps,dis_rxdet_inp3_quirk;
++                      snps,dis-del-phy-power-chg-quirk;
++                      snps,dis-tx-ipgap-linecheck-quirk;
++                      snps,dis-u1-entry-quirk;
++                      snps,dis-u2-entry-quirk;
++                      snps,dis-u2-freeclk-exists-quirk;
++                      snps,parkmode-disable-hs-quirk;
++                      snps,parkmode-disable-ss-quirk;
++                      status = "disabled";
++              };
++
+               gic: interrupt-controller@fed01000 {
+                       compatible = "arm,gic-400";
+                       reg = <0x0 0xfed01000 0 0x1000>,
+@@ -349,6 +373,30 @@
+                       #interrupt-cells = <3>;
+               };
++              usb_host0_ehci: usb@ff100000 {
++                      compatible = "generic-ehci";
++                      reg = <0x0 0xff100000 0x0 0x40000>;
++                      clocks = <&cru HCLK_USBHOST>, <&cru HCLK_USBHOST_ARB>,
++                               <&usb2phy>;
++                      interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
++                      phys = <&usb2phy_host>;
++                      phy-names = "usb";
++                      power-domains = <&power RK3528_PD_VO>;
++                      status = "disabled";
++              };
++
++              usb_host0_ohci: usb@ff140000 {
++                      compatible = "generic-ohci";
++                      reg = <0x0 0xff140000 0x0 0x40000>;
++                      clocks = <&cru HCLK_USBHOST>, <&cru HCLK_USBHOST_ARB>,
++                               <&usb2phy>;
++                      interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
++                      phys = <&usb2phy_host>;
++                      phy-names = "usb";
++                      power-domains = <&power RK3528_PD_VO>;
++                      status = "disabled";
++              };
++
+               qos_crypto_a: qos@ff200000 {
+                       compatible = "rockchip,rk3528-qos", "syscon";
+                       reg = <0x0 0xff200000 0x0 0x20>;
+@@ -1275,6 +1323,35 @@
+                       rockchip,pipe-phy-grf = <&pipe_phy_grf>;
+                       status = "disabled";
+               };
++
++              usb2phy: usb2phy@ffdf0000 {
++                      compatible = "rockchip,rk3528-usb2phy";
++                      reg = <0x0 0xffdf0000 0x0 0x10000>;
++                      clocks = <&cru CLK_REF_USBPHY>, <&cru PCLK_USBPHY>;
++                      clock-names = "phyclk", "pclk";
++                      #clock-cells = <0>;
++                      clock-output-names = "clk_usbphy_480m";
++                      power-domains = <&power RK3528_PD_VO>;
++                      rockchip,usbgrf = <&vo_grf>;
++                      status = "disabled";
++
++                      usb2phy_otg: otg-port {
++                              interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
++                                           <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
++                                           <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupt-names = "otg-bvalid", "otg-id",
++                                                "linestate";
++                              #phy-cells = <0>;
++                              status = "disabled";
++                      };
++
++                      usb2phy_host: host-port {
++                              interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
++                              interrupt-names = "linestate";
++                              #phy-cells = <0>;
++                              status = "disabled";
++                      };
++              };
+       };
+ };
diff --git a/target/linux/rockchip/patches-6.12/163-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch b/target/linux/rockchip/patches-6.12/163-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch
new file mode 100644 (file)
index 0000000..21d609e
--- /dev/null
@@ -0,0 +1,146 @@
+From bcc0886b4d25cc9d82e4aa0cfa78c1268c3fcb86 Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <[email protected]>
+Date: Thu, 13 Mar 2025 22:48:27 +0000
+Subject: [PATCH] arm64: dts: rockchip: Add TSADC controller for RK3528
+
+Signed-off-by: Jonas Karlman <[email protected]>
+---
+ arch/arm64/boot/dts/rockchip/rk3528.dtsi | 78 ++++++++++++++++++++++++
+ 1 file changed, 78 insertions(+)
+
+--- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi
+@@ -9,6 +9,7 @@
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/phy/phy.h>
+ #include <dt-bindings/pinctrl/rockchip.h>
++#include <dt-bindings/thermal/thermal.h>
+ #include <dt-bindings/clock/rockchip,rk3528-cru.h>
+ #include <dt-bindings/power/rockchip,rk3528-power.h>
+ #include <dt-bindings/reset/rockchip,rk3528-cru.h>
+@@ -55,6 +56,7 @@
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       clocks = <&scmi_clk SCMI_CLK_CPU>;
++                      #cooling-cells = <2>;
+                       operating-points-v2 = <&cpu_opp_table>;
+               };
+@@ -64,6 +66,7 @@
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       clocks = <&scmi_clk SCMI_CLK_CPU>;
++                      #cooling-cells = <2>;
+                       operating-points-v2 = <&cpu_opp_table>;
+               };
+@@ -73,6 +76,7 @@
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       clocks = <&scmi_clk SCMI_CLK_CPU>;
++                      #cooling-cells = <2>;
+                       operating-points-v2 = <&cpu_opp_table>;
+               };
+@@ -82,6 +86,7 @@
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       clocks = <&scmi_clk SCMI_CLK_CPU>;
++                      #cooling-cells = <2>;
+                       operating-points-v2 = <&cpu_opp_table>;
+               };
+       };
+@@ -255,6 +260,51 @@
+               };
+       };
++      thermal-zones {
++              soc_thermal: soc-thermal {
++                      polling-delay-passive = <20>;
++                      polling-delay = <1000>;
++                      sustainable-power = <638>;
++                      thermal-sensors = <&tsadc 0>;
++
++                      trips {
++                              threshold: trip-point-0 {
++                                      temperature = <70000>;
++                                      hysteresis = <2000>;
++                                      type = "passive";
++                              };
++                              target: trip-point-1 {
++                                      temperature = <85000>;
++                                      hysteresis = <2000>;
++                                      type = "passive";
++                              };
++                              soc_crit: soc-crit {
++                                      temperature = <95000>;
++                                      hysteresis = <2000>;
++                                      type = "critical";
++                              };
++                      };
++
++                      cooling-maps {
++                              map0 {
++                                      trip = <&target>;
++                                      cooling-device =
++                                              <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
++                                              <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
++                                              <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
++                                              <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
++                                      contribution = <2048>;
++                              };
++                              map1 {
++                                      trip = <&target>;
++                                      cooling-device =
++                                              <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
++                                      contribution = <1024>;
++                              };
++                      };
++              };
++      };
++
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+@@ -689,6 +739,7 @@
+                       assigned-clock-rates = <297000000>, <300000000>;
+                       clocks = <&cru ACLK_GPU_MALI>, <&scmi_clk SCMI_CLK_GPU>;
+                       clock-names = "bus", "core";
++                      #cooling-cells = <2>;
+                       interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
+@@ -1031,6 +1082,33 @@
+                       status = "disabled";
+               };
++              tsadc: tsadc@ffad0000 {
++                      compatible = "rockchip,rk3528-tsadc";
++                      reg = <0x0 0xffad0000 0x0 0x400>;
++                      assigned-clocks = <&cru CLK_TSADC>, <&cru CLK_TSADC_TSEN>;
++                      assigned-clock-rates = <1200000>, <12000000>;
++                      clocks = <&cru CLK_TSADC>, <&cru PCLK_TSADC>,
++                               <&cru CLK_TSADC_TSEN>;
++                      clock-names = "tsadc", "apb_pclk", "tsen";
++                      interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
++                      power-domains = <&power RK3528_PD_VPU>;
++                      resets = <&cru SRST_P_TSADC>, <&cru SRST_TSADC>;
++                      reset-names = "tsadc-apb", "tsadc";
++                      rockchip,grf = <&vpu_grf>;
++                      rockchip,hw-tshut-mode = <0>;
++                      rockchip,hw-tshut-polarity = <0>;
++                      rockchip,hw-tshut-temp = <100000>;
++                      #thermal-sensor-cells = <1>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      sensor@0 {
++                              reg = <0>;
++                              nvmem-cells = <&tsadc_trim>;
++                              nvmem-cell-names = "trim";
++                      };
++              };
++
+               saradc: adc@ffae0000 {
+                       compatible = "rockchip,rk3528-saradc";
+                       reg = <0x0 0xffae0000 0x0 0x10000>;