-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
nanopi-zero2: add USB support for RK3528 (current + edge) #9500
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
rubycomm
wants to merge
4
commits into
armbian:main
Choose a base branch
from
rubycomm:nanopi-zero2-usb-support-v2
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+942
−0
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
9dd7624
rockchip64: add USB support for RK3528 / NanoPi Zero2 (6.18 + 7.0)
rubycomm 52549b5
rockchip64: fix USB patches for RK3528 (6.18 + 7.0)
rubycomm 689a999
rockchip64: rk3528: change USB-C dr_mode from host to otg (6.18 + 7.0)
rubycomm 07c7868
rockchip64: rk3528: fix USB PHY regmap and revert dr_mode to host (6.…
rubycomm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
284 changes: 284 additions & 0 deletions
284
...nel/archive/rockchip64-6.18/rk3528-10-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,284 @@ | ||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
| From: Shlomi Marco <s.marco@rubycomm.com> | ||
| Date: Sun, 02 Mar 2026 00:00:00 +0000 | ||
| Subject: phy: rockchip-inno-usb2: Add support for RK3528 | ||
|
|
||
| Add USB2 PHY support for the Rockchip RK3528 SoC. | ||
|
|
||
| The RK3528 USB2 PHY is a standalone device with its own register space, | ||
| unlike older SoCs where the PHY registers live inside the GRF syscon. | ||
| This requires adding a separate phy_base regmap for direct PHY register | ||
| access, while the GRF (referenced via rockchip,usbgrf phandle) is used | ||
| for port control registers. For backward compatibility with existing | ||
| SoCs, phy_base is set equal to grf when the PHY is a GRF child node. | ||
|
|
||
| The clock output control register for RK3528 resides in the PHY register | ||
| space rather than the GRF, so a new clkout_ctl_phy config field and | ||
| helper function are added to select the correct regmap and register. | ||
|
|
||
| Based on work by Jonas Karlman <jonas@kwiboo.se> from his | ||
| next-20250910-rk3528 branch. | ||
|
|
||
| Signed-off-by: Shlomi Marco <s.marco@rubycomm.com> | ||
| --- | ||
| drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 136 +++++++++++++++--- | ||
| 1 file changed, 105 insertions(+), 31 deletions(-) | ||
|
|
||
| --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c | ||
| +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c | ||
| @@ -171,6 +171,7 @@ | ||
| * @num_ports: specify how many ports that the phy has. | ||
| * @phy_tuning: phy default parameters tuning. | ||
| * @clkout_ctl: keep on/turn off output clk of phy. | ||
| + * @clkout_ctl_phy: keep on/turn off output clk of phy via phy base. | ||
| * @port_cfgs: usb-phy port configurations. | ||
| * @chg_det: charger detection registers. | ||
| */ | ||
| @@ -179,6 +180,7 @@ | ||
| 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,7 +230,7 @@ | ||
| * struct rockchip_usb2phy - usb2.0 phy driver data. | ||
| * @dev: pointer to device. | ||
| * @grf: General Register Files regmap. | ||
| - * @usbgrf: USB 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. | ||
| @@ -246,7 +248,7 @@ | ||
| struct rockchip_usb2phy { | ||
| struct device *dev; | ||
| struct regmap *grf; | ||
| - struct regmap *usbgrf; | ||
| + struct regmap *phy_base; | ||
| struct clk_bulk_data *clks; | ||
| struct clk *clk480m; | ||
| struct clk_hw clk480m_hw; | ||
| @@ -263,7 +265,7 @@ | ||
|
|
||
| static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy) | ||
| { | ||
| - return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf; | ||
| + return rphy->grf; | ||
| } | ||
|
|
||
| static inline int property_enable(struct regmap *base, | ||
| @@ -319,16 +321,33 @@ | ||
| 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); | ||
| - struct regmap *base = get_reg_base(rphy); | ||
| + | ||
| + 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(base, &rphy->phy_cfg->clkout_ctl)) { | ||
| - ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true); | ||
| + if (!property_enabled(base, clkout_ctl)) { | ||
| + ret = property_enable(base, clkout_ctl, true); | ||
| if (ret) | ||
| return ret; | ||
|
|
||
| @@ -341,21 +360,23 @@ | ||
|
|
||
| static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw) | ||
| { | ||
| - struct rockchip_usb2phy *rphy = | ||
| - container_of(hw, struct rockchip_usb2phy, clk480m_hw); | ||
| - struct regmap *base = get_reg_base(rphy); | ||
| + 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(base, &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); | ||
| - struct regmap *base = get_reg_base(rphy); | ||
| + const struct usb2phy_reg *clkout_ctl; | ||
| + struct regmap *base; | ||
| + | ||
| + rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl); | ||
|
|
||
| - return property_enabled(base, &rphy->phy_cfg->clkout_ctl); | ||
| + return property_enabled(base, clkout_ctl); | ||
| } | ||
|
|
||
| static unsigned long | ||
| @@ -1360,27 +1381,18 @@ | ||
| 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->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"); | ||
| + rphy->grf = rphy->phy_base; | ||
| - 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->phy_base = rphy->grf; | ||
| } | ||
| + if (IS_ERR(rphy->grf)) | ||
| + return PTR_ERR(rphy->grf); | ||
|
|
||
| if (of_property_read_u32_index(np, "reg", 0, ®)) { | ||
| dev_err(dev, "the reg property is not assigned in %pOFn node\n", np); | ||
| @@ -1521,6 +1533,36 @@ | ||
| BIT(2) << BIT_WRITEABLE_SHIFT | 0); | ||
| } | ||
|
|
||
| +static int rk3528_usb2phy_tuning(struct rockchip_usb2phy *rphy) | ||
| +{ | ||
| + int ret; | ||
| + | ||
| + /* Turn off otg port differential receiver in suspend mode */ | ||
| + ret = regmap_write(rphy->phy_base, 0x30, BIT(18) | 0x0000); | ||
| + if (ret) | ||
| + return ret; | ||
| + | ||
| + /* Turn off host port differential receiver in suspend mode */ | ||
| + ret = regmap_write(rphy->phy_base, 0x430, BIT(18) | 0x0000); | ||
| + if (ret) | ||
| + return ret; | ||
| + | ||
| + /* Set otg port HS eye height to 400mv (default is 450mv) */ | ||
| + ret = regmap_write(rphy->phy_base, 0x30, GENMASK(22, 20) | 0x0000); | ||
| + if (ret) | ||
| + return ret; | ||
| + | ||
| + /* Set host port HS eye height to 400mv (default is 450mv) */ | ||
| + ret = regmap_write(rphy->phy_base, 0x430, GENMASK(22, 20) | 0x0000); | ||
| + if (ret) | ||
| + return ret; | ||
| + | ||
| + /* 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; | ||
| @@ -1934,6 +1968,57 @@ | ||
| { /* 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 rk3562_phy_cfgs[] = { | ||
| { | ||
| .reg = 0xff740000, | ||
| @@ -2301,6 +2386,7 @@ | ||
| { .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,rk3562-usb2phy", .data = &rk3562_phy_cfgs }, | ||
| { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs }, | ||
| { .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs }, | ||
| -- | ||
| Armbian | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.