usb: move ci13xxx and related code to drivers/usb/chipidea
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / usb / chipidea / ci13xxx_msm.c
1 /* 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.
6 */
7
8 #include <linux/module.h>
9 #include <linux/platform_device.h>
10 #include <linux/pm_runtime.h>
11 #include <linux/usb/msm_hsusb_hw.h>
12 #include <linux/usb/ulpi.h>
13 #include <linux/usb/gadget.h>
14
15 #include "ci13xxx_udc.h"
16
17 #define MSM_USB_BASE (udc->regs)
18
19 static 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 */
36 val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL);
37 val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
38 val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
39 usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL);
40 break;
41 default:
42 dev_dbg(dev, "unknown ci13xxx_udc event\n");
43 break;
44 }
45 }
46
47 static 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
57 static int ci13xxx_msm_probe(struct platform_device *pdev)
58 {
59 struct platform_device *plat_ci;
60 int ret;
61
62 dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
63
64 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");
67 return -ENOMEM;
68 }
69
70 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;
75 }
76
77 ret = platform_device_add_data(plat_ci, &ci13xxx_msm_udc_driver,
78 sizeof(ci13xxx_msm_udc_driver));
79 if (ret)
80 goto put_platform;
81
82 ret = platform_device_add(plat_ci);
83 if (ret)
84 goto put_platform;
85
86 pm_runtime_no_callbacks(&pdev->dev);
87 pm_runtime_enable(&pdev->dev);
88
89 return 0;
90
91 put_platform:
92 platform_device_put(plat_ci);
93
94 return ret;
95 }
96
97 static struct platform_driver ci13xxx_msm_driver = {
98 .probe = ci13xxx_msm_probe,
99 .driver = { .name = "msm_hsusb", },
100 };
101 MODULE_ALIAS("platform:msm_hsusb");
102
103 static int __init ci13xxx_msm_init(void)
104 {
105 return platform_driver_register(&ci13xxx_msm_driver);
106 }
107 module_init(ci13xxx_msm_init);
108
109 MODULE_LICENSE("GPL v2");