blob: 01ba16167f0bcae194f5e1153521c151873f0622 [file] [log] [blame]
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +02001/**
2 * dwc3_otg.c - DesignWare USB3 DRD Controller OTG
3 *
Jack Pham0fc12332012-11-19 13:14:22 -08004 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +02005 *
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
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +053028static void dwc3_otg_notify_host_mode(struct usb_otg *otg, int host_mode);
29static void dwc3_otg_reset(struct dwc3_otg *dotg);
30
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020031/**
32 * dwc3_otg_set_host_regs - reset dwc3 otg registers to host operation.
33 *
34 * This function sets the OTG registers to work in A-Device host mode.
35 * This function should be called just before entering to A-Device mode.
36 *
Manu Gautamf1fceddf2012-10-12 14:02:50 +053037 * @w: Pointer to the dwc3 otg struct
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020038 */
39static void dwc3_otg_set_host_regs(struct dwc3_otg *dotg)
40{
41 u32 octl;
42
43 /* Set OCTL[6](PeriMode) to 0 (host) */
44 octl = dwc3_readl(dotg->regs, DWC3_OCTL);
45 octl &= ~DWC3_OTG_OCTL_PERIMODE;
46 dwc3_writel(dotg->regs, DWC3_OCTL, octl);
Manu Gautamf1fceddf2012-10-12 14:02:50 +053047}
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020048
Manu Gautamf1fceddf2012-10-12 14:02:50 +053049/**
50 * dwc3_otg_set_host_power - Enable port power control for host operation
51 *
52 * This function enables the OTG Port Power required to operate in Host mode
53 * This function should be called only after XHCI driver has set the port
54 * power in PORTSC register.
55 *
56 * @w: Pointer to the dwc3 otg struct
57 */
58void dwc3_otg_set_host_power(struct dwc3_otg *dotg)
59{
60 u32 osts;
61
62 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
63 if (!(osts & 0x8))
64 dev_err(dotg->dwc->dev, "%s: xHCIPrtPower not set\n", __func__);
65
66 dwc3_writel(dotg->regs, DWC3_OCTL, DWC3_OTG_OCTL_PRTPWRCTL);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020067}
68
69/**
70 * dwc3_otg_set_peripheral_regs - reset dwc3 otg registers to peripheral operation.
71 *
72 * This function sets the OTG registers to work in B-Device peripheral mode.
73 * This function should be called just before entering to B-Device mode.
74 *
75 * @w: Pointer to the dwc3 otg workqueue.
76 */
77static void dwc3_otg_set_peripheral_regs(struct dwc3_otg *dotg)
78{
79 u32 octl;
80
81 /* Set OCTL[6](PeriMode) to 1 (peripheral) */
82 octl = dwc3_readl(dotg->regs, DWC3_OCTL);
83 octl |= DWC3_OTG_OCTL_PERIMODE;
84 dwc3_writel(dotg->regs, DWC3_OCTL, octl);
85
86 /*
87 * TODO: add more OTG registers writes for PERIPHERAL mode here,
88 * see figure 12-19 B-device flow in dwc3 Synopsis spec
89 */
90}
91
92/**
93 * dwc3_otg_start_host - helper function for starting/stoping the host controller driver.
94 *
95 * @otg: Pointer to the otg_transceiver structure.
96 * @on: start / stop the host controller driver.
97 *
98 * Returns 0 on success otherwise negative errno.
99 */
100static int dwc3_otg_start_host(struct usb_otg *otg, int on)
101{
102 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
Manu Gautam61721592012-11-06 18:09:39 +0530103 struct dwc3 *dwc = dotg->dwc;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200104 int ret = 0;
105
Manu Gautam61721592012-11-06 18:09:39 +0530106 if (!dwc->xhci)
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200107 return -EINVAL;
108
Manu Gautam61721592012-11-06 18:09:39 +0530109 if (!dotg->vbus_otg) {
110 dotg->vbus_otg = devm_regulator_get(dwc->dev->parent,
111 "vbus_dwc3");
112 if (IS_ERR(dotg->vbus_otg)) {
113 dev_err(dwc->dev, "Failed to get vbus regulator\n");
114 ret = PTR_ERR(dotg->vbus_otg);
115 dotg->vbus_otg = 0;
116 return ret;
117 }
118 }
119
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200120 if (on) {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530121 dev_dbg(otg->phy->dev, "%s: turn on host\n", __func__);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200122
123 /*
124 * This should be revisited for more testing post-silicon.
125 * In worst case we may need to disconnect the root hub
126 * before stopping the controller so that it does not
127 * interfere with runtime pm/system pm.
128 * We can also consider registering and unregistering xhci
129 * platform device. It is almost similar to add_hcd and
130 * remove_hcd, But we may not use standard set_host method
131 * anymore.
132 */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530133 dwc3_otg_set_host_regs(dotg);
Manu Gautam61721592012-11-06 18:09:39 +0530134 ret = platform_device_add(dwc->xhci);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200135 if (ret) {
136 dev_err(otg->phy->dev,
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530137 "%s: failed to add XHCI pdev ret=%d\n",
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200138 __func__, ret);
139 return ret;
140 }
141
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530142 dwc3_otg_notify_host_mode(otg, on);
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530143 ret = regulator_enable(dotg->vbus_otg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200144 if (ret) {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530145 dev_err(otg->phy->dev, "unable to enable vbus_otg\n");
Manu Gautam61721592012-11-06 18:09:39 +0530146 platform_device_del(dwc->xhci);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200147 return ret;
148 }
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530149
150 /* re-init OTG EVTEN register as XHCI reset clears it */
151 dwc3_otg_reset(dotg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200152 } else {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530153 dev_dbg(otg->phy->dev, "%s: turn off host\n", __func__);
154
Manu Gautam61721592012-11-06 18:09:39 +0530155 platform_device_del(dwc->xhci);
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530156
157 ret = regulator_disable(dotg->vbus_otg);
158 if (ret) {
159 dev_err(otg->phy->dev, "unable to disable vbus_otg\n");
160 return ret;
161 }
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530162 dwc3_otg_notify_host_mode(otg, on);
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530163
164 /* re-init core and OTG register as XHCI reset clears it */
Manu Gautam61721592012-11-06 18:09:39 +0530165 dwc3_post_host_reset_core_init(dwc);
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530166 dwc3_otg_reset(dotg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200167 }
168
169 return 0;
170}
171
172/**
173 * dwc3_otg_set_host - bind/unbind the host controller driver.
174 *
175 * @otg: Pointer to the otg_transceiver structure.
176 * @host: Pointer to the usb_bus structure.
177 *
178 * Returns 0 on success otherwise negative errno.
179 */
180static int dwc3_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
181{
182 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
183
184 if (host) {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530185 dev_dbg(otg->phy->dev, "%s: set host %s, portpower\n",
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200186 __func__, host->bus_name);
187 otg->host = host;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200188 /*
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530189 * Though XHCI power would be set by now, but some delay is
190 * required for XHCI controller before setting OTG Port Power
191 * TODO: Tune this delay
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200192 */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530193 msleep(300);
194 dwc3_otg_set_host_power(dotg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200195 } else {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530196 otg->host = NULL;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200197 }
198
199 return 0;
200}
201
202/**
203 * dwc3_otg_start_peripheral - bind/unbind the peripheral controller.
204 *
205 * @otg: Pointer to the otg_transceiver structure.
206 * @gadget: pointer to the usb_gadget structure.
207 *
208 * Returns 0 on success otherwise negative errno.
209 */
210static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on)
211{
212 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
213
214 if (!otg->gadget)
215 return -EINVAL;
216
217 if (on) {
218 dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n",
219 __func__, otg->gadget->name);
220 dwc3_otg_set_peripheral_regs(dotg);
221 usb_gadget_vbus_connect(otg->gadget);
222 } else {
223 dev_dbg(otg->phy->dev, "%s: turn off gadget %s\n",
224 __func__, otg->gadget->name);
225 usb_gadget_vbus_disconnect(otg->gadget);
226 }
227
228 return 0;
229}
230
231/**
232 * dwc3_otg_set_peripheral - bind/unbind the peripheral controller driver.
233 *
234 * @otg: Pointer to the otg_transceiver structure.
235 * @gadget: pointer to the usb_gadget structure.
236 *
237 * Returns 0 on success otherwise negative errno.
238 */
239static int dwc3_otg_set_peripheral(struct usb_otg *otg,
240 struct usb_gadget *gadget)
241{
242 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
243
244 if (gadget) {
245 dev_dbg(otg->phy->dev, "%s: set gadget %s\n",
246 __func__, gadget->name);
247 otg->gadget = gadget;
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530248 schedule_work(&dotg->sm_work);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200249 } else {
250 if (otg->phy->state == OTG_STATE_B_PERIPHERAL) {
251 dwc3_otg_start_peripheral(otg, 0);
252 otg->gadget = NULL;
253 otg->phy->state = OTG_STATE_UNDEFINED;
254 schedule_work(&dotg->sm_work);
255 } else {
256 otg->gadget = NULL;
257 }
258 }
259
260 return 0;
261}
262
263/**
Manu Gautam8c642812012-06-07 10:35:10 +0530264 * dwc3_ext_chg_det_done - callback to handle charger detection completion
265 * @otg: Pointer to the otg transceiver structure
266 * @charger: Pointer to the external charger structure
267 *
268 * Returns 0 on success
269 */
270static void dwc3_ext_chg_det_done(struct usb_otg *otg, struct dwc3_charger *chg)
271{
272 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
273
274 /*
275 * Ignore chg_detection notification if BSV has gone off by this time.
276 * STOP chg_det as part of !BSV handling would reset the chg_det flags
277 */
278 if (test_bit(B_SESS_VLD, &dotg->inputs))
279 schedule_work(&dotg->sm_work);
280}
281
282/**
283 * dwc3_set_charger - bind/unbind external charger driver
284 * @otg: Pointer to the otg transceiver structure
285 * @charger: Pointer to the external charger structure
286 *
287 * Returns 0 on success
288 */
289int dwc3_set_charger(struct usb_otg *otg, struct dwc3_charger *charger)
290{
291 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
292
293 dotg->charger = charger;
294 if (charger)
295 charger->notify_detection_complete = dwc3_ext_chg_det_done;
296
297 return 0;
298}
299
Manu Gautamb5067272012-07-02 09:53:41 +0530300/**
301 * dwc3_ext_event_notify - callback to handle events from external transceiver
302 * @otg: Pointer to the otg transceiver structure
303 * @event: Event reported by transceiver
304 *
305 * Returns 0 on success
306 */
307static void dwc3_ext_event_notify(struct usb_otg *otg,
308 enum dwc3_ext_events event)
309{
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530310 static bool init;
Manu Gautamb5067272012-07-02 09:53:41 +0530311 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
312 struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
313 struct usb_phy *phy = dotg->otg.phy;
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530314 int ret = 0;
Manu Gautamb5067272012-07-02 09:53:41 +0530315
316 if (event == DWC3_EVENT_PHY_RESUME) {
317 if (!pm_runtime_status_suspended(phy->dev)) {
318 dev_warn(phy->dev, "PHY_RESUME event out of LPM!!!!\n");
319 } else {
320 dev_dbg(phy->dev, "ext PHY_RESUME event received\n");
321 /* ext_xceiver would have taken h/w out of LPM by now */
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530322 ret = pm_runtime_get(phy->dev);
323 if (ret == -EACCES) {
324 /* pm_runtime_get may fail during system
325 resume with -EACCES error */
326 pm_runtime_disable(phy->dev);
327 pm_runtime_set_active(phy->dev);
328 pm_runtime_enable(phy->dev);
329 } else if (ret < 0) {
330 dev_warn(phy->dev, "pm_runtime_get failed!\n");
331 }
Manu Gautamb5067272012-07-02 09:53:41 +0530332 }
Manu Gautam377821c2012-09-28 16:53:24 +0530333 } else if (event == DWC3_EVENT_XCEIV_STATE) {
Jack Pham0fc12332012-11-19 13:14:22 -0800334 if (ext_xceiv->id == DWC3_ID_FLOAT) {
335 dev_dbg(phy->dev, "XCVR: ID set\n");
Manu Gautam377821c2012-09-28 16:53:24 +0530336 set_bit(ID, &dotg->inputs);
Jack Pham0fc12332012-11-19 13:14:22 -0800337 } else {
338 dev_dbg(phy->dev, "XCVR: ID clear\n");
Manu Gautam377821c2012-09-28 16:53:24 +0530339 clear_bit(ID, &dotg->inputs);
Jack Pham0fc12332012-11-19 13:14:22 -0800340 }
Manu Gautam377821c2012-09-28 16:53:24 +0530341
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530342 if (ext_xceiv->bsv) {
343 dev_dbg(phy->dev, "XCVR: BSV set\n");
Manu Gautam377821c2012-09-28 16:53:24 +0530344 set_bit(B_SESS_VLD, &dotg->inputs);
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530345 } else {
346 dev_dbg(phy->dev, "XCVR: BSV clear\n");
Manu Gautam377821c2012-09-28 16:53:24 +0530347 clear_bit(B_SESS_VLD, &dotg->inputs);
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530348 }
Manu Gautam377821c2012-09-28 16:53:24 +0530349
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530350 if (!init) {
351 init = true;
352 complete(&dotg->dwc3_xcvr_vbus_init);
353 dev_dbg(phy->dev, "XCVR: BSV init complete\n");
354 return;
355 }
Manu Gautam377821c2012-09-28 16:53:24 +0530356 schedule_work(&dotg->sm_work);
Manu Gautamb5067272012-07-02 09:53:41 +0530357 }
Manu Gautamb5067272012-07-02 09:53:41 +0530358}
359
360/**
361 * dwc3_set_ext_xceiv - bind/unbind external transceiver driver
362 * @otg: Pointer to the otg transceiver structure
363 * @ext_xceiv: Pointer to the external transceiver struccture
364 *
365 * Returns 0 on success
366 */
367int dwc3_set_ext_xceiv(struct usb_otg *otg, struct dwc3_ext_xceiv *ext_xceiv)
368{
369 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
370
371 dotg->ext_xceiv = ext_xceiv;
372 if (ext_xceiv)
373 ext_xceiv->notify_ext_events = dwc3_ext_event_notify;
374
375 return 0;
376}
377
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530378static void dwc3_otg_notify_host_mode(struct usb_otg *otg, int host_mode)
379{
380 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
381
382 if (!dotg->psy) {
383 dev_err(otg->phy->dev, "no usb power supply registered\n");
384 return;
385 }
386
387 if (host_mode)
388 power_supply_set_scope(dotg->psy, POWER_SUPPLY_SCOPE_SYSTEM);
389 else
390 power_supply_set_scope(dotg->psy, POWER_SUPPLY_SCOPE_DEVICE);
391}
392
393static int dwc3_otg_set_power(struct usb_phy *phy, unsigned mA)
394{
395 static int power_supply_type;
396 struct dwc3_otg *dotg = container_of(phy->otg, struct dwc3_otg, otg);
397
398
Manu Gautam6c0ff032012-11-02 14:55:35 +0530399 if (!dotg->psy || !dotg->charger) {
400 dev_err(phy->dev, "no usb power supply/charger registered\n");
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530401 return 0;
402 }
403
Manu Gautam6c0ff032012-11-02 14:55:35 +0530404 if (dotg->charger->charging_disabled)
405 return 0;
406
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530407 if (dotg->charger->chg_type == DWC3_SDP_CHARGER)
408 power_supply_type = POWER_SUPPLY_TYPE_USB;
409 else if (dotg->charger->chg_type == DWC3_CDP_CHARGER)
410 power_supply_type = POWER_SUPPLY_TYPE_USB_CDP;
411 else if (dotg->charger->chg_type == DWC3_DCP_CHARGER)
412 power_supply_type = POWER_SUPPLY_TYPE_USB_DCP;
413 else
414 power_supply_type = POWER_SUPPLY_TYPE_BATTERY;
415
416 power_supply_set_supply_type(dotg->psy, power_supply_type);
417
418 if (dotg->charger->max_power == mA)
419 return 0;
420
421 dev_info(phy->dev, "Avail curr from USB = %u\n", mA);
422
423 if (dotg->charger->max_power <= 2 && mA > 2) {
424 /* Enable charging */
425 if (power_supply_set_online(dotg->psy, true))
426 goto psy_error;
427 if (power_supply_set_current_limit(dotg->psy, 1000*mA))
428 goto psy_error;
429 } else if (dotg->charger->max_power > 0 && (mA == 0 || mA == 2)) {
430 /* Disable charging */
431 if (power_supply_set_online(dotg->psy, false))
432 goto psy_error;
433 /* Set max current limit */
434 if (power_supply_set_current_limit(dotg->psy, 0))
435 goto psy_error;
436 }
437
438 power_supply_changed(dotg->psy);
439 dotg->charger->max_power = mA;
440 return 0;
441
442psy_error:
443 dev_dbg(phy->dev, "power supply error when setting property\n");
444 return -ENXIO;
445}
446
Manu Gautam8c642812012-06-07 10:35:10 +0530447/* IRQs which OTG driver is interested in handling */
448#define DWC3_OEVT_MASK (DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT | \
449 DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT)
450
451/**
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200452 * dwc3_otg_interrupt - interrupt handler for dwc3 otg events.
453 * @_dotg: Pointer to out controller context structure
454 *
455 * Returns IRQ_HANDLED on success otherwise IRQ_NONE.
456 */
457static irqreturn_t dwc3_otg_interrupt(int irq, void *_dotg)
458{
459 struct dwc3_otg *dotg = (struct dwc3_otg *)_dotg;
Manu Gautam8c642812012-06-07 10:35:10 +0530460 u32 osts, oevt_reg;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200461 int ret = IRQ_NONE;
462 int handled_irqs = 0;
463
464 oevt_reg = dwc3_readl(dotg->regs, DWC3_OEVT);
465
Manu Gautam8c642812012-06-07 10:35:10 +0530466 if (!(oevt_reg & DWC3_OEVT_MASK))
467 return IRQ_NONE;
468
469 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
470
471 if ((oevt_reg & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) ||
472 (oevt_reg & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT)) {
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200473 /*
Manu Gautam8c642812012-06-07 10:35:10 +0530474 * ID sts has changed, set inputs later, in the workqueue
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200475 * function, switch from A to B or from B to A.
476 */
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200477
Manu Gautam8c642812012-06-07 10:35:10 +0530478 if (osts & DWC3_OTG_OSTS_CONIDSTS)
479 set_bit(ID, &dotg->inputs);
480 else
481 clear_bit(ID, &dotg->inputs);
482
483 if (osts & DWC3_OTG_OSTS_BSESVALID)
484 set_bit(B_SESS_VLD, &dotg->inputs);
485 else
486 clear_bit(B_SESS_VLD, &dotg->inputs);
487
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200488 schedule_work(&dotg->sm_work);
489
Manu Gautam8c642812012-06-07 10:35:10 +0530490 handled_irqs |= (oevt_reg & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) ?
491 DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT : 0;
492 handled_irqs |= (oevt_reg & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT) ?
493 DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT : 0;
494
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200495 ret = IRQ_HANDLED;
Manu Gautam8c642812012-06-07 10:35:10 +0530496
497 /* Clear the interrupts we handled */
498 dwc3_writel(dotg->regs, DWC3_OEVT, handled_irqs);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200499 }
500
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200501 return ret;
502}
503
504/**
Manu Gautam8c642812012-06-07 10:35:10 +0530505 * dwc3_otg_init_sm - initialize OTG statemachine input
506 * @dotg: Pointer to the dwc3_otg structure
507 *
508 */
509void dwc3_otg_init_sm(struct dwc3_otg *dotg)
510{
511 u32 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
512 struct usb_phy *phy = dotg->otg.phy;
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530513 struct dwc3_ext_xceiv *ext_xceiv;
514 int ret;
Manu Gautam8c642812012-06-07 10:35:10 +0530515
516 dev_dbg(phy->dev, "Initialize OTG inputs, osts: 0x%x\n", osts);
517
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530518 /*
519 * VBUS initial state is reported after PMIC
520 * driver initialization. Wait for it.
521 */
522 ret = wait_for_completion_timeout(&dotg->dwc3_xcvr_vbus_init, HZ * 5);
523 if (!ret)
524 dev_err(phy->dev, "%s: completion timeout\n", __func__);
Manu Gautam8c642812012-06-07 10:35:10 +0530525
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530526 ext_xceiv = dotg->ext_xceiv;
527 dwc3_otg_reset(dotg);
528 if (ext_xceiv && !ext_xceiv->otg_capability) {
529 if (osts & DWC3_OTG_OSTS_CONIDSTS)
530 set_bit(ID, &dotg->inputs);
531 else
532 clear_bit(ID, &dotg->inputs);
533
534 if (osts & DWC3_OTG_OSTS_BSESVALID)
535 set_bit(B_SESS_VLD, &dotg->inputs);
536 else
537 clear_bit(B_SESS_VLD, &dotg->inputs);
538 }
Manu Gautam8c642812012-06-07 10:35:10 +0530539}
540
541/**
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200542 * dwc3_otg_sm_work - workqueue function.
543 *
544 * @w: Pointer to the dwc3 otg workqueue
545 *
546 * NOTE: After any change in phy->state,
547 * we must reschdule the state machine.
548 */
549static void dwc3_otg_sm_work(struct work_struct *w)
550{
551 struct dwc3_otg *dotg = container_of(w, struct dwc3_otg, sm_work);
552 struct usb_phy *phy = dotg->otg.phy;
Manu Gautam8c642812012-06-07 10:35:10 +0530553 struct dwc3_charger *charger = dotg->charger;
554 bool work = 0;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200555
Manu Gautamb5067272012-07-02 09:53:41 +0530556 pm_runtime_resume(phy->dev);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200557 dev_dbg(phy->dev, "%s state\n", otg_state_string(phy->state));
558
559 /* Check OTG state */
560 switch (phy->state) {
561 case OTG_STATE_UNDEFINED:
Manu Gautam8c642812012-06-07 10:35:10 +0530562 dwc3_otg_init_sm(dotg);
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530563 if (!dotg->psy) {
564 dotg->psy = power_supply_get_by_name("usb");
565
566 if (!dotg->psy)
567 dev_err(phy->dev,
568 "couldn't get usb power supply\n");
569 }
570
Manu Gautam8c642812012-06-07 10:35:10 +0530571 /* Switch to A or B-Device according to ID / BSV */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530572 if (!test_bit(ID, &dotg->inputs)) {
Manu Gautam8c642812012-06-07 10:35:10 +0530573 dev_dbg(phy->dev, "!id\n");
574 phy->state = OTG_STATE_A_IDLE;
575 work = 1;
576 } else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
577 dev_dbg(phy->dev, "b_sess_vld\n");
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200578 phy->state = OTG_STATE_B_IDLE;
Manu Gautam8c642812012-06-07 10:35:10 +0530579 work = 1;
580 } else {
581 phy->state = OTG_STATE_B_IDLE;
Manu Gautamb5067272012-07-02 09:53:41 +0530582 dev_dbg(phy->dev, "No device, trying to suspend\n");
583 pm_runtime_put_sync(phy->dev);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200584 }
585 break;
Manu Gautam8c642812012-06-07 10:35:10 +0530586
587 case OTG_STATE_B_IDLE:
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530588 if (!test_bit(ID, &dotg->inputs)) {
Manu Gautam8c642812012-06-07 10:35:10 +0530589 dev_dbg(phy->dev, "!id\n");
590 phy->state = OTG_STATE_A_IDLE;
591 work = 1;
592 if (charger) {
593 if (charger->chg_type == DWC3_INVALID_CHARGER)
594 charger->start_detection(dotg->charger,
595 false);
596 else
597 charger->chg_type =
598 DWC3_INVALID_CHARGER;
599 }
600 } else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
601 dev_dbg(phy->dev, "b_sess_vld\n");
602 if (charger) {
603 /* Has charger been detected? If no detect it */
604 switch (charger->chg_type) {
605 case DWC3_DCP_CHARGER:
Manu Gautamb5067272012-07-02 09:53:41 +0530606 dev_dbg(phy->dev, "lpm, DCP charger\n");
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530607 dwc3_otg_set_power(phy,
608 DWC3_IDEV_CHG_MAX);
Manu Gautamb5067272012-07-02 09:53:41 +0530609 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530610 break;
611 case DWC3_CDP_CHARGER:
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530612 dwc3_otg_set_power(phy,
613 DWC3_IDEV_CHG_MAX);
Manu Gautam8c642812012-06-07 10:35:10 +0530614 dwc3_otg_start_peripheral(&dotg->otg,
615 1);
616 phy->state = OTG_STATE_B_PERIPHERAL;
617 work = 1;
618 break;
619 case DWC3_SDP_CHARGER:
620 dwc3_otg_start_peripheral(&dotg->otg,
621 1);
622 phy->state = OTG_STATE_B_PERIPHERAL;
623 work = 1;
624 break;
625 default:
626 dev_dbg(phy->dev, "chg_det started\n");
627 charger->start_detection(charger, true);
628 break;
629 }
630 } else {
631 /* no charger registered, start peripheral */
632 if (dwc3_otg_start_peripheral(&dotg->otg, 1)) {
633 /*
634 * Probably set_peripheral not called
635 * yet. We will re-try as soon as it
636 * will be called
637 */
Manu Gautamb5067272012-07-02 09:53:41 +0530638 dev_err(phy->dev, "enter lpm as\n"
Manu Gautam8c642812012-06-07 10:35:10 +0530639 "unable to start B-device\n");
640 phy->state = OTG_STATE_UNDEFINED;
Manu Gautamb5067272012-07-02 09:53:41 +0530641 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530642 return;
643 }
644 }
645 } else {
Manu Gautam98013c22012-11-20 17:42:42 +0530646 if (charger)
647 charger->start_detection(dotg->charger, false);
648
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530649 dwc3_otg_set_power(phy, 0);
Manu Gautamb5067272012-07-02 09:53:41 +0530650 dev_dbg(phy->dev, "No device, trying to suspend\n");
651 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530652 }
653 break;
654
655 case OTG_STATE_B_PERIPHERAL:
656 if (!test_bit(B_SESS_VLD, &dotg->inputs) ||
657 !test_bit(ID, &dotg->inputs)) {
658 dev_dbg(phy->dev, "!id || !bsv\n");
659 dwc3_otg_start_peripheral(&dotg->otg, 0);
660 phy->state = OTG_STATE_B_IDLE;
661 if (charger)
662 charger->chg_type = DWC3_INVALID_CHARGER;
663 work = 1;
664 }
665 break;
666
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200667 case OTG_STATE_A_IDLE:
668 /* Switch to A-Device*/
Manu Gautam8c642812012-06-07 10:35:10 +0530669 if (test_bit(ID, &dotg->inputs)) {
670 dev_dbg(phy->dev, "id\n");
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200671 phy->state = OTG_STATE_B_IDLE;
Manu Gautam8c642812012-06-07 10:35:10 +0530672 work = 1;
673 } else {
674 if (dwc3_otg_start_host(&dotg->otg, 1)) {
675 /*
676 * Probably set_host was not called yet.
677 * We will re-try as soon as it will be called
678 */
Manu Gautamb5067272012-07-02 09:53:41 +0530679 dev_dbg(phy->dev, "enter lpm as\n"
Manu Gautam8c642812012-06-07 10:35:10 +0530680 "unable to start A-device\n");
681 phy->state = OTG_STATE_UNDEFINED;
Manu Gautamb5067272012-07-02 09:53:41 +0530682 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530683 return;
684 }
685 phy->state = OTG_STATE_A_HOST;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200686 }
687 break;
Manu Gautam8c642812012-06-07 10:35:10 +0530688
689 case OTG_STATE_A_HOST:
690 if (test_bit(ID, &dotg->inputs)) {
691 dev_dbg(phy->dev, "id\n");
692 dwc3_otg_start_host(&dotg->otg, 0);
693 phy->state = OTG_STATE_B_IDLE;
694 work = 1;
695 }
696 break;
697
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200698 default:
699 dev_err(phy->dev, "%s: invalid otg-state\n", __func__);
700
701 }
Manu Gautam8c642812012-06-07 10:35:10 +0530702
703 if (work)
704 schedule_work(&dotg->sm_work);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200705}
706
707
708/**
709 * dwc3_otg_reset - reset dwc3 otg registers.
710 *
711 * @w: Pointer to the dwc3 otg workqueue
712 */
713static void dwc3_otg_reset(struct dwc3_otg *dotg)
714{
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530715 static int once;
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530716 struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
717
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200718 /*
719 * OCFG[2] - OTG-Version = 1
720 * OCFG[1] - HNPCap = 0
721 * OCFG[0] - SRPCap = 0
722 */
723 dwc3_writel(dotg->regs, DWC3_OCFG, 0x4);
724
725 /*
726 * OCTL[6] - PeriMode = 1
727 * OCTL[5] - PrtPwrCtl = 0
728 * OCTL[4] - HNPReq = 0
729 * OCTL[3] - SesReq = 0
730 * OCTL[2] - TermSelDLPulse = 0
731 * OCTL[1] - DevSetHNPEn = 0
732 * OCTL[0] - HstSetHNPEn = 0
733 */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530734 if (!once) {
735 dwc3_writel(dotg->regs, DWC3_OCTL, 0x40);
736 once++;
737 }
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200738
739 /* Clear all otg events (interrupts) indications */
740 dwc3_writel(dotg->regs, DWC3_OEVT, 0xFFFF);
741
Manu Gautam8c642812012-06-07 10:35:10 +0530742 /* Enable ID/BSV StsChngEn event*/
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530743 if (ext_xceiv && !ext_xceiv->otg_capability)
744 dwc3_writel(dotg->regs, DWC3_OEVTEN,
745 DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT |
746 DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200747}
748
749/**
750 * dwc3_otg_init - Initializes otg related registers
751 * @dwc: Pointer to out controller context structure
752 *
753 * Returns 0 on success otherwise negative errno.
754 */
755int dwc3_otg_init(struct dwc3 *dwc)
756{
757 u32 reg;
758 int ret = 0;
759 struct dwc3_otg *dotg;
760
761 dev_dbg(dwc->dev, "dwc3_otg_init\n");
762
763 /*
764 * GHWPARAMS6[10] bit is SRPSupport.
765 * This bit also reflects DWC_USB3_EN_OTG
766 */
767 reg = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
768 if (!(reg & DWC3_GHWPARAMS6_SRP_SUPPORT)) {
769 /*
770 * No OTG support in the HW core.
771 * We return 0 to indicate no error, since this is acceptable
772 * situation, just continue probe the dwc3 driver without otg.
773 */
774 dev_dbg(dwc->dev, "dwc3_otg address space is not supported\n");
775 return 0;
776 }
777
778 /* Allocate and init otg instance */
779 dotg = kzalloc(sizeof(struct dwc3_otg), GFP_KERNEL);
780 if (!dotg) {
781 dev_err(dwc->dev, "unable to allocate dwc3_otg\n");
782 return -ENOMEM;
783 }
784
Manu Gautam17206c22012-06-21 10:17:53 +0530785 /* DWC3 has separate IRQ line for OTG events (ID/BSV etc.) */
786 dotg->irq = platform_get_irq_byname(to_platform_device(dwc->dev),
787 "otg_irq");
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200788 if (dotg->irq < 0) {
Manu Gautam17206c22012-06-21 10:17:53 +0530789 dev_err(dwc->dev, "%s: missing OTG IRQ\n", __func__);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200790 ret = -ENODEV;
791 goto err1;
792 }
793
794 dotg->regs = dwc->regs;
795
796 dotg->otg.set_peripheral = dwc3_otg_set_peripheral;
797 dotg->otg.set_host = dwc3_otg_set_host;
798
799 /* This reference is used by dwc3 modules for checking otg existance */
800 dwc->dotg = dotg;
801
802 dotg->otg.phy = kzalloc(sizeof(struct usb_phy), GFP_KERNEL);
803 if (!dotg->otg.phy) {
804 dev_err(dwc->dev, "unable to allocate dwc3_otg.phy\n");
805 ret = -ENOMEM;
806 goto err1;
807 }
808
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530809 dotg->dwc = dwc;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200810 dotg->otg.phy->otg = &dotg->otg;
811 dotg->otg.phy->dev = dwc->dev;
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530812 dotg->otg.phy->set_power = dwc3_otg_set_power;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200813
814 ret = usb_set_transceiver(dotg->otg.phy);
815 if (ret) {
816 dev_err(dotg->otg.phy->dev,
817 "%s: failed to set transceiver, already exists\n",
818 __func__);
819 goto err2;
820 }
821
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200822 dotg->otg.phy->state = OTG_STATE_UNDEFINED;
823
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530824 init_completion(&dotg->dwc3_xcvr_vbus_init);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200825 INIT_WORK(&dotg->sm_work, dwc3_otg_sm_work);
826
827 ret = request_irq(dotg->irq, dwc3_otg_interrupt, IRQF_SHARED,
828 "dwc3_otg", dotg);
829 if (ret) {
830 dev_err(dotg->otg.phy->dev, "failed to request irq #%d --> %d\n",
831 dotg->irq, ret);
832 goto err3;
833 }
834
Manu Gautamb5067272012-07-02 09:53:41 +0530835 pm_runtime_get(dwc->dev);
836
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200837 return 0;
838
839err3:
840 cancel_work_sync(&dotg->sm_work);
841 usb_set_transceiver(NULL);
842err2:
843 kfree(dotg->otg.phy);
844err1:
845 dwc->dotg = NULL;
846 kfree(dotg);
847
848 return ret;
849}
850
851/**
852 * dwc3_otg_exit
853 * @dwc: Pointer to out controller context structure
854 *
855 * Returns 0 on success otherwise negative errno.
856 */
857void dwc3_otg_exit(struct dwc3 *dwc)
858{
859 struct dwc3_otg *dotg = dwc->dotg;
860
861 /* dotg is null when GHWPARAMS6[10]=SRPSupport=0, see dwc3_otg_init */
862 if (dotg) {
Manu Gautam8c642812012-06-07 10:35:10 +0530863 if (dotg->charger)
864 dotg->charger->start_detection(dotg->charger, false);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200865 cancel_work_sync(&dotg->sm_work);
866 usb_set_transceiver(NULL);
Manu Gautamb5067272012-07-02 09:53:41 +0530867 pm_runtime_put(dwc->dev);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200868 free_irq(dotg->irq, dotg);
869 kfree(dotg->otg.phy);
870 kfree(dotg);
871 dwc->dotg = NULL;
872 }
873}