From: Ladislav Michl <oss-lists@triops.cz>
To: Thomas Bogendoerfer <tsbogend@alpha.franken.de>,
Thinh Nguyen <Thinh.Nguyen@synopsys.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Liang He <windhl@126.com>
Cc: linux-mips@vger.kernel.org, linux-usb@vger.kernel.org
Subject: [PATCH v5 4/7] usb: dwc3: dwc3-octeon: Avoid half-initialized controller state
Date: Mon, 31 Jul 2023 11:32:16 +0200 [thread overview]
Message-ID: <ZMd/oMRx8ze22/kK@lenoch> (raw)
In-Reply-To: <ZMd/HzISn0mPsNWt@lenoch>
From: Ladislav Michl <ladis@linux-mips.org>
Power gpio configuration is done from the middle of
dwc3_octeon_clocks_start leaving hardware in half-initialized
state if it fails. As that indicates dwc3_octeon_clocks_start
does more than just initialize the clocks rename it appropriately
and verify power gpio configuration in advance at the beginning
of device probe.
Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
CHANGES:
- v4: new patch
- v5: use uintptr_t instead of u64 to retype base address to make 32bit
compilers happy.
drivers/usb/dwc3/dwc3-octeon.c | 90 ++++++++++++++++------------------
1 file changed, 43 insertions(+), 47 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-octeon.c b/drivers/usb/dwc3/dwc3-octeon.c
index 24e75881b5cf..0dc45dda134c 100644
--- a/drivers/usb/dwc3/dwc3-octeon.c
+++ b/drivers/usb/dwc3/dwc3-octeon.c
@@ -192,6 +192,8 @@ struct dwc3_octeon {
void __iomem *base;
};
+#define DWC3_GPIO_POWER_NONE (-1)
+
#ifdef CONFIG_CAVIUM_OCTEON_SOC
#include <asm/octeon/octeon.h>
static inline uint64_t dwc3_octeon_readq(void __iomem *addr)
@@ -258,55 +260,15 @@ static int dwc3_octeon_get_divider(void)
return div;
}
-static int dwc3_octeon_config_power(struct device *dev, void __iomem *base)
-{
- uint32_t gpio_pwr[3];
- int gpio, len, power_active_low;
- struct device_node *node = dev->of_node;
- u64 val;
- void __iomem *uctl_host_cfg_reg = base + USBDRD_UCTL_HOST_CFG;
-
- if (of_find_property(node, "power", &len) != NULL) {
- if (len == 12) {
- of_property_read_u32_array(node, "power", gpio_pwr, 3);
- power_active_low = gpio_pwr[2] & 0x01;
- gpio = gpio_pwr[1];
- } else if (len == 8) {
- of_property_read_u32_array(node, "power", gpio_pwr, 2);
- power_active_low = 0;
- gpio = gpio_pwr[1];
- } else {
- dev_err(dev, "invalid power configuration\n");
- return -EINVAL;
- }
- dwc3_octeon_config_gpio(((u64)base >> 24) & 1, gpio);
-
- /* Enable XHCI power control and set if active high or low. */
- val = dwc3_octeon_readq(uctl_host_cfg_reg);
- val |= USBDRD_UCTL_HOST_PPC_EN;
- if (power_active_low)
- val &= ~USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN;
- else
- val |= USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN;
- dwc3_octeon_writeq(uctl_host_cfg_reg, val);
- } else {
- /* Disable XHCI power control and set if active high. */
- val = dwc3_octeon_readq(uctl_host_cfg_reg);
- val &= ~USBDRD_UCTL_HOST_PPC_EN;
- val &= ~USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN;
- dwc3_octeon_writeq(uctl_host_cfg_reg, val);
- dev_info(dev, "power control disabled\n");
- }
- return 0;
-}
-
-static int dwc3_octeon_clocks_start(struct dwc3_octeon *octeon)
+static int dwc3_octeon_setup(struct dwc3_octeon *octeon,
+ int power_gpio, int power_active_low)
{
int i, div, mpll_mul, ref_clk_fsel, ref_clk_sel = 2;
u32 clock_rate;
u64 val;
struct device *dev = octeon->dev;
void __iomem *uctl_ctl_reg = octeon->base + USBDRD_UCTL_CTL;
+ void __iomem *uctl_host_cfg_reg = octeon->base + USBDRD_UCTL_HOST_CFG;
if (dev->of_node) {
const char *ss_clock_type;
@@ -454,8 +416,21 @@ static int dwc3_octeon_clocks_start(struct dwc3_octeon *octeon)
udelay(10);
/* Step 8c: Setup power control. */
- if (dwc3_octeon_config_power(dev, octeon->base))
- return -EINVAL;
+ val = dwc3_octeon_readq(uctl_host_cfg_reg);
+ val |= USBDRD_UCTL_HOST_PPC_EN;
+ if (power_gpio == DWC3_GPIO_POWER_NONE) {
+ val &= ~USBDRD_UCTL_HOST_PPC_EN;
+ } else {
+ val |= USBDRD_UCTL_HOST_PPC_EN;
+ dwc3_octeon_config_gpio(((__force uintptr_t)octeon->base >> 24) & 1,
+ power_gpio);
+ dev_dbg(dev, "power control is using gpio%d\n", power_gpio);
+ }
+ if (power_active_low)
+ val &= ~USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN;
+ else
+ val |= USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN;
+ dwc3_octeon_writeq(uctl_host_cfg_reg, val);
/* Step 8d: Deassert UAHC reset signal. */
val = dwc3_octeon_readq(uctl_ctl_reg);
@@ -508,7 +483,28 @@ static int dwc3_octeon_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct dwc3_octeon *octeon;
- int err;
+ int power_active_low, power_gpio;
+ int err, len;
+
+ power_gpio = DWC3_GPIO_POWER_NONE;
+ power_active_low = 0;
+ if (of_find_property(node, "power", &len)) {
+ u32 gpio_pwr[3];
+
+ switch (len) {
+ case 8:
+ of_property_read_u32_array(node, "power", gpio_pwr, 2);
+ break;
+ case 12:
+ of_property_read_u32_array(node, "power", gpio_pwr, 3);
+ power_active_low = gpio_pwr[2] & 0x01;
+ break;
+ default:
+ dev_err(dev, "invalid power configuration\n");
+ return -EINVAL;
+ }
+ power_gpio = gpio_pwr[1];
+ }
octeon = devm_kzalloc(dev, sizeof(*octeon), GFP_KERNEL);
if (!octeon)
@@ -519,7 +515,7 @@ static int dwc3_octeon_probe(struct platform_device *pdev)
if (IS_ERR(octeon->base))
return PTR_ERR(octeon->base);
- err = dwc3_octeon_clocks_start(octeon);
+ err = dwc3_octeon_setup(octeon, power_gpio, power_active_low);
if (err)
return err;
--
2.39.2
next prev parent reply other threads:[~2023-07-31 9:33 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-31 9:30 [PATCH v5 0/7] Cleanup Octeon DWC3 glue code Ladislav Michl
2023-07-31 9:30 ` [PATCH v5 1/7] usb: dwc3: dwc3-octeon: Convert to glue driver Ladislav Michl
2023-07-31 9:31 ` [PATCH v5 2/7] usb: dwc3: dwc3-octeon: Use _ULL bitfields defines Ladislav Michl
2023-07-31 23:54 ` Thinh Nguyen
2023-08-01 13:41 ` Philippe Mathieu-Daudé
2023-07-31 9:31 ` [PATCH v5 3/7] usb: dwc3: dwc3-octeon: Pass dwc3_octeon to setup functions Ladislav Michl
2023-08-01 0:01 ` Thinh Nguyen
2023-08-01 0:06 ` Thinh Nguyen
2023-07-31 9:32 ` Ladislav Michl [this message]
2023-08-01 0:38 ` [PATCH v5 4/7] usb: dwc3: dwc3-octeon: Avoid half-initialized controller state Thinh Nguyen
2023-08-01 5:37 ` Ladislav Michl
2023-08-01 8:42 ` Ladislav Michl
2023-08-02 0:47 ` Thinh Nguyen
2023-08-02 0:42 ` Thinh Nguyen
2023-08-02 0:45 ` Thinh Nguyen
2023-07-31 9:32 ` [PATCH v5 5/7] usb: dwc3: dwc3-octeon: Move node parsing into driver probe Ladislav Michl
2023-08-01 0:42 ` Thinh Nguyen
2023-07-31 9:33 ` [PATCH v5 6/7] usb: dwc3: dwc3-octeon: Dump control register on clock init failure Ladislav Michl
2023-08-01 0:44 ` Thinh Nguyen
2023-07-31 9:33 ` [PATCH v5 7/7] usb: dwc3: dwc3-octeon: Add SPDX header and copyright Ladislav Michl
2023-08-01 0:45 ` Thinh Nguyen
2023-08-01 13:50 ` Philippe Mathieu-Daudé
2023-08-01 14:24 ` [EXTERNAL] " David Daney
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=ZMd/oMRx8ze22/kK@lenoch \
--to=oss-lists@triops.cz \
--cc=Thinh.Nguyen@synopsys.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-mips@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=tsbogend@alpha.franken.de \
--cc=windhl@126.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.