From: Krzysztof Kozlowski <krzk@kernel.org>
To: Peter Geis <pgwipeout@gmail.com>, Heiko Stuebner <heiko@sntech.de>
Cc: Kishon Vijay Abraham I <kishon@kernel.org>,
Algea Cao <algea.cao@rock-chips.com>,
linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>,
frank.wang@rock-chips.com, william.wu@rock-chips.com,
kever.yang@rock-chips.com, linux-phy@lists.infradead.org,
Sebastian Reichel <sebastian.reichel@collabora.com>,
linux-rockchip@lists.infradead.org, Vinod Koul <vkoul@kernel.org>,
Zhang Yubing <yubing.zhang@rock-chips.com>,
Philipp Zabel <p.zabel@pengutronix.de>,
zyw@rock-chips.com, wulf@rock-chips.com,
linux-arm-kernel@lists.infradead.org
Subject: Re: [RFC PATCH v1 3/6] phy: rockchip: add driver for rk3328 usb3 phy
Date: Thu, 16 Jan 2025 13:59:38 +0100 [thread overview]
Message-ID: <87001334-5a37-4fba-b08c-3679fb556f83@kernel.org> (raw)
In-Reply-To: <20250115012628.1035928-4-pgwipeout@gmail.com>
On 15/01/2025 02:26, Peter Geis wrote:
> The rk3328 has a combined usb2 and usb3 phy block for the usb3 dwc
> interface. The implementation up until now has been bugged, with
> multiple issues ranging from disconnect detection failures to low
> performance. This driver fixes the majority of the original issues and
> allows better performance for the rk3328 usb3 port.
>
> This driver sources data from multiple sources, including the rk3328
> trm, the rk3228h trm, emails from Rockchip, and both the 4.4 and 5.10
> downstream drivers. The current implementation allows for basic bring up
> of the phy block and fixes the detection issues. Interrupts are enabled,
> but currently only used for debugging. Features missing currently are
> power management, OTG handling, board specific tuning, regulator control,
>
> Currently the only known bugs are a AX88179 usb3 gigabit adapter crashes
> when operating at usb3 speeds and transmitting large amounts of data and
> full disconnection detections may be slower than expected (~5-10 seconds).
>
> Signed-off-by: Peter Geis <pgwipeout@gmail.com>
> ---
...
> +}
> +
> +static int rockchip_usb3phy_parse_dt(struct rockchip_usb3phy *usb3phy, struct device *dev)
> +{
> + int ret;
> +
> + usb3phy->clk_pipe = devm_clk_get(dev, "usb3phy-pipe");
> + if (IS_ERR(usb3phy->clk_pipe)) {
> + dev_err(dev, "could not get usb3phy pipe clock\n");
Syntax is always:
return dev_err_probe
> + return PTR_ERR(usb3phy->clk_pipe);
> + }
> +
> + usb3phy->clk_otg = devm_clk_get(dev, "usb3phy-otg");
> + if (IS_ERR(usb3phy->clk_otg)) {
> + dev_err(dev, "could not get usb3phy otg clock\n");
> + return PTR_ERR(usb3phy->clk_otg);
> + }
> +
> + usb3phy->clk_ref = devm_clk_get(dev, "refclk-usb3otg");
> + if (IS_ERR(usb3phy->clk_ref)) {
> + dev_err(dev, "could not get usb3phy ref clock\n");
> + return PTR_ERR(usb3phy->clk_ref);
> + }
> +
> + usb3phy->u2por_rst = devm_reset_control_get(dev, "usb3phy-u2-por");
> + if (IS_ERR(usb3phy->u2por_rst)) {
> + dev_err(dev, "no usb3phy-u2-por reset control found\n");
> + return PTR_ERR(usb3phy->u2por_rst);
> + }
> +
> + usb3phy->u3por_rst = devm_reset_control_get(dev, "usb3phy-u3-por");
> + if (IS_ERR(usb3phy->u3por_rst)) {
> + dev_err(dev, "no usb3phy-u3-por reset control found\n");
> + return PTR_ERR(usb3phy->u3por_rst);
> + }
> +
> + usb3phy->pipe_rst = devm_reset_control_get(dev, "usb3phy-pipe-mac");
> + if (IS_ERR(usb3phy->pipe_rst)) {
> + dev_err(dev, "no usb3phy_pipe_mac reset control found\n");
> + return PTR_ERR(usb3phy->pipe_rst);
> + }
> +
> + usb3phy->utmi_rst = devm_reset_control_get(dev, "usb3phy-utmi-mac");
> + if (IS_ERR(usb3phy->utmi_rst)) {
> + dev_err(dev, "no usb3phy-utmi-mac reset control found\n");
> + return PTR_ERR(usb3phy->utmi_rst);
> + }
> +
> + usb3phy->pipe_apb_rst = devm_reset_control_get(dev, "usb3phy-pipe-apb");
> + if (IS_ERR(usb3phy->pipe_apb_rst)) {
> + dev_err(dev, "no usb3phy-pipe-apb reset control found\n");
> + return PTR_ERR(usb3phy->pipe_apb_rst);
> + }
> +
> + usb3phy->utmi_apb_rst = devm_reset_control_get(dev, "usb3phy-utmi-apb");
> + if (IS_ERR(usb3phy->utmi_apb_rst)) {
> + dev_err(dev, "no usb3phy-utmi-apb reset control found\n");
> + return PTR_ERR(usb3phy->utmi_apb_rst);
> + }
> +
> + usb3phy->ls_irq = of_irq_get_byname(dev->of_node, "linestate");
> + if (usb3phy->ls_irq < 0) {
> + dev_err(dev, "no linestate irq provided\n");
> + return usb3phy->ls_irq;
> + }
> +
> + ret = devm_request_threaded_irq(dev, usb3phy->ls_irq, NULL, rockchip_usb3phy_linestate_irq,
> + IRQF_ONESHOT, "rockchip_usb3phy_ls", usb3phy);
> + if (ret) {
> + dev_err(dev, "failed to request linestate irq handle\n");
> + return ret;
> + }
> +
> + usb3phy->bvalid_irq = of_irq_get_byname(dev->of_node, "bvalid");
> + if (usb3phy->bvalid_irq < 0) {
> + dev_err(dev, "no bvalid irq provided\n");
> + return usb3phy->bvalid_irq;
> + }
> +
> + ret = devm_request_threaded_irq(dev, usb3phy->bvalid_irq, NULL, rockchip_usb3phy_bvalid_irq,
> + IRQF_ONESHOT, "rockchip_usb3phy_bvalid", usb3phy);
> + if (ret) {
> + dev_err(dev, "failed to request bvalid irq handle\n");
> + return ret;
> + }
> +
> + usb3phy->id_irq = of_irq_get_byname(dev->of_node, "id");
> + if (usb3phy->id_irq < 0) {
> + dev_err(dev, "no id irq provided\n");
> + return usb3phy->id_irq;
> + }
> +
> + ret = devm_request_threaded_irq(dev, usb3phy->id_irq, NULL, rockchip_usb3phy_id_irq,
> + IRQF_ONESHOT, "rockchip_usb3phy-id", usb3phy);
> + if (ret) {
> + dev_err(dev, "failed to request id irq handle\n");
> + return ret;
> + }
> +
> + usb3phy->rxdet_irq = of_irq_get_byname(dev->of_node, "rxdet");
> + if (usb3phy->rxdet_irq < 0) {
> + dev_err(dev, "no rxdet irq provided\n");
> + return usb3phy->rxdet_irq;
> + }
> +
> + ret = devm_request_threaded_irq(dev, usb3phy->rxdet_irq, NULL, rockchip_usb3phy_rxdet_irq,
> + IRQF_ONESHOT, "rockchip_usb3phy-rxdet", usb3phy);
> + if (ret) {
> + dev_err(dev, "failed to request rxdet irq handle\n");
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int rockchip_usb3phy_exit(struct phy *phy)
> +{
> + struct rockchip_usb3phy_port *port = phy_get_drvdata(phy);
> + struct rockchip_usb3phy *usb3phy = dev_get_drvdata(phy->dev.parent);
> +
> + dev_dbg(usb3phy->dev, "usb3phy_shutdown\n");
> + rockchip_usb3phy_reset(usb3phy, true, port->type);
> +
> + return 0;
> +}
> +
> +static const struct phy_ops rockchip_usb3phy_ops = {
> + .init = rockchip_usb3phy_init,
> + .exit = rockchip_usb3phy_exit,
> + .owner = THIS_MODULE,
> +};
> +
> +static const struct regmap_config rockchip_usb3phy_utmi_port_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0x400,
> + .cache_type = REGCACHE_NONE,
> + .fast_io = true,
> + .name = "utmi-port",
> +};
> +
> +static const struct regmap_config rockchip_usb3phy_pipe_port_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0x400,
> + .cache_type = REGCACHE_NONE,
> + .fast_io = true,
> + .name = "pipe-port",
> +};
> +
> +static const struct regmap_config rockchip_usb3phy_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0x400,
> + .write_flag_mask = REG_WRITE_MASK,
> + .cache_type = REGCACHE_NONE,
> + .fast_io = true,
> +};
> +
> +static int rockchip_usb3phy_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + struct device_node *child_np;
> + struct phy_provider *provider;
> + struct rockchip_usb3phy *usb3phy;
> + const struct regmap_config regmap_config = rockchip_usb3phy_regmap_config;
> + void __iomem *base;
> + int i, ret;
> +
> + dev_dbg(dev, "Probe usb3phy main block\n");
> + usb3phy = devm_kzalloc(dev, sizeof(*usb3phy), GFP_KERNEL);
> + if (!usb3phy)
> + return -ENOMEM;
> +
> + ret = rockchip_usb3phy_parse_dt(usb3phy, dev);
> + if (ret) {
> + dev_err(dev, "parse dt failed %i\n", ret);
return dev_err_probe()
And do not print errors twice.
> + return ret;
> +
> + /* take apb interface out of reset */
> + reset_control_deassert(usb3phy->utmi_apb_rst);
> + reset_control_deassert(usb3phy->pipe_apb_rst);
> +
> + /* enable usb3phy rx detection to fix disconnection issues */
> + regmap_write(usb3phy->regmap, USB3PHY_WAKEUP_CON_REG,
> + (USB3_RXDET_EN | (USB3_RXDET_EN << REG_WRITE_SHIFT)));
> +
> + dev_dbg(dev, "Completed usb3phy core probe\n");
Drop.
> +
> + /* probe the actual ports */
> + i = 0;
> + for_each_available_child_of_node(np, child_np) {
> + const struct regmap_config *regmap_port_config;
> + struct rockchip_usb3phy_port *port = &usb3phy->ports[i];
> + struct phy *phy;
> +
> + if (of_node_name_eq(child_np, "utmi-port")) {
Why are you comparing node names, if you decided to put there compatibles?
Decide on one method, but wait for full DT review.
> + port->type = USB3PHY_TYPE_USB2;
> + regmap_port_config = &rockchip_usb3phy_utmi_port_regmap_config;
> + } else if (of_node_name_eq(child_np, "pipe-port")) {
> + port->type = USB3PHY_TYPE_USB3;
> + regmap_port_config = &rockchip_usb3phy_pipe_port_regmap_config;
> + } else {
> + dev_err(dev, "unknown child node port type %s\n", child_np->name);
> + goto err_port;
> + }
> +
> + base = devm_of_iomap(dev, child_np, 0, NULL);
> + if (IS_ERR(base)) {
> + dev_err(dev, "failed port ioremap\n");
> + ret = PTR_ERR(base);
> + goto err_port;
> + }
> +
> + port->regmap = devm_regmap_init_mmio(dev, base, regmap_port_config);
> + if (IS_ERR(port->regmap)) {
> + dev_err(dev, "regmap init failed\n");
> + ret = PTR_ERR(port->regmap);
> + goto err_port;
> + }
> +
> + phy = devm_phy_create(dev, child_np, &rockchip_usb3phy_ops);
> + if (IS_ERR(phy)) {
> + dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
> + ret = PTR_ERR(phy);
Just read how dev_err_probe() works. The syntax is:
ret = dev_err_probe.
> + goto err_port;
> + }
> +
> + port->phy = phy;
> + phy_set_drvdata(port->phy, port);
> +
> + /* to prevent out of boundary */
> + if (++i >= USB3PHY_TYPE_MAX) {
> + of_node_put(child_np);
> + break;
> + }
> +
> + dev_info(dev, "Completed usb3phy %s port init\n", child_np->name);
Drop, not really helping.
Best regards,
Krzysztof
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
next prev parent reply other threads:[~2025-01-16 13:01 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-15 1:26 [RFC PATCH v1 0/6] rockchip: add a functional usb3 phy driver for rk3328 Peter Geis
2025-01-15 1:26 ` [RFC PATCH v1 1/6] clk: rockchip: fix wrong clk_ref_usb3otg parent " Peter Geis
2025-01-15 1:26 ` [RFC PATCH v1 2/6] dt-bindings: phy: rockchip: add rk3328 usb3 phy Peter Geis
2025-01-16 13:08 ` Krzysztof Kozlowski
2025-01-16 13:32 ` Peter Geis
2025-01-16 13:59 ` Peter Geis
2025-01-18 9:06 ` Krzysztof Kozlowski
2025-01-15 1:26 ` [RFC PATCH v1 3/6] phy: rockchip: add driver for " Peter Geis
2025-01-15 11:24 ` Piotr Oniszczuk
2025-01-16 14:09 ` Peter Geis
2025-01-16 12:59 ` Krzysztof Kozlowski [this message]
2025-01-16 13:14 ` Peter Geis
2025-01-16 15:26 ` Diederik de Haas
2025-01-16 15:57 ` Peter Geis
2025-01-15 1:26 ` [RFC PATCH v1 4/6] arm64: dts: rockchip: add rk3328 usb3 phy node Peter Geis
2025-01-16 13:01 ` Krzysztof Kozlowski
2025-01-16 16:53 ` Diederik de Haas
2025-01-17 4:10 ` Dragan Simic
2025-01-18 8:46 ` Krzysztof Kozlowski
2025-01-18 9:25 ` Dragan Simic
2025-01-18 9:31 ` Krzysztof Kozlowski
2025-01-18 9:43 ` Dragan Simic
2025-01-18 9:52 ` Krzysztof Kozlowski
2025-01-18 10:10 ` Dragan Simic
2025-01-18 10:29 ` Krzysztof Kozlowski
2025-01-18 10:45 ` Dragan Simic
2025-01-18 14:22 ` Peter Geis
2025-01-18 8:41 ` Krzysztof Kozlowski
2025-01-18 9:19 ` Krzysztof Kozlowski
2025-01-18 9:34 ` Dragan Simic
2025-01-18 15:55 ` Diederik de Haas
2025-01-15 1:26 ` [RFC PATCH v1 5/6] arm64: dts: rockchip: enable the usb3 phy on rk3328-roc boards Peter Geis
2025-01-15 1:26 ` [RFC PATCH v1 6/6] arm64: dts: rockchip: enable the usb3 phy on remaining rk3328 boards Peter Geis
2025-01-15 11:22 ` [RFC PATCH v1 0/6] rockchip: add a functional usb3 phy driver for rk3328 Piotr Oniszczuk
2025-01-15 12:25 ` Peter Geis
2025-01-15 12:35 ` Piotr Oniszczuk
2025-01-15 13:15 ` Peter Geis
2025-01-15 13:25 ` Piotr Oniszczuk
2025-01-16 14:02 ` Peter Geis
2025-01-16 14:35 ` Piotr Oniszczuk
2025-01-16 16:00 ` Peter Geis
2025-01-18 9:08 ` Krzysztof Kozlowski
2025-01-18 14:35 ` Peter Geis
2025-02-26 19:49 ` (subset) " Heiko Stuebner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87001334-5a37-4fba-b08c-3679fb556f83@kernel.org \
--to=krzk@kernel.org \
--cc=algea.cao@rock-chips.com \
--cc=arnd@arndb.de \
--cc=frank.wang@rock-chips.com \
--cc=heiko@sntech.de \
--cc=kever.yang@rock-chips.com \
--cc=kishon@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=p.zabel@pengutronix.de \
--cc=pgwipeout@gmail.com \
--cc=sebastian.reichel@collabora.com \
--cc=vkoul@kernel.org \
--cc=william.wu@rock-chips.com \
--cc=wulf@rock-chips.com \
--cc=yubing.zhang@rock-chips.com \
--cc=zyw@rock-chips.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox