blob: 0d0272c9b298fe76a7d91dde1aea7d85050078a1 [file] [log] [blame]
Varadarajan Narayanana6935c22016-03-02 16:57:10 +05301/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2014 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
Kyösti Mälkki13f66502019-03-03 08:01:05 +020016#include <device/mmio.h>
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053017#include <console/console.h>
18#include <delay.h>
19#include <soc/clock.h>
20#include <soc/iomap.h>
21#include <soc/usb.h>
22
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +053023/**
24 * USB Hardware registers
25 */
26#define PHY_CTRL0_ADDR 0x000
27#define PHY_CTRL1_ADDR 0x004
28#define PHY_CTRL2_ADDR 0x008
29#define PHY_CTRL3_ADDR 0x00C
30#define PHY_CTRL4_ADDR 0x010
31#define PHY_MISC_ADDR 0x024
32#define PHY_IPG_ADDR 0x030
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053033
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +053034#define PHY_CTRL0_VAL 0xA4600015
35#define PHY_CTRL1_VAL 0x09500000
36#define PHY_CTRL2_VAL 0x00058180
37#define PHY_CTRL3_VAL 0x6DB6DCD6
38#define PHY_CTRL4_VAL 0x836DB6DB
39#define PHY_MISC_VAL 0x3803FB0C
40#define PHY_IPG_VAL 0x47323232
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053041
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +053042#define USB_HOST3_PHY_BASE ((void *)0x8a00000)
43#define USB_HOST3_BALDUR_PHY_BASE ((void *)0xa6000)
44#define GCC_USB3_RST_CTRL ((void *)0x0181E038)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053045
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +053046#define DWC3_GCTL 0xc110
47#define DWC3_GUSB3PIPECTL(n) (0xc2c0 + (n * 0x04))
48#define DWC3_GUSB2PHYCFG(n) (0xc200 + (n * 0x04))
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053049
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +053050/* Global USB3 PIPE Control Register */
51#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31)
52#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17)
53#define DWC3_GCTL_CORESOFTRESET (1 << 11)
54#define DWC3_GCTL_PRTCAPDIR(n) ((n) << 12)
55#define DWC3_GCTL_PRTCAP_OTG 3
56#define DWC3_DCTL_CSFTRST (1 << 30)
57#define DWC3_GSNPSID 0xc120
58#define DWC3_DCTL 0xc704
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053059
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053060
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +053061/* Global USB2 PHY Configuration Register */
62#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31)
63#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6)
64#define DWC3_GSNPSID_MASK 0xffff0000
65#define DWC3_GEVTEN 0xc114
66
67
68#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4)
69#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3)
70#define DWC3_GCTL_DISSCRAMBLE (1 << 3)
71#define DWC3_GCTL_DSBLCLKGTNG (1 << 0)
72#define DWC3_GCTL_U2RSTECN (1 << 16)
73#define DWC3_REVISION_190A 0x5533190a
74
75#define USB30_HS_PHY_CTRL 0x00000010
76#define SW_SESSVLD (0x01 << 0x1C)
77#define UTMI_OTG_VBUS_VALID (0x01 << 0x14)
78
79#define USB30_SS_PHY_CTRL 0x00000030
80#define LANE0_PWR_PRESENT (0x01 << 0x18)
81
82static void setup_dwc3(void);
83
84/**
85 * Write register.
86 *
Martin Roth49348182016-07-06 10:17:19 -060087 * @param base - PHY base virtual address.
88 * @param offset - register offset.
89 * @param val - value to write.
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +053090 */
91static inline void qscratch_write(void *base, u32 offset, u32 val)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053092{
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +053093 write32(base + offset, val);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053094}
95
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +053096/**
97 * Write register and read back masked value to confirm it is written
98 *
Martin Roth49348182016-07-06 10:17:19 -060099 * @param base - base virtual address.
100 * @param offset - register offset.
101 * @param mask - register bitmask specifying what should be updated
102 * @param val - value to write.
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530103 */
104static inline void qscratch_write_readback(void *base, u32 offset,
105 const u32 mask, u32 val)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530106{
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530107 u32 write_val, tmp = read32(base + offset);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530108
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530109 tmp &= ~mask; /* retain other bits */
110 write_val = tmp | val;
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530111
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530112 write32(base + offset, write_val);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530113
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530114 /* Read back to see if val was written */
115 tmp = read32(base + offset);
116 tmp &= mask; /* clear other bits */
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530117
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530118 if (tmp != val) {
119 printk(BIOS_INFO, "write: %x to QSCRATCH: %x FAILED\n",
120 val, offset);
121 }
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530122}
123
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530124static void dwc3_ipq40xx_enable_vbus_valid(void)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530125{
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530126 /* Enable VBUS valid for HS PHY*/
127 qscratch_write_readback((void *)0x8af8800, USB30_HS_PHY_CTRL,
128 SW_SESSVLD, SW_SESSVLD);
129 qscratch_write_readback((void *)0x8af8800, USB30_HS_PHY_CTRL,
130 UTMI_OTG_VBUS_VALID, UTMI_OTG_VBUS_VALID);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530131
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530132 /* Enable VBUS valid for SS PHY*/
133 qscratch_write_readback((void *)0x8af8800, USB30_SS_PHY_CTRL,
134 LANE0_PWR_PRESENT, LANE0_PWR_PRESENT);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530135}
136
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530137static void qcom_baldur_hs_phy_init(void)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530138{
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530139 u32 reg;
140
141 /* assert HS PHY POR reset */
142 reg = read32(GCC_USB3_RST_CTRL);
143 reg = reg | 0x10;
144 write32(GCC_USB3_RST_CTRL, reg);
145 mdelay(10);
146
147 /* assert HS PHY SRIF reset */
148 reg = read32(GCC_USB3_RST_CTRL);
149 reg = reg | 0x4;
150 write32(GCC_USB3_RST_CTRL, reg);
151 mdelay(10);
152
153 /* deassert HS PHY SRIF reset and program HS PHY registers */
154 reg = read32(GCC_USB3_RST_CTRL);
155 reg = reg & ~0x4;
156 write32(GCC_USB3_RST_CTRL, reg);
157
158 mdelay(10);
159
160 /* perform PHY register writes */
161 write32(USB_HOST3_BALDUR_PHY_BASE + PHY_CTRL0_ADDR, PHY_CTRL0_VAL);
162 write32(USB_HOST3_BALDUR_PHY_BASE + PHY_CTRL1_ADDR, PHY_CTRL1_VAL);
163 write32(USB_HOST3_BALDUR_PHY_BASE + PHY_CTRL2_ADDR, PHY_CTRL2_VAL);
164 write32(USB_HOST3_BALDUR_PHY_BASE + PHY_CTRL3_ADDR, PHY_CTRL3_VAL);
165 write32(USB_HOST3_BALDUR_PHY_BASE + PHY_CTRL4_ADDR, PHY_CTRL4_VAL);
166 write32(USB_HOST3_BALDUR_PHY_BASE + PHY_MISC_ADDR, PHY_MISC_VAL);
167 write32(USB_HOST3_BALDUR_PHY_BASE + PHY_IPG_ADDR, PHY_IPG_VAL);
168
169 mdelay(10);
170
171 /* de-assert USB3 HS PHY POR reset */
172 reg = read32(GCC_USB3_RST_CTRL);
173 reg = reg & ~0x10;
174 write32(GCC_USB3_RST_CTRL, reg);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530175}
176
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530177static void qcom_uni_ss_phy_init(void)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530178{
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530179 u32 reg;
180
181 /* assert SS PHY POR reset */
182 reg = read32(GCC_USB3_RST_CTRL);
183 reg = reg | 0x20;
184 write32(GCC_USB3_RST_CTRL, reg);
185
186 mdelay(100);
187
188 /* deassert SS PHY POR reset */
189 reg = read32(GCC_USB3_RST_CTRL);
190 reg = reg & ~0x20;
191 write32(GCC_USB3_RST_CTRL, reg);
192}
193
194void setup_dwc3(void)
195{
196 u32 reg;
197 u32 revision;
198
199 revision = read32(USB_HOST3_PHY_BASE + DWC3_GSNPSID);
200 /* This should read as U3 followed by revision number */
201 if ((revision & DWC3_GSNPSID_MASK) != 0x55330000)
202 printk(BIOS_INFO, "Error in reading Version\n");
203
204 printk(BIOS_INFO, "Version = %x\n", revision);
205
206 /* issue device SoftReset too */
207 write32(USB_HOST3_PHY_BASE + DWC3_DCTL, DWC3_DCTL_CSFTRST);
208 do {
209 reg = read32(USB_HOST3_PHY_BASE + DWC3_DCTL);
210 if (!(reg & DWC3_DCTL_CSFTRST))
211 break;
212
213 udelay(10);
214 } while (true);
215 printk(BIOS_INFO, "software reset done\n");
216
217 /* Before Resetting PHY, put Core in Reset */
218 reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL);
219 reg |= DWC3_GCTL_CORESOFTRESET;
220 write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg);
221
222 /* Assert USB3 PHY reset */
223 reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0));
224 reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
225 write32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0), reg);
226
227 /* Assert USB2 PHY reset */
228 reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0));
229 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
230 write32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0), reg);
231
232 qcom_baldur_hs_phy_init();
233 qcom_uni_ss_phy_init();
234 mdelay(100);
235
236 /* Clear USB3 PHY reset */
237 reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0));
238 reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
239 write32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0), reg);
240
241 /* Clear USB2 PHY reset */
242 reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0));
243 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
244 write32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0), reg);
245
246 mdelay(100);
247
248 /* After PHYs are stable we can take Core out of reset state */
249 reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL);
250 reg &= ~DWC3_GCTL_CORESOFTRESET;
251 write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg);
252
253#if 0
254 /* Enable Suspend USB2.0 HS/FS/LS PHY (SusPHY) */
255 reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0));
256 reg |= DWC3_GUSB2PHYCFG_SUSPHY;
257 write32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0), reg);
258
259 /* Enable Suspend USB3.0 SS PHY (Suspend_en) */
260 reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0));
261 reg |= DWC3_GUSB3PIPECTL_SUSPHY;
262 write32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0), reg);
263#endif
264
265 /* configure controller in Host mode */
266 reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL);
267 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
268 reg |= DWC3_GCTL_PRTCAPDIR(0x1); /* host mode */
269 write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg);
270 printk(BIOS_INFO, "USB Host mode reg = %x\n", reg);
271
272 reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL);
273 reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
274 reg &= ~DWC3_GCTL_DISSCRAMBLE;
275
276 reg &= ~DWC3_GCTL_DSBLCLKGTNG;
277 /*
278 * WORKAROUND: DWC3 revisions <1.90a have a bug
279 * where the device can fail to connect at SuperSpeed
280 * and falls back to high-speed mode which causes
281 * the device to enter a Connect/Disconnect loop
282 */
283 if (revision < DWC3_REVISION_190A)
284 reg |= DWC3_GCTL_U2RSTECN;
285
286 write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530287}
288
289void setup_usb_host1(void)
290{
Varadarajan Narayanan3939aca2015-11-03 14:42:21 +0530291 printk(BIOS_INFO, "Setting up USB HOST1 controller.\n");
292 setup_dwc3();
293 dwc3_ipq40xx_enable_vbus_valid();
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530294}