xref: /openbmc/linux/drivers/usb/cdns3/drd.c (revision 82df5b73)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Cadence USBSS DRD Driver.
4  *
5  * Copyright (C) 2018-2019 Cadence.
6  * Copyright (C) 2019 Texas Instruments
7  *
8  * Author: Pawel Laszczak <pawell@cadence.com>
9  *         Roger Quadros <rogerq@ti.com>
10  *
11  *
12  */
13 #include <linux/kernel.h>
14 #include <linux/interrupt.h>
15 #include <linux/delay.h>
16 #include <linux/iopoll.h>
17 #include <linux/usb/otg.h>
18 
19 #include "gadget.h"
20 #include "drd.h"
21 #include "core.h"
22 
23 /**
24  * cdns3_set_mode - change mode of OTG Core
25  * @cdns: pointer to context structure
26  * @mode: selected mode from cdns_role
27  *
28  * Returns 0 on success otherwise negative errno
29  */
30 int cdns3_set_mode(struct cdns3 *cdns, enum usb_dr_mode mode)
31 {
32 	int ret = 0;
33 	u32 reg;
34 
35 	switch (mode) {
36 	case USB_DR_MODE_PERIPHERAL:
37 		break;
38 	case USB_DR_MODE_HOST:
39 		break;
40 	case USB_DR_MODE_OTG:
41 		dev_dbg(cdns->dev, "Set controller to OTG mode\n");
42 		if (cdns->version == CDNS3_CONTROLLER_V1) {
43 			reg = readl(&cdns->otg_v1_regs->override);
44 			reg |= OVERRIDE_IDPULLUP;
45 			writel(reg, &cdns->otg_v1_regs->override);
46 		} else {
47 			reg = readl(&cdns->otg_v0_regs->ctrl1);
48 			reg |= OVERRIDE_IDPULLUP_V0;
49 			writel(reg, &cdns->otg_v0_regs->ctrl1);
50 		}
51 
52 		/*
53 		 * Hardware specification says: "ID_VALUE must be valid within
54 		 * 50ms after idpullup is set to '1" so driver must wait
55 		 * 50ms before reading this pin.
56 		 */
57 		usleep_range(50000, 60000);
58 		break;
59 	default:
60 		dev_err(cdns->dev, "Unsupported mode of operation %d\n", mode);
61 		return -EINVAL;
62 	}
63 
64 	return ret;
65 }
66 
67 int cdns3_get_id(struct cdns3 *cdns)
68 {
69 	int id;
70 
71 	id = readl(&cdns->otg_regs->sts) & OTGSTS_ID_VALUE;
72 	dev_dbg(cdns->dev, "OTG ID: %d", id);
73 
74 	return id;
75 }
76 
77 int cdns3_get_vbus(struct cdns3 *cdns)
78 {
79 	int vbus;
80 
81 	vbus = !!(readl(&cdns->otg_regs->sts) & OTGSTS_VBUS_VALID);
82 	dev_dbg(cdns->dev, "OTG VBUS: %d", vbus);
83 
84 	return vbus;
85 }
86 
87 int cdns3_is_host(struct cdns3 *cdns)
88 {
89 	if (cdns->dr_mode == USB_DR_MODE_HOST)
90 		return 1;
91 	else if (!cdns3_get_id(cdns))
92 		return 1;
93 
94 	return 0;
95 }
96 
97 int cdns3_is_device(struct cdns3 *cdns)
98 {
99 	if (cdns->dr_mode == USB_DR_MODE_PERIPHERAL)
100 		return 1;
101 	else if (cdns->dr_mode == USB_DR_MODE_OTG)
102 		if (cdns3_get_id(cdns))
103 			return 1;
104 
105 	return 0;
106 }
107 
108 /**
109  * cdns3_otg_disable_irq - Disable all OTG interrupts
110  * @cdns: Pointer to controller context structure
111  */
112 static void cdns3_otg_disable_irq(struct cdns3 *cdns)
113 {
114 	writel(0, &cdns->otg_regs->ien);
115 }
116 
117 /**
118  * cdns3_otg_enable_irq - enable id and sess_valid interrupts
119  * @cdns: Pointer to controller context structure
120  */
121 static void cdns3_otg_enable_irq(struct cdns3 *cdns)
122 {
123 	writel(OTGIEN_ID_CHANGE_INT | OTGIEN_VBUSVALID_RISE_INT |
124 	       OTGIEN_VBUSVALID_FALL_INT, &cdns->otg_regs->ien);
125 }
126 
127 /**
128  * cdns3_drd_switch_host - start/stop host
129  * @cdns: Pointer to controller context structure
130  * @on: 1 for start, 0 for stop
131  *
132  * Returns 0 on success otherwise negative errno
133  */
134 int cdns3_drd_switch_host(struct cdns3 *cdns, int on)
135 {
136 	int ret, val;
137 	u32 reg = OTGCMD_OTG_DIS;
138 
139 	/* switch OTG core */
140 	if (on) {
141 		writel(OTGCMD_HOST_BUS_REQ | reg, &cdns->otg_regs->cmd);
142 
143 		dev_dbg(cdns->dev, "Waiting till Host mode is turned on\n");
144 		ret = readl_poll_timeout_atomic(&cdns->otg_regs->sts, val,
145 						val & OTGSTS_XHCI_READY,
146 						1, 100000);
147 		if (ret) {
148 			dev_err(cdns->dev, "timeout waiting for xhci_ready\n");
149 			return ret;
150 		}
151 	} else {
152 		writel(OTGCMD_HOST_BUS_DROP | OTGCMD_DEV_BUS_DROP |
153 		       OTGCMD_DEV_POWER_OFF | OTGCMD_HOST_POWER_OFF,
154 		       &cdns->otg_regs->cmd);
155 		/* Waiting till H_IDLE state.*/
156 		readl_poll_timeout_atomic(&cdns->otg_regs->state, val,
157 					  !(val & OTGSTATE_HOST_STATE_MASK),
158 					  1, 2000000);
159 	}
160 
161 	return 0;
162 }
163 
164 /**
165  * cdns3_drd_switch_gadget - start/stop gadget
166  * @cdns: Pointer to controller context structure
167  * @on: 1 for start, 0 for stop
168  *
169  * Returns 0 on success otherwise negative errno
170  */
171 int cdns3_drd_switch_gadget(struct cdns3 *cdns, int on)
172 {
173 	int ret, val;
174 	u32 reg = OTGCMD_OTG_DIS;
175 
176 	/* switch OTG core */
177 	if (on) {
178 		writel(OTGCMD_DEV_BUS_REQ | reg, &cdns->otg_regs->cmd);
179 
180 		dev_dbg(cdns->dev, "Waiting till Device mode is turned on\n");
181 
182 		ret = readl_poll_timeout_atomic(&cdns->otg_regs->sts, val,
183 						val & OTGSTS_DEV_READY,
184 						1, 100000);
185 		if (ret) {
186 			dev_err(cdns->dev, "timeout waiting for dev_ready\n");
187 			return ret;
188 		}
189 	} else {
190 		/*
191 		 * driver should wait at least 10us after disabling Device
192 		 * before turning-off Device (DEV_BUS_DROP)
193 		 */
194 		usleep_range(20, 30);
195 		writel(OTGCMD_HOST_BUS_DROP | OTGCMD_DEV_BUS_DROP |
196 		       OTGCMD_DEV_POWER_OFF | OTGCMD_HOST_POWER_OFF,
197 		       &cdns->otg_regs->cmd);
198 		/* Waiting till DEV_IDLE state.*/
199 		readl_poll_timeout_atomic(&cdns->otg_regs->state, val,
200 					  !(val & OTGSTATE_DEV_STATE_MASK),
201 					  1, 2000000);
202 	}
203 
204 	return 0;
205 }
206 
207 /**
208  * cdns3_init_otg_mode - initialize drd controller
209  * @cdns: Pointer to controller context structure
210  *
211  * Returns 0 on success otherwise negative errno
212  */
213 static int cdns3_init_otg_mode(struct cdns3 *cdns)
214 {
215 	int ret = 0;
216 
217 	cdns3_otg_disable_irq(cdns);
218 	/* clear all interrupts */
219 	writel(~0, &cdns->otg_regs->ivect);
220 
221 	ret = cdns3_set_mode(cdns, USB_DR_MODE_OTG);
222 	if (ret)
223 		return ret;
224 
225 	cdns3_otg_enable_irq(cdns);
226 	return ret;
227 }
228 
229 /**
230  * cdns3_drd_update_mode - initialize mode of operation
231  * @cdns: Pointer to controller context structure
232  *
233  * Returns 0 on success otherwise negative errno
234  */
235 int cdns3_drd_update_mode(struct cdns3 *cdns)
236 {
237 	int ret = 0;
238 
239 	switch (cdns->dr_mode) {
240 	case USB_DR_MODE_PERIPHERAL:
241 		ret = cdns3_set_mode(cdns, USB_DR_MODE_PERIPHERAL);
242 		break;
243 	case USB_DR_MODE_HOST:
244 		ret = cdns3_set_mode(cdns, USB_DR_MODE_HOST);
245 		break;
246 	case USB_DR_MODE_OTG:
247 		ret = cdns3_init_otg_mode(cdns);
248 		break;
249 	default:
250 		dev_err(cdns->dev, "Unsupported mode of operation %d\n",
251 			cdns->dr_mode);
252 		return -EINVAL;
253 	}
254 
255 	return ret;
256 }
257 
258 static irqreturn_t cdns3_drd_thread_irq(int irq, void *data)
259 {
260 	struct cdns3 *cdns = data;
261 
262 	cdns3_hw_role_switch(cdns);
263 
264 	return IRQ_HANDLED;
265 }
266 
267 /**
268  * cdns3_drd_irq - interrupt handler for OTG events
269  *
270  * @irq: irq number for cdns3 core device
271  * @data: structure of cdns3
272  *
273  * Returns IRQ_HANDLED or IRQ_NONE
274  */
275 static irqreturn_t cdns3_drd_irq(int irq, void *data)
276 {
277 	irqreturn_t ret = IRQ_NONE;
278 	struct cdns3 *cdns = data;
279 	u32 reg;
280 
281 	if (cdns->dr_mode != USB_DR_MODE_OTG)
282 		return ret;
283 
284 	reg = readl(&cdns->otg_regs->ivect);
285 
286 	if (!reg)
287 		return ret;
288 
289 	if (reg & OTGIEN_ID_CHANGE_INT) {
290 		dev_dbg(cdns->dev, "OTG IRQ: new ID: %d\n",
291 			cdns3_get_id(cdns));
292 
293 		ret = IRQ_WAKE_THREAD;
294 	}
295 
296 	if (reg & (OTGIEN_VBUSVALID_RISE_INT | OTGIEN_VBUSVALID_FALL_INT)) {
297 		dev_dbg(cdns->dev, "OTG IRQ: new VBUS: %d\n",
298 			cdns3_get_vbus(cdns));
299 
300 		ret = IRQ_WAKE_THREAD;
301 	}
302 
303 	writel(~0, &cdns->otg_regs->ivect);
304 	return ret;
305 }
306 
307 int cdns3_drd_init(struct cdns3 *cdns)
308 {
309 	void __iomem *regs;
310 	int ret = 0;
311 	u32 state;
312 
313 	regs = devm_ioremap_resource(cdns->dev, &cdns->otg_res);
314 	if (IS_ERR(regs))
315 		return PTR_ERR(regs);
316 
317 	/* Detection of DRD version. Controller has been released
318 	 * in two versions. Both are similar, but they have same changes
319 	 * in register maps.
320 	 * The first register in old version is command register and it's read
321 	 * only, so driver should read 0 from it. On the other hand, in v1
322 	 * the first register contains device ID number which is not set to 0.
323 	 * Driver uses this fact to detect the proper version of
324 	 * controller.
325 	 */
326 	cdns->otg_v0_regs = regs;
327 	if (!readl(&cdns->otg_v0_regs->cmd)) {
328 		cdns->version  = CDNS3_CONTROLLER_V0;
329 		cdns->otg_v1_regs = NULL;
330 		cdns->otg_regs = regs;
331 		writel(1, &cdns->otg_v0_regs->simulate);
332 		dev_dbg(cdns->dev, "DRD version v0 (%08x)\n",
333 			 readl(&cdns->otg_v0_regs->version));
334 	} else {
335 		cdns->otg_v0_regs = NULL;
336 		cdns->otg_v1_regs = regs;
337 		cdns->otg_regs = (void *)&cdns->otg_v1_regs->cmd;
338 		cdns->version  = CDNS3_CONTROLLER_V1;
339 		writel(1, &cdns->otg_v1_regs->simulate);
340 		dev_dbg(cdns->dev, "DRD version v1 (ID: %08x, rev: %08x)\n",
341 			 readl(&cdns->otg_v1_regs->did),
342 			 readl(&cdns->otg_v1_regs->rid));
343 	}
344 
345 	state = OTGSTS_STRAP(readl(&cdns->otg_regs->sts));
346 
347 	/* Update dr_mode according to STRAP configuration. */
348 	cdns->dr_mode = USB_DR_MODE_OTG;
349 	if (state == OTGSTS_STRAP_HOST) {
350 		dev_dbg(cdns->dev, "Controller strapped to HOST\n");
351 		cdns->dr_mode = USB_DR_MODE_HOST;
352 	} else if (state == OTGSTS_STRAP_GADGET) {
353 		dev_dbg(cdns->dev, "Controller strapped to PERIPHERAL\n");
354 		cdns->dr_mode = USB_DR_MODE_PERIPHERAL;
355 	}
356 
357 	ret = devm_request_threaded_irq(cdns->dev, cdns->otg_irq,
358 					cdns3_drd_irq,
359 					cdns3_drd_thread_irq,
360 					IRQF_SHARED,
361 					dev_name(cdns->dev), cdns);
362 
363 	if (ret) {
364 		dev_err(cdns->dev, "couldn't get otg_irq\n");
365 		return ret;
366 	}
367 
368 	state = readl(&cdns->otg_regs->sts);
369 	if (OTGSTS_OTG_NRDY(state) != 0) {
370 		dev_err(cdns->dev, "Cadence USB3 OTG device not ready\n");
371 		return -ENODEV;
372 	}
373 
374 	return ret;
375 }
376 
377 int cdns3_drd_exit(struct cdns3 *cdns)
378 {
379 	cdns3_otg_disable_irq(cdns);
380 	return 0;
381 }
382