blob: 418de0e61c5a8e082f180d76acd91a317cb71418 [file] [log] [blame]
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +05301/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +05306 */
7
8#include <linux/module.h>
9#include <linux/platform_device.h>
Pavankumar Kondeti2d0cdcc2010-12-07 17:54:05 +053010#include <linux/pm_runtime.h>
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053011#include <linux/usb/msm_hsusb_hw.h>
12#include <linux/usb/ulpi.h>
Alexander Shishkin62bb84e2012-05-08 23:29:01 +030013#include <linux/usb/gadget.h>
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053014
Alexander Shishkin62bb84e2012-05-08 23:29:01 +030015#include "ci13xxx_udc.h"
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053016
17#define MSM_USB_BASE (udc->regs)
18
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053019static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
20{
21 struct device *dev = udc->gadget.dev.parent;
22 int val;
23
24 switch (event) {
25 case CI13XXX_CONTROLLER_RESET_EVENT:
26 dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
27 writel(0, USB_AHBBURST);
28 writel(0, USB_AHBMODE);
29 break;
30 case CI13XXX_CONTROLLER_STOPPED_EVENT:
31 dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n");
32 /*
33 * Put the transceiver in non-driving mode. Otherwise host
34 * may not detect soft-disconnection.
35 */
Heikki Krogerusb96d3b02012-02-13 13:24:18 +020036 val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL);
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053037 val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
38 val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
Heikki Krogerusb96d3b02012-02-13 13:24:18 +020039 usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL);
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053040 break;
41 default:
42 dev_dbg(dev, "unknown ci13xxx_udc event\n");
43 break;
44 }
45}
46
47static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
48 .name = "ci13xxx_msm",
49 .flags = CI13XXX_REGS_SHARED |
50 CI13XXX_REQUIRE_TRANSCEIVER |
51 CI13XXX_PULLUP_ON_VBUS |
52 CI13XXX_DISABLE_STREAMING,
53
54 .notify_event = ci13xxx_msm_notify_event,
55};
56
57static int ci13xxx_msm_probe(struct platform_device *pdev)
58{
Alexander Shishkin62bb84e2012-05-08 23:29:01 +030059 struct platform_device *plat_ci;
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053060 int ret;
61
62 dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
63
Alexander Shishkin62bb84e2012-05-08 23:29:01 +030064 plat_ci = platform_device_alloc("ci_udc", -1);
65 if (!plat_ci) {
66 dev_err(&pdev->dev, "can't allocate ci_udc platform device\n");
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053067 return -ENOMEM;
68 }
69
Alexander Shishkin62bb84e2012-05-08 23:29:01 +030070 ret = platform_device_add_resources(plat_ci, pdev->resource,
71 pdev->num_resources);
72 if (ret) {
73 dev_err(&pdev->dev, "can't add resources to platform device\n");
74 goto put_platform;
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053075 }
76
Alexander Shishkin62bb84e2012-05-08 23:29:01 +030077 ret = platform_device_add_data(plat_ci, &ci13xxx_msm_udc_driver,
78 sizeof(ci13xxx_msm_udc_driver));
79 if (ret)
80 goto put_platform;
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053081
Alexander Shishkin62bb84e2012-05-08 23:29:01 +030082 ret = platform_device_add(plat_ci);
83 if (ret)
84 goto put_platform;
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053085
Pavankumar Kondeti2d0cdcc2010-12-07 17:54:05 +053086 pm_runtime_no_callbacks(&pdev->dev);
87 pm_runtime_enable(&pdev->dev);
88
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053089 return 0;
90
Alexander Shishkin62bb84e2012-05-08 23:29:01 +030091put_platform:
92 platform_device_put(plat_ci);
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +053093
94 return ret;
95}
96
97static struct platform_driver ci13xxx_msm_driver = {
98 .probe = ci13xxx_msm_probe,
99 .driver = { .name = "msm_hsusb", },
100};
Sebastian Andrzej Siewior86081d72011-06-29 16:41:55 +0300101MODULE_ALIAS("platform:msm_hsusb");
Pavankumar Kondeti33f82f382010-12-07 17:54:03 +0530102
103static int __init ci13xxx_msm_init(void)
104{
105 return platform_driver_register(&ci13xxx_msm_driver);
106}
107module_init(ci13xxx_msm_init);
Marc Kleine-Budde4703d2e2011-10-10 18:38:11 +0200108
109MODULE_LICENSE("GPL v2");