All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/3] Cleanup Octeon DWC3 glue code
@ 2023-07-14  7:37 Ladislav Michl
  2023-07-14  7:39 ` [PATCH v3 1/3] usb: dwc3: dwc3-octeon: Convert to glue driver Ladislav Michl
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Ladislav Michl @ 2023-07-14  7:37 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Thinh Nguyen, Greg Kroah-Hartman, Liang He
  Cc: linux-mips, linux-usb

Hi!

The glue code currently lives in arch/mips/cavium-octeon/octeon-usb.c
and loops for each "cavium,octeon-7130-usb-uctl" compatible.
However there is no bond with dwc3 core code, so if anything goes
wrong in glue code, the loop breaks, leaving dwc3 in reset.
  
Later on when dwc3 core tries to read any device register, bus error
is emited, leading to kernel panic.

Therefore move it to drivers/usb/dwc3 while making it glue driver.
 
This is a third attempt, see changelog appended to patches.

Ladislav Michl (3):
  usb: dwc3: dwc3-octeon: Convert to glue driver
  usb: dwc3: dwc3-octeon: Move node parsing into driver probe
  usb: dwc3: Add SPDX header and copyright

 arch/mips/cavium-octeon/Makefile              |   1 -
 arch/mips/cavium-octeon/octeon-platform.c     |   1 -
 drivers/usb/dwc3/Kconfig                      |  10 +
 drivers/usb/dwc3/Makefile                     |   1 +
 .../usb/dwc3/dwc3-octeon.c                    | 343 +++++++++---------
 drivers/usb/dwc3/dwc3-of-simple.c             |   1 -
 6 files changed, 177 insertions(+), 180 deletions(-)
 rename arch/mips/cavium-octeon/octeon-usb.c => drivers/usb/dwc3/dwc3-octeon.c (75%)

-- 
2.39.2


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 1/3] usb: dwc3: dwc3-octeon: Convert to glue driver
  2023-07-14  7:37 [PATCH v3 0/3] Cleanup Octeon DWC3 glue code Ladislav Michl
@ 2023-07-14  7:39 ` Ladislav Michl
  2023-07-14 21:44   ` Thinh Nguyen
  2023-07-14  7:41 ` [PATCH v3 2/3] usb: dwc3: dwc3-octeon: Move node parsing into driver probe Ladislav Michl
  2023-07-14  7:41 ` [PATCH v3 3/3] usb: dwc3: Add SPDX header and copyright Ladislav Michl
  2 siblings, 1 reply; 9+ messages in thread
From: Ladislav Michl @ 2023-07-14  7:39 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Thinh Nguyen, Greg Kroah-Hartman, Liang He
  Cc: linux-mips, linux-usb

From: Ladislav Michl <ladis@linux-mips.org>

DWC3 as implemented in Cavium SoC is using UCTL bridge unit
between I/O interconnect and USB controller.

Currently there is no bond with dwc3 core code, so if anything goes
wrong in UCTL setup dwc3 is left in reset, which leads to bus error
while trying to read any device register. Thus any failure in UCTL
initialization ends with kernel panic.

To avoid this move Octeon DWC3 glue code from arch/mips and make it
proper glue driver which is used instead of dwc3-of-simple.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
Acked-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
 CHANGES:
 - v2: squashed move and glue conversion patch, fixed sparse warning
       and formatting issue. Set private data at the end of probe.
       Clear drvdata on remove. Added host mode only notice.
       Collected ack for move from arch/mips.
 - v3: more descriptive commit message, dropped unrelated changes

 arch/mips/cavium-octeon/Makefile              |   1 -
 arch/mips/cavium-octeon/octeon-platform.c     |   1 -
 drivers/usb/dwc3/Kconfig                      |  10 ++
 drivers/usb/dwc3/Makefile                     |   1 +
 .../usb/dwc3/dwc3-octeon.c                    | 104 ++++++++++--------
 drivers/usb/dwc3/dwc3-of-simple.c             |   1 -
 6 files changed, 67 insertions(+), 51 deletions(-)
 rename arch/mips/cavium-octeon/octeon-usb.c => drivers/usb/dwc3/dwc3-octeon.c (91%)

diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 7c02e542959a..2a5926578841 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -18,4 +18,3 @@ obj-y += crypto/
 obj-$(CONFIG_MTD)		      += flash_setup.o
 obj-$(CONFIG_SMP)		      += smp.o
 obj-$(CONFIG_OCTEON_ILM)	      += oct_ilm.o
-obj-$(CONFIG_USB)		      += octeon-usb.o
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index ce05c0dd3acd..235c77ce7b18 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -450,7 +450,6 @@ static const struct of_device_id octeon_ids[] __initconst = {
 	{ .compatible = "cavium,octeon-3860-bootbus", },
 	{ .compatible = "cavium,mdio-mux", },
 	{ .compatible = "gpio-leds", },
-	{ .compatible = "cavium,octeon-7130-usb-uctl", },
 	{},
 };
 
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index be954a9abbe0..98efcbb76c88 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -168,4 +168,14 @@ config USB_DWC3_AM62
 	  The Designware Core USB3 IP is programmed to operate in
 	  in USB 2.0 mode only.
 	  Say 'Y' or 'M' here if you have one such device
+
+config USB_DWC3_OCTEON
+	tristate "Cavium Octeon Platforms"
+	depends on CAVIUM_OCTEON_SOC || COMPILE_TEST
+	default USB_DWC3
+	help
+	  Support Cavium Octeon platforms with DesignWare Core USB3 IP.
+	  Only the host mode is currently supported.
+	  Say 'Y' or 'M' here if you have one such device.
+
 endif
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 9f66bd82b639..fe1493d4bbe5 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -54,3 +54,4 @@ obj-$(CONFIG_USB_DWC3_ST)		+= dwc3-st.o
 obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom.o
 obj-$(CONFIG_USB_DWC3_IMX8MP)		+= dwc3-imx8mp.o
 obj-$(CONFIG_USB_DWC3_XILINX)		+= dwc3-xilinx.o
+obj-$(CONFIG_USB_DWC3_OCTEON)		+= dwc3-octeon.o
diff --git a/arch/mips/cavium-octeon/octeon-usb.c b/drivers/usb/dwc3/dwc3-octeon.c
similarity index 91%
rename from arch/mips/cavium-octeon/octeon-usb.c
rename to drivers/usb/dwc3/dwc3-octeon.c
index 2add435ad038..69bac61ccbe0 100644
--- a/arch/mips/cavium-octeon/octeon-usb.c
+++ b/drivers/usb/dwc3/dwc3-octeon.c
@@ -187,7 +187,10 @@
 #define USBDRD_UCTL_ECC				0xf0
 #define USBDRD_UCTL_SPARE1			0xf8
 
-static DEFINE_MUTEX(dwc3_octeon_clocks_mutex);
+struct dwc3_data {
+	struct device *dev;
+	void __iomem *base;
+};
 
 #ifdef CONFIG_CAVIUM_OCTEON_SOC
 #include <asm/octeon/octeon.h>
@@ -233,6 +236,11 @@ static inline uint64_t dwc3_octeon_readq(void __iomem *addr)
 static inline void dwc3_octeon_writeq(void __iomem *base, uint64_t val) { }
 
 static inline void dwc3_octeon_config_gpio(int index, int gpio) { }
+
+static uint64_t octeon_get_io_clock_rate(void)
+{
+	return 150000000;
+}
 #endif
 
 static int dwc3_octeon_get_divider(void)
@@ -494,58 +502,58 @@ static void __init dwc3_octeon_phy_reset(void __iomem *base)
 	dwc3_octeon_writeq(uctl_ctl_reg, val);
 }
 
-static int __init dwc3_octeon_device_init(void)
+static int dwc3_octeon_probe(struct platform_device *pdev)
 {
-	const char compat_node_name[] = "cavium,octeon-7130-usb-uctl";
-	struct platform_device *pdev;
-	struct device_node *node;
-	struct resource *res;
-	void __iomem *base;
+	struct device *dev = &pdev->dev;
+	struct dwc3_data *data;
+	int err;
 
-	/*
-	 * There should only be three universal controllers, "uctl"
-	 * in the device tree. Two USB and a SATA, which we ignore.
-	 */
-	node = NULL;
-	do {
-		node = of_find_node_by_name(node, "uctl");
-		if (!node)
-			return -ENODEV;
-
-		if (of_device_is_compatible(node, compat_node_name)) {
-			pdev = of_find_device_by_node(node);
-			if (!pdev)
-				return -ENODEV;
-
-			/*
-			 * The code below maps in the registers necessary for
-			 * setting up the clocks and reseting PHYs. We must
-			 * release the resources so the dwc3 subsystem doesn't
-			 * know the difference.
-			 */
-			base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
-			if (IS_ERR(base)) {
-				put_device(&pdev->dev);
-				return PTR_ERR(base);
-			}
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-			mutex_lock(&dwc3_octeon_clocks_mutex);
-			if (dwc3_octeon_clocks_start(&pdev->dev, base) == 0)
-				dev_info(&pdev->dev, "clocks initialized.\n");
-			dwc3_octeon_set_endian_mode(base);
-			dwc3_octeon_phy_reset(base);
-			mutex_unlock(&dwc3_octeon_clocks_mutex);
-			devm_iounmap(&pdev->dev, base);
-			devm_release_mem_region(&pdev->dev, res->start,
-						resource_size(res));
-			put_device(&pdev->dev);
-		}
-	} while (node != NULL);
+	data->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(data->base))
+		return PTR_ERR(data->base);
 
-	return 0;
+	err = dwc3_octeon_clocks_start(dev, data->base);
+	if (err)
+		return err;
+
+	dwc3_octeon_set_endian_mode(data->base);
+	dwc3_octeon_phy_reset(data->base);
+
+	data->dev = dev;
+	platform_set_drvdata(pdev, data);
+
+	return of_platform_populate(node, NULL, NULL, dev);
+}
+
+static void dwc3_octeon_remove(struct platform_device *pdev)
+{
+	struct dwc3_data *data = platform_get_drvdata(pdev);
+
+	of_platform_depopulate(data->dev);
+	platform_set_drvdata(pdev, NULL);
 }
-device_initcall(dwc3_octeon_device_init);
 
+static const struct of_device_id dwc3_octeon_of_match[] = {
+	{ .compatible = "cavium,octeon-7130-usb-uctl" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, dwc3_octeon_of_match);
+
+static struct platform_driver dwc3_octeon_driver = {
+	.probe		= dwc3_octeon_probe,
+	.remove_new	= dwc3_octeon_remove,
+	.driver		= {
+		.name	= "dwc3-octeon",
+		.of_match_table = dwc3_octeon_of_match,
+	},
+};
+module_platform_driver(dwc3_octeon_driver);
+
+MODULE_ALIAS("platform:dwc3-octeon");
 MODULE_AUTHOR("David Daney <david.daney@cavium.com>");
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("USB driver for OCTEON III SoC");
+MODULE_DESCRIPTION("DesignWare USB3 OCTEON III Glue Layer");
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
index 7e6ad8fe61a5..d1539fc9eabd 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -170,7 +170,6 @@ static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = {
 
 static const struct of_device_id of_dwc3_simple_match[] = {
 	{ .compatible = "rockchip,rk3399-dwc3" },
-	{ .compatible = "cavium,octeon-7130-usb-uctl" },
 	{ .compatible = "sprd,sc9860-dwc3" },
 	{ .compatible = "allwinner,sun50i-h6-dwc3" },
 	{ .compatible = "hisilicon,hi3670-dwc3" },
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 2/3] usb: dwc3: dwc3-octeon: Move node parsing into driver probe
  2023-07-14  7:37 [PATCH v3 0/3] Cleanup Octeon DWC3 glue code Ladislav Michl
  2023-07-14  7:39 ` [PATCH v3 1/3] usb: dwc3: dwc3-octeon: Convert to glue driver Ladislav Michl
@ 2023-07-14  7:41 ` Ladislav Michl
  2023-07-14 22:26   ` Thinh Nguyen
  2023-07-14  7:41 ` [PATCH v3 3/3] usb: dwc3: Add SPDX header and copyright Ladislav Michl
  2 siblings, 1 reply; 9+ messages in thread
From: Ladislav Michl @ 2023-07-14  7:41 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Thinh Nguyen, Greg Kroah-Hartman, Liang He
  Cc: linux-mips, linux-usb

From: Ladislav Michl <ladis@linux-mips.org>

Parse and verify device tree node first, then setup UCTL bridge
using verified values. This avoids half initialized hardware state
in case DT misconfiguration was found in the middle of setup.
As a dwc3_octeon_clocks_start already did more than just starting
a clock, rename it approprietly and move all hardware setup there.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 CHANGES:
 - v2: if else block bracket according CodingStyle
 - v3: more descriptive commit message, power gpio parsing in probe too,
       checkpatch --strict passed

 drivers/usb/dwc3/dwc3-octeon.c | 236 +++++++++++++++------------------
 1 file changed, 109 insertions(+), 127 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-octeon.c b/drivers/usb/dwc3/dwc3-octeon.c
index 69bac61ccbe0..dd47498f4efb 100644
--- a/drivers/usb/dwc3/dwc3-octeon.c
+++ b/drivers/usb/dwc3/dwc3-octeon.c
@@ -258,108 +258,14 @@ static int dwc3_octeon_get_divider(void)
 	return div;
 }
 
-static int dwc3_octeon_config_power(struct device *dev, void __iomem *base)
+static int dwc3_octeon_setup(void __iomem *base,
+			     int ref_clk_sel, int ref_clk_fsel, int mpll_mul,
+			     int power_gpio, int power_active_low)
 {
-	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 device *dev, void __iomem *base)
-{
-	int i, div, mpll_mul, ref_clk_fsel, ref_clk_sel = 2;
-	u32 clock_rate;
+	int div;
 	u64 val;
 	void __iomem *uctl_ctl_reg = base + USBDRD_UCTL_CTL;
-
-	if (dev->of_node) {
-		const char *ss_clock_type;
-		const char *hs_clock_type;
-
-		i = of_property_read_u32(dev->of_node,
-					 "refclk-frequency", &clock_rate);
-		if (i) {
-			dev_err(dev, "No UCTL \"refclk-frequency\"\n");
-			return -EINVAL;
-		}
-		i = of_property_read_string(dev->of_node,
-					    "refclk-type-ss", &ss_clock_type);
-		if (i) {
-			dev_err(dev, "No UCTL \"refclk-type-ss\"\n");
-			return -EINVAL;
-		}
-		i = of_property_read_string(dev->of_node,
-					    "refclk-type-hs", &hs_clock_type);
-		if (i) {
-			dev_err(dev, "No UCTL \"refclk-type-hs\"\n");
-			return -EINVAL;
-		}
-		if (strcmp("dlmc_ref_clk0", ss_clock_type) == 0) {
-			if (strcmp(hs_clock_type, "dlmc_ref_clk0") == 0)
-				ref_clk_sel = 0;
-			else if (strcmp(hs_clock_type, "pll_ref_clk") == 0)
-				ref_clk_sel = 2;
-			else
-				dev_warn(dev, "Invalid HS clock type %s, using pll_ref_clk instead\n",
-					 hs_clock_type);
-		} else if (strcmp(ss_clock_type, "dlmc_ref_clk1") == 0) {
-			if (strcmp(hs_clock_type, "dlmc_ref_clk1") == 0)
-				ref_clk_sel = 1;
-			else if (strcmp(hs_clock_type, "pll_ref_clk") == 0)
-				ref_clk_sel = 3;
-			else {
-				dev_warn(dev, "Invalid HS clock type %s, using pll_ref_clk instead\n",
-					 hs_clock_type);
-				ref_clk_sel = 3;
-			}
-		} else
-			dev_warn(dev, "Invalid SS clock type %s, using dlmc_ref_clk0 instead\n",
-				 ss_clock_type);
-
-		if ((ref_clk_sel == 0 || ref_clk_sel == 1) &&
-		    (clock_rate != 100000000))
-			dev_warn(dev, "Invalid UCTL clock rate of %u, using 100000000 instead\n",
-				 clock_rate);
-
-	} else {
-		dev_err(dev, "No USB UCTL device node\n");
-		return -EINVAL;
-	}
+	void __iomem *uctl_host_cfg_reg = base + USBDRD_UCTL_HOST_CFG;
 
 	/*
 	 * Step 1: Wait for all voltages to be stable...that surely
@@ -389,10 +295,8 @@ static int dwc3_octeon_clocks_start(struct device *dev, void __iomem *base)
 	dwc3_octeon_writeq(uctl_ctl_reg, val);
 	val = dwc3_octeon_readq(uctl_ctl_reg);
 	if ((div != FIELD_GET(USBDRD_UCTL_CTL_H_CLKDIV_SEL, val)) ||
-	    (!(FIELD_GET(USBDRD_UCTL_CTL_H_CLK_EN, val)))) {
-		dev_err(dev, "dwc3 controller clock init failure.\n");
-			return -EINVAL;
-	}
+	    (!(FIELD_GET(USBDRD_UCTL_CTL_H_CLK_EN, val))))
+		return -EINVAL;
 
 	/* Step 4c: Deassert the controller clock divider reset. */
 	val &= ~USBDRD_UCTL_CTL_H_CLKDIV_RST;
@@ -404,24 +308,6 @@ static int dwc3_octeon_clocks_start(struct device *dev, void __iomem *base)
 	val &= ~USBDRD_UCTL_CTL_REF_CLK_SEL;
 	val |= FIELD_PREP(USBDRD_UCTL_CTL_REF_CLK_SEL, ref_clk_sel);
 
-	ref_clk_fsel = 0x07;
-	switch (clock_rate) {
-	default:
-		dev_warn(dev, "Invalid ref_clk %u, using 100000000 instead\n",
-			 clock_rate);
-		fallthrough;
-	case 100000000:
-		mpll_mul = 0x19;
-		if (ref_clk_sel < 2)
-			ref_clk_fsel = 0x27;
-		break;
-	case 50000000:
-		mpll_mul = 0x32;
-		break;
-	case 125000000:
-		mpll_mul = 0x28;
-		break;
-	}
 	val &= ~USBDRD_UCTL_CTL_REF_CLK_FSEL;
 	val |= FIELD_PREP(USBDRD_UCTL_CTL_REF_CLK_FSEL, ref_clk_fsel);
 
@@ -452,9 +338,21 @@ static int dwc3_octeon_clocks_start(struct device *dev, void __iomem *base)
 	/* Step 8b: Wait 10 controller-clock cycles. */
 	udelay(10);
 
-	/* Steo 8c: Setup power-power control. */
-	if (dwc3_octeon_config_power(dev, base))
-		return -EINVAL;
+	/* Step 8c: Setup power control. */
+	val = dwc3_octeon_readq(uctl_host_cfg_reg);
+	val |= USBDRD_UCTL_HOST_PPC_EN;
+	if (power_gpio < 0) {
+		val &= ~USBDRD_UCTL_HOST_PPC_EN;
+	} else {
+		val |= USBDRD_UCTL_HOST_PPC_EN;
+		dwc3_octeon_config_gpio(((__force u64)base >> 24) & 1,
+					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);
@@ -505,8 +403,89 @@ static void __init dwc3_octeon_phy_reset(void __iomem *base)
 static int dwc3_octeon_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
 	struct dwc3_data *data;
-	int err;
+	int err, len, ref_clk_sel, ref_clk_fsel, mpll_mul;
+	int power_active_low, power_gpio;
+	u32 clock_rate, gpio_pwr[3];
+	const char *hs_clock_type, *ss_clock_type;
+
+	if (!node) {
+		dev_err(dev, "No USB UCTL device node\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(node, "refclk-frequency", &clock_rate)) {
+		dev_err(dev, "No UCTL \"refclk-frequency\"\n");
+		return -EINVAL;
+	}
+	if (of_property_read_string(node, "refclk-type-ss", &ss_clock_type)) {
+		dev_err(dev, "No UCTL \"refclk-type-ss\"\n");
+		return -EINVAL;
+	}
+	if (of_property_read_string(node, "refclk-type-hs", &hs_clock_type)) {
+		dev_err(dev, "No UCTL \"refclk-type-hs\"\n");
+		return -EINVAL;
+	}
+
+	ref_clk_sel = 2;
+	if (strcmp("dlmc_ref_clk0", ss_clock_type) == 0) {
+		if (strcmp(hs_clock_type, "dlmc_ref_clk0") == 0)
+			ref_clk_sel = 0;
+		else if (strcmp(hs_clock_type, "pll_ref_clk"))
+			dev_warn(dev, "Invalid HS clock type %s, using pll_ref_clk instead\n",
+				 hs_clock_type);
+	} else if (strcmp(ss_clock_type, "dlmc_ref_clk1") == 0) {
+		if (strcmp(hs_clock_type, "dlmc_ref_clk1") == 0) {
+			ref_clk_sel = 1;
+		} else {
+			ref_clk_sel = 3;
+			if (strcmp(hs_clock_type, "pll_ref_clk"))
+				dev_warn(dev, "Invalid HS clock type %s, using pll_ref_clk instead\n",
+					 hs_clock_type);
+		}
+	} else {
+		dev_warn(dev, "Invalid SS clock type %s, using dlmc_ref_clk0 instead\n",
+			 ss_clock_type);
+	}
+
+	ref_clk_fsel = 0x07;
+	switch (clock_rate) {
+	default:
+		dev_warn(dev, "Invalid ref_clk %u, using 100000000 instead\n",
+			 clock_rate);
+		fallthrough;
+	case 100000000:
+		mpll_mul = 0x19;
+		if (ref_clk_sel < 2)
+			ref_clk_fsel = 0x27;
+		break;
+	case 50000000:
+		mpll_mul = 0x32;
+		break;
+	case 125000000:
+		mpll_mul = 0x28;
+		break;
+	}
+
+	if (of_find_property(node, "power", &len)) {
+		if (len == 12) {
+			of_property_read_u32_array(node, "power", gpio_pwr, 3);
+			power_active_low = gpio_pwr[2] & 0x01;
+			power_gpio = gpio_pwr[1];
+		} else if (len == 8) {
+			of_property_read_u32_array(node, "power", gpio_pwr, 2);
+			power_active_low = 0;
+			power_gpio = gpio_pwr[1];
+		} else {
+			dev_err(dev, "invalid power configuration\n");
+			return -EINVAL;
+		}
+	} else {
+		power_gpio = -1;
+		power_active_low = 0;
+		dev_info(dev, "power control disabled\n");
+	}
 
 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
@@ -516,9 +495,12 @@ static int dwc3_octeon_probe(struct platform_device *pdev)
 	if (IS_ERR(data->base))
 		return PTR_ERR(data->base);
 
-	err = dwc3_octeon_clocks_start(dev, data->base);
-	if (err)
+	err = dwc3_octeon_setup(data->base, ref_clk_sel, ref_clk_fsel,
+				mpll_mul, power_gpio, power_active_low);
+	if (err) {
+		dev_err(dev, "controller init failure\n");
 		return err;
+	}
 
 	dwc3_octeon_set_endian_mode(data->base);
 	dwc3_octeon_phy_reset(data->base);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 3/3] usb: dwc3: Add SPDX header and copyright
  2023-07-14  7:37 [PATCH v3 0/3] Cleanup Octeon DWC3 glue code Ladislav Michl
  2023-07-14  7:39 ` [PATCH v3 1/3] usb: dwc3: dwc3-octeon: Convert to glue driver Ladislav Michl
  2023-07-14  7:41 ` [PATCH v3 2/3] usb: dwc3: dwc3-octeon: Move node parsing into driver probe Ladislav Michl
@ 2023-07-14  7:41 ` Ladislav Michl
  2023-07-14 21:46   ` Thinh Nguyen
  2 siblings, 1 reply; 9+ messages in thread
From: Ladislav Michl @ 2023-07-14  7:41 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Thinh Nguyen, Greg Kroah-Hartman, Liang He
  Cc: linux-mips, linux-usb

From: Ladislav Michl <ladis@linux-mips.org>

As driver is rewritten and David no longer works for Marvell (Cavium),
I'm to blame for breakage.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
---
 CHANGES:
 - v2: None
 - v3: None

 drivers/usb/dwc3/dwc3-octeon.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-octeon.c b/drivers/usb/dwc3/dwc3-octeon.c
index dd47498f4efb..a68d568b11a9 100644
--- a/drivers/usb/dwc3/dwc3-octeon.c
+++ b/drivers/usb/dwc3/dwc3-octeon.c
@@ -1,11 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * XHCI HCD glue for Cavium Octeon III SOCs.
+ * DWC3 glue for Cavium Octeon III SOCs.
  *
  * Copyright (C) 2010-2017 Cavium Networks
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
+ * Copyright (C) 2023 Ladislav Michl <ladis@linux-mips.org>
  */
 
 #include <linux/bitfield.h>
@@ -536,6 +534,6 @@ static struct platform_driver dwc3_octeon_driver = {
 module_platform_driver(dwc3_octeon_driver);
 
 MODULE_ALIAS("platform:dwc3-octeon");
-MODULE_AUTHOR("David Daney <david.daney@cavium.com>");
+MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("DesignWare USB3 OCTEON III Glue Layer");
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 1/3] usb: dwc3: dwc3-octeon: Convert to glue driver
  2023-07-14  7:39 ` [PATCH v3 1/3] usb: dwc3: dwc3-octeon: Convert to glue driver Ladislav Michl
@ 2023-07-14 21:44   ` Thinh Nguyen
  0 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2023-07-14 21:44 UTC (permalink / raw)
  To: Ladislav Michl
  Cc: Thomas Bogendoerfer, Thinh Nguyen, Greg Kroah-Hartman, Liang He,
	linux-mips, linux-usb

On Fri, Jul 14, 2023, Ladislav Michl wrote:
> From: Ladislav Michl <ladis@linux-mips.org>
> 
> DWC3 as implemented in Cavium SoC is using UCTL bridge unit
> between I/O interconnect and USB controller.
> 
> Currently there is no bond with dwc3 core code, so if anything goes
> wrong in UCTL setup dwc3 is left in reset, which leads to bus error
> while trying to read any device register. Thus any failure in UCTL
> initialization ends with kernel panic.
> 
> To avoid this move Octeon DWC3 glue code from arch/mips and make it
> proper glue driver which is used instead of dwc3-of-simple.
> 
> Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
> Acked-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> ---
>  CHANGES:
>  - v2: squashed move and glue conversion patch, fixed sparse warning
>        and formatting issue. Set private data at the end of probe.
>        Clear drvdata on remove. Added host mode only notice.
>        Collected ack for move from arch/mips.
>  - v3: more descriptive commit message, dropped unrelated changes
> 
>  arch/mips/cavium-octeon/Makefile              |   1 -
>  arch/mips/cavium-octeon/octeon-platform.c     |   1 -
>  drivers/usb/dwc3/Kconfig                      |  10 ++
>  drivers/usb/dwc3/Makefile                     |   1 +
>  .../usb/dwc3/dwc3-octeon.c                    | 104 ++++++++++--------
>  drivers/usb/dwc3/dwc3-of-simple.c             |   1 -
>  6 files changed, 67 insertions(+), 51 deletions(-)
>  rename arch/mips/cavium-octeon/octeon-usb.c => drivers/usb/dwc3/dwc3-octeon.c (91%)
> 
> diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
> index 7c02e542959a..2a5926578841 100644
> --- a/arch/mips/cavium-octeon/Makefile
> +++ b/arch/mips/cavium-octeon/Makefile
> @@ -18,4 +18,3 @@ obj-y += crypto/
>  obj-$(CONFIG_MTD)		      += flash_setup.o
>  obj-$(CONFIG_SMP)		      += smp.o
>  obj-$(CONFIG_OCTEON_ILM)	      += oct_ilm.o
> -obj-$(CONFIG_USB)		      += octeon-usb.o
> diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
> index ce05c0dd3acd..235c77ce7b18 100644
> --- a/arch/mips/cavium-octeon/octeon-platform.c
> +++ b/arch/mips/cavium-octeon/octeon-platform.c
> @@ -450,7 +450,6 @@ static const struct of_device_id octeon_ids[] __initconst = {
>  	{ .compatible = "cavium,octeon-3860-bootbus", },
>  	{ .compatible = "cavium,mdio-mux", },
>  	{ .compatible = "gpio-leds", },
> -	{ .compatible = "cavium,octeon-7130-usb-uctl", },
>  	{},
>  };
>  
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index be954a9abbe0..98efcbb76c88 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -168,4 +168,14 @@ config USB_DWC3_AM62
>  	  The Designware Core USB3 IP is programmed to operate in
>  	  in USB 2.0 mode only.
>  	  Say 'Y' or 'M' here if you have one such device
> +
> +config USB_DWC3_OCTEON
> +	tristate "Cavium Octeon Platforms"
> +	depends on CAVIUM_OCTEON_SOC || COMPILE_TEST
> +	default USB_DWC3
> +	help
> +	  Support Cavium Octeon platforms with DesignWare Core USB3 IP.
> +	  Only the host mode is currently supported.
> +	  Say 'Y' or 'M' here if you have one such device.
> +
>  endif
> diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
> index 9f66bd82b639..fe1493d4bbe5 100644
> --- a/drivers/usb/dwc3/Makefile
> +++ b/drivers/usb/dwc3/Makefile
> @@ -54,3 +54,4 @@ obj-$(CONFIG_USB_DWC3_ST)		+= dwc3-st.o
>  obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom.o
>  obj-$(CONFIG_USB_DWC3_IMX8MP)		+= dwc3-imx8mp.o
>  obj-$(CONFIG_USB_DWC3_XILINX)		+= dwc3-xilinx.o
> +obj-$(CONFIG_USB_DWC3_OCTEON)		+= dwc3-octeon.o
> diff --git a/arch/mips/cavium-octeon/octeon-usb.c b/drivers/usb/dwc3/dwc3-octeon.c
> similarity index 91%
> rename from arch/mips/cavium-octeon/octeon-usb.c
> rename to drivers/usb/dwc3/dwc3-octeon.c
> index 2add435ad038..69bac61ccbe0 100644
> --- a/arch/mips/cavium-octeon/octeon-usb.c
> +++ b/drivers/usb/dwc3/dwc3-octeon.c
> @@ -187,7 +187,10 @@
>  #define USBDRD_UCTL_ECC				0xf0
>  #define USBDRD_UCTL_SPARE1			0xf8
>  
> -static DEFINE_MUTEX(dwc3_octeon_clocks_mutex);
> +struct dwc3_data {

Can we rename this to dwc3_octeon? It would be consistent with other
glue drivers, and it's clearer that this is Octeon's specific.

> +	struct device *dev;
> +	void __iomem *base;
> +};
>  
>  #ifdef CONFIG_CAVIUM_OCTEON_SOC
>  #include <asm/octeon/octeon.h>
> @@ -233,6 +236,11 @@ static inline uint64_t dwc3_octeon_readq(void __iomem *addr)
>  static inline void dwc3_octeon_writeq(void __iomem *base, uint64_t val) { }
>  
>  static inline void dwc3_octeon_config_gpio(int index, int gpio) { }
> +
> +static uint64_t octeon_get_io_clock_rate(void)
> +{
> +	return 150000000;
> +}
>  #endif
>  
>  static int dwc3_octeon_get_divider(void)
> @@ -494,58 +502,58 @@ static void __init dwc3_octeon_phy_reset(void __iomem *base)
>  	dwc3_octeon_writeq(uctl_ctl_reg, val);
>  }
>  
> -static int __init dwc3_octeon_device_init(void)
> +static int dwc3_octeon_probe(struct platform_device *pdev)
>  {
> -	const char compat_node_name[] = "cavium,octeon-7130-usb-uctl";
> -	struct platform_device *pdev;
> -	struct device_node *node;
> -	struct resource *res;
> -	void __iomem *base;
> +	struct device *dev = &pdev->dev;
> +	struct dwc3_data *data;

Can we rename "data" variable here and other places to octeon?

> +	int err;
>  
> -	/*
> -	 * There should only be three universal controllers, "uctl"
> -	 * in the device tree. Two USB and a SATA, which we ignore.
> -	 */
> -	node = NULL;
> -	do {
> -		node = of_find_node_by_name(node, "uctl");
> -		if (!node)
> -			return -ENODEV;
> -
> -		if (of_device_is_compatible(node, compat_node_name)) {
> -			pdev = of_find_device_by_node(node);
> -			if (!pdev)
> -				return -ENODEV;
> -
> -			/*
> -			 * The code below maps in the registers necessary for
> -			 * setting up the clocks and reseting PHYs. We must
> -			 * release the resources so the dwc3 subsystem doesn't
> -			 * know the difference.
> -			 */
> -			base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
> -			if (IS_ERR(base)) {
> -				put_device(&pdev->dev);
> -				return PTR_ERR(base);
> -			}
> +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
>  
> -			mutex_lock(&dwc3_octeon_clocks_mutex);
> -			if (dwc3_octeon_clocks_start(&pdev->dev, base) == 0)
> -				dev_info(&pdev->dev, "clocks initialized.\n");
> -			dwc3_octeon_set_endian_mode(base);
> -			dwc3_octeon_phy_reset(base);
> -			mutex_unlock(&dwc3_octeon_clocks_mutex);
> -			devm_iounmap(&pdev->dev, base);
> -			devm_release_mem_region(&pdev->dev, res->start,
> -						resource_size(res));
> -			put_device(&pdev->dev);
> -		}
> -	} while (node != NULL);
> +	data->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(data->base))
> +		return PTR_ERR(data->base);
>  
> -	return 0;
> +	err = dwc3_octeon_clocks_start(dev, data->base);
> +	if (err)
> +		return err;
> +
> +	dwc3_octeon_set_endian_mode(data->base);
> +	dwc3_octeon_phy_reset(data->base);
> +
> +	data->dev = dev;
> +	platform_set_drvdata(pdev, data);
> +
> +	return of_platform_populate(node, NULL, NULL, dev);
> +}
> +
> +static void dwc3_octeon_remove(struct platform_device *pdev)
> +{
> +	struct dwc3_data *data = platform_get_drvdata(pdev);
> +
> +	of_platform_depopulate(data->dev);
> +	platform_set_drvdata(pdev, NULL);
>  }
> -device_initcall(dwc3_octeon_device_init);
>  
> +static const struct of_device_id dwc3_octeon_of_match[] = {
> +	{ .compatible = "cavium,octeon-7130-usb-uctl" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, dwc3_octeon_of_match);
> +
> +static struct platform_driver dwc3_octeon_driver = {
> +	.probe		= dwc3_octeon_probe,
> +	.remove_new	= dwc3_octeon_remove,
> +	.driver		= {
> +		.name	= "dwc3-octeon",
> +		.of_match_table = dwc3_octeon_of_match,
> +	},
> +};
> +module_platform_driver(dwc3_octeon_driver);
> +
> +MODULE_ALIAS("platform:dwc3-octeon");
>  MODULE_AUTHOR("David Daney <david.daney@cavium.com>");
>  MODULE_LICENSE("GPL");
> -MODULE_DESCRIPTION("USB driver for OCTEON III SoC");
> +MODULE_DESCRIPTION("DesignWare USB3 OCTEON III Glue Layer");
> diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
> index 7e6ad8fe61a5..d1539fc9eabd 100644
> --- a/drivers/usb/dwc3/dwc3-of-simple.c
> +++ b/drivers/usb/dwc3/dwc3-of-simple.c
> @@ -170,7 +170,6 @@ static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = {
>  
>  static const struct of_device_id of_dwc3_simple_match[] = {
>  	{ .compatible = "rockchip,rk3399-dwc3" },
> -	{ .compatible = "cavium,octeon-7130-usb-uctl" },
>  	{ .compatible = "sprd,sc9860-dwc3" },
>  	{ .compatible = "allwinner,sun50i-h6-dwc3" },
>  	{ .compatible = "hisilicon,hi3670-dwc3" },
> -- 
> 2.39.2
> 

After the change, you can add my Ack:

Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>

Thanks,
Thinh

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 3/3] usb: dwc3: Add SPDX header and copyright
  2023-07-14  7:41 ` [PATCH v3 3/3] usb: dwc3: Add SPDX header and copyright Ladislav Michl
@ 2023-07-14 21:46   ` Thinh Nguyen
  2023-07-15  5:23     ` Greg Kroah-Hartman
  0 siblings, 1 reply; 9+ messages in thread
From: Thinh Nguyen @ 2023-07-14 21:46 UTC (permalink / raw)
  To: Ladislav Michl
  Cc: Thomas Bogendoerfer, Thinh Nguyen, Greg Kroah-Hartman, Liang He,
	linux-mips, linux-usb

On Fri, Jul 14, 2023, Ladislav Michl wrote:
> From: Ladislav Michl <ladis@linux-mips.org>
> 
> As driver is rewritten and David no longer works for Marvell (Cavium),
> I'm to blame for breakage.
> 
> Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
> ---
>  CHANGES:
>  - v2: None
>  - v3: None
> 
>  drivers/usb/dwc3/dwc3-octeon.c | 10 ++++------
>  1 file changed, 4 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/dwc3-octeon.c b/drivers/usb/dwc3/dwc3-octeon.c
> index dd47498f4efb..a68d568b11a9 100644
> --- a/drivers/usb/dwc3/dwc3-octeon.c
> +++ b/drivers/usb/dwc3/dwc3-octeon.c
> @@ -1,11 +1,9 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
> - * XHCI HCD glue for Cavium Octeon III SOCs.
> + * DWC3 glue for Cavium Octeon III SOCs.
>   *
>   * Copyright (C) 2010-2017 Cavium Networks
> - *
> - * This file is subject to the terms and conditions of the GNU General Public
> - * License.  See the file "COPYING" in the main directory of this archive
> - * for more details.
> + * Copyright (C) 2023 Ladislav Michl <ladis@linux-mips.org>

I may not be an expert with Copyright, but is it correct to put your
name rather than the entity this belongs to?

BR,
Thinh

>   */
>  
>  #include <linux/bitfield.h>
> @@ -536,6 +534,6 @@ static struct platform_driver dwc3_octeon_driver = {
>  module_platform_driver(dwc3_octeon_driver);
>  
>  MODULE_ALIAS("platform:dwc3-octeon");
> -MODULE_AUTHOR("David Daney <david.daney@cavium.com>");
> +MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
>  MODULE_LICENSE("GPL");
>  MODULE_DESCRIPTION("DesignWare USB3 OCTEON III Glue Layer");
> -- 
> 2.39.2
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 2/3] usb: dwc3: dwc3-octeon: Move node parsing into driver probe
  2023-07-14  7:41 ` [PATCH v3 2/3] usb: dwc3: dwc3-octeon: Move node parsing into driver probe Ladislav Michl
@ 2023-07-14 22:26   ` Thinh Nguyen
  0 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2023-07-14 22:26 UTC (permalink / raw)
  To: Ladislav Michl
  Cc: Thomas Bogendoerfer, Thinh Nguyen, Greg Kroah-Hartman, Liang He,
	linux-mips, linux-usb

On Fri, Jul 14, 2023, Ladislav Michl wrote:
> From: Ladislav Michl <ladis@linux-mips.org>
> 
> Parse and verify device tree node first, then setup UCTL bridge
> using verified values. This avoids half initialized hardware state
> in case DT misconfiguration was found in the middle of setup.
> As a dwc3_octeon_clocks_start already did more than just starting
> a clock, rename it approprietly and move all hardware setup there.

There are multiple things happening here more than just moving the code.
Can you split them into separate commits?

> 
> Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
> ---
>  CHANGES:
>  - v2: if else block bracket according CodingStyle
>  - v3: more descriptive commit message, power gpio parsing in probe too,
>        checkpatch --strict passed
> 
>  drivers/usb/dwc3/dwc3-octeon.c | 236 +++++++++++++++------------------
>  1 file changed, 109 insertions(+), 127 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/dwc3-octeon.c b/drivers/usb/dwc3/dwc3-octeon.c
> index 69bac61ccbe0..dd47498f4efb 100644
> --- a/drivers/usb/dwc3/dwc3-octeon.c
> +++ b/drivers/usb/dwc3/dwc3-octeon.c
> @@ -258,108 +258,14 @@ static int dwc3_octeon_get_divider(void)
>  	return div;
>  }
>  
> -static int dwc3_octeon_config_power(struct device *dev, void __iomem *base)
> +static int dwc3_octeon_setup(void __iomem *base,

I would pass dwc3_data here instead of just the base. It fits with the
function name, and it requires less change in the future in case you
need access dwc3_data.

> +			     int ref_clk_sel, int ref_clk_fsel, int mpll_mul,
> +			     int power_gpio, int power_active_low)
>  {
> -	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 device *dev, void __iomem *base)
> -{
> -	int i, div, mpll_mul, ref_clk_fsel, ref_clk_sel = 2;
> -	u32 clock_rate;
> +	int div;
>  	u64 val;
>  	void __iomem *uctl_ctl_reg = base + USBDRD_UCTL_CTL;
> -
> -	if (dev->of_node) {
> -		const char *ss_clock_type;
> -		const char *hs_clock_type;
> -
> -		i = of_property_read_u32(dev->of_node,
> -					 "refclk-frequency", &clock_rate);
> -		if (i) {
> -			dev_err(dev, "No UCTL \"refclk-frequency\"\n");
> -			return -EINVAL;
> -		}
> -		i = of_property_read_string(dev->of_node,
> -					    "refclk-type-ss", &ss_clock_type);
> -		if (i) {
> -			dev_err(dev, "No UCTL \"refclk-type-ss\"\n");
> -			return -EINVAL;
> -		}
> -		i = of_property_read_string(dev->of_node,
> -					    "refclk-type-hs", &hs_clock_type);
> -		if (i) {
> -			dev_err(dev, "No UCTL \"refclk-type-hs\"\n");
> -			return -EINVAL;
> -		}
> -		if (strcmp("dlmc_ref_clk0", ss_clock_type) == 0) {
> -			if (strcmp(hs_clock_type, "dlmc_ref_clk0") == 0)
> -				ref_clk_sel = 0;
> -			else if (strcmp(hs_clock_type, "pll_ref_clk") == 0)
> -				ref_clk_sel = 2;
> -			else
> -				dev_warn(dev, "Invalid HS clock type %s, using pll_ref_clk instead\n",
> -					 hs_clock_type);
> -		} else if (strcmp(ss_clock_type, "dlmc_ref_clk1") == 0) {
> -			if (strcmp(hs_clock_type, "dlmc_ref_clk1") == 0)
> -				ref_clk_sel = 1;
> -			else if (strcmp(hs_clock_type, "pll_ref_clk") == 0)
> -				ref_clk_sel = 3;
> -			else {
> -				dev_warn(dev, "Invalid HS clock type %s, using pll_ref_clk instead\n",
> -					 hs_clock_type);
> -				ref_clk_sel = 3;
> -			}
> -		} else
> -			dev_warn(dev, "Invalid SS clock type %s, using dlmc_ref_clk0 instead\n",
> -				 ss_clock_type);
> -
> -		if ((ref_clk_sel == 0 || ref_clk_sel == 1) &&
> -		    (clock_rate != 100000000))
> -			dev_warn(dev, "Invalid UCTL clock rate of %u, using 100000000 instead\n",
> -				 clock_rate);
> -
> -	} else {
> -		dev_err(dev, "No USB UCTL device node\n");
> -		return -EINVAL;
> -	}
> +	void __iomem *uctl_host_cfg_reg = base + USBDRD_UCTL_HOST_CFG;
>  
>  	/*
>  	 * Step 1: Wait for all voltages to be stable...that surely
> @@ -389,10 +295,8 @@ static int dwc3_octeon_clocks_start(struct device *dev, void __iomem *base)
>  	dwc3_octeon_writeq(uctl_ctl_reg, val);
>  	val = dwc3_octeon_readq(uctl_ctl_reg);
>  	if ((div != FIELD_GET(USBDRD_UCTL_CTL_H_CLKDIV_SEL, val)) ||
> -	    (!(FIELD_GET(USBDRD_UCTL_CTL_H_CLK_EN, val)))) {
> -		dev_err(dev, "dwc3 controller clock init failure.\n");
> -			return -EINVAL;
> -	}
> +	    (!(FIELD_GET(USBDRD_UCTL_CTL_H_CLK_EN, val))))
> +		return -EINVAL;
>  
>  	/* Step 4c: Deassert the controller clock divider reset. */
>  	val &= ~USBDRD_UCTL_CTL_H_CLKDIV_RST;
> @@ -404,24 +308,6 @@ static int dwc3_octeon_clocks_start(struct device *dev, void __iomem *base)
>  	val &= ~USBDRD_UCTL_CTL_REF_CLK_SEL;
>  	val |= FIELD_PREP(USBDRD_UCTL_CTL_REF_CLK_SEL, ref_clk_sel);
>  
> -	ref_clk_fsel = 0x07;
> -	switch (clock_rate) {
> -	default:
> -		dev_warn(dev, "Invalid ref_clk %u, using 100000000 instead\n",
> -			 clock_rate);
> -		fallthrough;
> -	case 100000000:
> -		mpll_mul = 0x19;
> -		if (ref_clk_sel < 2)
> -			ref_clk_fsel = 0x27;
> -		break;
> -	case 50000000:
> -		mpll_mul = 0x32;
> -		break;
> -	case 125000000:
> -		mpll_mul = 0x28;
> -		break;
> -	}
>  	val &= ~USBDRD_UCTL_CTL_REF_CLK_FSEL;
>  	val |= FIELD_PREP(USBDRD_UCTL_CTL_REF_CLK_FSEL, ref_clk_fsel);
>  
> @@ -452,9 +338,21 @@ static int dwc3_octeon_clocks_start(struct device *dev, void __iomem *base)
>  	/* Step 8b: Wait 10 controller-clock cycles. */
>  	udelay(10);
>  
> -	/* Steo 8c: Setup power-power control. */
> -	if (dwc3_octeon_config_power(dev, base))
> -		return -EINVAL;
> +	/* Step 8c: Setup power control. */
> +	val = dwc3_octeon_readq(uctl_host_cfg_reg);
> +	val |= USBDRD_UCTL_HOST_PPC_EN;
> +	if (power_gpio < 0) {

This check makes more sense if you use a macro.
(e.g. if (power_gpio == UNKNOWN_PIN) ...)

> +		val &= ~USBDRD_UCTL_HOST_PPC_EN;
> +	} else {
> +		val |= USBDRD_UCTL_HOST_PPC_EN;
> +		dwc3_octeon_config_gpio(((__force u64)base >> 24) & 1,
> +					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);
> @@ -505,8 +403,89 @@ static void __init dwc3_octeon_phy_reset(void __iomem *base)
>  static int dwc3_octeon_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> +	struct device_node *node = dev->of_node;
>  	struct dwc3_data *data;
> -	int err;
> +	int err, len, ref_clk_sel, ref_clk_fsel, mpll_mul;
> +	int power_active_low, power_gpio;
> +	u32 clock_rate, gpio_pwr[3];
> +	const char *hs_clock_type, *ss_clock_type;
> +
> +	if (!node) {
> +		dev_err(dev, "No USB UCTL device node\n");
> +		return -EINVAL;
> +	}
> +
> +	if (of_property_read_u32(node, "refclk-frequency", &clock_rate)) {
> +		dev_err(dev, "No UCTL \"refclk-frequency\"\n");
> +		return -EINVAL;
> +	}
> +	if (of_property_read_string(node, "refclk-type-ss", &ss_clock_type)) {
> +		dev_err(dev, "No UCTL \"refclk-type-ss\"\n");
> +		return -EINVAL;
> +	}
> +	if (of_property_read_string(node, "refclk-type-hs", &hs_clock_type)) {
> +		dev_err(dev, "No UCTL \"refclk-type-hs\"\n");
> +		return -EINVAL;
> +	}
> +
> +	ref_clk_sel = 2;
> +	if (strcmp("dlmc_ref_clk0", ss_clock_type) == 0) {
> +		if (strcmp(hs_clock_type, "dlmc_ref_clk0") == 0)
> +			ref_clk_sel = 0;
> +		else if (strcmp(hs_clock_type, "pll_ref_clk"))
> +			dev_warn(dev, "Invalid HS clock type %s, using pll_ref_clk instead\n",
> +				 hs_clock_type);
> +	} else if (strcmp(ss_clock_type, "dlmc_ref_clk1") == 0) {
> +		if (strcmp(hs_clock_type, "dlmc_ref_clk1") == 0) {
> +			ref_clk_sel = 1;
> +		} else {
> +			ref_clk_sel = 3;
> +			if (strcmp(hs_clock_type, "pll_ref_clk"))
> +				dev_warn(dev, "Invalid HS clock type %s, using pll_ref_clk instead\n",
> +					 hs_clock_type);
> +		}
> +	} else {
> +		dev_warn(dev, "Invalid SS clock type %s, using dlmc_ref_clk0 instead\n",
> +			 ss_clock_type);
> +	}
> +
> +	ref_clk_fsel = 0x07;
> +	switch (clock_rate) {
> +	default:
> +		dev_warn(dev, "Invalid ref_clk %u, using 100000000 instead\n",
> +			 clock_rate);
> +		fallthrough;
> +	case 100000000:
> +		mpll_mul = 0x19;
> +		if (ref_clk_sel < 2)
> +			ref_clk_fsel = 0x27;
> +		break;
> +	case 50000000:
> +		mpll_mul = 0x32;
> +		break;
> +	case 125000000:
> +		mpll_mul = 0x28;
> +		break;
> +	}
> +
> +	if (of_find_property(node, "power", &len)) {
> +		if (len == 12) {
> +			of_property_read_u32_array(node, "power", gpio_pwr, 3);
> +			power_active_low = gpio_pwr[2] & 0x01;
> +			power_gpio = gpio_pwr[1];
> +		} else if (len == 8) {
> +			of_property_read_u32_array(node, "power", gpio_pwr, 2);
> +			power_active_low = 0;
> +			power_gpio = gpio_pwr[1];
> +		} else {
> +			dev_err(dev, "invalid power configuration\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		power_gpio = -1;

You should use a macro for this instead of -1. Use the same unsigned
type if possible.

> +		power_active_low = 0;
> +		dev_info(dev, "power control disabled\n");

If you do any cleanup later, reinspect these dev_info(). It seems
dev_dbg() is more fitting here.

> +	}
>  
>  	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
>  	if (!data)
> @@ -516,9 +495,12 @@ static int dwc3_octeon_probe(struct platform_device *pdev)
>  	if (IS_ERR(data->base))
>  		return PTR_ERR(data->base);
>  
> -	err = dwc3_octeon_clocks_start(dev, data->base);
> -	if (err)
> +	err = dwc3_octeon_setup(data->base, ref_clk_sel, ref_clk_fsel,
> +				mpll_mul, power_gpio, power_active_low);
> +	if (err) {
> +		dev_err(dev, "controller init failure\n");
>  		return err;
> +	}
>  
>  	dwc3_octeon_set_endian_mode(data->base);
>  	dwc3_octeon_phy_reset(data->base);
> -- 
> 2.39.2
> 

Thanks,
Thinh

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 3/3] usb: dwc3: Add SPDX header and copyright
  2023-07-14 21:46   ` Thinh Nguyen
@ 2023-07-15  5:23     ` Greg Kroah-Hartman
  2023-07-16 14:11       ` Ladislav Michl
  0 siblings, 1 reply; 9+ messages in thread
From: Greg Kroah-Hartman @ 2023-07-15  5:23 UTC (permalink / raw)
  To: Thinh Nguyen
  Cc: Ladislav Michl, Thomas Bogendoerfer, Liang He, linux-mips, linux-usb

On Fri, Jul 14, 2023 at 09:46:13PM +0000, Thinh Nguyen wrote:
> On Fri, Jul 14, 2023, Ladislav Michl wrote:
> > From: Ladislav Michl <ladis@linux-mips.org>
> > 
> > As driver is rewritten and David no longer works for Marvell (Cavium),
> > I'm to blame for breakage.
> > 
> > Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
> > ---
> >  CHANGES:
> >  - v2: None
> >  - v3: None
> > 
> >  drivers/usb/dwc3/dwc3-octeon.c | 10 ++++------
> >  1 file changed, 4 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/usb/dwc3/dwc3-octeon.c b/drivers/usb/dwc3/dwc3-octeon.c
> > index dd47498f4efb..a68d568b11a9 100644
> > --- a/drivers/usb/dwc3/dwc3-octeon.c
> > +++ b/drivers/usb/dwc3/dwc3-octeon.c
> > @@ -1,11 +1,9 @@
> > +// SPDX-License-Identifier: GPL-2.0
> >  /*
> > - * XHCI HCD glue for Cavium Octeon III SOCs.
> > + * DWC3 glue for Cavium Octeon III SOCs.
> >   *
> >   * Copyright (C) 2010-2017 Cavium Networks
> > - *
> > - * This file is subject to the terms and conditions of the GNU General Public
> > - * License.  See the file "COPYING" in the main directory of this archive
> > - * for more details.
> > + * Copyright (C) 2023 Ladislav Michl <ladis@linux-mips.org>
> 
> I may not be an expert with Copyright, but is it correct to put your
> name rather than the entity this belongs to?

That is up to the employer of the developer as to what they want to see
here.  Ladislav, you have run this by your legal group, right?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 3/3] usb: dwc3: Add SPDX header and copyright
  2023-07-15  5:23     ` Greg Kroah-Hartman
@ 2023-07-16 14:11       ` Ladislav Michl
  0 siblings, 0 replies; 9+ messages in thread
From: Ladislav Michl @ 2023-07-16 14:11 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Thinh Nguyen, Thomas Bogendoerfer, Liang He, linux-mips, linux-usb

On Sat, Jul 15, 2023 at 07:23:29AM +0200, Greg Kroah-Hartman wrote:
> On Fri, Jul 14, 2023 at 09:46:13PM +0000, Thinh Nguyen wrote:
> > On Fri, Jul 14, 2023, Ladislav Michl wrote:
> > > From: Ladislav Michl <ladis@linux-mips.org>
> > > 
> > > As driver is rewritten and David no longer works for Marvell (Cavium),
> > > I'm to blame for breakage.
> > > 
> > > Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
> > > ---
> > >  CHANGES:
> > >  - v2: None
> > >  - v3: None
> > > 
> > >  drivers/usb/dwc3/dwc3-octeon.c | 10 ++++------
> > >  1 file changed, 4 insertions(+), 6 deletions(-)
> > > 
> > > diff --git a/drivers/usb/dwc3/dwc3-octeon.c b/drivers/usb/dwc3/dwc3-octeon.c
> > > index dd47498f4efb..a68d568b11a9 100644
> > > --- a/drivers/usb/dwc3/dwc3-octeon.c
> > > +++ b/drivers/usb/dwc3/dwc3-octeon.c
> > > @@ -1,11 +1,9 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > >  /*
> > > - * XHCI HCD glue for Cavium Octeon III SOCs.
> > > + * DWC3 glue for Cavium Octeon III SOCs.
> > >   *
> > >   * Copyright (C) 2010-2017 Cavium Networks
> > > - *
> > > - * This file is subject to the terms and conditions of the GNU General Public
> > > - * License.  See the file "COPYING" in the main directory of this archive
> > > - * for more details.
> > > + * Copyright (C) 2023 Ladislav Michl <ladis@linux-mips.org>
> > 
> > I may not be an expert with Copyright, but is it correct to put your
> > name rather than the entity this belongs to?
> 
> That is up to the employer of the developer as to what they want to see
> here.  Ladislav, you have run this by your legal group, right?

Not this particular one as I do not have any legal group :) I started
this cleanup on my own, but it turned out there will be much more work
needed to make USB on Octeon reliable. So after asking my contact person
at Racom, copyright will be assigned to them. Note that it is not official
statement yet, but as Thinh is on holidays anyway, we have quite some
time to sort this out. I'll either confirm or send v5 - v4 is is on the
way with Thinh's comments addressed, so I'm lookign forward for feedback.

Thanks,
	ladis

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-07-16 14:12 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-14  7:37 [PATCH v3 0/3] Cleanup Octeon DWC3 glue code Ladislav Michl
2023-07-14  7:39 ` [PATCH v3 1/3] usb: dwc3: dwc3-octeon: Convert to glue driver Ladislav Michl
2023-07-14 21:44   ` Thinh Nguyen
2023-07-14  7:41 ` [PATCH v3 2/3] usb: dwc3: dwc3-octeon: Move node parsing into driver probe Ladislav Michl
2023-07-14 22:26   ` Thinh Nguyen
2023-07-14  7:41 ` [PATCH v3 3/3] usb: dwc3: Add SPDX header and copyright Ladislav Michl
2023-07-14 21:46   ` Thinh Nguyen
2023-07-15  5:23     ` Greg Kroah-Hartman
2023-07-16 14:11       ` Ladislav Michl

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.