blob: b81216d1380b0f99e067d5133db1ff52d588a857 [file] [log] [blame]
Felipe Balbi550a7372008-07-24 12:27:36 +03001/*
2 * Copyright (C) 2005-2007 by Texas Instruments
3 * Some code has been taken from tusb6010.c
4 * Copyrights for that are attributable to:
5 * Copyright (C) 2006 Nokia Corporation
Felipe Balbi550a7372008-07-24 12:27:36 +03006 * Tony Lindgren <tony@atomide.com>
7 *
8 * This file is part of the Inventra Controller Driver for Linux.
9 *
10 * The Inventra Controller Driver for Linux is free software; you
11 * can redistribute it and/or modify it under the terms of the GNU
12 * General Public License version 2 as published by the Free Software
13 * Foundation.
14 *
15 * The Inventra Controller Driver for Linux is distributed in
16 * the hope that it will be useful, but WITHOUT ANY WARRANTY;
17 * without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 * License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with The Inventra Controller Driver for Linux ; if not,
23 * write to the Free Software Foundation, Inc., 59 Temple Place,
24 * Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27#include <linux/module.h>
28#include <linux/kernel.h>
29#include <linux/sched.h>
Felipe Balbi550a7372008-07-24 12:27:36 +030030#include <linux/init.h>
31#include <linux/list.h>
Felipe Balbi550a7372008-07-24 12:27:36 +030032#include <linux/io.h>
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +053033#include <linux/of.h>
Felipe Balbidc098862010-12-01 15:01:11 +020034#include <linux/platform_device.h>
35#include <linux/dma-mapping.h>
Hema HK207b0e12011-02-17 12:07:22 +053036#include <linux/pm_runtime.h>
37#include <linux/err.h>
NeilBrown12a19b52012-08-13 12:32:58 +100038#include <linux/delay.h>
Tony Lindgren80555552015-11-30 21:37:12 -080039#include <linux/usb/musb.h>
Kishon Vijay Abraham I14da6992014-03-06 16:38:37 +020040#include <linux/phy/omap_control_phy.h>
Roger Quadros8934d3e2013-10-03 18:12:34 +030041#include <linux/of_platform.h>
Felipe Balbi550a7372008-07-24 12:27:36 +030042
Felipe Balbi550a7372008-07-24 12:27:36 +030043#include "musb_core.h"
44#include "omap2430.h"
45
Felipe Balbia3cee122010-12-02 09:27:29 +020046struct omap2430_glue {
47 struct device *dev;
48 struct platform_device *musb;
Tony Lindgren80555552015-11-30 21:37:12 -080049 enum musb_vbus_id_status status;
Kishon Vijay Abraham I1e5acb82012-06-22 17:40:51 +053050 struct work_struct omap_musb_mailbox_work;
Kishon Vijay Abraham Ica784be2013-01-25 15:54:00 +053051 struct device *control_otghs;
Tony Lindgren21f77be2016-05-31 10:05:15 -050052 bool cable_connected;
53 bool enabled;
54 bool powered;
Felipe Balbia3cee122010-12-02 09:27:29 +020055};
Felipe Balbic20aebb2010-12-02 12:44:40 +020056#define glue_to_musb(g) platform_get_drvdata(g->musb)
Felipe Balbia3cee122010-12-02 09:27:29 +020057
Aaro Koskinen4b58ed12013-03-05 13:04:24 +020058static struct omap2430_glue *_glue;
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +053059
Felipe Balbi550a7372008-07-24 12:27:36 +030060static struct timer_list musb_idle_timer;
61
62static void musb_do_idle(unsigned long _musb)
63{
64 struct musb *musb = (void *)_musb;
65 unsigned long flags;
66 u8 power;
Felipe Balbi550a7372008-07-24 12:27:36 +030067 u8 devctl;
68
Felipe Balbi550a7372008-07-24 12:27:36 +030069 spin_lock_irqsave(&musb->lock, flags);
70
Antoine Tenarte47d9252014-10-30 18:41:13 +010071 switch (musb->xceiv->otg->state) {
Felipe Balbi550a7372008-07-24 12:27:36 +030072 case OTG_STATE_A_WAIT_BCON:
Felipe Balbi550a7372008-07-24 12:27:36 +030073
74 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
75 if (devctl & MUSB_DEVCTL_BDEVICE) {
Antoine Tenarte47d9252014-10-30 18:41:13 +010076 musb->xceiv->otg->state = OTG_STATE_B_IDLE;
Felipe Balbi550a7372008-07-24 12:27:36 +030077 MUSB_DEV_MODE(musb);
78 } else {
Antoine Tenarte47d9252014-10-30 18:41:13 +010079 musb->xceiv->otg->state = OTG_STATE_A_IDLE;
Felipe Balbi550a7372008-07-24 12:27:36 +030080 MUSB_HST_MODE(musb);
81 }
82 break;
Felipe Balbi550a7372008-07-24 12:27:36 +030083 case OTG_STATE_A_SUSPEND:
84 /* finish RESUME signaling? */
85 if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
86 power = musb_readb(musb->mregs, MUSB_POWER);
87 power &= ~MUSB_POWER_RESUME;
Felipe Balbi5c8a86e2011-05-11 12:44:08 +030088 dev_dbg(musb->controller, "root port resume stopped, power %02x\n", power);
Felipe Balbi550a7372008-07-24 12:27:36 +030089 musb_writeb(musb->mregs, MUSB_POWER, power);
90 musb->is_active = 1;
91 musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
92 | MUSB_PORT_STAT_RESUME);
93 musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
Daniel Mack8b125df2013-04-10 21:55:50 +020094 usb_hcd_poll_rh_status(musb->hcd);
Felipe Balbi550a7372008-07-24 12:27:36 +030095 /* NOTE: it might really be A_WAIT_BCON ... */
Antoine Tenarte47d9252014-10-30 18:41:13 +010096 musb->xceiv->otg->state = OTG_STATE_A_HOST;
Felipe Balbi550a7372008-07-24 12:27:36 +030097 }
98 break;
Felipe Balbi550a7372008-07-24 12:27:36 +030099 case OTG_STATE_A_HOST:
100 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
101 if (devctl & MUSB_DEVCTL_BDEVICE)
Antoine Tenarte47d9252014-10-30 18:41:13 +0100102 musb->xceiv->otg->state = OTG_STATE_B_IDLE;
Felipe Balbi550a7372008-07-24 12:27:36 +0300103 else
Antoine Tenarte47d9252014-10-30 18:41:13 +0100104 musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
Felipe Balbi550a7372008-07-24 12:27:36 +0300105 default:
106 break;
107 }
108 spin_unlock_irqrestore(&musb->lock, flags);
109}
110
111
Felipe Balbi743411b2010-12-01 13:22:05 +0200112static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
Felipe Balbi550a7372008-07-24 12:27:36 +0300113{
114 unsigned long default_timeout = jiffies + msecs_to_jiffies(3);
115 static unsigned long last_timer;
116
117 if (timeout == 0)
118 timeout = default_timeout;
119
120 /* Never idle if active, or when VBUS timeout is not set as host */
121 if (musb->is_active || ((musb->a_wait_bcon == 0)
Antoine Tenarte47d9252014-10-30 18:41:13 +0100122 && (musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON))) {
Felipe Balbi5c8a86e2011-05-11 12:44:08 +0300123 dev_dbg(musb->controller, "%s active, deleting timer\n",
Antoine Tenarte47d9252014-10-30 18:41:13 +0100124 usb_otg_state_string(musb->xceiv->otg->state));
Felipe Balbi550a7372008-07-24 12:27:36 +0300125 del_timer(&musb_idle_timer);
126 last_timer = jiffies;
127 return;
128 }
129
130 if (time_after(last_timer, timeout)) {
131 if (!timer_pending(&musb_idle_timer))
132 last_timer = timeout;
133 else {
Felipe Balbi5c8a86e2011-05-11 12:44:08 +0300134 dev_dbg(musb->controller, "Longer idle timer already pending, ignoring\n");
Felipe Balbi550a7372008-07-24 12:27:36 +0300135 return;
136 }
137 }
138 last_timer = timeout;
139
Felipe Balbi5c8a86e2011-05-11 12:44:08 +0300140 dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
Antoine Tenarte47d9252014-10-30 18:41:13 +0100141 usb_otg_state_string(musb->xceiv->otg->state),
Felipe Balbi550a7372008-07-24 12:27:36 +0300142 (unsigned long)jiffies_to_msecs(timeout - jiffies));
143 mod_timer(&musb_idle_timer, timeout);
144}
145
Felipe Balbi743411b2010-12-01 13:22:05 +0200146static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
Felipe Balbi550a7372008-07-24 12:27:36 +0300147{
Heikki Krogerusd445b6d2012-02-13 13:24:15 +0200148 struct usb_otg *otg = musb->xceiv->otg;
Felipe Balbi550a7372008-07-24 12:27:36 +0300149 u8 devctl;
Hema HK594632e2010-12-10 18:10:51 +0530150 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
Felipe Balbi550a7372008-07-24 12:27:36 +0300151 /* HDRC controls CPEN, but beware current surges during device
152 * connect. They can trigger transient overcurrent conditions
153 * that must be ignored.
154 */
155
156 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
157
158 if (is_on) {
Antoine Tenarte47d9252014-10-30 18:41:13 +0100159 if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) {
NeilBrown12a19b52012-08-13 12:32:58 +1000160 int loops = 100;
Hema HK594632e2010-12-10 18:10:51 +0530161 /* start the session */
162 devctl |= MUSB_DEVCTL_SESSION;
163 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
164 /*
165 * Wait for the musb to set as A device to enable the
166 * VBUS
167 */
Sergei Shtylyov5a805302014-10-24 00:34:12 +0400168 while (musb_readb(musb->mregs, MUSB_DEVCTL) &
169 MUSB_DEVCTL_BDEVICE) {
Felipe Balbi550a7372008-07-24 12:27:36 +0300170
NeilBrown12a19b52012-08-13 12:32:58 +1000171 mdelay(5);
Hema HK594632e2010-12-10 18:10:51 +0530172 cpu_relax();
173
NeilBrown12a19b52012-08-13 12:32:58 +1000174 if (time_after(jiffies, timeout)
175 || loops-- <= 0) {
Hema HK594632e2010-12-10 18:10:51 +0530176 dev_err(musb->controller,
177 "configured as A device timeout");
Hema HK594632e2010-12-10 18:10:51 +0530178 break;
179 }
180 }
181
Kishon Vijay Abraham Ibb467cf2013-03-14 11:53:56 +0530182 otg_set_vbus(otg, 1);
Hema HK594632e2010-12-10 18:10:51 +0530183 } else {
184 musb->is_active = 1;
Heikki Krogerusd445b6d2012-02-13 13:24:15 +0200185 otg->default_a = 1;
Antoine Tenarte47d9252014-10-30 18:41:13 +0100186 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
Hema HK594632e2010-12-10 18:10:51 +0530187 devctl |= MUSB_DEVCTL_SESSION;
188 MUSB_HST_MODE(musb);
189 }
Felipe Balbi550a7372008-07-24 12:27:36 +0300190 } else {
191 musb->is_active = 0;
192
193 /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and
194 * jumping right to B_IDLE...
195 */
196
Heikki Krogerusd445b6d2012-02-13 13:24:15 +0200197 otg->default_a = 0;
Antoine Tenarte47d9252014-10-30 18:41:13 +0100198 musb->xceiv->otg->state = OTG_STATE_B_IDLE;
Felipe Balbi550a7372008-07-24 12:27:36 +0300199 devctl &= ~MUSB_DEVCTL_SESSION;
200
201 MUSB_DEV_MODE(musb);
202 }
203 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
204
Felipe Balbi5c8a86e2011-05-11 12:44:08 +0300205 dev_dbg(musb->controller, "VBUS %s, devctl %02x "
Felipe Balbi550a7372008-07-24 12:27:36 +0300206 /* otg %3x conf %08x prcm %08x */ "\n",
Antoine Tenarte47d9252014-10-30 18:41:13 +0100207 usb_otg_state_string(musb->xceiv->otg->state),
Felipe Balbi550a7372008-07-24 12:27:36 +0300208 musb_readb(musb->mregs, MUSB_DEVCTL));
209}
Felipe Balbi550a7372008-07-24 12:27:36 +0300210
Felipe Balbi743411b2010-12-01 13:22:05 +0200211static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode)
Felipe Balbi550a7372008-07-24 12:27:36 +0300212{
213 u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
214
215 devctl |= MUSB_DEVCTL_SESSION;
216 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
217
David Brownell96a274d2008-11-24 13:06:47 +0200218 return 0;
Felipe Balbi550a7372008-07-24 12:27:36 +0300219}
220
Felipe Balbic20aebb2010-12-02 12:44:40 +0200221static inline void omap2430_low_level_exit(struct musb *musb)
222{
223 u32 l;
224
225 /* in any role */
226 l = musb_readl(musb->mregs, OTG_FORCESTDBY);
227 l |= ENABLEFORCE; /* enable MSTANDBY */
228 musb_writel(musb->mregs, OTG_FORCESTDBY, l);
Felipe Balbic20aebb2010-12-02 12:44:40 +0200229}
230
231static inline void omap2430_low_level_init(struct musb *musb)
232{
233 u32 l;
234
Felipe Balbic20aebb2010-12-02 12:44:40 +0200235 l = musb_readl(musb->mregs, OTG_FORCESTDBY);
236 l &= ~ENABLEFORCE; /* disable MSTANDBY */
237 musb_writel(musb->mregs, OTG_FORCESTDBY, l);
238}
239
Tony Lindgren21f77be2016-05-31 10:05:15 -0500240/*
241 * We can get multiple cable events so we need to keep track
242 * of the power state. Only keep power enabled if USB cable is
243 * connected and a gadget is started.
244 */
245static void omap2430_set_power(struct musb *musb, bool enabled, bool cable)
246{
247 struct device *dev = musb->controller;
248 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
249 bool power_up;
250 int res;
251
252 if (glue->enabled != enabled)
253 glue->enabled = enabled;
254
255 if (glue->cable_connected != cable)
256 glue->cable_connected = cable;
257
258 power_up = glue->enabled && glue->cable_connected;
259 if (power_up == glue->powered) {
260 dev_warn(musb->controller, "power state already %i\n",
261 power_up);
262 return;
263 }
264
265 glue->powered = power_up;
266
267 if (power_up) {
268 res = pm_runtime_get_sync(musb->controller);
269 if (res < 0) {
270 dev_err(musb->controller, "could not enable: %i", res);
271 glue->powered = false;
272 }
273 } else {
274 pm_runtime_mark_last_busy(musb->controller);
275 pm_runtime_put_autosuspend(musb->controller);
276 }
277}
278
Tony Lindgren80555552015-11-30 21:37:12 -0800279static void omap2430_musb_mailbox(enum musb_vbus_id_status status)
Hema HK594632e2010-12-10 18:10:51 +0530280{
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530281 struct omap2430_glue *glue = _glue;
Vikram Pandita712d8ef2011-08-12 07:38:51 -0700282
Aaro Koskinenf8c4b0e2013-03-05 13:04:23 +0200283 if (!glue) {
284 pr_err("%s: musb core is not yet initialized\n", __func__);
285 return;
286 }
287 glue->status = status;
288
289 if (!glue_to_musb(glue)) {
Aaro Koskinen80ab72e2012-12-23 01:24:51 +0200290 pr_err("%s: musb core is not yet ready\n", __func__);
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530291 return;
292 }
293
Kishon Vijay Abraham I1e5acb82012-06-22 17:40:51 +0530294 schedule_work(&glue->omap_musb_mailbox_work);
Vikram Pandita712d8ef2011-08-12 07:38:51 -0700295}
296
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530297static void omap_musb_set_mailbox(struct omap2430_glue *glue)
Vikram Pandita712d8ef2011-08-12 07:38:51 -0700298{
Kishon Vijay Abraham I1e5acb82012-06-22 17:40:51 +0530299 struct musb *musb = glue_to_musb(glue);
Hema HK594632e2010-12-10 18:10:51 +0530300 struct device *dev = musb->controller;
Jingoo Hanc1a7d672013-07-30 17:03:12 +0900301 struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
Hema HK594632e2010-12-10 18:10:51 +0530302 struct omap_musb_board_data *data = pdata->board_data;
Kishon Vijay Abraham Ic83a8542012-06-22 17:40:53 +0530303 struct usb_otg *otg = musb->xceiv->otg;
Tony Lindgren21f77be2016-05-31 10:05:15 -0500304 bool cable_connected;
305
306 cable_connected = ((glue->status == MUSB_ID_GROUND) ||
307 (glue->status == MUSB_VBUS_VALID));
308
309 if (cable_connected)
310 omap2430_set_power(musb, glue->enabled, cable_connected);
Hema HK594632e2010-12-10 18:10:51 +0530311
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530312 switch (glue->status) {
Tony Lindgren80555552015-11-30 21:37:12 -0800313 case MUSB_ID_GROUND:
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530314 dev_dbg(dev, "ID GND\n");
Hema HK594632e2010-12-10 18:10:51 +0530315
Kishon Vijay Abraham Ic83a8542012-06-22 17:40:53 +0530316 otg->default_a = true;
Antoine Tenarte47d9252014-10-30 18:41:13 +0100317 musb->xceiv->otg->state = OTG_STATE_A_IDLE;
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530318 musb->xceiv->last_event = USB_EVENT_ID;
Felipe Balbi032ec492011-11-24 15:46:26 +0200319 if (musb->gadget_driver) {
Kishon Vijay Abraham Ica784be2013-01-25 15:54:00 +0530320 omap_control_usb_set_mode(glue->control_otghs,
321 USB_MODE_HOST);
Hema HK70045c52011-02-28 15:05:29 +0530322 omap2430_musb_set_vbus(musb, 1);
Hema HK594632e2010-12-10 18:10:51 +0530323 }
324 break;
325
Tony Lindgren80555552015-11-30 21:37:12 -0800326 case MUSB_VBUS_VALID:
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530327 dev_dbg(dev, "VBUS Connect\n");
Hema HK594632e2010-12-10 18:10:51 +0530328
Kishon Vijay Abraham Ic83a8542012-06-22 17:40:53 +0530329 otg->default_a = false;
Antoine Tenarte47d9252014-10-30 18:41:13 +0100330 musb->xceiv->otg->state = OTG_STATE_B_IDLE;
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530331 musb->xceiv->last_event = USB_EVENT_VBUS;
Kishon Vijay Abraham Ica784be2013-01-25 15:54:00 +0530332 omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
Hema HK594632e2010-12-10 18:10:51 +0530333 break;
334
Tony Lindgren80555552015-11-30 21:37:12 -0800335 case MUSB_ID_FLOAT:
336 case MUSB_VBUS_OFF:
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530337 dev_dbg(dev, "VBUS Disconnect\n");
Hema HK594632e2010-12-10 18:10:51 +0530338
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530339 musb->xceiv->last_event = USB_EVENT_NONE;
Tony Lindgren21f77be2016-05-31 10:05:15 -0500340 if (musb->gadget_driver)
Grazvydas Ignotas2c1fe892013-03-24 17:36:54 +0200341 omap2430_musb_set_vbus(musb, 0);
Hema HK7acc6192011-02-28 14:19:34 +0530342
Kishon Vijay Abraham Ibb467cf2013-03-14 11:53:56 +0530343 if (data->interface_type == MUSB_INTERFACE_UTMI)
344 otg_set_vbus(musb->xceiv->otg, 0);
345
Kishon Vijay Abraham Ica784be2013-01-25 15:54:00 +0530346 omap_control_usb_set_mode(glue->control_otghs,
347 USB_MODE_DISCONNECT);
Hema HK594632e2010-12-10 18:10:51 +0530348 break;
349 default:
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530350 dev_dbg(dev, "ID float\n");
Hema HK594632e2010-12-10 18:10:51 +0530351 }
Pali Rohár6fa71782013-09-18 19:03:34 +0200352
Tony Lindgren21f77be2016-05-31 10:05:15 -0500353 if (!cable_connected)
354 omap2430_set_power(musb, glue->enabled, cable_connected);
355
Pali Rohár6fa71782013-09-18 19:03:34 +0200356 atomic_notifier_call_chain(&musb->xceiv->notifier,
357 musb->xceiv->last_event, NULL);
Hema HK594632e2010-12-10 18:10:51 +0530358}
359
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530360
361static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
362{
363 struct omap2430_glue *glue = container_of(mailbox_work,
364 struct omap2430_glue, omap_musb_mailbox_work);
Felipe Balbi8b2bc2c2014-04-07 10:58:01 -0500365 struct musb *musb = glue_to_musb(glue);
366 struct device *dev = musb->controller;
367
368 pm_runtime_get_sync(dev);
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530369 omap_musb_set_mailbox(glue);
Felipe Balbi8b2bc2c2014-04-07 10:58:01 -0500370 pm_runtime_mark_last_busy(dev);
371 pm_runtime_put_autosuspend(dev);
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530372}
373
Philippe De Swertbaef6532012-11-06 15:32:13 +0200374static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
375{
376 unsigned long flags;
377 irqreturn_t retval = IRQ_NONE;
378 struct musb *musb = __hci;
379
380 spin_lock_irqsave(&musb->lock, flags);
381
382 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
383 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
384 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
385
386 if (musb->int_usb || musb->int_tx || musb->int_rx)
387 retval = musb_interrupt(musb);
388
389 spin_unlock_irqrestore(&musb->lock, flags);
390
391 return retval;
392}
393
Felipe Balbi743411b2010-12-01 13:22:05 +0200394static int omap2430_musb_init(struct musb *musb)
Felipe Balbi550a7372008-07-24 12:27:36 +0300395{
Shubhrajyoti Dad579692012-03-22 12:48:06 +0530396 u32 l;
397 int status = 0;
Hema Kalliguddiea65df52010-09-22 19:27:40 -0500398 struct device *dev = musb->controller;
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530399 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
Jingoo Hanc1a7d672013-07-30 17:03:12 +0900400 struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
Hema Kalliguddiea65df52010-09-22 19:27:40 -0500401 struct omap_musb_board_data *data = plat->board_data;
Felipe Balbi550a7372008-07-24 12:27:36 +0300402
David Brownell84e250f2009-03-31 12:30:04 -0700403 /* We require some kind of external transceiver, hooked
404 * up through ULPI. TWL4030-family PMICs include one,
405 * which needs a driver, drivers aren't always needed.
406 */
Kishon Vijay Abraham I3e3101d2013-09-27 11:53:30 +0530407 if (dev->parent->of_node) {
408 musb->phy = devm_phy_get(dev->parent, "usb2-phy");
409
410 /* We can't totally remove musb->xceiv as of now because
411 * musb core uses xceiv.state and xceiv.otg. Once we have
412 * a separate state machine to handle otg, these can be moved
413 * out of xceiv and then we can start using the generic PHY
414 * framework
415 */
Kishon Vijay Abraham Ib16604f2013-01-25 08:03:26 +0530416 musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
417 "usb-phy", 0);
Kishon Vijay Abraham I3e3101d2013-09-27 11:53:30 +0530418 } else {
Kishon Vijay Abraham Ib16604f2013-01-25 08:03:26 +0530419 musb->xceiv = devm_usb_get_phy_dev(dev, 0);
Kishon Vijay Abraham I3e3101d2013-09-27 11:53:30 +0530420 musb->phy = devm_phy_get(dev, "usb");
421 }
Kishon Vijay Abraham Ib16604f2013-01-25 08:03:26 +0530422
Felipe Balbia90199b2013-03-15 10:57:40 +0200423 if (IS_ERR(musb->xceiv)) {
424 status = PTR_ERR(musb->xceiv);
425
426 if (status == -ENXIO)
427 return status;
428
David Brownell84e250f2009-03-31 12:30:04 -0700429 pr_err("HS USB OTG: no transceiver configured\n");
Ming Lei25736e02013-01-04 23:13:58 +0800430 return -EPROBE_DEFER;
David Brownell84e250f2009-03-31 12:30:04 -0700431 }
432
Kishon Vijay Abraham I3e3101d2013-09-27 11:53:30 +0530433 if (IS_ERR(musb->phy)) {
434 pr_err("HS USB OTG: no PHY configured\n");
435 return PTR_ERR(musb->phy);
436 }
Philippe De Swertbaef6532012-11-06 15:32:13 +0200437 musb->isr = omap2430_musb_interrupt;
Tony Lindgrena83e17d2016-05-31 10:05:16 -0500438 phy_init(musb->phy);
Philippe De Swertbaef6532012-11-06 15:32:13 +0200439
Tony Lindgren8f2279d2015-10-28 10:16:04 -0700440 /*
441 * Enable runtime PM for musb parent (this driver). We can't
442 * do it earlier as struct musb is not yet allocated and we
443 * need to touch the musb registers for runtime PM.
444 */
445 pm_runtime_enable(glue->dev);
446 status = pm_runtime_get_sync(glue->dev);
447 if (status < 0)
448 goto err1;
449
Felipe Balbi8573e6a2010-01-21 15:33:53 +0200450 l = musb_readl(musb->mregs, OTG_INTERFSEL);
Maulik Mankadde2e1b02010-03-12 10:29:07 +0200451
452 if (data->interface_type == MUSB_INTERFACE_UTMI) {
453 /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
454 l &= ~ULPI_12PIN; /* Disable ULPI */
455 l |= UTMI_8BIT; /* Enable UTMI */
456 } else {
457 l |= ULPI_12PIN;
458 }
459
Felipe Balbi8573e6a2010-01-21 15:33:53 +0200460 musb_writel(musb->mregs, OTG_INTERFSEL, l);
Felipe Balbi550a7372008-07-24 12:27:36 +0300461
462 pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
463 "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n",
Felipe Balbi8573e6a2010-01-21 15:33:53 +0200464 musb_readl(musb->mregs, OTG_REVISION),
465 musb_readl(musb->mregs, OTG_SYSCONFIG),
466 musb_readl(musb->mregs, OTG_SYSSTATUS),
467 musb_readl(musb->mregs, OTG_INTERFSEL),
468 musb_readl(musb->mregs, OTG_SIMENABLE));
Felipe Balbi550a7372008-07-24 12:27:36 +0300469
Felipe Balbi550a7372008-07-24 12:27:36 +0300470 setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
471
Tony Lindgren80555552015-11-30 21:37:12 -0800472 if (glue->status != MUSB_UNKNOWN)
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530473 omap_musb_set_mailbox(glue);
474
Tony Lindgren7099dbc2016-05-31 10:05:11 -0500475 pm_runtime_put(glue->dev);
Felipe Balbi550a7372008-07-24 12:27:36 +0300476 return 0;
Hema HK7acc6192011-02-28 14:19:34 +0530477
478err1:
Hema HK7acc6192011-02-28 14:19:34 +0530479 return status;
Felipe Balbi550a7372008-07-24 12:27:36 +0300480}
481
Hema HK002eda12011-02-17 12:06:10 +0530482static void omap2430_musb_enable(struct musb *musb)
483{
484 u8 devctl;
485 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
486 struct device *dev = musb->controller;
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530487 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
Jingoo Hanc1a7d672013-07-30 17:03:12 +0900488 struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
Hema HK002eda12011-02-17 12:06:10 +0530489 struct omap_musb_board_data *data = pdata->board_data;
490
Tony Lindgrena83e17d2016-05-31 10:05:16 -0500491 if (!WARN_ON(!musb->phy))
492 phy_power_on(musb->phy);
493
Tony Lindgren21f77be2016-05-31 10:05:15 -0500494 omap2430_set_power(musb, true, glue->cable_connected);
495
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530496 switch (glue->status) {
Hema HK002eda12011-02-17 12:06:10 +0530497
Tony Lindgren80555552015-11-30 21:37:12 -0800498 case MUSB_ID_GROUND:
Kishon Vijay Abraham Ica784be2013-01-25 15:54:00 +0530499 omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST);
Felipe Contreras08dec562011-12-19 22:17:50 +0200500 if (data->interface_type != MUSB_INTERFACE_UTMI)
501 break;
502 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
503 /* start the session */
504 devctl |= MUSB_DEVCTL_SESSION;
505 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
506 while (musb_readb(musb->mregs, MUSB_DEVCTL) &
507 MUSB_DEVCTL_BDEVICE) {
508 cpu_relax();
Hema HK002eda12011-02-17 12:06:10 +0530509
Felipe Contreras08dec562011-12-19 22:17:50 +0200510 if (time_after(jiffies, timeout)) {
511 dev_err(dev, "configured as A device timeout");
512 break;
Hema HK002eda12011-02-17 12:06:10 +0530513 }
514 }
515 break;
516
Tony Lindgren80555552015-11-30 21:37:12 -0800517 case MUSB_VBUS_VALID:
Kishon Vijay Abraham Ica784be2013-01-25 15:54:00 +0530518 omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
Hema HK002eda12011-02-17 12:06:10 +0530519 break;
520
521 default:
522 break;
523 }
524}
525
526static void omap2430_musb_disable(struct musb *musb)
527{
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530528 struct device *dev = musb->controller;
529 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
530
Tony Lindgrena83e17d2016-05-31 10:05:16 -0500531 if (!WARN_ON(!musb->phy))
532 phy_power_off(musb->phy);
533
Tony Lindgren80555552015-11-30 21:37:12 -0800534 if (glue->status != MUSB_UNKNOWN)
Kishon Vijay Abraham Ica784be2013-01-25 15:54:00 +0530535 omap_control_usb_set_mode(glue->control_otghs,
536 USB_MODE_DISCONNECT);
Tony Lindgren21f77be2016-05-31 10:05:15 -0500537
538 omap2430_set_power(musb, false, glue->cable_connected);
Felipe Balbi550a7372008-07-24 12:27:36 +0300539}
540
Felipe Balbi743411b2010-12-01 13:22:05 +0200541static int omap2430_musb_exit(struct musb *musb)
Felipe Balbi550a7372008-07-24 12:27:36 +0300542{
Tony Lindgrena83e17d2016-05-31 10:05:16 -0500543 struct device *dev = musb->controller;
544 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
Felipe Balbi550a7372008-07-24 12:27:36 +0300545
Tony Lindgrena83e17d2016-05-31 10:05:16 -0500546 del_timer_sync(&musb_idle_timer);
Felipe Balbic20aebb2010-12-02 12:44:40 +0200547 omap2430_low_level_exit(musb);
Kishon Vijay Abraham I3e3101d2013-09-27 11:53:30 +0530548 phy_exit(musb->phy);
Tony Lindgrena83e17d2016-05-31 10:05:16 -0500549 musb->phy = NULL;
550 cancel_work_sync(&glue->omap_musb_mailbox_work);
Felipe Balbic20aebb2010-12-02 12:44:40 +0200551
Felipe Balbi550a7372008-07-24 12:27:36 +0300552 return 0;
553}
Felipe Balbi743411b2010-12-01 13:22:05 +0200554
Felipe Balbif7ec9432010-12-02 09:48:58 +0200555static const struct musb_platform_ops omap2430_ops = {
Tony Lindgrenf8e9f34f2015-05-01 12:29:27 -0700556 .quirks = MUSB_DMA_INVENTRA,
Tony Lindgren7f6283e2015-05-01 12:29:28 -0700557#ifdef CONFIG_USB_INVENTRA_DMA
558 .dma_init = musbhs_dma_controller_create,
559 .dma_exit = musbhs_dma_controller_destroy,
560#endif
Felipe Balbi743411b2010-12-01 13:22:05 +0200561 .init = omap2430_musb_init,
562 .exit = omap2430_musb_exit,
563
Felipe Balbi743411b2010-12-01 13:22:05 +0200564 .set_mode = omap2430_musb_set_mode,
565 .try_idle = omap2430_musb_try_idle,
566
567 .set_vbus = omap2430_musb_set_vbus,
Hema HK002eda12011-02-17 12:06:10 +0530568
569 .enable = omap2430_musb_enable,
570 .disable = omap2430_musb_disable,
Tony Lindgren80555552015-11-30 21:37:12 -0800571
572 .phy_callback = omap2430_musb_mailbox,
Felipe Balbi743411b2010-12-01 13:22:05 +0200573};
Felipe Balbidc098862010-12-01 15:01:11 +0200574
575static u64 omap2430_dmamask = DMA_BIT_MASK(32);
576
Bill Pemberton41ac7b32012-11-19 13:21:48 -0500577static int omap2430_probe(struct platform_device *pdev)
Felipe Balbidc098862010-12-01 15:01:11 +0200578{
Kishon Vijay Abraham Ic1f01be2013-07-17 10:51:22 +0300579 struct resource musb_resources[3];
Jingoo Hanc1a7d672013-07-30 17:03:12 +0900580 struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530581 struct omap_musb_board_data *data;
Felipe Balbidc098862010-12-01 15:01:11 +0200582 struct platform_device *musb;
Felipe Balbia3cee122010-12-02 09:27:29 +0200583 struct omap2430_glue *glue;
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530584 struct device_node *np = pdev->dev.of_node;
585 struct musb_hdrc_config *config;
Tony Lindgren606bf4d2015-02-04 06:28:49 -0800586 int ret = -ENOMEM, val;
Felipe Balbidc098862010-12-01 15:01:11 +0200587
Kishon Vijay Abraham Ib1183c22012-06-22 17:40:54 +0530588 glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
Peter Chenaf1bdfc2014-10-14 15:56:08 +0800589 if (!glue)
Felipe Balbia3cee122010-12-02 09:27:29 +0200590 goto err0;
Felipe Balbia3cee122010-12-02 09:27:29 +0200591
Sebastian Andrzej Siewior2f771162012-10-31 16:12:43 +0100592 musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
593 if (!musb) {
594 dev_err(&pdev->dev, "failed to allocate musb device\n");
Kishon Vijay Abraham Ib1183c22012-06-22 17:40:54 +0530595 goto err0;
Felipe Balbidc098862010-12-01 15:01:11 +0200596 }
597
598 musb->dev.parent = &pdev->dev;
599 musb->dev.dma_mask = &omap2430_dmamask;
600 musb->dev.coherent_dma_mask = omap2430_dmamask;
601
Felipe Balbia3cee122010-12-02 09:27:29 +0200602 glue->dev = &pdev->dev;
603 glue->musb = musb;
Tony Lindgren80555552015-11-30 21:37:12 -0800604 glue->status = MUSB_UNKNOWN;
Roger Quadros8934d3e2013-10-03 18:12:34 +0300605 glue->control_otghs = ERR_PTR(-ENODEV);
Felipe Balbia3cee122010-12-02 09:27:29 +0200606
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530607 if (np) {
Roger Quadros8934d3e2013-10-03 18:12:34 +0300608 struct device_node *control_node;
609 struct platform_device *control_pdev;
610
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530611 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
Peter Chenaf1bdfc2014-10-14 15:56:08 +0800612 if (!pdata)
Sebastian Andrzej Siewior2f771162012-10-31 16:12:43 +0100613 goto err2;
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530614
615 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
Peter Chenaf1bdfc2014-10-14 15:56:08 +0800616 if (!data)
Sebastian Andrzej Siewior2f771162012-10-31 16:12:43 +0100617 goto err2;
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530618
619 config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
Peter Chenaf1bdfc2014-10-14 15:56:08 +0800620 if (!config)
Sebastian Andrzej Siewior2f771162012-10-31 16:12:43 +0100621 goto err2;
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530622
623 of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
Kishon Vijay Abraham Ieee44da2013-03-07 18:51:46 +0530624 of_property_read_u32(np, "interface-type",
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530625 (u32 *)&data->interface_type);
Kishon Vijay Abraham Ieee44da2013-03-07 18:51:46 +0530626 of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
627 of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530628 of_property_read_u32(np, "power", (u32 *)&pdata->power);
Tony Lindgren606bf4d2015-02-04 06:28:49 -0800629
630 ret = of_property_read_u32(np, "multipoint", &val);
631 if (!ret && val)
632 config->multipoint = true;
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530633
634 pdata->board_data = data;
635 pdata->config = config;
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530636
Roger Quadros8934d3e2013-10-03 18:12:34 +0300637 control_node = of_parse_phandle(np, "ctrl-module", 0);
638 if (control_node) {
639 control_pdev = of_find_device_by_node(control_node);
640 if (!control_pdev) {
641 dev_err(&pdev->dev, "Failed to get control device\n");
642 ret = -EINVAL;
643 goto err2;
644 }
645 glue->control_otghs = &control_pdev->dev;
Kishon Vijay Abraham Ica784be2013-01-25 15:54:00 +0530646 }
Kishon Vijay Abraham Ica784be2013-01-25 15:54:00 +0530647 }
Felipe Balbif7ec9432010-12-02 09:48:58 +0200648 pdata->platform_ops = &omap2430_ops;
649
Felipe Balbia3cee122010-12-02 09:27:29 +0200650 platform_set_drvdata(pdev, glue);
Felipe Balbidc098862010-12-01 15:01:11 +0200651
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530652 /*
653 * REVISIT if we ever have two instances of the wrapper, we will be
654 * in big trouble
655 */
656 _glue = glue;
657
Kishon Vijay Abraham I1e5acb82012-06-22 17:40:51 +0530658 INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
659
Sebastian Andrzej Siewior3a0ddc72013-06-25 09:41:02 +0200660 memset(musb_resources, 0x00, sizeof(*musb_resources) *
Felipe Balbi09fc7d22013-04-24 17:21:42 +0300661 ARRAY_SIZE(musb_resources));
662
663 musb_resources[0].name = pdev->resource[0].name;
664 musb_resources[0].start = pdev->resource[0].start;
665 musb_resources[0].end = pdev->resource[0].end;
666 musb_resources[0].flags = pdev->resource[0].flags;
667
668 musb_resources[1].name = pdev->resource[1].name;
669 musb_resources[1].start = pdev->resource[1].start;
670 musb_resources[1].end = pdev->resource[1].end;
671 musb_resources[1].flags = pdev->resource[1].flags;
672
Kishon Vijay Abraham Ic1f01be2013-07-17 10:51:22 +0300673 musb_resources[2].name = pdev->resource[2].name;
674 musb_resources[2].start = pdev->resource[2].start;
675 musb_resources[2].end = pdev->resource[2].end;
676 musb_resources[2].flags = pdev->resource[2].flags;
677
Felipe Balbi09fc7d22013-04-24 17:21:42 +0300678 ret = platform_device_add_resources(musb, musb_resources,
679 ARRAY_SIZE(musb_resources));
Felipe Balbidc098862010-12-01 15:01:11 +0200680 if (ret) {
681 dev_err(&pdev->dev, "failed to add resources\n");
B, Ravi65b3d522012-08-31 11:09:49 +0000682 goto err2;
Felipe Balbidc098862010-12-01 15:01:11 +0200683 }
684
685 ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
686 if (ret) {
687 dev_err(&pdev->dev, "failed to add platform_data\n");
B, Ravi65b3d522012-08-31 11:09:49 +0000688 goto err2;
Felipe Balbidc098862010-12-01 15:01:11 +0200689 }
690
Tony Lindgren8f2279d2015-10-28 10:16:04 -0700691 /*
692 * Note that we cannot enable PM runtime yet for this
693 * driver as we need struct musb initialized first.
694 * See omap2430_musb_init above.
695 */
Kishon Vijay Abraham I3006dc82012-03-21 21:30:20 +0530696
Felipe Balbidc098862010-12-01 15:01:11 +0200697 ret = platform_device_add(musb);
698 if (ret) {
699 dev_err(&pdev->dev, "failed to register musb device\n");
B, Ravi65b3d522012-08-31 11:09:49 +0000700 goto err2;
Felipe Balbidc098862010-12-01 15:01:11 +0200701 }
702
703 return 0;
704
B, Ravi65b3d522012-08-31 11:09:49 +0000705err2:
Kishon Vijay Abraham Ib1183c22012-06-22 17:40:54 +0530706 platform_device_put(musb);
Felipe Balbia3cee122010-12-02 09:27:29 +0200707
Felipe Balbidc098862010-12-01 15:01:11 +0200708err0:
709 return ret;
710}
711
Bill Pembertonfb4e98a2012-11-19 13:26:20 -0500712static int omap2430_remove(struct platform_device *pdev)
Felipe Balbidc098862010-12-01 15:01:11 +0200713{
Tony Lindgren21f77be2016-05-31 10:05:15 -0500714 struct omap2430_glue *glue = platform_get_drvdata(pdev);
715 struct musb *musb = glue_to_musb(glue);
Felipe Balbidc098862010-12-01 15:01:11 +0200716
Tony Lindgren03e43522015-11-30 21:37:13 -0800717 pm_runtime_get_sync(glue->dev);
Kishon Vijay Abraham If039df52012-08-02 15:30:07 +0530718 platform_device_unregister(glue->musb);
Tony Lindgren21f77be2016-05-31 10:05:15 -0500719 omap2430_set_power(musb, false, false);
Tony Lindgren03e43522015-11-30 21:37:13 -0800720 pm_runtime_put_sync(glue->dev);
721 pm_runtime_disable(glue->dev);
Felipe Balbidc098862010-12-01 15:01:11 +0200722
723 return 0;
724}
725
Felipe Balbic20aebb2010-12-02 12:44:40 +0200726#ifdef CONFIG_PM
Felipe Balbic20aebb2010-12-02 12:44:40 +0200727
Hema HK7acc6192011-02-28 14:19:34 +0530728static int omap2430_runtime_suspend(struct device *dev)
Felipe Balbic20aebb2010-12-02 12:44:40 +0200729{
730 struct omap2430_glue *glue = dev_get_drvdata(dev);
731 struct musb *musb = glue_to_musb(glue);
732
Tony Lindgrena83e17d2016-05-31 10:05:16 -0500733 if (!musb)
734 return 0;
Hema HKe25bec12011-09-07 09:19:24 -0700735
Tony Lindgrena83e17d2016-05-31 10:05:16 -0500736 musb->context.otg_interfsel = musb_readl(musb->mregs,
737 OTG_INTERFSEL);
738
739 omap2430_low_level_exit(musb);
Felipe Balbic20aebb2010-12-02 12:44:40 +0200740
741 return 0;
742}
743
Hema HK7acc6192011-02-28 14:19:34 +0530744static int omap2430_runtime_resume(struct device *dev)
Felipe Balbic20aebb2010-12-02 12:44:40 +0200745{
746 struct omap2430_glue *glue = dev_get_drvdata(dev);
747 struct musb *musb = glue_to_musb(glue);
Felipe Balbic20aebb2010-12-02 12:44:40 +0200748
Tony Lindgren8f2279d2015-10-28 10:16:04 -0700749 if (!musb)
Tony Lindgrena83e17d2016-05-31 10:05:16 -0500750 return 0;
Tony Lindgren8f2279d2015-10-28 10:16:04 -0700751
752 omap2430_low_level_init(musb);
753 musb_writel(musb->mregs, OTG_INTERFSEL,
754 musb->context.otg_interfsel);
Felipe Balbic20aebb2010-12-02 12:44:40 +0200755
756 return 0;
757}
758
759static struct dev_pm_ops omap2430_pm_ops = {
Hema HK7acc6192011-02-28 14:19:34 +0530760 .runtime_suspend = omap2430_runtime_suspend,
761 .runtime_resume = omap2430_runtime_resume,
Felipe Balbic20aebb2010-12-02 12:44:40 +0200762};
763
764#define DEV_PM_OPS (&omap2430_pm_ops)
765#else
766#define DEV_PM_OPS NULL
767#endif
768
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530769#ifdef CONFIG_OF
770static const struct of_device_id omap2430_id_table[] = {
771 {
772 .compatible = "ti,omap4-musb"
773 },
774 {
775 .compatible = "ti,omap3-musb"
776 },
777 {},
778};
779MODULE_DEVICE_TABLE(of, omap2430_id_table);
780#endif
781
Felipe Balbidc098862010-12-01 15:01:11 +0200782static struct platform_driver omap2430_driver = {
Felipe Balbie9e8c852012-01-26 12:40:23 +0200783 .probe = omap2430_probe,
Bill Pemberton76904172012-11-19 13:21:08 -0500784 .remove = omap2430_remove,
Felipe Balbidc098862010-12-01 15:01:11 +0200785 .driver = {
786 .name = "musb-omap2430",
Felipe Balbic20aebb2010-12-02 12:44:40 +0200787 .pm = DEV_PM_OPS,
Kishon Vijay Abraham I00a0b1d2012-09-11 14:39:40 +0530788 .of_match_table = of_match_ptr(omap2430_id_table),
Felipe Balbidc098862010-12-01 15:01:11 +0200789 },
790};
791
792MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
793MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
794MODULE_LICENSE("GPL v2");
795
796static int __init omap2430_init(void)
797{
Felipe Balbie9e8c852012-01-26 12:40:23 +0200798 return platform_driver_register(&omap2430_driver);
Felipe Balbidc098862010-12-01 15:01:11 +0200799}
Kishon Vijay Abraham Ic9721432012-06-22 17:40:52 +0530800subsys_initcall(omap2430_init);
Felipe Balbidc098862010-12-01 15:01:11 +0200801
802static void __exit omap2430_exit(void)
803{
804 platform_driver_unregister(&omap2430_driver);
805}
806module_exit(omap2430_exit);