omap2430.c 17.8 KB
Newer Older
F
Felipe Balbi 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * Copyright (C) 2005-2007 by Texas Instruments
 * Some code has been taken from tusb6010.c
 * Copyrights for that are attributable to:
 * Copyright (C) 2006 Nokia Corporation
 * Tony Lindgren <tony@atomide.com>
 *
 * This file is part of the Inventra Controller Driver for Linux.
 *
 * The Inventra Controller Driver for Linux is free software; you
 * can redistribute it and/or modify it under the terms of the GNU
 * General Public License version 2 as published by the Free Software
 * Foundation.
 *
 * The Inventra Controller Driver for Linux is distributed in
 * the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 * License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with The Inventra Controller Driver for Linux ; if not,
 * write to the Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/io.h>
33
#include <linux/of.h>
34 35
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
36 37
#include <linux/pm_runtime.h>
#include <linux/err.h>
38
#include <linux/delay.h>
39
#include <linux/usb/musb.h>
40
#include <linux/phy/omap_control_phy.h>
41
#include <linux/of_platform.h>
F
Felipe Balbi 已提交
42 43 44 45

#include "musb_core.h"
#include "omap2430.h"

46 47 48
struct omap2430_glue {
	struct device		*dev;
	struct platform_device	*musb;
49
	enum musb_vbus_id_status status;
50
	struct work_struct	omap_musb_mailbox_work;
51
	struct device		*control_otghs;
52 53 54
	bool			cable_connected;
	bool			enabled;
	bool			powered;
55
};
56
#define glue_to_musb(g)		platform_get_drvdata(g->musb)
57

58
static struct omap2430_glue	*_glue;
59

60
static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
F
Felipe Balbi 已提交
61
{
62
	struct usb_otg	*otg = musb->xceiv->otg;
F
Felipe Balbi 已提交
63
	u8		devctl;
64
	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
F
Felipe Balbi 已提交
65 66 67 68 69 70 71 72
	/* HDRC controls CPEN, but beware current surges during device
	 * connect.  They can trigger transient overcurrent conditions
	 * that must be ignored.
	 */

	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);

	if (is_on) {
73
		if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) {
74
			int loops = 100;
75 76 77 78 79 80 81
			/* start the session */
			devctl |= MUSB_DEVCTL_SESSION;
			musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
			/*
			 * Wait for the musb to set as A device to enable the
			 * VBUS
			 */
82 83
			while (musb_readb(musb->mregs, MUSB_DEVCTL) &
			       MUSB_DEVCTL_BDEVICE) {
84

85
				mdelay(5);
86 87
				cpu_relax();

88 89
				if (time_after(jiffies, timeout)
				    || loops-- <= 0) {
90 91 92 93 94 95
					dev_err(musb->controller,
					"configured as A device timeout");
					break;
				}
			}

96
			otg_set_vbus(otg, 1);
97 98
		} else {
			musb->is_active = 1;
99
			otg->default_a = 1;
100
			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
101 102 103
			devctl |= MUSB_DEVCTL_SESSION;
			MUSB_HST_MODE(musb);
		}
F
Felipe Balbi 已提交
104 105 106 107 108 109 110
	} else {
		musb->is_active = 0;

		/* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
		 * jumping right to B_IDLE...
		 */

111
		otg->default_a = 0;
112
		musb->xceiv->otg->state = OTG_STATE_B_IDLE;
F
Felipe Balbi 已提交
113 114 115 116 117 118
		devctl &= ~MUSB_DEVCTL_SESSION;

		MUSB_DEV_MODE(musb);
	}
	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);

119
	dev_dbg(musb->controller, "VBUS %s, devctl %02x "
F
Felipe Balbi 已提交
120
		/* otg %3x conf %08x prcm %08x */ "\n",
121
		usb_otg_state_string(musb->xceiv->otg->state),
F
Felipe Balbi 已提交
122 123 124
		musb_readb(musb->mregs, MUSB_DEVCTL));
}

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
static inline void omap2430_low_level_exit(struct musb *musb)
{
	u32 l;

	/* in any role */
	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l |= ENABLEFORCE;	/* enable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}

static inline void omap2430_low_level_init(struct musb *musb)
{
	u32 l;

	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
/*
 * We can get multiple cable events so we need to keep track
 * of the power state. Only keep power enabled if USB cable is
 * connected and a gadget is started.
 */
static void omap2430_set_power(struct musb *musb, bool enabled, bool cable)
{
	struct device *dev = musb->controller;
	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
	bool power_up;
	int res;

	if (glue->enabled != enabled)
		glue->enabled = enabled;

	if (glue->cable_connected != cable)
		glue->cable_connected = cable;

	power_up = glue->enabled && glue->cable_connected;
	if (power_up == glue->powered) {
		dev_warn(musb->controller, "power state already %i\n",
			 power_up);
		return;
	}

	glue->powered = power_up;

	if (power_up) {
		res = pm_runtime_get_sync(musb->controller);
		if (res < 0) {
			dev_err(musb->controller, "could not enable: %i", res);
			glue->powered = false;
		}
	} else {
		pm_runtime_mark_last_busy(musb->controller);
		pm_runtime_put_autosuspend(musb->controller);
	}
}

183
static int omap2430_musb_mailbox(enum musb_vbus_id_status status)
184
{
185
	struct omap2430_glue	*glue = _glue;
186

187 188
	if (!glue) {
		pr_err("%s: musb core is not yet initialized\n", __func__);
189
		return -EPROBE_DEFER;
190 191 192 193
	}
	glue->status = status;

	if (!glue_to_musb(glue)) {
194
		pr_err("%s: musb core is not yet ready\n", __func__);
195
		return -EPROBE_DEFER;
196
	}
197

198
	schedule_work(&glue->omap_musb_mailbox_work);
199 200

	return 0;
201 202
}

203
static void omap_musb_set_mailbox(struct omap2430_glue *glue)
204
{
205
	struct musb *musb = glue_to_musb(glue);
206
	struct device *dev = musb->controller;
J
Jingoo Han 已提交
207
	struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
208
	struct omap_musb_board_data *data = pdata->board_data;
209
	struct usb_otg *otg = musb->xceiv->otg;
210 211 212 213 214 215 216
	bool cable_connected;

	cable_connected = ((glue->status == MUSB_ID_GROUND) ||
			   (glue->status == MUSB_VBUS_VALID));

	if (cable_connected)
		omap2430_set_power(musb, glue->enabled, cable_connected);
217

218
	switch (glue->status) {
219
	case MUSB_ID_GROUND:
220
		dev_dbg(dev, "ID GND\n");
221

222
		otg->default_a = true;
223
		musb->xceiv->otg->state = OTG_STATE_A_IDLE;
224
		musb->xceiv->last_event = USB_EVENT_ID;
225
		if (musb->gadget_driver) {
226 227
			omap_control_usb_set_mode(glue->control_otghs,
				USB_MODE_HOST);
228
			omap2430_musb_set_vbus(musb, 1);
229 230 231
		}
		break;

232
	case MUSB_VBUS_VALID:
233
		dev_dbg(dev, "VBUS Connect\n");
234

235
		otg->default_a = false;
236
		musb->xceiv->otg->state = OTG_STATE_B_IDLE;
237
		musb->xceiv->last_event = USB_EVENT_VBUS;
238
		omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
239 240
		break;

241 242
	case MUSB_ID_FLOAT:
	case MUSB_VBUS_OFF:
243
		dev_dbg(dev, "VBUS Disconnect\n");
244

245
		musb->xceiv->last_event = USB_EVENT_NONE;
246
		if (musb->gadget_driver)
247
			omap2430_musb_set_vbus(musb, 0);
248

249 250 251
		if (data->interface_type == MUSB_INTERFACE_UTMI)
			otg_set_vbus(musb->xceiv->otg, 0);

252 253
		omap_control_usb_set_mode(glue->control_otghs,
			USB_MODE_DISCONNECT);
254 255
		break;
	default:
256
		dev_dbg(dev, "ID float\n");
257
	}
258

259 260 261
	if (!cable_connected)
		omap2430_set_power(musb, glue->enabled, cable_connected);

262 263
	atomic_notifier_call_chain(&musb->xceiv->notifier,
			musb->xceiv->last_event, NULL);
264 265
}

266 267 268 269 270

static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
{
	struct omap2430_glue *glue = container_of(mailbox_work,
				struct omap2430_glue, omap_musb_mailbox_work);
271 272 273 274
	struct musb *musb = glue_to_musb(glue);
	struct device *dev = musb->controller;

	pm_runtime_get_sync(dev);
275
	omap_musb_set_mailbox(glue);
276 277
	pm_runtime_mark_last_busy(dev);
	pm_runtime_put_autosuspend(dev);
278 279
}

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
{
	unsigned long   flags;
	irqreturn_t     retval = IRQ_NONE;
	struct musb     *musb = __hci;

	spin_lock_irqsave(&musb->lock, flags);

	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);

	if (musb->int_usb || musb->int_tx || musb->int_rx)
		retval = musb_interrupt(musb);

	spin_unlock_irqrestore(&musb->lock, flags);

	return retval;
}

300
static int omap2430_musb_init(struct musb *musb)
F
Felipe Balbi 已提交
301
{
302 303
	u32 l;
	int status = 0;
304
	struct device *dev = musb->controller;
305
	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
J
Jingoo Han 已提交
306
	struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
307
	struct omap_musb_board_data *data = plat->board_data;
F
Felipe Balbi 已提交
308

309 310 311 312
	/* We require some kind of external transceiver, hooked
	 * up through ULPI.  TWL4030-family PMICs include one,
	 * which needs a driver, drivers aren't always needed.
	 */
313 314 315 316 317 318 319 320 321
	if (dev->parent->of_node) {
		musb->phy = devm_phy_get(dev->parent, "usb2-phy");

		/* We can't totally remove musb->xceiv as of now because
		 * musb core uses xceiv.state and xceiv.otg. Once we have
		 * a separate state machine to handle otg, these can be moved
		 * out of xceiv and then we can start using the generic PHY
		 * framework
		 */
322 323
		musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
		    "usb-phy", 0);
324
	} else {
325
		musb->xceiv = devm_usb_get_phy_dev(dev, 0);
326 327
		musb->phy = devm_phy_get(dev, "usb");
	}
328

329 330 331 332 333 334
	if (IS_ERR(musb->xceiv)) {
		status = PTR_ERR(musb->xceiv);

		if (status == -ENXIO)
			return status;

335
		pr_err("HS USB OTG: no transceiver configured\n");
336
		return -EPROBE_DEFER;
337 338
	}

339 340 341 342
	if (IS_ERR(musb->phy)) {
		pr_err("HS USB OTG: no PHY configured\n");
		return PTR_ERR(musb->phy);
	}
343
	musb->isr = omap2430_musb_interrupt;
344
	phy_init(musb->phy);
345

346 347 348 349 350 351 352 353 354 355
	/*
	 * Enable runtime PM for musb parent (this driver). We can't
	 * do it earlier as struct musb is not yet allocated and we
	 * need to touch the musb registers for runtime PM.
	 */
	pm_runtime_enable(glue->dev);
	status = pm_runtime_get_sync(glue->dev);
	if (status < 0)
		goto err1;

356
	l = musb_readl(musb->mregs, OTG_INTERFSEL);
357 358 359 360 361 362 363 364 365

	if (data->interface_type == MUSB_INTERFACE_UTMI) {
		/* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
		l &= ~ULPI_12PIN;       /* Disable ULPI */
		l |= UTMI_8BIT;         /* Enable UTMI  */
	} else {
		l |= ULPI_12PIN;
	}

366
	musb_writel(musb->mregs, OTG_INTERFSEL, l);
F
Felipe Balbi 已提交
367 368 369

	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
			"sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
370 371 372 373 374
			musb_readl(musb->mregs, OTG_REVISION),
			musb_readl(musb->mregs, OTG_SYSCONFIG),
			musb_readl(musb->mregs, OTG_SYSSTATUS),
			musb_readl(musb->mregs, OTG_INTERFSEL),
			musb_readl(musb->mregs, OTG_SIMENABLE));
F
Felipe Balbi 已提交
375

376
	if (glue->status != MUSB_UNKNOWN)
377 378
		omap_musb_set_mailbox(glue);

379
	pm_runtime_put(glue->dev);
F
Felipe Balbi 已提交
380
	return 0;
381 382 383

err1:
	return status;
F
Felipe Balbi 已提交
384 385
}

386 387 388 389 390
static void omap2430_musb_enable(struct musb *musb)
{
	u8		devctl;
	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
	struct device *dev = musb->controller;
391
	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
J
Jingoo Han 已提交
392
	struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
393 394
	struct omap_musb_board_data *data = pdata->board_data;

395 396 397
	if (!WARN_ON(!musb->phy))
		phy_power_on(musb->phy);

398 399
	omap2430_set_power(musb, true, glue->cable_connected);

400
	switch (glue->status) {
401

402
	case MUSB_ID_GROUND:
403
		omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST);
404 405 406 407 408 409 410 411 412 413 414 415 416
		if (data->interface_type != MUSB_INTERFACE_UTMI)
			break;
		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
		/* start the session */
		devctl |= MUSB_DEVCTL_SESSION;
		musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
		while (musb_readb(musb->mregs, MUSB_DEVCTL) &
				MUSB_DEVCTL_BDEVICE) {
			cpu_relax();

			if (time_after(jiffies, timeout)) {
				dev_err(dev, "configured as A device timeout");
				break;
417 418 419 420
			}
		}
		break;

421
	case MUSB_VBUS_VALID:
422
		omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
423 424 425 426 427 428 429 430 431
		break;

	default:
		break;
	}
}

static void omap2430_musb_disable(struct musb *musb)
{
432 433 434
	struct device *dev = musb->controller;
	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);

435 436 437
	if (!WARN_ON(!musb->phy))
		phy_power_off(musb->phy);

438
	if (glue->status != MUSB_UNKNOWN)
439 440
		omap_control_usb_set_mode(glue->control_otghs,
			USB_MODE_DISCONNECT);
441 442

	omap2430_set_power(musb, false, glue->cable_connected);
F
Felipe Balbi 已提交
443 444
}

445
static int omap2430_musb_exit(struct musb *musb)
F
Felipe Balbi 已提交
446
{
447 448
	struct device *dev = musb->controller;
	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
F
Felipe Balbi 已提交
449

450
	omap2430_low_level_exit(musb);
451
	phy_exit(musb->phy);
452 453
	musb->phy = NULL;
	cancel_work_sync(&glue->omap_musb_mailbox_work);
454

F
Felipe Balbi 已提交
455 456
	return 0;
}
457

458
static const struct musb_platform_ops omap2430_ops = {
459
	.quirks		= MUSB_DMA_INVENTRA,
460 461 462 463
#ifdef CONFIG_USB_INVENTRA_DMA
	.dma_init	= musbhs_dma_controller_create,
	.dma_exit	= musbhs_dma_controller_destroy,
#endif
464 465 466 467
	.init		= omap2430_musb_init,
	.exit		= omap2430_musb_exit,

	.set_vbus	= omap2430_musb_set_vbus,
468 469 470

	.enable		= omap2430_musb_enable,
	.disable	= omap2430_musb_disable,
471 472

	.phy_callback	= omap2430_musb_mailbox,
473
};
474 475 476

static u64 omap2430_dmamask = DMA_BIT_MASK(32);

B
Bill Pemberton 已提交
477
static int omap2430_probe(struct platform_device *pdev)
478
{
479
	struct resource			musb_resources[3];
J
Jingoo Han 已提交
480
	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
481
	struct omap_musb_board_data	*data;
482
	struct platform_device		*musb;
483
	struct omap2430_glue		*glue;
484 485
	struct device_node		*np = pdev->dev.of_node;
	struct musb_hdrc_config		*config;
486
	int				ret = -ENOMEM, val;
487

488
	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
489
	if (!glue)
490 491
		goto err0;

492
	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
493 494
	if (!musb) {
		dev_err(&pdev->dev, "failed to allocate musb device\n");
495
		goto err0;
496 497 498 499 500 501
	}

	musb->dev.parent		= &pdev->dev;
	musb->dev.dma_mask		= &omap2430_dmamask;
	musb->dev.coherent_dma_mask	= omap2430_dmamask;

502 503
	glue->dev			= &pdev->dev;
	glue->musb			= musb;
504
	glue->status			= MUSB_UNKNOWN;
505
	glue->control_otghs = ERR_PTR(-ENODEV);
506

507
	if (np) {
508 509 510
		struct device_node *control_node;
		struct platform_device *control_pdev;

511
		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
512
		if (!pdata)
513
			goto err2;
514 515

		data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
516
		if (!data)
517
			goto err2;
518 519

		config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
520
		if (!config)
521
			goto err2;
522 523

		of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
524
		of_property_read_u32(np, "interface-type",
525
						(u32 *)&data->interface_type);
526 527
		of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
		of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
528
		of_property_read_u32(np, "power", (u32 *)&pdata->power);
529 530 531 532

		ret = of_property_read_u32(np, "multipoint", &val);
		if (!ret && val)
			config->multipoint = true;
533 534 535 536

		pdata->board_data	= data;
		pdata->config		= config;

537 538 539 540 541 542 543 544 545
		control_node = of_parse_phandle(np, "ctrl-module", 0);
		if (control_node) {
			control_pdev = of_find_device_by_node(control_node);
			if (!control_pdev) {
				dev_err(&pdev->dev, "Failed to get control device\n");
				ret = -EINVAL;
				goto err2;
			}
			glue->control_otghs = &control_pdev->dev;
546 547
		}
	}
548 549
	pdata->platform_ops		= &omap2430_ops;

550
	platform_set_drvdata(pdev, glue);
551

552 553 554 555 556 557
	/*
	 * REVISIT if we ever have two instances of the wrapper, we will be
	 * in big trouble
	 */
	_glue	= glue;

558 559
	INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);

560
	memset(musb_resources, 0x00, sizeof(*musb_resources) *
561 562 563 564 565 566 567 568 569 570 571 572
			ARRAY_SIZE(musb_resources));

	musb_resources[0].name = pdev->resource[0].name;
	musb_resources[0].start = pdev->resource[0].start;
	musb_resources[0].end = pdev->resource[0].end;
	musb_resources[0].flags = pdev->resource[0].flags;

	musb_resources[1].name = pdev->resource[1].name;
	musb_resources[1].start = pdev->resource[1].start;
	musb_resources[1].end = pdev->resource[1].end;
	musb_resources[1].flags = pdev->resource[1].flags;

573 574 575 576 577
	musb_resources[2].name = pdev->resource[2].name;
	musb_resources[2].start = pdev->resource[2].start;
	musb_resources[2].end = pdev->resource[2].end;
	musb_resources[2].flags = pdev->resource[2].flags;

578 579
	ret = platform_device_add_resources(musb, musb_resources,
			ARRAY_SIZE(musb_resources));
580 581
	if (ret) {
		dev_err(&pdev->dev, "failed to add resources\n");
582
		goto err2;
583 584 585 586 587
	}

	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
	if (ret) {
		dev_err(&pdev->dev, "failed to add platform_data\n");
588
		goto err2;
589 590
	}

591 592 593 594 595
	/*
	 * Note that we cannot enable PM runtime yet for this
	 * driver as we need struct musb initialized first.
	 * See omap2430_musb_init above.
	 */
596

597 598 599
	ret = platform_device_add(musb);
	if (ret) {
		dev_err(&pdev->dev, "failed to register musb device\n");
600
		goto err2;
601 602
	}

603
	return 0;
604

605
err2:
606
	platform_device_put(musb);
607

608 609 610 611
err0:
	return ret;
}

B
Bill Pemberton 已提交
612
static int omap2430_remove(struct platform_device *pdev)
613
{
614 615
	struct omap2430_glue *glue = platform_get_drvdata(pdev);
	struct musb *musb = glue_to_musb(glue);
616

617
	pm_runtime_get_sync(glue->dev);
618
	platform_device_unregister(glue->musb);
619
	omap2430_set_power(musb, false, false);
620 621
	pm_runtime_put_sync(glue->dev);
	pm_runtime_disable(glue->dev);
622 623 624 625

	return 0;
}

626 627
#ifdef CONFIG_PM

628
static int omap2430_runtime_suspend(struct device *dev)
629 630 631 632
{
	struct omap2430_glue		*glue = dev_get_drvdata(dev);
	struct musb			*musb = glue_to_musb(glue);

633 634
	if (!musb)
		return 0;
635

636 637 638 639
	musb->context.otg_interfsel = musb_readl(musb->mregs,
						 OTG_INTERFSEL);

	omap2430_low_level_exit(musb);
640 641 642 643

	return 0;
}

644
static int omap2430_runtime_resume(struct device *dev)
645 646 647 648
{
	struct omap2430_glue		*glue = dev_get_drvdata(dev);
	struct musb			*musb = glue_to_musb(glue);

649
	if (!musb)
650
		return 0;
651 652 653 654

	omap2430_low_level_init(musb);
	musb_writel(musb->mregs, OTG_INTERFSEL,
		    musb->context.otg_interfsel);
655 656 657 658 659

	return 0;
}

static struct dev_pm_ops omap2430_pm_ops = {
660 661
	.runtime_suspend = omap2430_runtime_suspend,
	.runtime_resume = omap2430_runtime_resume,
662 663 664 665 666 667 668
};

#define DEV_PM_OPS	(&omap2430_pm_ops)
#else
#define DEV_PM_OPS	NULL
#endif

669 670 671 672 673 674 675 676 677 678 679 680 681
#ifdef CONFIG_OF
static const struct of_device_id omap2430_id_table[] = {
	{
		.compatible = "ti,omap4-musb"
	},
	{
		.compatible = "ti,omap3-musb"
	},
	{},
};
MODULE_DEVICE_TABLE(of, omap2430_id_table);
#endif

682
static struct platform_driver omap2430_driver = {
683
	.probe		= omap2430_probe,
B
Bill Pemberton 已提交
684
	.remove		= omap2430_remove,
685 686
	.driver		= {
		.name	= "musb-omap2430",
687
		.pm	= DEV_PM_OPS,
688
		.of_match_table = of_match_ptr(omap2430_id_table),
689 690 691 692 693 694 695 696 697
	},
};

MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
MODULE_LICENSE("GPL v2");

static int __init omap2430_init(void)
{
698
	return platform_driver_register(&omap2430_driver);
699
}
700
subsys_initcall(omap2430_init);
701 702 703 704 705 706

static void __exit omap2430_exit(void)
{
	platform_driver_unregister(&omap2430_driver);
}
module_exit(omap2430_exit);