Angel Pons | 7c1d70e | 2020-04-04 18:51:19 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 2 | |
Kyösti Mälkki | 13f6650 | 2019-03-03 08:01:05 +0200 | [diff] [blame] | 3 | #include <device/mmio.h> |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 4 | #include <console/console.h> |
| 5 | #include <delay.h> |
| 6 | #include <soc/clock.h> |
| 7 | #include <soc/iomap.h> |
| 8 | #include <soc/usb.h> |
| 9 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 10 | /** |
| 11 | * USB Hardware registers |
| 12 | */ |
| 13 | #define PHY_CTRL0_ADDR 0x000 |
| 14 | #define PHY_CTRL1_ADDR 0x004 |
| 15 | #define PHY_CTRL2_ADDR 0x008 |
| 16 | #define PHY_CTRL3_ADDR 0x00C |
| 17 | #define PHY_CTRL4_ADDR 0x010 |
| 18 | #define PHY_MISC_ADDR 0x024 |
| 19 | #define PHY_IPG_ADDR 0x030 |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 20 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 21 | #define PHY_CTRL0_VAL 0xA4600015 |
| 22 | #define PHY_CTRL1_VAL 0x09500000 |
| 23 | #define PHY_CTRL2_VAL 0x00058180 |
| 24 | #define PHY_CTRL3_VAL 0x6DB6DCD6 |
| 25 | #define PHY_CTRL4_VAL 0x836DB6DB |
| 26 | #define PHY_MISC_VAL 0x3803FB0C |
| 27 | #define PHY_IPG_VAL 0x47323232 |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 28 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 29 | #define USB_HOST3_PHY_BASE ((void *)0x8a00000) |
| 30 | #define USB_HOST3_BALDUR_PHY_BASE ((void *)0xa6000) |
| 31 | #define GCC_USB3_RST_CTRL ((void *)0x0181E038) |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 32 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 33 | #define DWC3_GCTL 0xc110 |
| 34 | #define DWC3_GUSB3PIPECTL(n) (0xc2c0 + (n * 0x04)) |
| 35 | #define DWC3_GUSB2PHYCFG(n) (0xc200 + (n * 0x04)) |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 36 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 37 | /* Global USB3 PIPE Control Register */ |
| 38 | #define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) |
| 39 | #define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) |
| 40 | #define DWC3_GCTL_CORESOFTRESET (1 << 11) |
| 41 | #define DWC3_GCTL_PRTCAPDIR(n) ((n) << 12) |
| 42 | #define DWC3_GCTL_PRTCAP_OTG 3 |
| 43 | #define DWC3_DCTL_CSFTRST (1 << 30) |
| 44 | #define DWC3_GSNPSID 0xc120 |
| 45 | #define DWC3_DCTL 0xc704 |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 46 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 47 | /* Global USB2 PHY Configuration Register */ |
| 48 | #define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) |
| 49 | #define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) |
| 50 | #define DWC3_GSNPSID_MASK 0xffff0000 |
| 51 | #define DWC3_GEVTEN 0xc114 |
| 52 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 53 | #define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) |
| 54 | #define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) |
| 55 | #define DWC3_GCTL_DISSCRAMBLE (1 << 3) |
| 56 | #define DWC3_GCTL_DSBLCLKGTNG (1 << 0) |
| 57 | #define DWC3_GCTL_U2RSTECN (1 << 16) |
| 58 | #define DWC3_REVISION_190A 0x5533190a |
| 59 | |
| 60 | #define USB30_HS_PHY_CTRL 0x00000010 |
| 61 | #define SW_SESSVLD (0x01 << 0x1C) |
| 62 | #define UTMI_OTG_VBUS_VALID (0x01 << 0x14) |
| 63 | |
| 64 | #define USB30_SS_PHY_CTRL 0x00000030 |
| 65 | #define LANE0_PWR_PRESENT (0x01 << 0x18) |
| 66 | |
| 67 | static void setup_dwc3(void); |
| 68 | |
| 69 | /** |
| 70 | * Write register. |
| 71 | * |
Martin Roth | 4934818 | 2016-07-06 10:17:19 -0600 | [diff] [blame] | 72 | * @param base - PHY base virtual address. |
| 73 | * @param offset - register offset. |
| 74 | * @param val - value to write. |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 75 | */ |
| 76 | static inline void qscratch_write(void *base, u32 offset, u32 val) |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 77 | { |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 78 | write32(base + offset, val); |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 79 | } |
| 80 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 81 | /** |
| 82 | * Write register and read back masked value to confirm it is written |
| 83 | * |
Martin Roth | 4934818 | 2016-07-06 10:17:19 -0600 | [diff] [blame] | 84 | * @param base - base virtual address. |
| 85 | * @param offset - register offset. |
| 86 | * @param mask - register bitmask specifying what should be updated |
| 87 | * @param val - value to write. |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 88 | */ |
| 89 | static inline void qscratch_write_readback(void *base, u32 offset, |
| 90 | const u32 mask, u32 val) |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 91 | { |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 92 | u32 write_val, tmp = read32(base + offset); |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 93 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 94 | tmp &= ~mask; /* retain other bits */ |
| 95 | write_val = tmp | val; |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 96 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 97 | write32(base + offset, write_val); |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 98 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 99 | /* Read back to see if val was written */ |
| 100 | tmp = read32(base + offset); |
| 101 | tmp &= mask; /* clear other bits */ |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 102 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 103 | if (tmp != val) { |
| 104 | printk(BIOS_INFO, "write: %x to QSCRATCH: %x FAILED\n", |
| 105 | val, offset); |
| 106 | } |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 107 | } |
| 108 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 109 | static void dwc3_ipq40xx_enable_vbus_valid(void) |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 110 | { |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 111 | /* Enable VBUS valid for HS PHY*/ |
| 112 | qscratch_write_readback((void *)0x8af8800, USB30_HS_PHY_CTRL, |
| 113 | SW_SESSVLD, SW_SESSVLD); |
| 114 | qscratch_write_readback((void *)0x8af8800, USB30_HS_PHY_CTRL, |
| 115 | UTMI_OTG_VBUS_VALID, UTMI_OTG_VBUS_VALID); |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 116 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 117 | /* Enable VBUS valid for SS PHY*/ |
| 118 | qscratch_write_readback((void *)0x8af8800, USB30_SS_PHY_CTRL, |
| 119 | LANE0_PWR_PRESENT, LANE0_PWR_PRESENT); |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 120 | } |
| 121 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 122 | static void qcom_baldur_hs_phy_init(void) |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 123 | { |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 124 | u32 reg; |
| 125 | |
| 126 | /* assert HS PHY POR reset */ |
| 127 | reg = read32(GCC_USB3_RST_CTRL); |
| 128 | reg = reg | 0x10; |
| 129 | write32(GCC_USB3_RST_CTRL, reg); |
| 130 | mdelay(10); |
| 131 | |
| 132 | /* assert HS PHY SRIF reset */ |
| 133 | reg = read32(GCC_USB3_RST_CTRL); |
| 134 | reg = reg | 0x4; |
| 135 | write32(GCC_USB3_RST_CTRL, reg); |
| 136 | mdelay(10); |
| 137 | |
| 138 | /* deassert HS PHY SRIF reset and program HS PHY registers */ |
| 139 | reg = read32(GCC_USB3_RST_CTRL); |
| 140 | reg = reg & ~0x4; |
| 141 | write32(GCC_USB3_RST_CTRL, reg); |
| 142 | |
| 143 | mdelay(10); |
| 144 | |
| 145 | /* perform PHY register writes */ |
| 146 | write32(USB_HOST3_BALDUR_PHY_BASE + PHY_CTRL0_ADDR, PHY_CTRL0_VAL); |
| 147 | write32(USB_HOST3_BALDUR_PHY_BASE + PHY_CTRL1_ADDR, PHY_CTRL1_VAL); |
| 148 | write32(USB_HOST3_BALDUR_PHY_BASE + PHY_CTRL2_ADDR, PHY_CTRL2_VAL); |
| 149 | write32(USB_HOST3_BALDUR_PHY_BASE + PHY_CTRL3_ADDR, PHY_CTRL3_VAL); |
| 150 | write32(USB_HOST3_BALDUR_PHY_BASE + PHY_CTRL4_ADDR, PHY_CTRL4_VAL); |
| 151 | write32(USB_HOST3_BALDUR_PHY_BASE + PHY_MISC_ADDR, PHY_MISC_VAL); |
| 152 | write32(USB_HOST3_BALDUR_PHY_BASE + PHY_IPG_ADDR, PHY_IPG_VAL); |
| 153 | |
| 154 | mdelay(10); |
| 155 | |
| 156 | /* de-assert USB3 HS PHY POR reset */ |
| 157 | reg = read32(GCC_USB3_RST_CTRL); |
| 158 | reg = reg & ~0x10; |
| 159 | write32(GCC_USB3_RST_CTRL, reg); |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 160 | } |
| 161 | |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 162 | static void qcom_uni_ss_phy_init(void) |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 163 | { |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 164 | u32 reg; |
| 165 | |
| 166 | /* assert SS PHY POR reset */ |
| 167 | reg = read32(GCC_USB3_RST_CTRL); |
| 168 | reg = reg | 0x20; |
| 169 | write32(GCC_USB3_RST_CTRL, reg); |
| 170 | |
| 171 | mdelay(100); |
| 172 | |
| 173 | /* deassert SS PHY POR reset */ |
| 174 | reg = read32(GCC_USB3_RST_CTRL); |
| 175 | reg = reg & ~0x20; |
| 176 | write32(GCC_USB3_RST_CTRL, reg); |
| 177 | } |
| 178 | |
| 179 | void setup_dwc3(void) |
| 180 | { |
| 181 | u32 reg; |
| 182 | u32 revision; |
| 183 | |
| 184 | revision = read32(USB_HOST3_PHY_BASE + DWC3_GSNPSID); |
| 185 | /* This should read as U3 followed by revision number */ |
| 186 | if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) |
| 187 | printk(BIOS_INFO, "Error in reading Version\n"); |
| 188 | |
| 189 | printk(BIOS_INFO, "Version = %x\n", revision); |
| 190 | |
| 191 | /* issue device SoftReset too */ |
| 192 | write32(USB_HOST3_PHY_BASE + DWC3_DCTL, DWC3_DCTL_CSFTRST); |
| 193 | do { |
| 194 | reg = read32(USB_HOST3_PHY_BASE + DWC3_DCTL); |
| 195 | if (!(reg & DWC3_DCTL_CSFTRST)) |
| 196 | break; |
| 197 | |
| 198 | udelay(10); |
| 199 | } while (true); |
| 200 | printk(BIOS_INFO, "software reset done\n"); |
| 201 | |
| 202 | /* Before Resetting PHY, put Core in Reset */ |
| 203 | reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL); |
| 204 | reg |= DWC3_GCTL_CORESOFTRESET; |
| 205 | write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg); |
| 206 | |
| 207 | /* Assert USB3 PHY reset */ |
| 208 | reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0)); |
| 209 | reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; |
| 210 | write32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0), reg); |
| 211 | |
| 212 | /* Assert USB2 PHY reset */ |
| 213 | reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0)); |
| 214 | reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; |
| 215 | write32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0), reg); |
| 216 | |
| 217 | qcom_baldur_hs_phy_init(); |
| 218 | qcom_uni_ss_phy_init(); |
| 219 | mdelay(100); |
| 220 | |
| 221 | /* Clear USB3 PHY reset */ |
| 222 | reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0)); |
| 223 | reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; |
| 224 | write32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0), reg); |
| 225 | |
| 226 | /* Clear USB2 PHY reset */ |
| 227 | reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0)); |
| 228 | reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; |
| 229 | write32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0), reg); |
| 230 | |
| 231 | mdelay(100); |
| 232 | |
| 233 | /* After PHYs are stable we can take Core out of reset state */ |
| 234 | reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL); |
| 235 | reg &= ~DWC3_GCTL_CORESOFTRESET; |
| 236 | write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg); |
| 237 | |
| 238 | #if 0 |
| 239 | /* Enable Suspend USB2.0 HS/FS/LS PHY (SusPHY) */ |
| 240 | reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0)); |
| 241 | reg |= DWC3_GUSB2PHYCFG_SUSPHY; |
| 242 | write32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0), reg); |
| 243 | |
| 244 | /* Enable Suspend USB3.0 SS PHY (Suspend_en) */ |
| 245 | reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0)); |
| 246 | reg |= DWC3_GUSB3PIPECTL_SUSPHY; |
| 247 | write32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0), reg); |
| 248 | #endif |
| 249 | |
| 250 | /* configure controller in Host mode */ |
| 251 | reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL); |
| 252 | reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); |
| 253 | reg |= DWC3_GCTL_PRTCAPDIR(0x1); /* host mode */ |
| 254 | write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg); |
| 255 | printk(BIOS_INFO, "USB Host mode reg = %x\n", reg); |
| 256 | |
| 257 | reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL); |
| 258 | reg &= ~DWC3_GCTL_SCALEDOWN_MASK; |
| 259 | reg &= ~DWC3_GCTL_DISSCRAMBLE; |
| 260 | |
| 261 | reg &= ~DWC3_GCTL_DSBLCLKGTNG; |
| 262 | /* |
| 263 | * WORKAROUND: DWC3 revisions <1.90a have a bug |
| 264 | * where the device can fail to connect at SuperSpeed |
| 265 | * and falls back to high-speed mode which causes |
| 266 | * the device to enter a Connect/Disconnect loop |
| 267 | */ |
| 268 | if (revision < DWC3_REVISION_190A) |
| 269 | reg |= DWC3_GCTL_U2RSTECN; |
| 270 | |
| 271 | write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg); |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 272 | } |
| 273 | |
| 274 | void setup_usb_host1(void) |
| 275 | { |
Varadarajan Narayanan | 3939aca | 2015-11-03 14:42:21 +0530 | [diff] [blame] | 276 | printk(BIOS_INFO, "Setting up USB HOST1 controller.\n"); |
| 277 | setup_dwc3(); |
| 278 | dwc3_ipq40xx_enable_vbus_valid(); |
Varadarajan Narayanan | a6935c2 | 2016-03-02 16:57:10 +0530 | [diff] [blame] | 279 | } |