soc: renesas: r9a06g032-sysctrl: Handle h2mode setting based on USBF presence
authorHerve Codina <herve.codina@bootlin.com>
Thu, 5 Jan 2023 15:22:54 +0000 (16:22 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 Jan 2023 16:22:32 +0000 (17:22 +0100)
The CFG_USB[H2MODE] allows to switch the USB configuration. The
configuration supported are:
  - One host and one device
or
  - Two hosts

Set CFG_USB[H2MODE] based on the USBF controller (USB device)
availability.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/20230105152257.310642-3-herve.codina@bootlin.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/clk/renesas/r9a06g032-clocks.c

index 983faa5707b9cf4d192ba4c53564f8cd74e13f38..087146f2ee068713208cb23efe16cc0f2ff9658c 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/spinlock.h>
 #include <dt-bindings/clock/r9a06g032-sysctrl.h>
 
+#define R9A06G032_SYSCTRL_USB    0x00
+#define R9A06G032_SYSCTRL_USB_H2MODE  (1<<1)
 #define R9A06G032_SYSCTRL_DMAMUX 0xA0
 
 struct r9a06g032_gate {
@@ -918,6 +920,29 @@ static void r9a06g032_clocks_del_clk_provider(void *data)
        of_clk_del_provider(data);
 }
 
+static void __init r9a06g032_init_h2mode(struct r9a06g032_priv *clocks)
+{
+       struct device_node *usbf_np = NULL;
+       u32 usb;
+
+       while ((usbf_np = of_find_compatible_node(usbf_np, NULL,
+                                                 "renesas,rzn1-usbf"))) {
+               if (of_device_is_available(usbf_np))
+                       break;
+       }
+
+       usb = readl(clocks->reg + R9A06G032_SYSCTRL_USB);
+       if (usbf_np) {
+               /* 1 host and 1 device mode */
+               usb &= ~R9A06G032_SYSCTRL_USB_H2MODE;
+               of_node_put(usbf_np);
+       } else {
+               /* 2 hosts mode */
+               usb |= R9A06G032_SYSCTRL_USB_H2MODE;
+       }
+       writel(usb, clocks->reg + R9A06G032_SYSCTRL_USB);
+}
+
 static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -947,6 +972,9 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
        clocks->reg = of_iomap(np, 0);
        if (WARN_ON(!clocks->reg))
                return -ENOMEM;
+
+       r9a06g032_init_h2mode(clocks);
+
        for (i = 0; i < ARRAY_SIZE(r9a06g032_clocks); ++i) {
                const struct r9a06g032_clkdesc *d = &r9a06g032_clocks[i];
                const char *parent_name = d->source ?