blob: 136cc5d94d2d5eae5132a6de5757ef904ff0bf36 [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{
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +053041 u32 reg;
42 struct dwc3 *dwc = dotg->dwc;
43 struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020044
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +053045 if (ext_xceiv && !ext_xceiv->otg_capability) {
46 /* Set OCTL[6](PeriMode) to 0 (host) */
47 reg = dwc3_readl(dotg->regs, DWC3_OCTL);
48 reg &= ~DWC3_OTG_OCTL_PERIMODE;
49 dwc3_writel(dotg->regs, DWC3_OCTL, reg);
50 } else {
51 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
52 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
53 reg |= DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST);
54 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
55 }
Manu Gautamf1fceddf2012-10-12 14:02:50 +053056}
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020057
Manu Gautamf1fceddf2012-10-12 14:02:50 +053058/**
59 * dwc3_otg_set_host_power - Enable port power control for host operation
60 *
61 * This function enables the OTG Port Power required to operate in Host mode
62 * This function should be called only after XHCI driver has set the port
63 * power in PORTSC register.
64 *
65 * @w: Pointer to the dwc3 otg struct
66 */
67void dwc3_otg_set_host_power(struct dwc3_otg *dotg)
68{
69 u32 osts;
70
71 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
72 if (!(osts & 0x8))
73 dev_err(dotg->dwc->dev, "%s: xHCIPrtPower not set\n", __func__);
74
75 dwc3_writel(dotg->regs, DWC3_OCTL, DWC3_OTG_OCTL_PRTPWRCTL);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020076}
77
78/**
79 * dwc3_otg_set_peripheral_regs - reset dwc3 otg registers to peripheral operation.
80 *
81 * This function sets the OTG registers to work in B-Device peripheral mode.
82 * This function should be called just before entering to B-Device mode.
83 *
84 * @w: Pointer to the dwc3 otg workqueue.
85 */
86static void dwc3_otg_set_peripheral_regs(struct dwc3_otg *dotg)
87{
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +053088 u32 reg;
89 struct dwc3 *dwc = dotg->dwc;
90 struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +020091
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +053092 if (ext_xceiv && !ext_xceiv->otg_capability) {
93 /* Set OCTL[6](PeriMode) to 1 (peripheral) */
94 reg = dwc3_readl(dotg->regs, DWC3_OCTL);
95 reg |= DWC3_OTG_OCTL_PERIMODE;
96 dwc3_writel(dotg->regs, DWC3_OCTL, reg);
97 /*
98 * TODO: add more OTG registers writes for PERIPHERAL mode here,
99 * see figure 12-19 B-device flow in dwc3 Synopsis spec
100 */
101 } else {
102 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
103 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
104 reg |= DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_DEVICE);
105 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
106 }
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200107}
108
109/**
110 * dwc3_otg_start_host - helper function for starting/stoping the host controller driver.
111 *
112 * @otg: Pointer to the otg_transceiver structure.
113 * @on: start / stop the host controller driver.
114 *
115 * Returns 0 on success otherwise negative errno.
116 */
117static int dwc3_otg_start_host(struct usb_otg *otg, int on)
118{
119 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530120 struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
Manu Gautam61721592012-11-06 18:09:39 +0530121 struct dwc3 *dwc = dotg->dwc;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200122 int ret = 0;
123
Manu Gautam61721592012-11-06 18:09:39 +0530124 if (!dwc->xhci)
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200125 return -EINVAL;
126
Manu Gautam61721592012-11-06 18:09:39 +0530127 if (!dotg->vbus_otg) {
128 dotg->vbus_otg = devm_regulator_get(dwc->dev->parent,
129 "vbus_dwc3");
130 if (IS_ERR(dotg->vbus_otg)) {
131 dev_err(dwc->dev, "Failed to get vbus regulator\n");
132 ret = PTR_ERR(dotg->vbus_otg);
133 dotg->vbus_otg = 0;
134 return ret;
135 }
136 }
137
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200138 if (on) {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530139 dev_dbg(otg->phy->dev, "%s: turn on host\n", __func__);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200140
141 /*
142 * This should be revisited for more testing post-silicon.
143 * In worst case we may need to disconnect the root hub
144 * before stopping the controller so that it does not
145 * interfere with runtime pm/system pm.
146 * We can also consider registering and unregistering xhci
147 * platform device. It is almost similar to add_hcd and
148 * remove_hcd, But we may not use standard set_host method
149 * anymore.
150 */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530151 dwc3_otg_set_host_regs(dotg);
Manu Gautam61721592012-11-06 18:09:39 +0530152 ret = platform_device_add(dwc->xhci);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200153 if (ret) {
154 dev_err(otg->phy->dev,
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530155 "%s: failed to add XHCI pdev ret=%d\n",
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200156 __func__, ret);
157 return ret;
158 }
159
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530160 dwc3_otg_notify_host_mode(otg, on);
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530161 ret = regulator_enable(dotg->vbus_otg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200162 if (ret) {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530163 dev_err(otg->phy->dev, "unable to enable vbus_otg\n");
Manu Gautam61721592012-11-06 18:09:39 +0530164 platform_device_del(dwc->xhci);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200165 return ret;
166 }
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530167
168 /* re-init OTG EVTEN register as XHCI reset clears it */
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530169 if (ext_xceiv && !ext_xceiv->otg_capability)
170 dwc3_otg_reset(dotg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200171 } else {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530172 dev_dbg(otg->phy->dev, "%s: turn off host\n", __func__);
173
Manu Gautam61721592012-11-06 18:09:39 +0530174 platform_device_del(dwc->xhci);
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530175
176 ret = regulator_disable(dotg->vbus_otg);
177 if (ret) {
178 dev_err(otg->phy->dev, "unable to disable vbus_otg\n");
179 return ret;
180 }
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530181 dwc3_otg_notify_host_mode(otg, on);
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530182
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530183 /* Do block reset for Host <-> peripheral switching to work */
184 if (ext_xceiv && ext_xceiv->otg_capability &&
185 ext_xceiv->ext_block_reset)
186 ext_xceiv->ext_block_reset();
187
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530188 /* re-init core and OTG register as XHCI reset clears it */
Manu Gautam61721592012-11-06 18:09:39 +0530189 dwc3_post_host_reset_core_init(dwc);
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530190 if (ext_xceiv && !ext_xceiv->otg_capability)
191 dwc3_otg_reset(dotg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200192 }
193
194 return 0;
195}
196
197/**
198 * dwc3_otg_set_host - bind/unbind the host controller driver.
199 *
200 * @otg: Pointer to the otg_transceiver structure.
201 * @host: Pointer to the usb_bus structure.
202 *
203 * Returns 0 on success otherwise negative errno.
204 */
205static int dwc3_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
206{
207 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
208
209 if (host) {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530210 dev_dbg(otg->phy->dev, "%s: set host %s, portpower\n",
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200211 __func__, host->bus_name);
212 otg->host = host;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200213 /*
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530214 * Though XHCI power would be set by now, but some delay is
215 * required for XHCI controller before setting OTG Port Power
216 * TODO: Tune this delay
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200217 */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530218 msleep(300);
219 dwc3_otg_set_host_power(dotg);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200220 } else {
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530221 otg->host = NULL;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200222 }
223
224 return 0;
225}
226
227/**
228 * dwc3_otg_start_peripheral - bind/unbind the peripheral controller.
229 *
230 * @otg: Pointer to the otg_transceiver structure.
231 * @gadget: pointer to the usb_gadget structure.
232 *
233 * Returns 0 on success otherwise negative errno.
234 */
235static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on)
236{
237 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
238
239 if (!otg->gadget)
240 return -EINVAL;
241
242 if (on) {
243 dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n",
244 __func__, otg->gadget->name);
245 dwc3_otg_set_peripheral_regs(dotg);
246 usb_gadget_vbus_connect(otg->gadget);
247 } else {
248 dev_dbg(otg->phy->dev, "%s: turn off gadget %s\n",
249 __func__, otg->gadget->name);
250 usb_gadget_vbus_disconnect(otg->gadget);
251 }
252
253 return 0;
254}
255
256/**
257 * dwc3_otg_set_peripheral - bind/unbind the peripheral controller driver.
258 *
259 * @otg: Pointer to the otg_transceiver structure.
260 * @gadget: pointer to the usb_gadget structure.
261 *
262 * Returns 0 on success otherwise negative errno.
263 */
264static int dwc3_otg_set_peripheral(struct usb_otg *otg,
265 struct usb_gadget *gadget)
266{
267 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
268
269 if (gadget) {
270 dev_dbg(otg->phy->dev, "%s: set gadget %s\n",
271 __func__, gadget->name);
272 otg->gadget = gadget;
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530273 schedule_work(&dotg->sm_work);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200274 } else {
275 if (otg->phy->state == OTG_STATE_B_PERIPHERAL) {
276 dwc3_otg_start_peripheral(otg, 0);
277 otg->gadget = NULL;
278 otg->phy->state = OTG_STATE_UNDEFINED;
279 schedule_work(&dotg->sm_work);
280 } else {
281 otg->gadget = NULL;
282 }
283 }
284
285 return 0;
286}
287
288/**
Manu Gautam8c642812012-06-07 10:35:10 +0530289 * dwc3_ext_chg_det_done - callback to handle charger detection completion
290 * @otg: Pointer to the otg transceiver structure
291 * @charger: Pointer to the external charger structure
292 *
293 * Returns 0 on success
294 */
295static void dwc3_ext_chg_det_done(struct usb_otg *otg, struct dwc3_charger *chg)
296{
297 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
298
299 /*
300 * Ignore chg_detection notification if BSV has gone off by this time.
301 * STOP chg_det as part of !BSV handling would reset the chg_det flags
302 */
303 if (test_bit(B_SESS_VLD, &dotg->inputs))
304 schedule_work(&dotg->sm_work);
305}
306
307/**
308 * dwc3_set_charger - bind/unbind external charger driver
309 * @otg: Pointer to the otg transceiver structure
310 * @charger: Pointer to the external charger structure
311 *
312 * Returns 0 on success
313 */
314int dwc3_set_charger(struct usb_otg *otg, struct dwc3_charger *charger)
315{
316 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
317
318 dotg->charger = charger;
319 if (charger)
320 charger->notify_detection_complete = dwc3_ext_chg_det_done;
321
322 return 0;
323}
324
Manu Gautamb5067272012-07-02 09:53:41 +0530325/**
326 * dwc3_ext_event_notify - callback to handle events from external transceiver
327 * @otg: Pointer to the otg transceiver structure
328 * @event: Event reported by transceiver
329 *
330 * Returns 0 on success
331 */
332static void dwc3_ext_event_notify(struct usb_otg *otg,
333 enum dwc3_ext_events event)
334{
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530335 static bool init;
Manu Gautamb5067272012-07-02 09:53:41 +0530336 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
337 struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
338 struct usb_phy *phy = dotg->otg.phy;
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530339 int ret = 0;
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530340 int work = 0;
Manu Gautamb5067272012-07-02 09:53:41 +0530341
342 if (event == DWC3_EVENT_PHY_RESUME) {
343 if (!pm_runtime_status_suspended(phy->dev)) {
344 dev_warn(phy->dev, "PHY_RESUME event out of LPM!!!!\n");
345 } else {
346 dev_dbg(phy->dev, "ext PHY_RESUME event received\n");
347 /* ext_xceiver would have taken h/w out of LPM by now */
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530348 ret = pm_runtime_get(phy->dev);
349 if (ret == -EACCES) {
350 /* pm_runtime_get may fail during system
351 resume with -EACCES error */
352 pm_runtime_disable(phy->dev);
353 pm_runtime_set_active(phy->dev);
354 pm_runtime_enable(phy->dev);
355 } else if (ret < 0) {
356 dev_warn(phy->dev, "pm_runtime_get failed!\n");
357 }
Manu Gautamb5067272012-07-02 09:53:41 +0530358 }
Manu Gautam377821c2012-09-28 16:53:24 +0530359 } else if (event == DWC3_EVENT_XCEIV_STATE) {
Jack Pham0fc12332012-11-19 13:14:22 -0800360 if (ext_xceiv->id == DWC3_ID_FLOAT) {
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530361 if (!test_and_set_bit(ID, &dotg->inputs)) {
362 dev_dbg(phy->dev, "XCVR: ID set\n");
363 work = 1;
364 }
Jack Pham0fc12332012-11-19 13:14:22 -0800365 } else {
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530366 if (test_and_clear_bit(ID, &dotg->inputs)) {
367 dev_dbg(phy->dev, "XCVR: ID clear\n");
368 work = 1;
369 }
Jack Pham0fc12332012-11-19 13:14:22 -0800370 }
Manu Gautam377821c2012-09-28 16:53:24 +0530371
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530372 if (ext_xceiv->bsv) {
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530373 if (!test_and_set_bit(B_SESS_VLD, &dotg->inputs)) {
374 dev_dbg(phy->dev, "XCVR: BSV set\n");
375 work = 1;
376 }
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530377 } else {
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530378 if (test_and_clear_bit(B_SESS_VLD, &dotg->inputs)) {
379 dev_dbg(phy->dev, "XCVR: BSV clear\n");
380 work = 1;
381 }
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530382 }
Manu Gautam377821c2012-09-28 16:53:24 +0530383
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530384 if (!init) {
385 init = true;
386 complete(&dotg->dwc3_xcvr_vbus_init);
387 dev_dbg(phy->dev, "XCVR: BSV init complete\n");
388 return;
389 }
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530390 if (work)
391 schedule_work(&dotg->sm_work);
Manu Gautamb5067272012-07-02 09:53:41 +0530392 }
Manu Gautamb5067272012-07-02 09:53:41 +0530393}
394
395/**
396 * dwc3_set_ext_xceiv - bind/unbind external transceiver driver
397 * @otg: Pointer to the otg transceiver structure
398 * @ext_xceiv: Pointer to the external transceiver struccture
399 *
400 * Returns 0 on success
401 */
402int dwc3_set_ext_xceiv(struct usb_otg *otg, struct dwc3_ext_xceiv *ext_xceiv)
403{
404 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
405
406 dotg->ext_xceiv = ext_xceiv;
407 if (ext_xceiv)
408 ext_xceiv->notify_ext_events = dwc3_ext_event_notify;
409
410 return 0;
411}
412
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530413static void dwc3_otg_notify_host_mode(struct usb_otg *otg, int host_mode)
414{
415 struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
416
417 if (!dotg->psy) {
418 dev_err(otg->phy->dev, "no usb power supply registered\n");
419 return;
420 }
421
422 if (host_mode)
423 power_supply_set_scope(dotg->psy, POWER_SUPPLY_SCOPE_SYSTEM);
424 else
425 power_supply_set_scope(dotg->psy, POWER_SUPPLY_SCOPE_DEVICE);
426}
427
428static int dwc3_otg_set_power(struct usb_phy *phy, unsigned mA)
429{
430 static int power_supply_type;
431 struct dwc3_otg *dotg = container_of(phy->otg, struct dwc3_otg, otg);
432
433
Manu Gautam6c0ff032012-11-02 14:55:35 +0530434 if (!dotg->psy || !dotg->charger) {
435 dev_err(phy->dev, "no usb power supply/charger registered\n");
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530436 return 0;
437 }
438
Manu Gautam6c0ff032012-11-02 14:55:35 +0530439 if (dotg->charger->charging_disabled)
440 return 0;
441
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530442 if (dotg->charger->chg_type == DWC3_SDP_CHARGER)
443 power_supply_type = POWER_SUPPLY_TYPE_USB;
444 else if (dotg->charger->chg_type == DWC3_CDP_CHARGER)
445 power_supply_type = POWER_SUPPLY_TYPE_USB_CDP;
446 else if (dotg->charger->chg_type == DWC3_DCP_CHARGER)
447 power_supply_type = POWER_SUPPLY_TYPE_USB_DCP;
448 else
449 power_supply_type = POWER_SUPPLY_TYPE_BATTERY;
450
451 power_supply_set_supply_type(dotg->psy, power_supply_type);
452
453 if (dotg->charger->max_power == mA)
454 return 0;
455
456 dev_info(phy->dev, "Avail curr from USB = %u\n", mA);
457
458 if (dotg->charger->max_power <= 2 && mA > 2) {
459 /* Enable charging */
460 if (power_supply_set_online(dotg->psy, true))
461 goto psy_error;
462 if (power_supply_set_current_limit(dotg->psy, 1000*mA))
463 goto psy_error;
464 } else if (dotg->charger->max_power > 0 && (mA == 0 || mA == 2)) {
465 /* Disable charging */
466 if (power_supply_set_online(dotg->psy, false))
467 goto psy_error;
468 /* Set max current limit */
469 if (power_supply_set_current_limit(dotg->psy, 0))
470 goto psy_error;
471 }
472
473 power_supply_changed(dotg->psy);
474 dotg->charger->max_power = mA;
475 return 0;
476
477psy_error:
478 dev_dbg(phy->dev, "power supply error when setting property\n");
479 return -ENXIO;
480}
481
Manu Gautam8c642812012-06-07 10:35:10 +0530482/* IRQs which OTG driver is interested in handling */
483#define DWC3_OEVT_MASK (DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT | \
484 DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT)
485
486/**
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200487 * dwc3_otg_interrupt - interrupt handler for dwc3 otg events.
488 * @_dotg: Pointer to out controller context structure
489 *
490 * Returns IRQ_HANDLED on success otherwise IRQ_NONE.
491 */
492static irqreturn_t dwc3_otg_interrupt(int irq, void *_dotg)
493{
494 struct dwc3_otg *dotg = (struct dwc3_otg *)_dotg;
Manu Gautam8c642812012-06-07 10:35:10 +0530495 u32 osts, oevt_reg;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200496 int ret = IRQ_NONE;
497 int handled_irqs = 0;
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530498 struct usb_phy *phy = dotg->otg.phy;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200499
500 oevt_reg = dwc3_readl(dotg->regs, DWC3_OEVT);
501
Manu Gautam8c642812012-06-07 10:35:10 +0530502 if (!(oevt_reg & DWC3_OEVT_MASK))
503 return IRQ_NONE;
504
505 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
506
507 if ((oevt_reg & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) ||
508 (oevt_reg & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT)) {
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200509 /*
Manu Gautam8c642812012-06-07 10:35:10 +0530510 * ID sts has changed, set inputs later, in the workqueue
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200511 * function, switch from A to B or from B to A.
512 */
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200513
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530514 if (oevt_reg & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) {
515 if (osts & DWC3_OTG_OSTS_CONIDSTS) {
516 dev_dbg(phy->dev, "ID set\n");
517 set_bit(ID, &dotg->inputs);
518 } else {
519 dev_dbg(phy->dev, "ID clear\n");
520 clear_bit(ID, &dotg->inputs);
521 }
522 handled_irqs |= DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT;
523 }
Manu Gautam8c642812012-06-07 10:35:10 +0530524
Vijayavardhan Vennapusab7434562012-12-12 16:48:49 +0530525 if (oevt_reg & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT) {
526 if (osts & DWC3_OTG_OSTS_BSESVALID) {
527 dev_dbg(phy->dev, "BSV set\n");
528 set_bit(B_SESS_VLD, &dotg->inputs);
529 } else {
530 dev_dbg(phy->dev, "BSV clear\n");
531 clear_bit(B_SESS_VLD, &dotg->inputs);
532 }
533 handled_irqs |= DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT;
534 }
Manu Gautam8c642812012-06-07 10:35:10 +0530535
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200536 schedule_work(&dotg->sm_work);
537
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200538 ret = IRQ_HANDLED;
Manu Gautam8c642812012-06-07 10:35:10 +0530539
540 /* Clear the interrupts we handled */
541 dwc3_writel(dotg->regs, DWC3_OEVT, handled_irqs);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200542 }
543
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200544 return ret;
545}
546
547/**
Manu Gautam8c642812012-06-07 10:35:10 +0530548 * dwc3_otg_init_sm - initialize OTG statemachine input
549 * @dotg: Pointer to the dwc3_otg structure
550 *
551 */
552void dwc3_otg_init_sm(struct dwc3_otg *dotg)
553{
554 u32 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
555 struct usb_phy *phy = dotg->otg.phy;
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530556 struct dwc3_ext_xceiv *ext_xceiv;
557 int ret;
Manu Gautam8c642812012-06-07 10:35:10 +0530558
559 dev_dbg(phy->dev, "Initialize OTG inputs, osts: 0x%x\n", osts);
560
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530561 /*
562 * VBUS initial state is reported after PMIC
563 * driver initialization. Wait for it.
564 */
565 ret = wait_for_completion_timeout(&dotg->dwc3_xcvr_vbus_init, HZ * 5);
566 if (!ret)
567 dev_err(phy->dev, "%s: completion timeout\n", __func__);
Manu Gautam8c642812012-06-07 10:35:10 +0530568
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530569 ext_xceiv = dotg->ext_xceiv;
570 dwc3_otg_reset(dotg);
571 if (ext_xceiv && !ext_xceiv->otg_capability) {
572 if (osts & DWC3_OTG_OSTS_CONIDSTS)
573 set_bit(ID, &dotg->inputs);
574 else
575 clear_bit(ID, &dotg->inputs);
576
577 if (osts & DWC3_OTG_OSTS_BSESVALID)
578 set_bit(B_SESS_VLD, &dotg->inputs);
579 else
580 clear_bit(B_SESS_VLD, &dotg->inputs);
581 }
Manu Gautam8c642812012-06-07 10:35:10 +0530582}
583
584/**
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200585 * dwc3_otg_sm_work - workqueue function.
586 *
587 * @w: Pointer to the dwc3 otg workqueue
588 *
589 * NOTE: After any change in phy->state,
590 * we must reschdule the state machine.
591 */
592static void dwc3_otg_sm_work(struct work_struct *w)
593{
594 struct dwc3_otg *dotg = container_of(w, struct dwc3_otg, sm_work);
595 struct usb_phy *phy = dotg->otg.phy;
Manu Gautam8c642812012-06-07 10:35:10 +0530596 struct dwc3_charger *charger = dotg->charger;
597 bool work = 0;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200598
Manu Gautamb5067272012-07-02 09:53:41 +0530599 pm_runtime_resume(phy->dev);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200600 dev_dbg(phy->dev, "%s state\n", otg_state_string(phy->state));
601
602 /* Check OTG state */
603 switch (phy->state) {
604 case OTG_STATE_UNDEFINED:
Manu Gautam8c642812012-06-07 10:35:10 +0530605 dwc3_otg_init_sm(dotg);
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530606 if (!dotg->psy) {
607 dotg->psy = power_supply_get_by_name("usb");
608
609 if (!dotg->psy)
610 dev_err(phy->dev,
611 "couldn't get usb power supply\n");
612 }
613
Manu Gautam8c642812012-06-07 10:35:10 +0530614 /* Switch to A or B-Device according to ID / BSV */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530615 if (!test_bit(ID, &dotg->inputs)) {
Manu Gautam8c642812012-06-07 10:35:10 +0530616 dev_dbg(phy->dev, "!id\n");
617 phy->state = OTG_STATE_A_IDLE;
618 work = 1;
619 } else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
620 dev_dbg(phy->dev, "b_sess_vld\n");
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200621 phy->state = OTG_STATE_B_IDLE;
Manu Gautam8c642812012-06-07 10:35:10 +0530622 work = 1;
623 } else {
624 phy->state = OTG_STATE_B_IDLE;
Manu Gautamb5067272012-07-02 09:53:41 +0530625 dev_dbg(phy->dev, "No device, trying to suspend\n");
626 pm_runtime_put_sync(phy->dev);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200627 }
628 break;
Manu Gautam8c642812012-06-07 10:35:10 +0530629
630 case OTG_STATE_B_IDLE:
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530631 if (!test_bit(ID, &dotg->inputs)) {
Manu Gautam8c642812012-06-07 10:35:10 +0530632 dev_dbg(phy->dev, "!id\n");
633 phy->state = OTG_STATE_A_IDLE;
634 work = 1;
635 if (charger) {
636 if (charger->chg_type == DWC3_INVALID_CHARGER)
637 charger->start_detection(dotg->charger,
638 false);
639 else
640 charger->chg_type =
641 DWC3_INVALID_CHARGER;
642 }
643 } else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
644 dev_dbg(phy->dev, "b_sess_vld\n");
645 if (charger) {
646 /* Has charger been detected? If no detect it */
647 switch (charger->chg_type) {
648 case DWC3_DCP_CHARGER:
Manu Gautamb5067272012-07-02 09:53:41 +0530649 dev_dbg(phy->dev, "lpm, DCP charger\n");
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530650 dwc3_otg_set_power(phy,
651 DWC3_IDEV_CHG_MAX);
Manu Gautamb5067272012-07-02 09:53:41 +0530652 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530653 break;
654 case DWC3_CDP_CHARGER:
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530655 dwc3_otg_set_power(phy,
656 DWC3_IDEV_CHG_MAX);
Manu Gautam8c642812012-06-07 10:35:10 +0530657 dwc3_otg_start_peripheral(&dotg->otg,
658 1);
659 phy->state = OTG_STATE_B_PERIPHERAL;
660 work = 1;
661 break;
662 case DWC3_SDP_CHARGER:
663 dwc3_otg_start_peripheral(&dotg->otg,
664 1);
665 phy->state = OTG_STATE_B_PERIPHERAL;
666 work = 1;
667 break;
668 default:
669 dev_dbg(phy->dev, "chg_det started\n");
670 charger->start_detection(charger, true);
671 break;
672 }
673 } else {
674 /* no charger registered, start peripheral */
675 if (dwc3_otg_start_peripheral(&dotg->otg, 1)) {
676 /*
677 * Probably set_peripheral not called
678 * yet. We will re-try as soon as it
679 * will be called
680 */
Manu Gautamb5067272012-07-02 09:53:41 +0530681 dev_err(phy->dev, "enter lpm as\n"
Manu Gautam8c642812012-06-07 10:35:10 +0530682 "unable to start B-device\n");
683 phy->state = OTG_STATE_UNDEFINED;
Manu Gautamb5067272012-07-02 09:53:41 +0530684 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530685 return;
686 }
687 }
688 } else {
Manu Gautam98013c22012-11-20 17:42:42 +0530689 if (charger)
690 charger->start_detection(dotg->charger, false);
691
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530692 dwc3_otg_set_power(phy, 0);
Manu Gautamb5067272012-07-02 09:53:41 +0530693 dev_dbg(phy->dev, "No device, trying to suspend\n");
694 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530695 }
696 break;
697
698 case OTG_STATE_B_PERIPHERAL:
699 if (!test_bit(B_SESS_VLD, &dotg->inputs) ||
700 !test_bit(ID, &dotg->inputs)) {
701 dev_dbg(phy->dev, "!id || !bsv\n");
702 dwc3_otg_start_peripheral(&dotg->otg, 0);
703 phy->state = OTG_STATE_B_IDLE;
704 if (charger)
705 charger->chg_type = DWC3_INVALID_CHARGER;
706 work = 1;
707 }
708 break;
709
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200710 case OTG_STATE_A_IDLE:
711 /* Switch to A-Device*/
Manu Gautam8c642812012-06-07 10:35:10 +0530712 if (test_bit(ID, &dotg->inputs)) {
713 dev_dbg(phy->dev, "id\n");
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200714 phy->state = OTG_STATE_B_IDLE;
Manu Gautam8c642812012-06-07 10:35:10 +0530715 work = 1;
716 } else {
717 if (dwc3_otg_start_host(&dotg->otg, 1)) {
718 /*
719 * Probably set_host was not called yet.
720 * We will re-try as soon as it will be called
721 */
Manu Gautamb5067272012-07-02 09:53:41 +0530722 dev_dbg(phy->dev, "enter lpm as\n"
Manu Gautam8c642812012-06-07 10:35:10 +0530723 "unable to start A-device\n");
724 phy->state = OTG_STATE_UNDEFINED;
Manu Gautamb5067272012-07-02 09:53:41 +0530725 pm_runtime_put_sync(phy->dev);
Manu Gautam8c642812012-06-07 10:35:10 +0530726 return;
727 }
728 phy->state = OTG_STATE_A_HOST;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200729 }
730 break;
Manu Gautam8c642812012-06-07 10:35:10 +0530731
732 case OTG_STATE_A_HOST:
733 if (test_bit(ID, &dotg->inputs)) {
734 dev_dbg(phy->dev, "id\n");
735 dwc3_otg_start_host(&dotg->otg, 0);
736 phy->state = OTG_STATE_B_IDLE;
737 work = 1;
738 }
739 break;
740
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200741 default:
742 dev_err(phy->dev, "%s: invalid otg-state\n", __func__);
743
744 }
Manu Gautam8c642812012-06-07 10:35:10 +0530745
746 if (work)
747 schedule_work(&dotg->sm_work);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200748}
749
750
751/**
752 * dwc3_otg_reset - reset dwc3 otg registers.
753 *
754 * @w: Pointer to the dwc3 otg workqueue
755 */
756static void dwc3_otg_reset(struct dwc3_otg *dotg)
757{
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530758 static int once;
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530759 struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
760
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200761 /*
762 * OCFG[2] - OTG-Version = 1
763 * OCFG[1] - HNPCap = 0
764 * OCFG[0] - SRPCap = 0
765 */
766 dwc3_writel(dotg->regs, DWC3_OCFG, 0x4);
767
768 /*
769 * OCTL[6] - PeriMode = 1
770 * OCTL[5] - PrtPwrCtl = 0
771 * OCTL[4] - HNPReq = 0
772 * OCTL[3] - SesReq = 0
773 * OCTL[2] - TermSelDLPulse = 0
774 * OCTL[1] - DevSetHNPEn = 0
775 * OCTL[0] - HstSetHNPEn = 0
776 */
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530777 if (!once) {
778 dwc3_writel(dotg->regs, DWC3_OCTL, 0x40);
779 once++;
780 }
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200781
782 /* Clear all otg events (interrupts) indications */
783 dwc3_writel(dotg->regs, DWC3_OEVT, 0xFFFF);
784
Manu Gautam8c642812012-06-07 10:35:10 +0530785 /* Enable ID/BSV StsChngEn event*/
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530786 if (ext_xceiv && !ext_xceiv->otg_capability)
787 dwc3_writel(dotg->regs, DWC3_OEVTEN,
788 DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT |
789 DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200790}
791
792/**
793 * dwc3_otg_init - Initializes otg related registers
794 * @dwc: Pointer to out controller context structure
795 *
796 * Returns 0 on success otherwise negative errno.
797 */
798int dwc3_otg_init(struct dwc3 *dwc)
799{
800 u32 reg;
801 int ret = 0;
802 struct dwc3_otg *dotg;
803
804 dev_dbg(dwc->dev, "dwc3_otg_init\n");
805
806 /*
807 * GHWPARAMS6[10] bit is SRPSupport.
808 * This bit also reflects DWC_USB3_EN_OTG
809 */
810 reg = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
811 if (!(reg & DWC3_GHWPARAMS6_SRP_SUPPORT)) {
812 /*
813 * No OTG support in the HW core.
814 * We return 0 to indicate no error, since this is acceptable
815 * situation, just continue probe the dwc3 driver without otg.
816 */
817 dev_dbg(dwc->dev, "dwc3_otg address space is not supported\n");
818 return 0;
819 }
820
821 /* Allocate and init otg instance */
822 dotg = kzalloc(sizeof(struct dwc3_otg), GFP_KERNEL);
823 if (!dotg) {
824 dev_err(dwc->dev, "unable to allocate dwc3_otg\n");
825 return -ENOMEM;
826 }
827
Manu Gautam17206c22012-06-21 10:17:53 +0530828 /* DWC3 has separate IRQ line for OTG events (ID/BSV etc.) */
829 dotg->irq = platform_get_irq_byname(to_platform_device(dwc->dev),
830 "otg_irq");
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200831 if (dotg->irq < 0) {
Manu Gautam17206c22012-06-21 10:17:53 +0530832 dev_err(dwc->dev, "%s: missing OTG IRQ\n", __func__);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200833 ret = -ENODEV;
834 goto err1;
835 }
836
837 dotg->regs = dwc->regs;
838
839 dotg->otg.set_peripheral = dwc3_otg_set_peripheral;
840 dotg->otg.set_host = dwc3_otg_set_host;
841
842 /* This reference is used by dwc3 modules for checking otg existance */
843 dwc->dotg = dotg;
844
845 dotg->otg.phy = kzalloc(sizeof(struct usb_phy), GFP_KERNEL);
846 if (!dotg->otg.phy) {
847 dev_err(dwc->dev, "unable to allocate dwc3_otg.phy\n");
848 ret = -ENOMEM;
849 goto err1;
850 }
851
Manu Gautamf1fceddf2012-10-12 14:02:50 +0530852 dotg->dwc = dwc;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200853 dotg->otg.phy->otg = &dotg->otg;
854 dotg->otg.phy->dev = dwc->dev;
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530855 dotg->otg.phy->set_power = dwc3_otg_set_power;
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200856
857 ret = usb_set_transceiver(dotg->otg.phy);
858 if (ret) {
859 dev_err(dotg->otg.phy->dev,
860 "%s: failed to set transceiver, already exists\n",
861 __func__);
862 goto err2;
863 }
864
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200865 dotg->otg.phy->state = OTG_STATE_UNDEFINED;
866
Vijayavardhan Vennapusa42eeea32012-10-22 17:56:11 +0530867 init_completion(&dotg->dwc3_xcvr_vbus_init);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200868 INIT_WORK(&dotg->sm_work, dwc3_otg_sm_work);
869
870 ret = request_irq(dotg->irq, dwc3_otg_interrupt, IRQF_SHARED,
871 "dwc3_otg", dotg);
872 if (ret) {
873 dev_err(dotg->otg.phy->dev, "failed to request irq #%d --> %d\n",
874 dotg->irq, ret);
875 goto err3;
876 }
877
Manu Gautamb5067272012-07-02 09:53:41 +0530878 pm_runtime_get(dwc->dev);
879
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200880 return 0;
881
882err3:
883 cancel_work_sync(&dotg->sm_work);
884 usb_set_transceiver(NULL);
885err2:
886 kfree(dotg->otg.phy);
887err1:
888 dwc->dotg = NULL;
889 kfree(dotg);
890
891 return ret;
892}
893
894/**
895 * dwc3_otg_exit
896 * @dwc: Pointer to out controller context structure
897 *
898 * Returns 0 on success otherwise negative errno.
899 */
900void dwc3_otg_exit(struct dwc3 *dwc)
901{
902 struct dwc3_otg *dotg = dwc->dotg;
903
904 /* dotg is null when GHWPARAMS6[10]=SRPSupport=0, see dwc3_otg_init */
905 if (dotg) {
Manu Gautam8c642812012-06-07 10:35:10 +0530906 if (dotg->charger)
907 dotg->charger->start_detection(dotg->charger, false);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200908 cancel_work_sync(&dotg->sm_work);
909 usb_set_transceiver(NULL);
Manu Gautamb5067272012-07-02 09:53:41 +0530910 pm_runtime_put(dwc->dev);
Ido Shayevitzcdeef4c2012-05-29 13:17:41 +0200911 free_irq(dotg->irq, dotg);
912 kfree(dotg->otg.phy);
913 kfree(dotg);
914 dwc->dotg = NULL;
915 }
916}