1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Renesas USB driver R-Car Gen. 3 initialization and power control 4 * 5 * Copyright (C) 2016 Renesas Electronics Corporation 6 */ 7 8 #include <linux/delay.h> 9 #include <linux/io.h> 10 #include "common.h" 11 #include "rcar3.h" 12 13 #define LPSTS 0x102 14 #define UGCTRL 0x180 /* 32-bit register */ 15 #define UGCTRL2 0x184 /* 32-bit register */ 16 #define UGSTS 0x188 /* 32-bit register */ 17 18 /* Low Power Status register (LPSTS) */ 19 #define LPSTS_SUSPM 0x4000 20 21 /* R-Car D3 only: USB General control register (UGCTRL) */ 22 #define UGCTRL_PLLRESET 0x00000001 23 #define UGCTRL_CONNECT 0x00000004 24 25 /* 26 * USB General control register 2 (UGCTRL2) 27 * Remarks: bit[31:11] and bit[9:6] should be 0 28 */ 29 #define UGCTRL2_RESERVED_3 0x00000001 /* bit[3:0] should be B'0001 */ 30 #define UGCTRL2_USB0SEL_EHCI 0x00000010 31 #define UGCTRL2_USB0SEL_HSUSB 0x00000020 32 #define UGCTRL2_USB0SEL_OTG 0x00000030 33 #define UGCTRL2_VBUSSEL 0x00000400 34 35 /* R-Car D3 only: USB General status register (UGSTS) */ 36 #define UGSTS_LOCK 0x00000100 37 38 static void usbhs_write32(struct usbhs_priv *priv, u32 reg, u32 data) 39 { 40 iowrite32(data, priv->base + reg); 41 } 42 43 static u32 usbhs_read32(struct usbhs_priv *priv, u32 reg) 44 { 45 return ioread32(priv->base + reg); 46 } 47 48 static void usbhs_rcar3_set_ugctrl2(struct usbhs_priv *priv, u32 val) 49 { 50 usbhs_write32(priv, UGCTRL2, val | UGCTRL2_RESERVED_3); 51 } 52 53 static void usbhs_rcar3_set_usbsel(struct usbhs_priv *priv, bool ehci) 54 { 55 if (ehci) 56 usbhs_rcar3_set_ugctrl2(priv, UGCTRL2_USB0SEL_EHCI); 57 else 58 usbhs_rcar3_set_ugctrl2(priv, UGCTRL2_USB0SEL_HSUSB); 59 } 60 61 static int usbhs_rcar3_power_ctrl(struct platform_device *pdev, 62 void __iomem *base, int enable) 63 { 64 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 65 66 usbhs_rcar3_set_ugctrl2(priv, UGCTRL2_USB0SEL_OTG | UGCTRL2_VBUSSEL); 67 68 if (enable) { 69 usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM); 70 /* The controller on R-Car Gen3 needs to wait up to 45 usec */ 71 udelay(45); 72 } else { 73 usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0); 74 } 75 76 return 0; 77 } 78 79 /* R-Car D3 needs to release UGCTRL.PLLRESET */ 80 static int usbhs_rcar3_power_and_pll_ctrl(struct platform_device *pdev, 81 void __iomem *base, int enable) 82 { 83 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 84 u32 val; 85 int timeout = 1000; 86 bool is_host = false; 87 88 if (enable) { 89 usbhs_write32(priv, UGCTRL, 0); /* release PLLRESET */ 90 if (priv->edev) 91 is_host = extcon_get_state(priv->edev, EXTCON_USB_HOST); 92 93 usbhs_rcar3_set_usbsel(priv, is_host); 94 95 usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM); 96 do { 97 val = usbhs_read32(priv, UGSTS); 98 udelay(1); 99 } while (!(val & UGSTS_LOCK) && timeout--); 100 usbhs_write32(priv, UGCTRL, UGCTRL_CONNECT); 101 } else { 102 usbhs_write32(priv, UGCTRL, 0); 103 usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0); 104 usbhs_write32(priv, UGCTRL, UGCTRL_PLLRESET); 105 } 106 107 return 0; 108 } 109 110 static int usbhs_rcar3_get_id(struct platform_device *pdev) 111 { 112 return USBHS_GADGET; 113 } 114 115 static int usbhs_rcar3_notifier(struct notifier_block *nb, unsigned long event, 116 void *data) 117 { 118 struct usbhs_priv *priv = container_of(nb, struct usbhs_priv, nb); 119 120 usbhs_rcar3_set_usbsel(priv, !!event); 121 122 return NOTIFY_DONE; 123 } 124 125 const struct renesas_usbhs_platform_callback usbhs_rcar3_ops = { 126 .power_ctrl = usbhs_rcar3_power_ctrl, 127 .get_id = usbhs_rcar3_get_id, 128 }; 129 130 const struct renesas_usbhs_platform_callback usbhs_rcar3_with_pll_ops = { 131 .power_ctrl = usbhs_rcar3_power_and_pll_ctrl, 132 .get_id = usbhs_rcar3_get_id, 133 .notifier = usbhs_rcar3_notifier, 134 }; 135