blob: f96b88a3110f4a0cf543a28c3f3b1453ccd4ba86 [file] [log] [blame]
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +02001/**
2 * dwc3_otg.c - DesignWare USB3 DRD Controller OTG
3 *
4 * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
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 version 2 and
8 * only version 2 as published by the Free Software Foundation.
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
16#include <linux/usb.h>
17#include <linux/usb/hcd.h>
18#include <linux/platform_device.h>
Manu Gautamf1fceddf2012-10-12 14:02:50 +053019#include <linux/regulator/consumer.h>
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020020
21#include "core.h"
22#include "dwc3_otg.h"
23#include "io.h"
24#include "xhci.h"
25
Manu Gautamf1fceddf2012-10-12 14:02:50 +053026static void dwc3_otg_reset(struct dwc3_otg *dotg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020027
28/**
29 * dwc3_otg_set_host_regs - reset dwc3 otg registers to host operation.
30 *
31 * This function sets the OTG registers to work in A-Device host mode.
32 * This function should be called just before entering to A-Device mode.
33 *
Manu Gautamf1fceddf2012-10-12 14:02:50 +053034 * @w: Pointer to the dwc3 otg struct
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020035 */
36static void dwc3_otg_set_host_regs(struct dwc3_otg *dotg)
37{
38 u32 octl;
39
40 /* Set OCTL[6](PeriMode) to 0 (host) */
41 octl = dwc3_readl(dotg->regs, DWC3_OCTL);
42 octl &= ~DWC3_OTG_OCTL_PERIMODE;
43 dwc3_writel(dotg->regs, DWC3_OCTL, octl);
Manu Gautamf1fceddf2012-10-12 14:02:50 +053044}
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020045
Manu Gautamf1fceddf2012-10-12 14:02:50 +053046/**
47 * dwc3_otg_set_host_power - Enable port power control for host operation
48 *
49 * This function enables the OTG Port Power required to operate in Host mode
50 * This function should be called only after XHCI driver has set the port
51 * power in PORTSC register.
52 *
53 * @w: Pointer to the dwc3 otg struct
54 */
55void dwc3_otg_set_host_power(struct dwc3_otg *dotg)
56{
57 u32 osts;
58
59 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
60 if (!(osts & 0x8))
61 dev_err(dotg->dwc->dev, "%s: xHCIPrtPower not set\n", __func__);
62
63 dwc3_writel(dotg->regs, DWC3_OCTL, DWC3_OTG_OCTL_PRTPWRCTL);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020064}
65
66/**
67 * dwc3_otg_set_peripheral_regs - reset dwc3 otg registers to peripheral operation.
68 *
69 * This function sets the OTG registers to work in B-Device peripheral mode.
70 * This function should be called just before entering to B-Device mode.
71 *
72 * @w: Pointer to the dwc3 otg workqueue.
73 */
74static void dwc3_otg_set_peripheral_regs(struct dwc3_otg *dotg)
75{
76 u32 octl;
77
78 /* Set OCTL[6](PeriMode) to 1 (peripheral) */
79 octl = dwc3_readl(dotg->regs, DWC3_OCTL);
80 octl |= DWC3_OTG_OCTL_PERIMODE;
81 dwc3_writel(dotg->regs, DWC3_OCTL, octl);
82
83 /*
84 * TODO: add more OTG registers writes for PERIPHERAL mode here,
85 * see figure 12-19 B-device flow in dwc3 Synopsis spec
86 */
87}
88
89/**
90 * dwc3_otg_start_host - helper function for starting/stoping the host controller driver.
91 *
92 * @otg: Pointer to the otg_transceiver structure.
93 * @on: start / stop the host controller driver.
94 *
95 * Returns 0 on success otherwise negative errno.
96 */
97static int dwc3_otg_start_host(struct usb_otg *otg, int on)
98{
99 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200100 int ret = 0;
101
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530102 if (!dotg->dwc->xhci)
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200103 return -EINVAL;
104
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200105 if (on) {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530106 dev_dbg(otg->phy->dev, "%s: turn on host\n", __func__);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200107
108 /*
109 * This should be revisited for more testing post-silicon.
110 * In worst case we may need to disconnect the root hub
111 * before stopping the controller so that it does not
112 * interfere with runtime pm/system pm.
113 * We can also consider registering and unregistering xhci
114 * platform device. It is almost similar to add_hcd and
115 * remove_hcd, But we may not use standard set_host method
116 * anymore.
117 */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530118 dwc3_otg_set_host_regs(dotg);
119 ret = platform_device_add(dotg->dwc->xhci);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200120 if (ret) {
121 dev_err(otg->phy->dev,
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530122 "%s: failed to add XHCI pdev ret=%d\n",
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200123 __func__, ret);
124 return ret;
125 }
126
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530127 ret = regulator_enable(dotg->vbus_otg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200128 if (ret) {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530129 dev_err(otg->phy->dev, "unable to enable vbus_otg\n");
130 platform_device_del(dotg->dwc->xhci);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200131 return ret;
132 }
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530133
134 /* re-init OTG EVTEN register as XHCI reset clears it */
135 dwc3_otg_reset(dotg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200136 } else {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530137 dev_dbg(otg->phy->dev, "%s: turn off host\n", __func__);
138
139 platform_device_del(dotg->dwc->xhci);
140
141 ret = regulator_disable(dotg->vbus_otg);
142 if (ret) {
143 dev_err(otg->phy->dev, "unable to disable vbus_otg\n");
144 return ret;
145 }
146
147 /* re-init core and OTG register as XHCI reset clears it */
148 dwc3_post_host_reset_core_init(dotg->dwc);
149 dwc3_otg_reset(dotg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200150 }
151
152 return 0;
153}
154
155/**
156 * dwc3_otg_set_host - bind/unbind the host controller driver.
157 *
158 * @otg: Pointer to the otg_transceiver structure.
159 * @host: Pointer to the usb_bus structure.
160 *
161 * Returns 0 on success otherwise negative errno.
162 */
163static int dwc3_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
164{
165 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
166
167 if (host) {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530168 dev_dbg(otg->phy->dev, "%s: set host %s, portpower\n",
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200169 __func__, host->bus_name);
170 otg->host = host;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200171 /*
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530172 * Though XHCI power would be set by now, but some delay is
173 * required for XHCI controller before setting OTG Port Power
174 * TODO: Tune this delay
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200175 */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530176 msleep(300);
177 dwc3_otg_set_host_power(dotg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200178 } else {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530179 otg->host = NULL;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200180 }
181
182 return 0;
183}
184
185/**
186 * dwc3_otg_start_peripheral - bind/unbind the peripheral controller.
187 *
188 * @otg: Pointer to the otg_transceiver structure.
189 * @gadget: pointer to the usb_gadget structure.
190 *
191 * Returns 0 on success otherwise negative errno.
192 */
193static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on)
194{
195 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
196
197 if (!otg->gadget)
198 return -EINVAL;
199
200 if (on) {
201 dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n",
202 __func__, otg->gadget->name);
203 dwc3_otg_set_peripheral_regs(dotg);
204 usb_gadget_vbus_connect(otg->gadget);
205 } else {
206 dev_dbg(otg->phy->dev, "%s: turn off gadget %s\n",
207 __func__, otg->gadget->name);
208 usb_gadget_vbus_disconnect(otg->gadget);
209 }
210
211 return 0;
212}
213
214/**
215 * dwc3_otg_set_peripheral - bind/unbind the peripheral controller driver.
216 *
217 * @otg: Pointer to the otg_transceiver structure.
218 * @gadget: pointer to the usb_gadget structure.
219 *
220 * Returns 0 on success otherwise negative errno.
221 */
222static int dwc3_otg_set_peripheral(struct usb_otg *otg,
223 struct usb_gadget *gadget)
224{
225 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
226
227 if (gadget) {
228 dev_dbg(otg->phy->dev, "%s: set gadget %s\n",
229 __func__, gadget->name);
230 otg->gadget = gadget;
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530231 schedule_work(&dotg->sm_work);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200232 } else {
233 if (otg->phy->state == OTG_STATE_B_PERIPHERAL) {
234 dwc3_otg_start_peripheral(otg, 0);
235 otg->gadget = NULL;
236 otg->phy->state = OTG_STATE_UNDEFINED;
237 schedule_work(&dotg->sm_work);
238 } else {
239 otg->gadget = NULL;
240 }
241 }
242
243 return 0;
244}
245
246/**
Manu Gautam8c642812012-06-07 10:35:10 +0530247 * dwc3_ext_chg_det_done - callback to handle charger detection completion
248 * @otg: Pointer to the otg transceiver structure
249 * @charger: Pointer to the external charger structure
250 *
251 * Returns 0 on success
252 */
253static void dwc3_ext_chg_det_done(struct usb_otg *otg, struct dwc3_charger *chg)
254{
255 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
256
257 /*
258 * Ignore chg_detection notification if BSV has gone off by this time.
259 * STOP chg_det as part of !BSV handling would reset the chg_det flags
260 */
261 if (test_bit(B_SESS_VLD, &dotg->inputs))
262 schedule_work(&dotg->sm_work);
263}
264
265/**
266 * dwc3_set_charger - bind/unbind external charger driver
267 * @otg: Pointer to the otg transceiver structure
268 * @charger: Pointer to the external charger structure
269 *
270 * Returns 0 on success
271 */
272int dwc3_set_charger(struct usb_otg *otg, struct dwc3_charger *charger)
273{
274 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
275
276 dotg->charger = charger;
277 if (charger)
278 charger->notify_detection_complete = dwc3_ext_chg_det_done;
279
280 return 0;
281}
282
Manu Gautamb5067272012-07-02 09:53:41 +0530283/**
284 * dwc3_ext_event_notify - callback to handle events from external transceiver
285 * @otg: Pointer to the otg transceiver structure
286 * @event: Event reported by transceiver
287 *
288 * Returns 0 on success
289 */
290static void dwc3_ext_event_notify(struct usb_otg *otg,
291 enum dwc3_ext_events event)
292{
293 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
294 struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
295 struct usb_phy *phy = dotg->otg.phy;
296
297 if (event == DWC3_EVENT_PHY_RESUME) {
298 if (!pm_runtime_status_suspended(phy->dev)) {
299 dev_warn(phy->dev, "PHY_RESUME event out of LPM!!!!\n");
300 } else {
301 dev_dbg(phy->dev, "ext PHY_RESUME event received\n");
302 /* ext_xceiver would have taken h/w out of LPM by now */
303 pm_runtime_get(phy->dev);
304 }
Manu Gautam377821c2012-09-28 16:53:24 +0530305 } else if (event == DWC3_EVENT_XCEIV_STATE) {
306 if (ext_xceiv->id == DWC3_ID_FLOAT)
307 set_bit(ID, &dotg->inputs);
308 else
309 clear_bit(ID, &dotg->inputs);
310
311 if (ext_xceiv->bsv)
312 set_bit(B_SESS_VLD, &dotg->inputs);
313 else
314 clear_bit(B_SESS_VLD, &dotg->inputs);
315
316 schedule_work(&dotg->sm_work);
Manu Gautamb5067272012-07-02 09:53:41 +0530317 }
Manu Gautamb5067272012-07-02 09:53:41 +0530318}
319
320/**
321 * dwc3_set_ext_xceiv - bind/unbind external transceiver driver
322 * @otg: Pointer to the otg transceiver structure
323 * @ext_xceiv: Pointer to the external transceiver struccture
324 *
325 * Returns 0 on success
326 */
327int dwc3_set_ext_xceiv(struct usb_otg *otg, struct dwc3_ext_xceiv *ext_xceiv)
328{
329 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
330
331 dotg->ext_xceiv = ext_xceiv;
332 if (ext_xceiv)
333 ext_xceiv->notify_ext_events = dwc3_ext_event_notify;
334
335 return 0;
336}
337
Manu Gautam8c642812012-06-07 10:35:10 +0530338/* IRQs which OTG driver is interested in handling */
339#define DWC3_OEVT_MASK (DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT | \
340 DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT)
341
342/**
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200343 * dwc3_otg_interrupt - interrupt handler for dwc3 otg events.
344 * @_dotg: Pointer to out controller context structure
345 *
346 * Returns IRQ_HANDLED on success otherwise IRQ_NONE.
347 */
348static irqreturn_t dwc3_otg_interrupt(int irq, void *_dotg)
349{
350 struct dwc3_otg *dotg = (struct dwc3_otg *)_dotg;
Manu Gautam8c642812012-06-07 10:35:10 +0530351 u32 osts, oevt_reg;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200352 int ret = IRQ_NONE;
353 int handled_irqs = 0;
354
355 oevt_reg = dwc3_readl(dotg->regs, DWC3_OEVT);
356
Manu Gautam8c642812012-06-07 10:35:10 +0530357 if (!(oevt_reg & DWC3_OEVT_MASK))
358 return IRQ_NONE;
359
360 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
361
362 if ((oevt_reg & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) ||
363 (oevt_reg & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT)) {
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200364 /*
Manu Gautam8c642812012-06-07 10:35:10 +0530365 * ID sts has changed, set inputs later, in the workqueue
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200366 * function, switch from A to B or from B to A.
367 */
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200368
Manu Gautam8c642812012-06-07 10:35:10 +0530369 if (osts & DWC3_OTG_OSTS_CONIDSTS)
370 set_bit(ID, &dotg->inputs);
371 else
372 clear_bit(ID, &dotg->inputs);
373
374 if (osts & DWC3_OTG_OSTS_BSESVALID)
375 set_bit(B_SESS_VLD, &dotg->inputs);
376 else
377 clear_bit(B_SESS_VLD, &dotg->inputs);
378
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200379 schedule_work(&dotg->sm_work);
380
Manu Gautam8c642812012-06-07 10:35:10 +0530381 handled_irqs |= (oevt_reg & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) ?
382 DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT : 0;
383 handled_irqs |= (oevt_reg & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT) ?
384 DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT : 0;
385
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200386 ret = IRQ_HANDLED;
Manu Gautam8c642812012-06-07 10:35:10 +0530387
388 /* Clear the interrupts we handled */
389 dwc3_writel(dotg->regs, DWC3_OEVT, handled_irqs);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200390 }
391
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200392 return ret;
393}
394
395/**
Manu Gautam8c642812012-06-07 10:35:10 +0530396 * dwc3_otg_init_sm - initialize OTG statemachine input
397 * @dotg: Pointer to the dwc3_otg structure
398 *
399 */
400void dwc3_otg_init_sm(struct dwc3_otg *dotg)
401{
402 u32 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
403 struct usb_phy *phy = dotg->otg.phy;
404
405 /*
406 * TODO: If using external notifications then wait here till initial
407 * state is reported
408 */
409
410 dev_dbg(phy->dev, "Initialize OTG inputs, osts: 0x%x\n", osts);
411
412 if (osts & DWC3_OTG_OSTS_CONIDSTS)
413 set_bit(ID, &dotg->inputs);
414 else
415 clear_bit(ID, &dotg->inputs);
416
417 if (osts & DWC3_OTG_OSTS_BSESVALID)
418 set_bit(B_SESS_VLD, &dotg->inputs);
419 else
420 clear_bit(B_SESS_VLD, &dotg->inputs);
421}
422
423/**
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200424 * dwc3_otg_sm_work - workqueue function.
425 *
426 * @w: Pointer to the dwc3 otg workqueue
427 *
428 * NOTE: After any change in phy->state,
429 * we must reschdule the state machine.
430 */
431static void dwc3_otg_sm_work(struct work_struct *w)
432{
433 struct dwc3_otg *dotg = container_of(w, struct dwc3_otg, sm_work);
434 struct usb_phy *phy = dotg->otg.phy;
Manu Gautam8c642812012-06-07 10:35:10 +0530435 struct dwc3_charger *charger = dotg->charger;
436 bool work = 0;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200437
Manu Gautamb5067272012-07-02 09:53:41 +0530438 pm_runtime_resume(phy->dev);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200439 dev_dbg(phy->dev, "%s state\n", otg_state_string(phy->state));
440
441 /* Check OTG state */
442 switch (phy->state) {
443 case OTG_STATE_UNDEFINED:
Manu Gautam8c642812012-06-07 10:35:10 +0530444 dwc3_otg_init_sm(dotg);
445 /* Switch to A or B-Device according to ID / BSV */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530446 if (!test_bit(ID, &dotg->inputs)) {
Manu Gautam8c642812012-06-07 10:35:10 +0530447 dev_dbg(phy->dev, "!id\n");
448 phy->state = OTG_STATE_A_IDLE;
449 work = 1;
450 } else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
451 dev_dbg(phy->dev, "b_sess_vld\n");
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200452 phy->state = OTG_STATE_B_IDLE;
Manu Gautam8c642812012-06-07 10:35:10 +0530453 work = 1;
454 } else {
455 phy->state = OTG_STATE_B_IDLE;
Manu Gautamb5067272012-07-02 09:53:41 +0530456 dev_dbg(phy->dev, "No device, trying to suspend\n");
457 pm_runtime_put_sync(phy->dev);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200458 }
459 break;
Manu Gautam8c642812012-06-07 10:35:10 +0530460
461 case OTG_STATE_B_IDLE:
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530462 if (!test_bit(ID, &dotg->inputs)) {
Manu Gautam8c642812012-06-07 10:35:10 +0530463 dev_dbg(phy->dev, "!id\n");
464 phy->state = OTG_STATE_A_IDLE;
465 work = 1;
466 if (charger) {
467 if (charger->chg_type == DWC3_INVALID_CHARGER)
468 charger->start_detection(dotg->charger,
469 false);
470 else
471 charger->chg_type =
472 DWC3_INVALID_CHARGER;
473 }
474 } else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
475 dev_dbg(phy->dev, "b_sess_vld\n");
476 if (charger) {
477 /* Has charger been detected? If no detect it */
478 switch (charger->chg_type) {
479 case DWC3_DCP_CHARGER:
Manu Gautamb5067272012-07-02 09:53:41 +0530480 dev_dbg(phy->dev, "lpm, DCP charger\n");
481 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530482 break;
483 case DWC3_CDP_CHARGER:
484 dwc3_otg_start_peripheral(&dotg->otg,
485 1);
486 phy->state = OTG_STATE_B_PERIPHERAL;
487 work = 1;
488 break;
489 case DWC3_SDP_CHARGER:
490 dwc3_otg_start_peripheral(&dotg->otg,
491 1);
492 phy->state = OTG_STATE_B_PERIPHERAL;
493 work = 1;
494 break;
495 default:
496 dev_dbg(phy->dev, "chg_det started\n");
497 charger->start_detection(charger, true);
498 break;
499 }
500 } else {
501 /* no charger registered, start peripheral */
502 if (dwc3_otg_start_peripheral(&dotg->otg, 1)) {
503 /*
504 * Probably set_peripheral not called
505 * yet. We will re-try as soon as it
506 * will be called
507 */
Manu Gautamb5067272012-07-02 09:53:41 +0530508 dev_err(phy->dev, "enter lpm as\n"
Manu Gautam8c642812012-06-07 10:35:10 +0530509 "unable to start B-device\n");
510 phy->state = OTG_STATE_UNDEFINED;
Manu Gautamb5067272012-07-02 09:53:41 +0530511 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530512 return;
513 }
514 }
515 } else {
516 if (charger) {
517 if (charger->chg_type == DWC3_INVALID_CHARGER)
518 charger->start_detection(dotg->charger,
519 false);
520 else
521 charger->chg_type =
522 DWC3_INVALID_CHARGER;
523 }
Manu Gautamb5067272012-07-02 09:53:41 +0530524 dev_dbg(phy->dev, "No device, trying to suspend\n");
525 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530526 }
527 break;
528
529 case OTG_STATE_B_PERIPHERAL:
530 if (!test_bit(B_SESS_VLD, &dotg->inputs) ||
531 !test_bit(ID, &dotg->inputs)) {
532 dev_dbg(phy->dev, "!id || !bsv\n");
533 dwc3_otg_start_peripheral(&dotg->otg, 0);
534 phy->state = OTG_STATE_B_IDLE;
535 if (charger)
536 charger->chg_type = DWC3_INVALID_CHARGER;
537 work = 1;
538 }
539 break;
540
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200541 case OTG_STATE_A_IDLE:
542 /* Switch to A-Device*/
Manu Gautam8c642812012-06-07 10:35:10 +0530543 if (test_bit(ID, &dotg->inputs)) {
544 dev_dbg(phy->dev, "id\n");
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200545 phy->state = OTG_STATE_B_IDLE;
Manu Gautam8c642812012-06-07 10:35:10 +0530546 work = 1;
547 } else {
548 if (dwc3_otg_start_host(&dotg->otg, 1)) {
549 /*
550 * Probably set_host was not called yet.
551 * We will re-try as soon as it will be called
552 */
Manu Gautamb5067272012-07-02 09:53:41 +0530553 dev_dbg(phy->dev, "enter lpm as\n"
Manu Gautam8c642812012-06-07 10:35:10 +0530554 "unable to start A-device\n");
555 phy->state = OTG_STATE_UNDEFINED;
Manu Gautamb5067272012-07-02 09:53:41 +0530556 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530557 return;
558 }
559 phy->state = OTG_STATE_A_HOST;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200560 }
561 break;
Manu Gautam8c642812012-06-07 10:35:10 +0530562
563 case OTG_STATE_A_HOST:
564 if (test_bit(ID, &dotg->inputs)) {
565 dev_dbg(phy->dev, "id\n");
566 dwc3_otg_start_host(&dotg->otg, 0);
567 phy->state = OTG_STATE_B_IDLE;
568 work = 1;
569 }
570 break;
571
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200572 default:
573 dev_err(phy->dev, "%s: invalid otg-state\n", __func__);
574
575 }
Manu Gautam8c642812012-06-07 10:35:10 +0530576
577 if (work)
578 schedule_work(&dotg->sm_work);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200579}
580
581
582/**
583 * dwc3_otg_reset - reset dwc3 otg registers.
584 *
585 * @w: Pointer to the dwc3 otg workqueue
586 */
587static void dwc3_otg_reset(struct dwc3_otg *dotg)
588{
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530589 static int once;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200590 /*
591 * OCFG[2] - OTG-Version = 1
592 * OCFG[1] - HNPCap = 0
593 * OCFG[0] - SRPCap = 0
594 */
595 dwc3_writel(dotg->regs, DWC3_OCFG, 0x4);
596
597 /*
598 * OCTL[6] - PeriMode = 1
599 * OCTL[5] - PrtPwrCtl = 0
600 * OCTL[4] - HNPReq = 0
601 * OCTL[3] - SesReq = 0
602 * OCTL[2] - TermSelDLPulse = 0
603 * OCTL[1] - DevSetHNPEn = 0
604 * OCTL[0] - HstSetHNPEn = 0
605 */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530606 if (!once) {
607 dwc3_writel(dotg->regs, DWC3_OCTL, 0x40);
608 once++;
609 }
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200610
611 /* Clear all otg events (interrupts) indications */
612 dwc3_writel(dotg->regs, DWC3_OEVT, 0xFFFF);
613
Manu Gautam8c642812012-06-07 10:35:10 +0530614 /* Enable ID/BSV StsChngEn event*/
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200615 dwc3_writel(dotg->regs, DWC3_OEVTEN,
Manu Gautam8c642812012-06-07 10:35:10 +0530616 DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT |
617 DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200618}
619
620/**
621 * dwc3_otg_init - Initializes otg related registers
622 * @dwc: Pointer to out controller context structure
623 *
624 * Returns 0 on success otherwise negative errno.
625 */
626int dwc3_otg_init(struct dwc3 *dwc)
627{
628 u32 reg;
629 int ret = 0;
630 struct dwc3_otg *dotg;
631
632 dev_dbg(dwc->dev, "dwc3_otg_init\n");
633
634 /*
635 * GHWPARAMS6[10] bit is SRPSupport.
636 * This bit also reflects DWC_USB3_EN_OTG
637 */
638 reg = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
639 if (!(reg & DWC3_GHWPARAMS6_SRP_SUPPORT)) {
640 /*
641 * No OTG support in the HW core.
642 * We return 0 to indicate no error, since this is acceptable
643 * situation, just continue probe the dwc3 driver without otg.
644 */
645 dev_dbg(dwc->dev, "dwc3_otg address space is not supported\n");
646 return 0;
647 }
648
649 /* Allocate and init otg instance */
650 dotg = kzalloc(sizeof(struct dwc3_otg), GFP_KERNEL);
651 if (!dotg) {
652 dev_err(dwc->dev, "unable to allocate dwc3_otg\n");
653 return -ENOMEM;
654 }
655
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530656 dotg->vbus_otg = devm_regulator_get(dwc->dev->parent, "vbus_dwc3");
657 if (IS_ERR(dotg->vbus_otg)) {
658 dev_err(dwc->dev, "Unable to get vbus_dwc3 regulator\n");
659 ret = PTR_ERR(dotg->vbus_otg);
660 goto err1;
661 }
662
Manu Gautam17206c22012-06-21 10:17:53 +0530663 /* DWC3 has separate IRQ line for OTG events (ID/BSV etc.) */
664 dotg->irq = platform_get_irq_byname(to_platform_device(dwc->dev),
665 "otg_irq");
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200666 if (dotg->irq < 0) {
Manu Gautam17206c22012-06-21 10:17:53 +0530667 dev_err(dwc->dev, "%s: missing OTG IRQ\n", __func__);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200668 ret = -ENODEV;
669 goto err1;
670 }
671
672 dotg->regs = dwc->regs;
673
674 dotg->otg.set_peripheral = dwc3_otg_set_peripheral;
675 dotg->otg.set_host = dwc3_otg_set_host;
676
677 /* This reference is used by dwc3 modules for checking otg existance */
678 dwc->dotg = dotg;
679
680 dotg->otg.phy = kzalloc(sizeof(struct usb_phy), GFP_KERNEL);
681 if (!dotg->otg.phy) {
682 dev_err(dwc->dev, "unable to allocate dwc3_otg.phy\n");
683 ret = -ENOMEM;
684 goto err1;
685 }
686
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530687 dotg->dwc = dwc;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200688 dotg->otg.phy->otg = &dotg->otg;
689 dotg->otg.phy->dev = dwc->dev;
690
691 ret = usb_set_transceiver(dotg->otg.phy);
692 if (ret) {
693 dev_err(dotg->otg.phy->dev,
694 "%s: failed to set transceiver, already exists\n",
695 __func__);
696 goto err2;
697 }
698
699 dwc3_otg_reset(dotg);
700
701 dotg->otg.phy->state = OTG_STATE_UNDEFINED;
702
703 INIT_WORK(&dotg->sm_work, dwc3_otg_sm_work);
704
705 ret = request_irq(dotg->irq, dwc3_otg_interrupt, IRQF_SHARED,
706 "dwc3_otg", dotg);
707 if (ret) {
708 dev_err(dotg->otg.phy->dev, "failed to request irq #%d --> %d\n",
709 dotg->irq, ret);
710 goto err3;
711 }
712
Manu Gautamb5067272012-07-02 09:53:41 +0530713 pm_runtime_get(dwc->dev);
714
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200715 return 0;
716
717err3:
718 cancel_work_sync(&dotg->sm_work);
719 usb_set_transceiver(NULL);
720err2:
721 kfree(dotg->otg.phy);
722err1:
723 dwc->dotg = NULL;
724 kfree(dotg);
725
726 return ret;
727}
728
729/**
730 * dwc3_otg_exit
731 * @dwc: Pointer to out controller context structure
732 *
733 * Returns 0 on success otherwise negative errno.
734 */
735void dwc3_otg_exit(struct dwc3 *dwc)
736{
737 struct dwc3_otg *dotg = dwc->dotg;
738
739 /* dotg is null when GHWPARAMS6[10]=SRPSupport=0, see dwc3_otg_init */
740 if (dotg) {
Manu Gautam8c642812012-06-07 10:35:10 +0530741 if (dotg->charger)
742 dotg->charger->start_detection(dotg->charger, false);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200743 cancel_work_sync(&dotg->sm_work);
744 usb_set_transceiver(NULL);
Manu Gautamb5067272012-07-02 09:53:41 +0530745 pm_runtime_put(dwc->dev);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200746 free_irq(dotg->irq, dotg);
747 kfree(dotg->otg.phy);
748 kfree(dotg);
749 dwc->dotg = NULL;
750 }
751}