diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 13:05:06 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 13:05:06 -0500 |
commit | 36facadd9ea98f8415d0dbb63e0763b7ee9d3911 (patch) | |
tree | 99dea00b332ed852f2b0a4923b581dd723f03634 /drivers/usb/otg | |
parent | 2faa83e2a519abea1055d156ce1b42b8fa57e87b (diff) | |
parent | 0b83ae960cd7d4a5ee02786ecf41ab45688999bf (diff) |
Merge branch 'usb-next' into musb-merge
* usb-next: (132 commits)
USB: uas: Use GFP_NOIO instead of GFP_KERNEL in I/O submission path
USB: uas: Ensure we only bind to a UAS interface
USB: uas: Rename sense pipe and sense urb to status pipe and status urb
USB: uas: Use kzalloc instead of kmalloc
USB: uas: Fix up the Sense IU
usb: musb: core: kill unneeded #include's
DA8xx: assign name to MUSB IRQ resource
usb: gadget: g_ncm added
usb: gadget: f_ncm.c added
usb: gadget: u_ether: prepare for NCM
usb: pch_udc: Fix setup transfers with data out
usb: pch_udc: Fix compile error, warnings and checkpatch warnings
usb: add ab8500 usb transceiver driver
USB: gadget: Implement runtime PM for MSM bus glue driver
USB: gadget: Implement runtime PM for ci13xxx gadget
USB: gadget: Add USB controller driver for MSM SoC
USB: gadget: Introduce ci13xxx_udc_driver struct
USB: gadget: Initialize ci13xxx gadget device's coherent DMA mask
USB: gadget: Fix "scheduling while atomic" bugs in ci13xxx_udc
USB: gadget: Separate out PCI bus code from ci13xxx_udc
...
Diffstat (limited to 'drivers/usb/otg')
-rw-r--r-- | drivers/usb/otg/Kconfig | 32 | ||||
-rw-r--r-- | drivers/usb/otg/Makefile | 3 | ||||
-rw-r--r-- | drivers/usb/otg/ab8500-usb.c | 585 | ||||
-rw-r--r-- | drivers/usb/otg/msm72k_otg.c | 1125 | ||||
-rw-r--r-- | drivers/usb/otg/twl4030-usb.c | 3 | ||||
-rw-r--r-- | drivers/usb/otg/twl6030-usb.c | 493 |
6 files changed, 2240 insertions, 1 deletions
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 5ce07528cd0c..9fb875d5f09c 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -59,6 +59,18 @@ config TWL4030_USB | |||
59 | This transceiver supports high and full speed devices plus, | 59 | This transceiver supports high and full speed devices plus, |
60 | in host mode, low speed. | 60 | in host mode, low speed. |
61 | 61 | ||
62 | config TWL6030_USB | ||
63 | tristate "TWL6030 USB Transceiver Driver" | ||
64 | depends on TWL4030_CORE | ||
65 | select USB_OTG_UTILS | ||
66 | help | ||
67 | Enable this to support the USB OTG transceiver on TWL6030 | ||
68 | family chips. This TWL6030 transceiver has the VBUS and ID GND | ||
69 | and OTG SRP events capabilities. For all other transceiver functionality | ||
70 | UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs | ||
71 | are hooked to this driver through platform_data structure. | ||
72 | The definition of internal PHY APIs are in the mach-omap2 layer. | ||
73 | |||
62 | config NOP_USB_XCEIV | 74 | config NOP_USB_XCEIV |
63 | tristate "NOP USB Transceiver Driver" | 75 | tristate "NOP USB Transceiver Driver" |
64 | select USB_OTG_UTILS | 76 | select USB_OTG_UTILS |
@@ -81,4 +93,24 @@ config USB_LANGWELL_OTG | |||
81 | To compile this driver as a module, choose M here: the | 93 | To compile this driver as a module, choose M here: the |
82 | module will be called langwell_otg. | 94 | module will be called langwell_otg. |
83 | 95 | ||
96 | config USB_MSM_OTG_72K | ||
97 | tristate "OTG support for Qualcomm on-chip USB controller" | ||
98 | depends on (USB || USB_GADGET) && ARCH_MSM | ||
99 | select USB_OTG_UTILS | ||
100 | help | ||
101 | Enable this to support the USB OTG transceiver on MSM chips. It | ||
102 | handles PHY initialization, clock management, and workarounds | ||
103 | required after resetting the hardware and power management. | ||
104 | This driver is required even for peripheral only or host only | ||
105 | mode configurations. | ||
106 | |||
107 | config AB8500_USB | ||
108 | tristate "AB8500 USB Transceiver Driver" | ||
109 | depends on AB8500_CORE | ||
110 | select USB_OTG_UTILS | ||
111 | help | ||
112 | Enable this to support the USB OTG transceiver in AB8500 chip. | ||
113 | This transceiver supports high and full speed devices plus, | ||
114 | in host mode, low speed. | ||
115 | |||
84 | endif # USB || OTG | 116 | endif # USB || OTG |
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 66f1b83e4fa7..a520e715cfd6 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile | |||
@@ -12,6 +12,9 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o | |||
12 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o | 12 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o |
13 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o | 13 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o |
14 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o | 14 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o |
15 | obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o | ||
15 | obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o | 16 | obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o |
16 | obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o | 17 | obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o |
17 | obj-$(CONFIG_USB_ULPI) += ulpi.o | 18 | obj-$(CONFIG_USB_ULPI) += ulpi.o |
19 | obj-$(CONFIG_USB_MSM_OTG_72K) += msm72k_otg.o | ||
20 | obj-$(CONFIG_AB8500_USB) += ab8500-usb.o | ||
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c new file mode 100644 index 000000000000..d14736b3107b --- /dev/null +++ b/drivers/usb/otg/ab8500-usb.c | |||
@@ -0,0 +1,585 @@ | |||
1 | /* | ||
2 | * drivers/usb/otg/ab8500_usb.c | ||
3 | * | ||
4 | * USB transceiver driver for AB8500 chip | ||
5 | * | ||
6 | * Copyright (C) 2010 ST-Ericsson AB | ||
7 | * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/usb/otg.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/notifier.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/mfd/abx500.h> | ||
33 | #include <linux/mfd/ab8500.h> | ||
34 | |||
35 | #define AB8500_MAIN_WD_CTRL_REG 0x01 | ||
36 | #define AB8500_USB_LINE_STAT_REG 0x80 | ||
37 | #define AB8500_USB_PHY_CTRL_REG 0x8A | ||
38 | |||
39 | #define AB8500_BIT_OTG_STAT_ID (1 << 0) | ||
40 | #define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0) | ||
41 | #define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1) | ||
42 | #define AB8500_BIT_WD_CTRL_ENABLE (1 << 0) | ||
43 | #define AB8500_BIT_WD_CTRL_KICK (1 << 1) | ||
44 | |||
45 | #define AB8500_V1x_LINK_STAT_WAIT (HZ/10) | ||
46 | #define AB8500_WD_KICK_DELAY_US 100 /* usec */ | ||
47 | #define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */ | ||
48 | #define AB8500_WD_V10_DISABLE_DELAY_MS 100 /* ms */ | ||
49 | |||
50 | /* Usb line status register */ | ||
51 | enum ab8500_usb_link_status { | ||
52 | USB_LINK_NOT_CONFIGURED = 0, | ||
53 | USB_LINK_STD_HOST_NC, | ||
54 | USB_LINK_STD_HOST_C_NS, | ||
55 | USB_LINK_STD_HOST_C_S, | ||
56 | USB_LINK_HOST_CHG_NM, | ||
57 | USB_LINK_HOST_CHG_HS, | ||
58 | USB_LINK_HOST_CHG_HS_CHIRP, | ||
59 | USB_LINK_DEDICATED_CHG, | ||
60 | USB_LINK_ACA_RID_A, | ||
61 | USB_LINK_ACA_RID_B, | ||
62 | USB_LINK_ACA_RID_C_NM, | ||
63 | USB_LINK_ACA_RID_C_HS, | ||
64 | USB_LINK_ACA_RID_C_HS_CHIRP, | ||
65 | USB_LINK_HM_IDGND, | ||
66 | USB_LINK_RESERVED, | ||
67 | USB_LINK_NOT_VALID_LINK | ||
68 | }; | ||
69 | |||
70 | struct ab8500_usb { | ||
71 | struct otg_transceiver otg; | ||
72 | struct device *dev; | ||
73 | int irq_num_id_rise; | ||
74 | int irq_num_id_fall; | ||
75 | int irq_num_vbus_rise; | ||
76 | int irq_num_vbus_fall; | ||
77 | int irq_num_link_status; | ||
78 | unsigned vbus_draw; | ||
79 | struct delayed_work dwork; | ||
80 | struct work_struct phy_dis_work; | ||
81 | unsigned long link_status_wait; | ||
82 | int rev; | ||
83 | }; | ||
84 | |||
85 | static inline struct ab8500_usb *xceiv_to_ab(struct otg_transceiver *x) | ||
86 | { | ||
87 | return container_of(x, struct ab8500_usb, otg); | ||
88 | } | ||
89 | |||
90 | static void ab8500_usb_wd_workaround(struct ab8500_usb *ab) | ||
91 | { | ||
92 | abx500_set_register_interruptible(ab->dev, | ||
93 | AB8500_SYS_CTRL2_BLOCK, | ||
94 | AB8500_MAIN_WD_CTRL_REG, | ||
95 | AB8500_BIT_WD_CTRL_ENABLE); | ||
96 | |||
97 | udelay(AB8500_WD_KICK_DELAY_US); | ||
98 | |||
99 | abx500_set_register_interruptible(ab->dev, | ||
100 | AB8500_SYS_CTRL2_BLOCK, | ||
101 | AB8500_MAIN_WD_CTRL_REG, | ||
102 | (AB8500_BIT_WD_CTRL_ENABLE | ||
103 | | AB8500_BIT_WD_CTRL_KICK)); | ||
104 | |||
105 | if (ab->rev > 0x10) /* v1.1 v2.0 */ | ||
106 | udelay(AB8500_WD_V11_DISABLE_DELAY_US); | ||
107 | else /* v1.0 */ | ||
108 | msleep(AB8500_WD_V10_DISABLE_DELAY_MS); | ||
109 | |||
110 | abx500_set_register_interruptible(ab->dev, | ||
111 | AB8500_SYS_CTRL2_BLOCK, | ||
112 | AB8500_MAIN_WD_CTRL_REG, | ||
113 | 0); | ||
114 | } | ||
115 | |||
116 | static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host, | ||
117 | bool enable) | ||
118 | { | ||
119 | u8 ctrl_reg; | ||
120 | abx500_get_register_interruptible(ab->dev, | ||
121 | AB8500_USB, | ||
122 | AB8500_USB_PHY_CTRL_REG, | ||
123 | &ctrl_reg); | ||
124 | if (sel_host) { | ||
125 | if (enable) | ||
126 | ctrl_reg |= AB8500_BIT_PHY_CTRL_HOST_EN; | ||
127 | else | ||
128 | ctrl_reg &= ~AB8500_BIT_PHY_CTRL_HOST_EN; | ||
129 | } else { | ||
130 | if (enable) | ||
131 | ctrl_reg |= AB8500_BIT_PHY_CTRL_DEVICE_EN; | ||
132 | else | ||
133 | ctrl_reg &= ~AB8500_BIT_PHY_CTRL_DEVICE_EN; | ||
134 | } | ||
135 | |||
136 | abx500_set_register_interruptible(ab->dev, | ||
137 | AB8500_USB, | ||
138 | AB8500_USB_PHY_CTRL_REG, | ||
139 | ctrl_reg); | ||
140 | |||
141 | /* Needed to enable the phy.*/ | ||
142 | if (enable) | ||
143 | ab8500_usb_wd_workaround(ab); | ||
144 | } | ||
145 | |||
146 | #define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_ctrl(ab, true, true) | ||
147 | #define ab8500_usb_host_phy_dis(ab) ab8500_usb_phy_ctrl(ab, true, false) | ||
148 | #define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_ctrl(ab, false, true) | ||
149 | #define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_ctrl(ab, false, false) | ||
150 | |||
151 | static int ab8500_usb_link_status_update(struct ab8500_usb *ab) | ||
152 | { | ||
153 | u8 reg; | ||
154 | enum ab8500_usb_link_status lsts; | ||
155 | void *v = NULL; | ||
156 | enum usb_xceiv_events event; | ||
157 | |||
158 | abx500_get_register_interruptible(ab->dev, | ||
159 | AB8500_USB, | ||
160 | AB8500_USB_LINE_STAT_REG, | ||
161 | ®); | ||
162 | |||
163 | lsts = (reg >> 3) & 0x0F; | ||
164 | |||
165 | switch (lsts) { | ||
166 | case USB_LINK_NOT_CONFIGURED: | ||
167 | case USB_LINK_RESERVED: | ||
168 | case USB_LINK_NOT_VALID_LINK: | ||
169 | /* TODO: Disable regulators. */ | ||
170 | ab8500_usb_host_phy_dis(ab); | ||
171 | ab8500_usb_peri_phy_dis(ab); | ||
172 | ab->otg.state = OTG_STATE_B_IDLE; | ||
173 | ab->otg.default_a = false; | ||
174 | ab->vbus_draw = 0; | ||
175 | event = USB_EVENT_NONE; | ||
176 | break; | ||
177 | |||
178 | case USB_LINK_STD_HOST_NC: | ||
179 | case USB_LINK_STD_HOST_C_NS: | ||
180 | case USB_LINK_STD_HOST_C_S: | ||
181 | case USB_LINK_HOST_CHG_NM: | ||
182 | case USB_LINK_HOST_CHG_HS: | ||
183 | case USB_LINK_HOST_CHG_HS_CHIRP: | ||
184 | if (ab->otg.gadget) { | ||
185 | /* TODO: Enable regulators. */ | ||
186 | ab8500_usb_peri_phy_en(ab); | ||
187 | v = ab->otg.gadget; | ||
188 | } | ||
189 | event = USB_EVENT_VBUS; | ||
190 | break; | ||
191 | |||
192 | case USB_LINK_HM_IDGND: | ||
193 | if (ab->otg.host) { | ||
194 | /* TODO: Enable regulators. */ | ||
195 | ab8500_usb_host_phy_en(ab); | ||
196 | v = ab->otg.host; | ||
197 | } | ||
198 | ab->otg.state = OTG_STATE_A_IDLE; | ||
199 | ab->otg.default_a = true; | ||
200 | event = USB_EVENT_ID; | ||
201 | break; | ||
202 | |||
203 | case USB_LINK_ACA_RID_A: | ||
204 | case USB_LINK_ACA_RID_B: | ||
205 | /* TODO */ | ||
206 | case USB_LINK_ACA_RID_C_NM: | ||
207 | case USB_LINK_ACA_RID_C_HS: | ||
208 | case USB_LINK_ACA_RID_C_HS_CHIRP: | ||
209 | case USB_LINK_DEDICATED_CHG: | ||
210 | /* TODO: vbus_draw */ | ||
211 | event = USB_EVENT_CHARGER; | ||
212 | break; | ||
213 | } | ||
214 | |||
215 | blocking_notifier_call_chain(&ab->otg.notifier, event, v); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static void ab8500_usb_delayed_work(struct work_struct *work) | ||
221 | { | ||
222 | struct ab8500_usb *ab = container_of(work, struct ab8500_usb, | ||
223 | dwork.work); | ||
224 | |||
225 | ab8500_usb_link_status_update(ab); | ||
226 | } | ||
227 | |||
228 | static irqreturn_t ab8500_usb_v1x_common_irq(int irq, void *data) | ||
229 | { | ||
230 | struct ab8500_usb *ab = (struct ab8500_usb *) data; | ||
231 | |||
232 | /* Wait for link status to become stable. */ | ||
233 | schedule_delayed_work(&ab->dwork, ab->link_status_wait); | ||
234 | |||
235 | return IRQ_HANDLED; | ||
236 | } | ||
237 | |||
238 | static irqreturn_t ab8500_usb_v1x_vbus_fall_irq(int irq, void *data) | ||
239 | { | ||
240 | struct ab8500_usb *ab = (struct ab8500_usb *) data; | ||
241 | |||
242 | /* Link status will not be updated till phy is disabled. */ | ||
243 | ab8500_usb_peri_phy_dis(ab); | ||
244 | |||
245 | /* Wait for link status to become stable. */ | ||
246 | schedule_delayed_work(&ab->dwork, ab->link_status_wait); | ||
247 | |||
248 | return IRQ_HANDLED; | ||
249 | } | ||
250 | |||
251 | static irqreturn_t ab8500_usb_v20_irq(int irq, void *data) | ||
252 | { | ||
253 | struct ab8500_usb *ab = (struct ab8500_usb *) data; | ||
254 | |||
255 | ab8500_usb_link_status_update(ab); | ||
256 | |||
257 | return IRQ_HANDLED; | ||
258 | } | ||
259 | |||
260 | static void ab8500_usb_phy_disable_work(struct work_struct *work) | ||
261 | { | ||
262 | struct ab8500_usb *ab = container_of(work, struct ab8500_usb, | ||
263 | phy_dis_work); | ||
264 | |||
265 | if (!ab->otg.host) | ||
266 | ab8500_usb_host_phy_dis(ab); | ||
267 | |||
268 | if (!ab->otg.gadget) | ||
269 | ab8500_usb_peri_phy_dis(ab); | ||
270 | } | ||
271 | |||
272 | static int ab8500_usb_set_power(struct otg_transceiver *otg, unsigned mA) | ||
273 | { | ||
274 | struct ab8500_usb *ab; | ||
275 | |||
276 | if (!otg) | ||
277 | return -ENODEV; | ||
278 | |||
279 | ab = xceiv_to_ab(otg); | ||
280 | |||
281 | ab->vbus_draw = mA; | ||
282 | |||
283 | if (mA) | ||
284 | blocking_notifier_call_chain(&ab->otg.notifier, | ||
285 | USB_EVENT_ENUMERATED, ab->otg.gadget); | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | /* TODO: Implement some way for charging or other drivers to read | ||
290 | * ab->vbus_draw. | ||
291 | */ | ||
292 | |||
293 | static int ab8500_usb_set_suspend(struct otg_transceiver *x, int suspend) | ||
294 | { | ||
295 | /* TODO */ | ||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static int ab8500_usb_set_peripheral(struct otg_transceiver *otg, | ||
300 | struct usb_gadget *gadget) | ||
301 | { | ||
302 | struct ab8500_usb *ab; | ||
303 | |||
304 | if (!otg) | ||
305 | return -ENODEV; | ||
306 | |||
307 | ab = xceiv_to_ab(otg); | ||
308 | |||
309 | /* Some drivers call this function in atomic context. | ||
310 | * Do not update ab8500 registers directly till this | ||
311 | * is fixed. | ||
312 | */ | ||
313 | |||
314 | if (!gadget) { | ||
315 | /* TODO: Disable regulators. */ | ||
316 | ab->otg.gadget = NULL; | ||
317 | schedule_work(&ab->phy_dis_work); | ||
318 | } else { | ||
319 | ab->otg.gadget = gadget; | ||
320 | ab->otg.state = OTG_STATE_B_IDLE; | ||
321 | |||
322 | /* Phy will not be enabled if cable is already | ||
323 | * plugged-in. Schedule to enable phy. | ||
324 | * Use same delay to avoid any race condition. | ||
325 | */ | ||
326 | schedule_delayed_work(&ab->dwork, ab->link_status_wait); | ||
327 | } | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static int ab8500_usb_set_host(struct otg_transceiver *otg, | ||
333 | struct usb_bus *host) | ||
334 | { | ||
335 | struct ab8500_usb *ab; | ||
336 | |||
337 | if (!otg) | ||
338 | return -ENODEV; | ||
339 | |||
340 | ab = xceiv_to_ab(otg); | ||
341 | |||
342 | /* Some drivers call this function in atomic context. | ||
343 | * Do not update ab8500 registers directly till this | ||
344 | * is fixed. | ||
345 | */ | ||
346 | |||
347 | if (!host) { | ||
348 | /* TODO: Disable regulators. */ | ||
349 | ab->otg.host = NULL; | ||
350 | schedule_work(&ab->phy_dis_work); | ||
351 | } else { | ||
352 | ab->otg.host = host; | ||
353 | /* Phy will not be enabled if cable is already | ||
354 | * plugged-in. Schedule to enable phy. | ||
355 | * Use same delay to avoid any race condition. | ||
356 | */ | ||
357 | schedule_delayed_work(&ab->dwork, ab->link_status_wait); | ||
358 | } | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static void ab8500_usb_irq_free(struct ab8500_usb *ab) | ||
364 | { | ||
365 | if (ab->rev < 0x20) { | ||
366 | free_irq(ab->irq_num_id_rise, ab); | ||
367 | free_irq(ab->irq_num_id_fall, ab); | ||
368 | free_irq(ab->irq_num_vbus_rise, ab); | ||
369 | free_irq(ab->irq_num_vbus_fall, ab); | ||
370 | } else { | ||
371 | free_irq(ab->irq_num_link_status, ab); | ||
372 | } | ||
373 | } | ||
374 | |||
375 | static int ab8500_usb_v1x_res_setup(struct platform_device *pdev, | ||
376 | struct ab8500_usb *ab) | ||
377 | { | ||
378 | int err; | ||
379 | |||
380 | ab->irq_num_id_rise = platform_get_irq_byname(pdev, "ID_WAKEUP_R"); | ||
381 | if (ab->irq_num_id_rise < 0) { | ||
382 | dev_err(&pdev->dev, "ID rise irq not found\n"); | ||
383 | return ab->irq_num_id_rise; | ||
384 | } | ||
385 | err = request_threaded_irq(ab->irq_num_id_rise, NULL, | ||
386 | ab8500_usb_v1x_common_irq, | ||
387 | IRQF_NO_SUSPEND | IRQF_SHARED, | ||
388 | "usb-id-rise", ab); | ||
389 | if (err < 0) { | ||
390 | dev_err(ab->dev, "request_irq failed for ID rise irq\n"); | ||
391 | goto fail0; | ||
392 | } | ||
393 | |||
394 | ab->irq_num_id_fall = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); | ||
395 | if (ab->irq_num_id_fall < 0) { | ||
396 | dev_err(&pdev->dev, "ID fall irq not found\n"); | ||
397 | return ab->irq_num_id_fall; | ||
398 | } | ||
399 | err = request_threaded_irq(ab->irq_num_id_fall, NULL, | ||
400 | ab8500_usb_v1x_common_irq, | ||
401 | IRQF_NO_SUSPEND | IRQF_SHARED, | ||
402 | "usb-id-fall", ab); | ||
403 | if (err < 0) { | ||
404 | dev_err(ab->dev, "request_irq failed for ID fall irq\n"); | ||
405 | goto fail1; | ||
406 | } | ||
407 | |||
408 | ab->irq_num_vbus_rise = platform_get_irq_byname(pdev, "VBUS_DET_R"); | ||
409 | if (ab->irq_num_vbus_rise < 0) { | ||
410 | dev_err(&pdev->dev, "VBUS rise irq not found\n"); | ||
411 | return ab->irq_num_vbus_rise; | ||
412 | } | ||
413 | err = request_threaded_irq(ab->irq_num_vbus_rise, NULL, | ||
414 | ab8500_usb_v1x_common_irq, | ||
415 | IRQF_NO_SUSPEND | IRQF_SHARED, | ||
416 | "usb-vbus-rise", ab); | ||
417 | if (err < 0) { | ||
418 | dev_err(ab->dev, "request_irq failed for Vbus rise irq\n"); | ||
419 | goto fail2; | ||
420 | } | ||
421 | |||
422 | ab->irq_num_vbus_fall = platform_get_irq_byname(pdev, "VBUS_DET_F"); | ||
423 | if (ab->irq_num_vbus_fall < 0) { | ||
424 | dev_err(&pdev->dev, "VBUS fall irq not found\n"); | ||
425 | return ab->irq_num_vbus_fall; | ||
426 | } | ||
427 | err = request_threaded_irq(ab->irq_num_vbus_fall, NULL, | ||
428 | ab8500_usb_v1x_vbus_fall_irq, | ||
429 | IRQF_NO_SUSPEND | IRQF_SHARED, | ||
430 | "usb-vbus-fall", ab); | ||
431 | if (err < 0) { | ||
432 | dev_err(ab->dev, "request_irq failed for Vbus fall irq\n"); | ||
433 | goto fail3; | ||
434 | } | ||
435 | |||
436 | return 0; | ||
437 | fail3: | ||
438 | free_irq(ab->irq_num_vbus_rise, ab); | ||
439 | fail2: | ||
440 | free_irq(ab->irq_num_id_fall, ab); | ||
441 | fail1: | ||
442 | free_irq(ab->irq_num_id_rise, ab); | ||
443 | fail0: | ||
444 | return err; | ||
445 | } | ||
446 | |||
447 | static int ab8500_usb_v2_res_setup(struct platform_device *pdev, | ||
448 | struct ab8500_usb *ab) | ||
449 | { | ||
450 | int err; | ||
451 | |||
452 | ab->irq_num_link_status = platform_get_irq_byname(pdev, | ||
453 | "USB_LINK_STATUS"); | ||
454 | if (ab->irq_num_link_status < 0) { | ||
455 | dev_err(&pdev->dev, "Link status irq not found\n"); | ||
456 | return ab->irq_num_link_status; | ||
457 | } | ||
458 | |||
459 | err = request_threaded_irq(ab->irq_num_link_status, NULL, | ||
460 | ab8500_usb_v20_irq, | ||
461 | IRQF_NO_SUSPEND | IRQF_SHARED, | ||
462 | "usb-link-status", ab); | ||
463 | if (err < 0) { | ||
464 | dev_err(ab->dev, | ||
465 | "request_irq failed for link status irq\n"); | ||
466 | return err; | ||
467 | } | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static int __devinit ab8500_usb_probe(struct platform_device *pdev) | ||
473 | { | ||
474 | struct ab8500_usb *ab; | ||
475 | int err; | ||
476 | int rev; | ||
477 | |||
478 | rev = abx500_get_chip_id(&pdev->dev); | ||
479 | if (rev < 0) { | ||
480 | dev_err(&pdev->dev, "Chip id read failed\n"); | ||
481 | return rev; | ||
482 | } else if (rev < 0x10) { | ||
483 | dev_err(&pdev->dev, "Unsupported AB8500 chip\n"); | ||
484 | return -ENODEV; | ||
485 | } | ||
486 | |||
487 | ab = kzalloc(sizeof *ab, GFP_KERNEL); | ||
488 | if (!ab) | ||
489 | return -ENOMEM; | ||
490 | |||
491 | ab->dev = &pdev->dev; | ||
492 | ab->rev = rev; | ||
493 | ab->otg.dev = ab->dev; | ||
494 | ab->otg.label = "ab8500"; | ||
495 | ab->otg.state = OTG_STATE_UNDEFINED; | ||
496 | ab->otg.set_host = ab8500_usb_set_host; | ||
497 | ab->otg.set_peripheral = ab8500_usb_set_peripheral; | ||
498 | ab->otg.set_suspend = ab8500_usb_set_suspend; | ||
499 | ab->otg.set_power = ab8500_usb_set_power; | ||
500 | |||
501 | platform_set_drvdata(pdev, ab); | ||
502 | |||
503 | BLOCKING_INIT_NOTIFIER_HEAD(&ab->otg.notifier); | ||
504 | |||
505 | /* v1: Wait for link status to become stable. | ||
506 | * all: Updates form set_host and set_peripheral as they are atomic. | ||
507 | */ | ||
508 | INIT_DELAYED_WORK(&ab->dwork, ab8500_usb_delayed_work); | ||
509 | |||
510 | /* all: Disable phy when called from set_host and set_peripheral */ | ||
511 | INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); | ||
512 | |||
513 | if (ab->rev < 0x20) { | ||
514 | err = ab8500_usb_v1x_res_setup(pdev, ab); | ||
515 | ab->link_status_wait = AB8500_V1x_LINK_STAT_WAIT; | ||
516 | } else { | ||
517 | err = ab8500_usb_v2_res_setup(pdev, ab); | ||
518 | } | ||
519 | |||
520 | if (err < 0) | ||
521 | goto fail0; | ||
522 | |||
523 | err = otg_set_transceiver(&ab->otg); | ||
524 | if (err) { | ||
525 | dev_err(&pdev->dev, "Can't register transceiver\n"); | ||
526 | goto fail1; | ||
527 | } | ||
528 | |||
529 | dev_info(&pdev->dev, "AB8500 usb driver initialized\n"); | ||
530 | |||
531 | return 0; | ||
532 | fail1: | ||
533 | ab8500_usb_irq_free(ab); | ||
534 | fail0: | ||
535 | kfree(ab); | ||
536 | return err; | ||
537 | } | ||
538 | |||
539 | static int __devexit ab8500_usb_remove(struct platform_device *pdev) | ||
540 | { | ||
541 | struct ab8500_usb *ab = platform_get_drvdata(pdev); | ||
542 | |||
543 | ab8500_usb_irq_free(ab); | ||
544 | |||
545 | cancel_delayed_work_sync(&ab->dwork); | ||
546 | |||
547 | cancel_work_sync(&ab->phy_dis_work); | ||
548 | |||
549 | otg_set_transceiver(NULL); | ||
550 | |||
551 | ab8500_usb_host_phy_dis(ab); | ||
552 | ab8500_usb_peri_phy_dis(ab); | ||
553 | |||
554 | platform_set_drvdata(pdev, NULL); | ||
555 | |||
556 | kfree(ab); | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static struct platform_driver ab8500_usb_driver = { | ||
562 | .probe = ab8500_usb_probe, | ||
563 | .remove = __devexit_p(ab8500_usb_remove), | ||
564 | .driver = { | ||
565 | .name = "ab8500-usb", | ||
566 | .owner = THIS_MODULE, | ||
567 | }, | ||
568 | }; | ||
569 | |||
570 | static int __init ab8500_usb_init(void) | ||
571 | { | ||
572 | return platform_driver_register(&ab8500_usb_driver); | ||
573 | } | ||
574 | subsys_initcall(ab8500_usb_init); | ||
575 | |||
576 | static void __exit ab8500_usb_exit(void) | ||
577 | { | ||
578 | platform_driver_unregister(&ab8500_usb_driver); | ||
579 | } | ||
580 | module_exit(ab8500_usb_exit); | ||
581 | |||
582 | MODULE_ALIAS("platform:ab8500_usb"); | ||
583 | MODULE_AUTHOR("ST-Ericsson AB"); | ||
584 | MODULE_DESCRIPTION("AB8500 usb transceiver driver"); | ||
585 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c new file mode 100644 index 000000000000..1cd52edcd0c2 --- /dev/null +++ b/drivers/usb/otg/msm72k_otg.c | |||
@@ -0,0 +1,1125 @@ | |||
1 | /* Copyright (c) 2009-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 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/ioport.h> | ||
29 | #include <linux/uaccess.h> | ||
30 | #include <linux/debugfs.h> | ||
31 | #include <linux/seq_file.h> | ||
32 | #include <linux/pm_runtime.h> | ||
33 | |||
34 | #include <linux/usb.h> | ||
35 | #include <linux/usb/otg.h> | ||
36 | #include <linux/usb/ulpi.h> | ||
37 | #include <linux/usb/gadget.h> | ||
38 | #include <linux/usb/hcd.h> | ||
39 | #include <linux/usb/msm_hsusb.h> | ||
40 | #include <linux/usb/msm_hsusb_hw.h> | ||
41 | |||
42 | #include <mach/clk.h> | ||
43 | |||
44 | #define MSM_USB_BASE (motg->regs) | ||
45 | #define DRIVER_NAME "msm_otg" | ||
46 | |||
47 | #define ULPI_IO_TIMEOUT_USEC (10 * 1000) | ||
48 | static int ulpi_read(struct otg_transceiver *otg, u32 reg) | ||
49 | { | ||
50 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
51 | int cnt = 0; | ||
52 | |||
53 | /* initiate read operation */ | ||
54 | writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg), | ||
55 | USB_ULPI_VIEWPORT); | ||
56 | |||
57 | /* wait for completion */ | ||
58 | while (cnt < ULPI_IO_TIMEOUT_USEC) { | ||
59 | if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN)) | ||
60 | break; | ||
61 | udelay(1); | ||
62 | cnt++; | ||
63 | } | ||
64 | |||
65 | if (cnt >= ULPI_IO_TIMEOUT_USEC) { | ||
66 | dev_err(otg->dev, "ulpi_read: timeout %08x\n", | ||
67 | readl(USB_ULPI_VIEWPORT)); | ||
68 | return -ETIMEDOUT; | ||
69 | } | ||
70 | return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT)); | ||
71 | } | ||
72 | |||
73 | static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg) | ||
74 | { | ||
75 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
76 | int cnt = 0; | ||
77 | |||
78 | /* initiate write operation */ | ||
79 | writel(ULPI_RUN | ULPI_WRITE | | ||
80 | ULPI_ADDR(reg) | ULPI_DATA(val), | ||
81 | USB_ULPI_VIEWPORT); | ||
82 | |||
83 | /* wait for completion */ | ||
84 | while (cnt < ULPI_IO_TIMEOUT_USEC) { | ||
85 | if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN)) | ||
86 | break; | ||
87 | udelay(1); | ||
88 | cnt++; | ||
89 | } | ||
90 | |||
91 | if (cnt >= ULPI_IO_TIMEOUT_USEC) { | ||
92 | dev_err(otg->dev, "ulpi_write: timeout\n"); | ||
93 | return -ETIMEDOUT; | ||
94 | } | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static struct otg_io_access_ops msm_otg_io_ops = { | ||
99 | .read = ulpi_read, | ||
100 | .write = ulpi_write, | ||
101 | }; | ||
102 | |||
103 | static void ulpi_init(struct msm_otg *motg) | ||
104 | { | ||
105 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
106 | int *seq = pdata->phy_init_seq; | ||
107 | |||
108 | if (!seq) | ||
109 | return; | ||
110 | |||
111 | while (seq[0] >= 0) { | ||
112 | dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n", | ||
113 | seq[0], seq[1]); | ||
114 | ulpi_write(&motg->otg, seq[0], seq[1]); | ||
115 | seq += 2; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) | ||
120 | { | ||
121 | int ret; | ||
122 | |||
123 | if (assert) { | ||
124 | ret = clk_reset(motg->clk, CLK_RESET_ASSERT); | ||
125 | if (ret) | ||
126 | dev_err(motg->otg.dev, "usb hs_clk assert failed\n"); | ||
127 | } else { | ||
128 | ret = clk_reset(motg->clk, CLK_RESET_DEASSERT); | ||
129 | if (ret) | ||
130 | dev_err(motg->otg.dev, "usb hs_clk deassert failed\n"); | ||
131 | } | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static int msm_otg_phy_clk_reset(struct msm_otg *motg) | ||
136 | { | ||
137 | int ret; | ||
138 | |||
139 | ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT); | ||
140 | if (ret) { | ||
141 | dev_err(motg->otg.dev, "usb phy clk assert failed\n"); | ||
142 | return ret; | ||
143 | } | ||
144 | usleep_range(10000, 12000); | ||
145 | ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT); | ||
146 | if (ret) | ||
147 | dev_err(motg->otg.dev, "usb phy clk deassert failed\n"); | ||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | static int msm_otg_phy_reset(struct msm_otg *motg) | ||
152 | { | ||
153 | u32 val; | ||
154 | int ret; | ||
155 | int retries; | ||
156 | |||
157 | ret = msm_otg_link_clk_reset(motg, 1); | ||
158 | if (ret) | ||
159 | return ret; | ||
160 | ret = msm_otg_phy_clk_reset(motg); | ||
161 | if (ret) | ||
162 | return ret; | ||
163 | ret = msm_otg_link_clk_reset(motg, 0); | ||
164 | if (ret) | ||
165 | return ret; | ||
166 | |||
167 | val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK; | ||
168 | writel(val | PORTSC_PTS_ULPI, USB_PORTSC); | ||
169 | |||
170 | for (retries = 3; retries > 0; retries--) { | ||
171 | ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM, | ||
172 | ULPI_CLR(ULPI_FUNC_CTRL)); | ||
173 | if (!ret) | ||
174 | break; | ||
175 | ret = msm_otg_phy_clk_reset(motg); | ||
176 | if (ret) | ||
177 | return ret; | ||
178 | } | ||
179 | if (!retries) | ||
180 | return -ETIMEDOUT; | ||
181 | |||
182 | /* This reset calibrates the phy, if the above write succeeded */ | ||
183 | ret = msm_otg_phy_clk_reset(motg); | ||
184 | if (ret) | ||
185 | return ret; | ||
186 | |||
187 | for (retries = 3; retries > 0; retries--) { | ||
188 | ret = ulpi_read(&motg->otg, ULPI_DEBUG); | ||
189 | if (ret != -ETIMEDOUT) | ||
190 | break; | ||
191 | ret = msm_otg_phy_clk_reset(motg); | ||
192 | if (ret) | ||
193 | return ret; | ||
194 | } | ||
195 | if (!retries) | ||
196 | return -ETIMEDOUT; | ||
197 | |||
198 | dev_info(motg->otg.dev, "phy_reset: success\n"); | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | #define LINK_RESET_TIMEOUT_USEC (250 * 1000) | ||
203 | static int msm_otg_reset(struct otg_transceiver *otg) | ||
204 | { | ||
205 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
206 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
207 | int cnt = 0; | ||
208 | int ret; | ||
209 | u32 val = 0; | ||
210 | u32 ulpi_val = 0; | ||
211 | |||
212 | ret = msm_otg_phy_reset(motg); | ||
213 | if (ret) { | ||
214 | dev_err(otg->dev, "phy_reset failed\n"); | ||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | ulpi_init(motg); | ||
219 | |||
220 | writel(USBCMD_RESET, USB_USBCMD); | ||
221 | while (cnt < LINK_RESET_TIMEOUT_USEC) { | ||
222 | if (!(readl(USB_USBCMD) & USBCMD_RESET)) | ||
223 | break; | ||
224 | udelay(1); | ||
225 | cnt++; | ||
226 | } | ||
227 | if (cnt >= LINK_RESET_TIMEOUT_USEC) | ||
228 | return -ETIMEDOUT; | ||
229 | |||
230 | /* select ULPI phy */ | ||
231 | writel(0x80000000, USB_PORTSC); | ||
232 | |||
233 | msleep(100); | ||
234 | |||
235 | writel(0x0, USB_AHBBURST); | ||
236 | writel(0x00, USB_AHBMODE); | ||
237 | |||
238 | if (pdata->otg_control == OTG_PHY_CONTROL) { | ||
239 | val = readl(USB_OTGSC); | ||
240 | if (pdata->mode == USB_OTG) { | ||
241 | ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID; | ||
242 | val |= OTGSC_IDIE | OTGSC_BSVIE; | ||
243 | } else if (pdata->mode == USB_PERIPHERAL) { | ||
244 | ulpi_val = ULPI_INT_SESS_VALID; | ||
245 | val |= OTGSC_BSVIE; | ||
246 | } | ||
247 | writel(val, USB_OTGSC); | ||
248 | ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE); | ||
249 | ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL); | ||
250 | } | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | #define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000) | ||
256 | static int msm_otg_suspend(struct msm_otg *motg) | ||
257 | { | ||
258 | struct otg_transceiver *otg = &motg->otg; | ||
259 | struct usb_bus *bus = otg->host; | ||
260 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
261 | int cnt = 0; | ||
262 | |||
263 | if (atomic_read(&motg->in_lpm)) | ||
264 | return 0; | ||
265 | |||
266 | disable_irq(motg->irq); | ||
267 | /* | ||
268 | * Interrupt Latch Register auto-clear feature is not present | ||
269 | * in all PHY versions. Latch register is clear on read type. | ||
270 | * Clear latch register to avoid spurious wakeup from | ||
271 | * low power mode (LPM). | ||
272 | */ | ||
273 | ulpi_read(otg, 0x14); | ||
274 | |||
275 | /* | ||
276 | * PHY comparators are disabled when PHY enters into low power | ||
277 | * mode (LPM). Keep PHY comparators ON in LPM only when we expect | ||
278 | * VBUS/Id notifications from USB PHY. Otherwise turn off USB | ||
279 | * PHY comparators. This save significant amount of power. | ||
280 | */ | ||
281 | if (pdata->otg_control == OTG_PHY_CONTROL) | ||
282 | ulpi_write(otg, 0x01, 0x30); | ||
283 | |||
284 | /* | ||
285 | * PLL is not turned off when PHY enters into low power mode (LPM). | ||
286 | * Disable PLL for maximum power savings. | ||
287 | */ | ||
288 | ulpi_write(otg, 0x08, 0x09); | ||
289 | |||
290 | /* | ||
291 | * PHY may take some time or even fail to enter into low power | ||
292 | * mode (LPM). Hence poll for 500 msec and reset the PHY and link | ||
293 | * in failure case. | ||
294 | */ | ||
295 | writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); | ||
296 | while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { | ||
297 | if (readl(USB_PORTSC) & PORTSC_PHCD) | ||
298 | break; | ||
299 | udelay(1); | ||
300 | cnt++; | ||
301 | } | ||
302 | |||
303 | if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) { | ||
304 | dev_err(otg->dev, "Unable to suspend PHY\n"); | ||
305 | msm_otg_reset(otg); | ||
306 | enable_irq(motg->irq); | ||
307 | return -ETIMEDOUT; | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * PHY has capability to generate interrupt asynchronously in low | ||
312 | * power mode (LPM). This interrupt is level triggered. So USB IRQ | ||
313 | * line must be disabled till async interrupt enable bit is cleared | ||
314 | * in USBCMD register. Assert STP (ULPI interface STOP signal) to | ||
315 | * block data communication from PHY. | ||
316 | */ | ||
317 | writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); | ||
318 | |||
319 | clk_disable(motg->pclk); | ||
320 | clk_disable(motg->clk); | ||
321 | if (motg->core_clk) | ||
322 | clk_disable(motg->core_clk); | ||
323 | |||
324 | if (device_may_wakeup(otg->dev)) | ||
325 | enable_irq_wake(motg->irq); | ||
326 | if (bus) | ||
327 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); | ||
328 | |||
329 | atomic_set(&motg->in_lpm, 1); | ||
330 | enable_irq(motg->irq); | ||
331 | |||
332 | dev_info(otg->dev, "USB in low power mode\n"); | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | #define PHY_RESUME_TIMEOUT_USEC (100 * 1000) | ||
338 | static int msm_otg_resume(struct msm_otg *motg) | ||
339 | { | ||
340 | struct otg_transceiver *otg = &motg->otg; | ||
341 | struct usb_bus *bus = otg->host; | ||
342 | int cnt = 0; | ||
343 | unsigned temp; | ||
344 | |||
345 | if (!atomic_read(&motg->in_lpm)) | ||
346 | return 0; | ||
347 | |||
348 | clk_enable(motg->pclk); | ||
349 | clk_enable(motg->clk); | ||
350 | if (motg->core_clk) | ||
351 | clk_enable(motg->core_clk); | ||
352 | |||
353 | temp = readl(USB_USBCMD); | ||
354 | temp &= ~ASYNC_INTR_CTRL; | ||
355 | temp &= ~ULPI_STP_CTRL; | ||
356 | writel(temp, USB_USBCMD); | ||
357 | |||
358 | /* | ||
359 | * PHY comes out of low power mode (LPM) in case of wakeup | ||
360 | * from asynchronous interrupt. | ||
361 | */ | ||
362 | if (!(readl(USB_PORTSC) & PORTSC_PHCD)) | ||
363 | goto skip_phy_resume; | ||
364 | |||
365 | writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC); | ||
366 | while (cnt < PHY_RESUME_TIMEOUT_USEC) { | ||
367 | if (!(readl(USB_PORTSC) & PORTSC_PHCD)) | ||
368 | break; | ||
369 | udelay(1); | ||
370 | cnt++; | ||
371 | } | ||
372 | |||
373 | if (cnt >= PHY_RESUME_TIMEOUT_USEC) { | ||
374 | /* | ||
375 | * This is a fatal error. Reset the link and | ||
376 | * PHY. USB state can not be restored. Re-insertion | ||
377 | * of USB cable is the only way to get USB working. | ||
378 | */ | ||
379 | dev_err(otg->dev, "Unable to resume USB." | ||
380 | "Re-plugin the cable\n"); | ||
381 | msm_otg_reset(otg); | ||
382 | } | ||
383 | |||
384 | skip_phy_resume: | ||
385 | if (device_may_wakeup(otg->dev)) | ||
386 | disable_irq_wake(motg->irq); | ||
387 | if (bus) | ||
388 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); | ||
389 | |||
390 | if (motg->async_int) { | ||
391 | motg->async_int = 0; | ||
392 | pm_runtime_put(otg->dev); | ||
393 | enable_irq(motg->irq); | ||
394 | } | ||
395 | |||
396 | atomic_set(&motg->in_lpm, 0); | ||
397 | |||
398 | dev_info(otg->dev, "USB exited from low power mode\n"); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static void msm_otg_start_host(struct otg_transceiver *otg, int on) | ||
404 | { | ||
405 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
406 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
407 | struct usb_hcd *hcd; | ||
408 | |||
409 | if (!otg->host) | ||
410 | return; | ||
411 | |||
412 | hcd = bus_to_hcd(otg->host); | ||
413 | |||
414 | if (on) { | ||
415 | dev_dbg(otg->dev, "host on\n"); | ||
416 | |||
417 | if (pdata->vbus_power) | ||
418 | pdata->vbus_power(1); | ||
419 | /* | ||
420 | * Some boards have a switch cotrolled by gpio | ||
421 | * to enable/disable internal HUB. Enable internal | ||
422 | * HUB before kicking the host. | ||
423 | */ | ||
424 | if (pdata->setup_gpio) | ||
425 | pdata->setup_gpio(OTG_STATE_A_HOST); | ||
426 | #ifdef CONFIG_USB | ||
427 | usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); | ||
428 | #endif | ||
429 | } else { | ||
430 | dev_dbg(otg->dev, "host off\n"); | ||
431 | |||
432 | #ifdef CONFIG_USB | ||
433 | usb_remove_hcd(hcd); | ||
434 | #endif | ||
435 | if (pdata->setup_gpio) | ||
436 | pdata->setup_gpio(OTG_STATE_UNDEFINED); | ||
437 | if (pdata->vbus_power) | ||
438 | pdata->vbus_power(0); | ||
439 | } | ||
440 | } | ||
441 | |||
442 | static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) | ||
443 | { | ||
444 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
445 | struct usb_hcd *hcd; | ||
446 | |||
447 | /* | ||
448 | * Fail host registration if this board can support | ||
449 | * only peripheral configuration. | ||
450 | */ | ||
451 | if (motg->pdata->mode == USB_PERIPHERAL) { | ||
452 | dev_info(otg->dev, "Host mode is not supported\n"); | ||
453 | return -ENODEV; | ||
454 | } | ||
455 | |||
456 | if (!host) { | ||
457 | if (otg->state == OTG_STATE_A_HOST) { | ||
458 | pm_runtime_get_sync(otg->dev); | ||
459 | msm_otg_start_host(otg, 0); | ||
460 | otg->host = NULL; | ||
461 | otg->state = OTG_STATE_UNDEFINED; | ||
462 | schedule_work(&motg->sm_work); | ||
463 | } else { | ||
464 | otg->host = NULL; | ||
465 | } | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | hcd = bus_to_hcd(host); | ||
471 | hcd->power_budget = motg->pdata->power_budget; | ||
472 | |||
473 | otg->host = host; | ||
474 | dev_dbg(otg->dev, "host driver registered w/ tranceiver\n"); | ||
475 | |||
476 | /* | ||
477 | * Kick the state machine work, if peripheral is not supported | ||
478 | * or peripheral is already registered with us. | ||
479 | */ | ||
480 | if (motg->pdata->mode == USB_HOST || otg->gadget) { | ||
481 | pm_runtime_get_sync(otg->dev); | ||
482 | schedule_work(&motg->sm_work); | ||
483 | } | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on) | ||
489 | { | ||
490 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
491 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
492 | |||
493 | if (!otg->gadget) | ||
494 | return; | ||
495 | |||
496 | if (on) { | ||
497 | dev_dbg(otg->dev, "gadget on\n"); | ||
498 | /* | ||
499 | * Some boards have a switch cotrolled by gpio | ||
500 | * to enable/disable internal HUB. Disable internal | ||
501 | * HUB before kicking the gadget. | ||
502 | */ | ||
503 | if (pdata->setup_gpio) | ||
504 | pdata->setup_gpio(OTG_STATE_B_PERIPHERAL); | ||
505 | usb_gadget_vbus_connect(otg->gadget); | ||
506 | } else { | ||
507 | dev_dbg(otg->dev, "gadget off\n"); | ||
508 | usb_gadget_vbus_disconnect(otg->gadget); | ||
509 | if (pdata->setup_gpio) | ||
510 | pdata->setup_gpio(OTG_STATE_UNDEFINED); | ||
511 | } | ||
512 | |||
513 | } | ||
514 | |||
515 | static int msm_otg_set_peripheral(struct otg_transceiver *otg, | ||
516 | struct usb_gadget *gadget) | ||
517 | { | ||
518 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
519 | |||
520 | /* | ||
521 | * Fail peripheral registration if this board can support | ||
522 | * only host configuration. | ||
523 | */ | ||
524 | if (motg->pdata->mode == USB_HOST) { | ||
525 | dev_info(otg->dev, "Peripheral mode is not supported\n"); | ||
526 | return -ENODEV; | ||
527 | } | ||
528 | |||
529 | if (!gadget) { | ||
530 | if (otg->state == OTG_STATE_B_PERIPHERAL) { | ||
531 | pm_runtime_get_sync(otg->dev); | ||
532 | msm_otg_start_peripheral(otg, 0); | ||
533 | otg->gadget = NULL; | ||
534 | otg->state = OTG_STATE_UNDEFINED; | ||
535 | schedule_work(&motg->sm_work); | ||
536 | } else { | ||
537 | otg->gadget = NULL; | ||
538 | } | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | otg->gadget = gadget; | ||
543 | dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n"); | ||
544 | |||
545 | /* | ||
546 | * Kick the state machine work, if host is not supported | ||
547 | * or host is already registered with us. | ||
548 | */ | ||
549 | if (motg->pdata->mode == USB_PERIPHERAL || otg->host) { | ||
550 | pm_runtime_get_sync(otg->dev); | ||
551 | schedule_work(&motg->sm_work); | ||
552 | } | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /* | ||
558 | * We support OTG, Peripheral only and Host only configurations. In case | ||
559 | * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen | ||
560 | * via Id pin status or user request (debugfs). Id/BSV interrupts are not | ||
561 | * enabled when switch is controlled by user and default mode is supplied | ||
562 | * by board file, which can be changed by userspace later. | ||
563 | */ | ||
564 | static void msm_otg_init_sm(struct msm_otg *motg) | ||
565 | { | ||
566 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
567 | u32 otgsc = readl(USB_OTGSC); | ||
568 | |||
569 | switch (pdata->mode) { | ||
570 | case USB_OTG: | ||
571 | if (pdata->otg_control == OTG_PHY_CONTROL) { | ||
572 | if (otgsc & OTGSC_ID) | ||
573 | set_bit(ID, &motg->inputs); | ||
574 | else | ||
575 | clear_bit(ID, &motg->inputs); | ||
576 | |||
577 | if (otgsc & OTGSC_BSV) | ||
578 | set_bit(B_SESS_VLD, &motg->inputs); | ||
579 | else | ||
580 | clear_bit(B_SESS_VLD, &motg->inputs); | ||
581 | } else if (pdata->otg_control == OTG_USER_CONTROL) { | ||
582 | if (pdata->default_mode == USB_HOST) { | ||
583 | clear_bit(ID, &motg->inputs); | ||
584 | } else if (pdata->default_mode == USB_PERIPHERAL) { | ||
585 | set_bit(ID, &motg->inputs); | ||
586 | set_bit(B_SESS_VLD, &motg->inputs); | ||
587 | } else { | ||
588 | set_bit(ID, &motg->inputs); | ||
589 | clear_bit(B_SESS_VLD, &motg->inputs); | ||
590 | } | ||
591 | } | ||
592 | break; | ||
593 | case USB_HOST: | ||
594 | clear_bit(ID, &motg->inputs); | ||
595 | break; | ||
596 | case USB_PERIPHERAL: | ||
597 | set_bit(ID, &motg->inputs); | ||
598 | if (otgsc & OTGSC_BSV) | ||
599 | set_bit(B_SESS_VLD, &motg->inputs); | ||
600 | else | ||
601 | clear_bit(B_SESS_VLD, &motg->inputs); | ||
602 | break; | ||
603 | default: | ||
604 | break; | ||
605 | } | ||
606 | } | ||
607 | |||
608 | static void msm_otg_sm_work(struct work_struct *w) | ||
609 | { | ||
610 | struct msm_otg *motg = container_of(w, struct msm_otg, sm_work); | ||
611 | struct otg_transceiver *otg = &motg->otg; | ||
612 | |||
613 | switch (otg->state) { | ||
614 | case OTG_STATE_UNDEFINED: | ||
615 | dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n"); | ||
616 | msm_otg_reset(otg); | ||
617 | msm_otg_init_sm(motg); | ||
618 | otg->state = OTG_STATE_B_IDLE; | ||
619 | /* FALL THROUGH */ | ||
620 | case OTG_STATE_B_IDLE: | ||
621 | dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n"); | ||
622 | if (!test_bit(ID, &motg->inputs) && otg->host) { | ||
623 | /* disable BSV bit */ | ||
624 | writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC); | ||
625 | msm_otg_start_host(otg, 1); | ||
626 | otg->state = OTG_STATE_A_HOST; | ||
627 | } else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) { | ||
628 | msm_otg_start_peripheral(otg, 1); | ||
629 | otg->state = OTG_STATE_B_PERIPHERAL; | ||
630 | } | ||
631 | pm_runtime_put_sync(otg->dev); | ||
632 | break; | ||
633 | case OTG_STATE_B_PERIPHERAL: | ||
634 | dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n"); | ||
635 | if (!test_bit(B_SESS_VLD, &motg->inputs) || | ||
636 | !test_bit(ID, &motg->inputs)) { | ||
637 | msm_otg_start_peripheral(otg, 0); | ||
638 | otg->state = OTG_STATE_B_IDLE; | ||
639 | msm_otg_reset(otg); | ||
640 | schedule_work(w); | ||
641 | } | ||
642 | break; | ||
643 | case OTG_STATE_A_HOST: | ||
644 | dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n"); | ||
645 | if (test_bit(ID, &motg->inputs)) { | ||
646 | msm_otg_start_host(otg, 0); | ||
647 | otg->state = OTG_STATE_B_IDLE; | ||
648 | msm_otg_reset(otg); | ||
649 | schedule_work(w); | ||
650 | } | ||
651 | break; | ||
652 | default: | ||
653 | break; | ||
654 | } | ||
655 | } | ||
656 | |||
657 | static irqreturn_t msm_otg_irq(int irq, void *data) | ||
658 | { | ||
659 | struct msm_otg *motg = data; | ||
660 | struct otg_transceiver *otg = &motg->otg; | ||
661 | u32 otgsc = 0; | ||
662 | |||
663 | if (atomic_read(&motg->in_lpm)) { | ||
664 | disable_irq_nosync(irq); | ||
665 | motg->async_int = 1; | ||
666 | pm_runtime_get(otg->dev); | ||
667 | return IRQ_HANDLED; | ||
668 | } | ||
669 | |||
670 | otgsc = readl(USB_OTGSC); | ||
671 | if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS))) | ||
672 | return IRQ_NONE; | ||
673 | |||
674 | if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) { | ||
675 | if (otgsc & OTGSC_ID) | ||
676 | set_bit(ID, &motg->inputs); | ||
677 | else | ||
678 | clear_bit(ID, &motg->inputs); | ||
679 | dev_dbg(otg->dev, "ID set/clear\n"); | ||
680 | pm_runtime_get_noresume(otg->dev); | ||
681 | } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) { | ||
682 | if (otgsc & OTGSC_BSV) | ||
683 | set_bit(B_SESS_VLD, &motg->inputs); | ||
684 | else | ||
685 | clear_bit(B_SESS_VLD, &motg->inputs); | ||
686 | dev_dbg(otg->dev, "BSV set/clear\n"); | ||
687 | pm_runtime_get_noresume(otg->dev); | ||
688 | } | ||
689 | |||
690 | writel(otgsc, USB_OTGSC); | ||
691 | schedule_work(&motg->sm_work); | ||
692 | return IRQ_HANDLED; | ||
693 | } | ||
694 | |||
695 | static int msm_otg_mode_show(struct seq_file *s, void *unused) | ||
696 | { | ||
697 | struct msm_otg *motg = s->private; | ||
698 | struct otg_transceiver *otg = &motg->otg; | ||
699 | |||
700 | switch (otg->state) { | ||
701 | case OTG_STATE_A_HOST: | ||
702 | seq_printf(s, "host\n"); | ||
703 | break; | ||
704 | case OTG_STATE_B_PERIPHERAL: | ||
705 | seq_printf(s, "peripheral\n"); | ||
706 | break; | ||
707 | default: | ||
708 | seq_printf(s, "none\n"); | ||
709 | break; | ||
710 | } | ||
711 | |||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | static int msm_otg_mode_open(struct inode *inode, struct file *file) | ||
716 | { | ||
717 | return single_open(file, msm_otg_mode_show, inode->i_private); | ||
718 | } | ||
719 | |||
720 | static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, | ||
721 | size_t count, loff_t *ppos) | ||
722 | { | ||
723 | struct msm_otg *motg = file->private_data; | ||
724 | char buf[16]; | ||
725 | struct otg_transceiver *otg = &motg->otg; | ||
726 | int status = count; | ||
727 | enum usb_mode_type req_mode; | ||
728 | |||
729 | memset(buf, 0x00, sizeof(buf)); | ||
730 | |||
731 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) { | ||
732 | status = -EFAULT; | ||
733 | goto out; | ||
734 | } | ||
735 | |||
736 | if (!strncmp(buf, "host", 4)) { | ||
737 | req_mode = USB_HOST; | ||
738 | } else if (!strncmp(buf, "peripheral", 10)) { | ||
739 | req_mode = USB_PERIPHERAL; | ||
740 | } else if (!strncmp(buf, "none", 4)) { | ||
741 | req_mode = USB_NONE; | ||
742 | } else { | ||
743 | status = -EINVAL; | ||
744 | goto out; | ||
745 | } | ||
746 | |||
747 | switch (req_mode) { | ||
748 | case USB_NONE: | ||
749 | switch (otg->state) { | ||
750 | case OTG_STATE_A_HOST: | ||
751 | case OTG_STATE_B_PERIPHERAL: | ||
752 | set_bit(ID, &motg->inputs); | ||
753 | clear_bit(B_SESS_VLD, &motg->inputs); | ||
754 | break; | ||
755 | default: | ||
756 | goto out; | ||
757 | } | ||
758 | break; | ||
759 | case USB_PERIPHERAL: | ||
760 | switch (otg->state) { | ||
761 | case OTG_STATE_B_IDLE: | ||
762 | case OTG_STATE_A_HOST: | ||
763 | set_bit(ID, &motg->inputs); | ||
764 | set_bit(B_SESS_VLD, &motg->inputs); | ||
765 | break; | ||
766 | default: | ||
767 | goto out; | ||
768 | } | ||
769 | break; | ||
770 | case USB_HOST: | ||
771 | switch (otg->state) { | ||
772 | case OTG_STATE_B_IDLE: | ||
773 | case OTG_STATE_B_PERIPHERAL: | ||
774 | clear_bit(ID, &motg->inputs); | ||
775 | break; | ||
776 | default: | ||
777 | goto out; | ||
778 | } | ||
779 | break; | ||
780 | default: | ||
781 | goto out; | ||
782 | } | ||
783 | |||
784 | pm_runtime_get_sync(otg->dev); | ||
785 | schedule_work(&motg->sm_work); | ||
786 | out: | ||
787 | return status; | ||
788 | } | ||
789 | |||
790 | const struct file_operations msm_otg_mode_fops = { | ||
791 | .open = msm_otg_mode_open, | ||
792 | .read = seq_read, | ||
793 | .write = msm_otg_mode_write, | ||
794 | .llseek = seq_lseek, | ||
795 | .release = single_release, | ||
796 | }; | ||
797 | |||
798 | static struct dentry *msm_otg_dbg_root; | ||
799 | static struct dentry *msm_otg_dbg_mode; | ||
800 | |||
801 | static int msm_otg_debugfs_init(struct msm_otg *motg) | ||
802 | { | ||
803 | msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL); | ||
804 | |||
805 | if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root)) | ||
806 | return -ENODEV; | ||
807 | |||
808 | msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO | S_IWUSR, | ||
809 | msm_otg_dbg_root, motg, &msm_otg_mode_fops); | ||
810 | if (!msm_otg_dbg_mode) { | ||
811 | debugfs_remove(msm_otg_dbg_root); | ||
812 | msm_otg_dbg_root = NULL; | ||
813 | return -ENODEV; | ||
814 | } | ||
815 | |||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | static void msm_otg_debugfs_cleanup(void) | ||
820 | { | ||
821 | debugfs_remove(msm_otg_dbg_mode); | ||
822 | debugfs_remove(msm_otg_dbg_root); | ||
823 | } | ||
824 | |||
825 | static int __init msm_otg_probe(struct platform_device *pdev) | ||
826 | { | ||
827 | int ret = 0; | ||
828 | struct resource *res; | ||
829 | struct msm_otg *motg; | ||
830 | struct otg_transceiver *otg; | ||
831 | |||
832 | dev_info(&pdev->dev, "msm_otg probe\n"); | ||
833 | if (!pdev->dev.platform_data) { | ||
834 | dev_err(&pdev->dev, "No platform data given. Bailing out\n"); | ||
835 | return -ENODEV; | ||
836 | } | ||
837 | |||
838 | motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL); | ||
839 | if (!motg) { | ||
840 | dev_err(&pdev->dev, "unable to allocate msm_otg\n"); | ||
841 | return -ENOMEM; | ||
842 | } | ||
843 | |||
844 | motg->pdata = pdev->dev.platform_data; | ||
845 | otg = &motg->otg; | ||
846 | otg->dev = &pdev->dev; | ||
847 | |||
848 | motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk"); | ||
849 | if (IS_ERR(motg->phy_reset_clk)) { | ||
850 | dev_err(&pdev->dev, "failed to get usb_phy_clk\n"); | ||
851 | ret = PTR_ERR(motg->phy_reset_clk); | ||
852 | goto free_motg; | ||
853 | } | ||
854 | |||
855 | motg->clk = clk_get(&pdev->dev, "usb_hs_clk"); | ||
856 | if (IS_ERR(motg->clk)) { | ||
857 | dev_err(&pdev->dev, "failed to get usb_hs_clk\n"); | ||
858 | ret = PTR_ERR(motg->clk); | ||
859 | goto put_phy_reset_clk; | ||
860 | } | ||
861 | |||
862 | motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk"); | ||
863 | if (IS_ERR(motg->pclk)) { | ||
864 | dev_err(&pdev->dev, "failed to get usb_hs_pclk\n"); | ||
865 | ret = PTR_ERR(motg->pclk); | ||
866 | goto put_clk; | ||
867 | } | ||
868 | |||
869 | /* | ||
870 | * USB core clock is not present on all MSM chips. This | ||
871 | * clock is introduced to remove the dependency on AXI | ||
872 | * bus frequency. | ||
873 | */ | ||
874 | motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk"); | ||
875 | if (IS_ERR(motg->core_clk)) | ||
876 | motg->core_clk = NULL; | ||
877 | |||
878 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
879 | if (!res) { | ||
880 | dev_err(&pdev->dev, "failed to get platform resource mem\n"); | ||
881 | ret = -ENODEV; | ||
882 | goto put_core_clk; | ||
883 | } | ||
884 | |||
885 | motg->regs = ioremap(res->start, resource_size(res)); | ||
886 | if (!motg->regs) { | ||
887 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
888 | ret = -ENOMEM; | ||
889 | goto put_core_clk; | ||
890 | } | ||
891 | dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs); | ||
892 | |||
893 | motg->irq = platform_get_irq(pdev, 0); | ||
894 | if (!motg->irq) { | ||
895 | dev_err(&pdev->dev, "platform_get_irq failed\n"); | ||
896 | ret = -ENODEV; | ||
897 | goto free_regs; | ||
898 | } | ||
899 | |||
900 | clk_enable(motg->clk); | ||
901 | clk_enable(motg->pclk); | ||
902 | if (motg->core_clk) | ||
903 | clk_enable(motg->core_clk); | ||
904 | |||
905 | writel(0, USB_USBINTR); | ||
906 | writel(0, USB_OTGSC); | ||
907 | |||
908 | INIT_WORK(&motg->sm_work, msm_otg_sm_work); | ||
909 | ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED, | ||
910 | "msm_otg", motg); | ||
911 | if (ret) { | ||
912 | dev_err(&pdev->dev, "request irq failed\n"); | ||
913 | goto disable_clks; | ||
914 | } | ||
915 | |||
916 | otg->init = msm_otg_reset; | ||
917 | otg->set_host = msm_otg_set_host; | ||
918 | otg->set_peripheral = msm_otg_set_peripheral; | ||
919 | |||
920 | otg->io_ops = &msm_otg_io_ops; | ||
921 | |||
922 | ret = otg_set_transceiver(&motg->otg); | ||
923 | if (ret) { | ||
924 | dev_err(&pdev->dev, "otg_set_transceiver failed\n"); | ||
925 | goto free_irq; | ||
926 | } | ||
927 | |||
928 | platform_set_drvdata(pdev, motg); | ||
929 | device_init_wakeup(&pdev->dev, 1); | ||
930 | |||
931 | if (motg->pdata->mode == USB_OTG && | ||
932 | motg->pdata->otg_control == OTG_USER_CONTROL) { | ||
933 | ret = msm_otg_debugfs_init(motg); | ||
934 | if (ret) | ||
935 | dev_dbg(&pdev->dev, "mode debugfs file is" | ||
936 | "not available\n"); | ||
937 | } | ||
938 | |||
939 | pm_runtime_set_active(&pdev->dev); | ||
940 | pm_runtime_enable(&pdev->dev); | ||
941 | |||
942 | return 0; | ||
943 | free_irq: | ||
944 | free_irq(motg->irq, motg); | ||
945 | disable_clks: | ||
946 | clk_disable(motg->pclk); | ||
947 | clk_disable(motg->clk); | ||
948 | free_regs: | ||
949 | iounmap(motg->regs); | ||
950 | put_core_clk: | ||
951 | if (motg->core_clk) | ||
952 | clk_put(motg->core_clk); | ||
953 | clk_put(motg->pclk); | ||
954 | put_clk: | ||
955 | clk_put(motg->clk); | ||
956 | put_phy_reset_clk: | ||
957 | clk_put(motg->phy_reset_clk); | ||
958 | free_motg: | ||
959 | kfree(motg); | ||
960 | return ret; | ||
961 | } | ||
962 | |||
963 | static int __devexit msm_otg_remove(struct platform_device *pdev) | ||
964 | { | ||
965 | struct msm_otg *motg = platform_get_drvdata(pdev); | ||
966 | struct otg_transceiver *otg = &motg->otg; | ||
967 | int cnt = 0; | ||
968 | |||
969 | if (otg->host || otg->gadget) | ||
970 | return -EBUSY; | ||
971 | |||
972 | msm_otg_debugfs_cleanup(); | ||
973 | cancel_work_sync(&motg->sm_work); | ||
974 | |||
975 | msm_otg_resume(motg); | ||
976 | |||
977 | device_init_wakeup(&pdev->dev, 0); | ||
978 | pm_runtime_disable(&pdev->dev); | ||
979 | |||
980 | otg_set_transceiver(NULL); | ||
981 | free_irq(motg->irq, motg); | ||
982 | |||
983 | /* | ||
984 | * Put PHY in low power mode. | ||
985 | */ | ||
986 | ulpi_read(otg, 0x14); | ||
987 | ulpi_write(otg, 0x08, 0x09); | ||
988 | |||
989 | writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); | ||
990 | while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { | ||
991 | if (readl(USB_PORTSC) & PORTSC_PHCD) | ||
992 | break; | ||
993 | udelay(1); | ||
994 | cnt++; | ||
995 | } | ||
996 | if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) | ||
997 | dev_err(otg->dev, "Unable to suspend PHY\n"); | ||
998 | |||
999 | clk_disable(motg->pclk); | ||
1000 | clk_disable(motg->clk); | ||
1001 | if (motg->core_clk) | ||
1002 | clk_disable(motg->core_clk); | ||
1003 | |||
1004 | iounmap(motg->regs); | ||
1005 | pm_runtime_set_suspended(&pdev->dev); | ||
1006 | |||
1007 | clk_put(motg->phy_reset_clk); | ||
1008 | clk_put(motg->pclk); | ||
1009 | clk_put(motg->clk); | ||
1010 | if (motg->core_clk) | ||
1011 | clk_put(motg->core_clk); | ||
1012 | |||
1013 | kfree(motg); | ||
1014 | |||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
1018 | #ifdef CONFIG_PM_RUNTIME | ||
1019 | static int msm_otg_runtime_idle(struct device *dev) | ||
1020 | { | ||
1021 | struct msm_otg *motg = dev_get_drvdata(dev); | ||
1022 | struct otg_transceiver *otg = &motg->otg; | ||
1023 | |||
1024 | dev_dbg(dev, "OTG runtime idle\n"); | ||
1025 | |||
1026 | /* | ||
1027 | * It is observed some times that a spurious interrupt | ||
1028 | * comes when PHY is put into LPM immediately after PHY reset. | ||
1029 | * This 1 sec delay also prevents entering into LPM immediately | ||
1030 | * after asynchronous interrupt. | ||
1031 | */ | ||
1032 | if (otg->state != OTG_STATE_UNDEFINED) | ||
1033 | pm_schedule_suspend(dev, 1000); | ||
1034 | |||
1035 | return -EAGAIN; | ||
1036 | } | ||
1037 | |||
1038 | static int msm_otg_runtime_suspend(struct device *dev) | ||
1039 | { | ||
1040 | struct msm_otg *motg = dev_get_drvdata(dev); | ||
1041 | |||
1042 | dev_dbg(dev, "OTG runtime suspend\n"); | ||
1043 | return msm_otg_suspend(motg); | ||
1044 | } | ||
1045 | |||
1046 | static int msm_otg_runtime_resume(struct device *dev) | ||
1047 | { | ||
1048 | struct msm_otg *motg = dev_get_drvdata(dev); | ||
1049 | |||
1050 | dev_dbg(dev, "OTG runtime resume\n"); | ||
1051 | return msm_otg_resume(motg); | ||
1052 | } | ||
1053 | #else | ||
1054 | #define msm_otg_runtime_idle NULL | ||
1055 | #define msm_otg_runtime_suspend NULL | ||
1056 | #define msm_otg_runtime_resume NULL | ||
1057 | #endif | ||
1058 | |||
1059 | #ifdef CONFIG_PM | ||
1060 | static int msm_otg_pm_suspend(struct device *dev) | ||
1061 | { | ||
1062 | struct msm_otg *motg = dev_get_drvdata(dev); | ||
1063 | |||
1064 | dev_dbg(dev, "OTG PM suspend\n"); | ||
1065 | return msm_otg_suspend(motg); | ||
1066 | } | ||
1067 | |||
1068 | static int msm_otg_pm_resume(struct device *dev) | ||
1069 | { | ||
1070 | struct msm_otg *motg = dev_get_drvdata(dev); | ||
1071 | int ret; | ||
1072 | |||
1073 | dev_dbg(dev, "OTG PM resume\n"); | ||
1074 | |||
1075 | ret = msm_otg_resume(motg); | ||
1076 | if (ret) | ||
1077 | return ret; | ||
1078 | |||
1079 | /* | ||
1080 | * Runtime PM Documentation recommends bringing the | ||
1081 | * device to full powered state upon resume. | ||
1082 | */ | ||
1083 | pm_runtime_disable(dev); | ||
1084 | pm_runtime_set_active(dev); | ||
1085 | pm_runtime_enable(dev); | ||
1086 | |||
1087 | return 0; | ||
1088 | } | ||
1089 | #else | ||
1090 | #define msm_otg_pm_suspend NULL | ||
1091 | #define msm_otg_pm_resume NULL | ||
1092 | #endif | ||
1093 | |||
1094 | static const struct dev_pm_ops msm_otg_dev_pm_ops = { | ||
1095 | .runtime_suspend = msm_otg_runtime_suspend, | ||
1096 | .runtime_resume = msm_otg_runtime_resume, | ||
1097 | .runtime_idle = msm_otg_runtime_idle, | ||
1098 | .suspend = msm_otg_pm_suspend, | ||
1099 | .resume = msm_otg_pm_resume, | ||
1100 | }; | ||
1101 | |||
1102 | static struct platform_driver msm_otg_driver = { | ||
1103 | .remove = __devexit_p(msm_otg_remove), | ||
1104 | .driver = { | ||
1105 | .name = DRIVER_NAME, | ||
1106 | .owner = THIS_MODULE, | ||
1107 | .pm = &msm_otg_dev_pm_ops, | ||
1108 | }, | ||
1109 | }; | ||
1110 | |||
1111 | static int __init msm_otg_init(void) | ||
1112 | { | ||
1113 | return platform_driver_probe(&msm_otg_driver, msm_otg_probe); | ||
1114 | } | ||
1115 | |||
1116 | static void __exit msm_otg_exit(void) | ||
1117 | { | ||
1118 | platform_driver_unregister(&msm_otg_driver); | ||
1119 | } | ||
1120 | |||
1121 | module_init(msm_otg_init); | ||
1122 | module_exit(msm_otg_exit); | ||
1123 | |||
1124 | MODULE_LICENSE("GPL v2"); | ||
1125 | MODULE_DESCRIPTION("MSM USB transceiver driver"); | ||
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index d335f484fcd8..6ca505f333e4 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c | |||
@@ -678,7 +678,8 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) | |||
678 | /* disable complete OTG block */ | 678 | /* disable complete OTG block */ |
679 | twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); | 679 | twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); |
680 | 680 | ||
681 | twl4030_phy_power(twl, 0); | 681 | if (!twl->asleep) |
682 | twl4030_phy_power(twl, 0); | ||
682 | regulator_put(twl->usb1v5); | 683 | regulator_put(twl->usb1v5); |
683 | regulator_put(twl->usb1v8); | 684 | regulator_put(twl->usb1v8); |
684 | regulator_put(twl->usb3v1); | 685 | regulator_put(twl->usb3v1); |
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c new file mode 100644 index 000000000000..28f770103640 --- /dev/null +++ b/drivers/usb/otg/twl6030-usb.c | |||
@@ -0,0 +1,493 @@ | |||
1 | /* | ||
2 | * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver. | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * Author: Hema HK <hemahk@ti.com> | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/usb/otg.h> | ||
29 | #include <linux/i2c/twl.h> | ||
30 | #include <linux/regulator/consumer.h> | ||
31 | #include <linux/err.h> | ||
32 | #include <linux/notifier.h> | ||
33 | #include <linux/slab.h> | ||
34 | |||
35 | /* usb register definitions */ | ||
36 | #define USB_VENDOR_ID_LSB 0x00 | ||
37 | #define USB_VENDOR_ID_MSB 0x01 | ||
38 | #define USB_PRODUCT_ID_LSB 0x02 | ||
39 | #define USB_PRODUCT_ID_MSB 0x03 | ||
40 | #define USB_VBUS_CTRL_SET 0x04 | ||
41 | #define USB_VBUS_CTRL_CLR 0x05 | ||
42 | #define USB_ID_CTRL_SET 0x06 | ||
43 | #define USB_ID_CTRL_CLR 0x07 | ||
44 | #define USB_VBUS_INT_SRC 0x08 | ||
45 | #define USB_VBUS_INT_LATCH_SET 0x09 | ||
46 | #define USB_VBUS_INT_LATCH_CLR 0x0A | ||
47 | #define USB_VBUS_INT_EN_LO_SET 0x0B | ||
48 | #define USB_VBUS_INT_EN_LO_CLR 0x0C | ||
49 | #define USB_VBUS_INT_EN_HI_SET 0x0D | ||
50 | #define USB_VBUS_INT_EN_HI_CLR 0x0E | ||
51 | #define USB_ID_INT_SRC 0x0F | ||
52 | #define USB_ID_INT_LATCH_SET 0x10 | ||
53 | #define USB_ID_INT_LATCH_CLR 0x11 | ||
54 | |||
55 | #define USB_ID_INT_EN_LO_SET 0x12 | ||
56 | #define USB_ID_INT_EN_LO_CLR 0x13 | ||
57 | #define USB_ID_INT_EN_HI_SET 0x14 | ||
58 | #define USB_ID_INT_EN_HI_CLR 0x15 | ||
59 | #define USB_OTG_ADP_CTRL 0x16 | ||
60 | #define USB_OTG_ADP_HIGH 0x17 | ||
61 | #define USB_OTG_ADP_LOW 0x18 | ||
62 | #define USB_OTG_ADP_RISE 0x19 | ||
63 | #define USB_OTG_REVISION 0x1A | ||
64 | |||
65 | /* to be moved to LDO */ | ||
66 | #define TWL6030_MISC2 0xE5 | ||
67 | #define TWL6030_CFG_LDO_PD2 0xF5 | ||
68 | #define TWL6030_BACKUP_REG 0xFA | ||
69 | |||
70 | #define STS_HW_CONDITIONS 0x21 | ||
71 | |||
72 | /* In module TWL6030_MODULE_PM_MASTER */ | ||
73 | #define STS_HW_CONDITIONS 0x21 | ||
74 | #define STS_USB_ID BIT(2) | ||
75 | |||
76 | /* In module TWL6030_MODULE_PM_RECEIVER */ | ||
77 | #define VUSB_CFG_TRANS 0x71 | ||
78 | #define VUSB_CFG_STATE 0x72 | ||
79 | #define VUSB_CFG_VOLTAGE 0x73 | ||
80 | |||
81 | /* in module TWL6030_MODULE_MAIN_CHARGE */ | ||
82 | |||
83 | #define CHARGERUSB_CTRL1 0x8 | ||
84 | |||
85 | #define CONTROLLER_STAT1 0x03 | ||
86 | #define VBUS_DET BIT(2) | ||
87 | |||
88 | struct twl6030_usb { | ||
89 | struct otg_transceiver otg; | ||
90 | struct device *dev; | ||
91 | |||
92 | /* for vbus reporting with irqs disabled */ | ||
93 | spinlock_t lock; | ||
94 | |||
95 | struct regulator *usb3v3; | ||
96 | |||
97 | int irq1; | ||
98 | int irq2; | ||
99 | u8 linkstat; | ||
100 | u8 asleep; | ||
101 | bool irq_enabled; | ||
102 | }; | ||
103 | |||
104 | #define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg); | ||
105 | |||
106 | /*-------------------------------------------------------------------------*/ | ||
107 | |||
108 | static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module, | ||
109 | u8 data, u8 address) | ||
110 | { | ||
111 | int ret = 0; | ||
112 | |||
113 | ret = twl_i2c_write_u8(module, data, address); | ||
114 | if (ret < 0) | ||
115 | dev_err(twl->dev, | ||
116 | "Write[0x%x] Error %d\n", address, ret); | ||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address) | ||
121 | { | ||
122 | u8 data, ret = 0; | ||
123 | |||
124 | ret = twl_i2c_read_u8(module, &data, address); | ||
125 | if (ret >= 0) | ||
126 | ret = data; | ||
127 | else | ||
128 | dev_err(twl->dev, | ||
129 | "readb[0x%x,0x%x] Error %d\n", | ||
130 | module, address, ret); | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | /*-------------------------------------------------------------------------*/ | ||
135 | static int twl6030_set_phy_clk(struct otg_transceiver *x, int on) | ||
136 | { | ||
137 | struct twl6030_usb *twl; | ||
138 | struct device *dev; | ||
139 | struct twl4030_usb_data *pdata; | ||
140 | |||
141 | twl = xceiv_to_twl(x); | ||
142 | dev = twl->dev; | ||
143 | pdata = dev->platform_data; | ||
144 | |||
145 | pdata->phy_set_clock(twl->dev, on); | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int twl6030_phy_init(struct otg_transceiver *x) | ||
151 | { | ||
152 | u8 hw_state; | ||
153 | struct twl6030_usb *twl; | ||
154 | struct device *dev; | ||
155 | struct twl4030_usb_data *pdata; | ||
156 | |||
157 | twl = xceiv_to_twl(x); | ||
158 | dev = twl->dev; | ||
159 | pdata = dev->platform_data; | ||
160 | |||
161 | regulator_enable(twl->usb3v3); | ||
162 | |||
163 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | ||
164 | |||
165 | if (hw_state & STS_USB_ID) | ||
166 | pdata->phy_power(twl->dev, 1, 1); | ||
167 | else | ||
168 | pdata->phy_power(twl->dev, 0, 1); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static void twl6030_phy_shutdown(struct otg_transceiver *x) | ||
174 | { | ||
175 | struct twl6030_usb *twl; | ||
176 | struct device *dev; | ||
177 | struct twl4030_usb_data *pdata; | ||
178 | |||
179 | twl = xceiv_to_twl(x); | ||
180 | dev = twl->dev; | ||
181 | pdata = dev->platform_data; | ||
182 | pdata->phy_power(twl->dev, 0, 0); | ||
183 | regulator_disable(twl->usb3v3); | ||
184 | } | ||
185 | |||
186 | static int twl6030_usb_ldo_init(struct twl6030_usb *twl) | ||
187 | { | ||
188 | |||
189 | /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ | ||
190 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); | ||
191 | |||
192 | /* Program CFG_LDO_PD2 register and set VUSB bit */ | ||
193 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2); | ||
194 | |||
195 | /* Program MISC2 register and set bit VUSB_IN_VBAT */ | ||
196 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); | ||
197 | |||
198 | twl->usb3v3 = regulator_get(twl->dev, "vusb"); | ||
199 | if (IS_ERR(twl->usb3v3)) | ||
200 | return -ENODEV; | ||
201 | |||
202 | regulator_enable(twl->usb3v3); | ||
203 | |||
204 | /* Program the VUSB_CFG_TRANS for ACTIVE state. */ | ||
205 | twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x3F, | ||
206 | VUSB_CFG_TRANS); | ||
207 | |||
208 | /* Program the VUSB_CFG_STATE register to ON on all groups. */ | ||
209 | twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0xE1, | ||
210 | VUSB_CFG_STATE); | ||
211 | |||
212 | /* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */ | ||
213 | twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET); | ||
214 | |||
215 | /* | ||
216 | * Program the USB_ID_CTRL_SET register to enable GND drive | ||
217 | * and the ID comparators | ||
218 | */ | ||
219 | twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static ssize_t twl6030_usb_vbus_show(struct device *dev, | ||
225 | struct device_attribute *attr, char *buf) | ||
226 | { | ||
227 | struct twl6030_usb *twl = dev_get_drvdata(dev); | ||
228 | unsigned long flags; | ||
229 | int ret = -EINVAL; | ||
230 | |||
231 | spin_lock_irqsave(&twl->lock, flags); | ||
232 | |||
233 | switch (twl->linkstat) { | ||
234 | case USB_EVENT_VBUS: | ||
235 | ret = snprintf(buf, PAGE_SIZE, "vbus\n"); | ||
236 | break; | ||
237 | case USB_EVENT_ID: | ||
238 | ret = snprintf(buf, PAGE_SIZE, "id\n"); | ||
239 | break; | ||
240 | case USB_EVENT_NONE: | ||
241 | ret = snprintf(buf, PAGE_SIZE, "none\n"); | ||
242 | break; | ||
243 | default: | ||
244 | ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n"); | ||
245 | } | ||
246 | spin_unlock_irqrestore(&twl->lock, flags); | ||
247 | |||
248 | return ret; | ||
249 | } | ||
250 | static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL); | ||
251 | |||
252 | static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | ||
253 | { | ||
254 | struct twl6030_usb *twl = _twl; | ||
255 | int status; | ||
256 | u8 vbus_state, hw_state; | ||
257 | |||
258 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | ||
259 | |||
260 | vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE, | ||
261 | CONTROLLER_STAT1); | ||
262 | if (!(hw_state & STS_USB_ID)) { | ||
263 | if (vbus_state & VBUS_DET) { | ||
264 | status = USB_EVENT_VBUS; | ||
265 | twl->otg.default_a = false; | ||
266 | twl->otg.state = OTG_STATE_B_IDLE; | ||
267 | } else { | ||
268 | status = USB_EVENT_NONE; | ||
269 | } | ||
270 | if (status >= 0) { | ||
271 | twl->linkstat = status; | ||
272 | blocking_notifier_call_chain(&twl->otg.notifier, | ||
273 | status, twl->otg.gadget); | ||
274 | } | ||
275 | } | ||
276 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); | ||
277 | |||
278 | return IRQ_HANDLED; | ||
279 | } | ||
280 | |||
281 | static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | ||
282 | { | ||
283 | struct twl6030_usb *twl = _twl; | ||
284 | int status = USB_EVENT_NONE; | ||
285 | u8 hw_state; | ||
286 | |||
287 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | ||
288 | |||
289 | if (hw_state & STS_USB_ID) { | ||
290 | |||
291 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1); | ||
292 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, | ||
293 | 0x10); | ||
294 | status = USB_EVENT_ID; | ||
295 | twl->otg.default_a = true; | ||
296 | twl->otg.state = OTG_STATE_A_IDLE; | ||
297 | blocking_notifier_call_chain(&twl->otg.notifier, status, | ||
298 | twl->otg.gadget); | ||
299 | } else { | ||
300 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, | ||
301 | 0x10); | ||
302 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, | ||
303 | 0x1); | ||
304 | } | ||
305 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status); | ||
306 | twl->linkstat = status; | ||
307 | |||
308 | return IRQ_HANDLED; | ||
309 | } | ||
310 | |||
311 | static int twl6030_set_peripheral(struct otg_transceiver *x, | ||
312 | struct usb_gadget *gadget) | ||
313 | { | ||
314 | struct twl6030_usb *twl; | ||
315 | |||
316 | if (!x) | ||
317 | return -ENODEV; | ||
318 | |||
319 | twl = xceiv_to_twl(x); | ||
320 | twl->otg.gadget = gadget; | ||
321 | if (!gadget) | ||
322 | twl->otg.state = OTG_STATE_UNDEFINED; | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int twl6030_enable_irq(struct otg_transceiver *x) | ||
328 | { | ||
329 | struct twl6030_usb *twl = xceiv_to_twl(x); | ||
330 | |||
331 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1); | ||
332 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); | ||
333 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C); | ||
334 | |||
335 | twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, | ||
336 | REG_INT_MSK_LINE_C); | ||
337 | twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, | ||
338 | REG_INT_MSK_STS_C); | ||
339 | twl6030_usb_irq(twl->irq2, twl); | ||
340 | twl6030_usbotg_irq(twl->irq1, twl); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) | ||
346 | { | ||
347 | struct twl6030_usb *twl = xceiv_to_twl(x); | ||
348 | |||
349 | /* | ||
350 | * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1 | ||
351 | * register. This enables boost mode. | ||
352 | */ | ||
353 | if (enabled) | ||
354 | twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40, | ||
355 | CHARGERUSB_CTRL1); | ||
356 | else | ||
357 | twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00, | ||
358 | CHARGERUSB_CTRL1); | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host) | ||
363 | { | ||
364 | struct twl6030_usb *twl; | ||
365 | |||
366 | if (!x) | ||
367 | return -ENODEV; | ||
368 | |||
369 | twl = xceiv_to_twl(x); | ||
370 | twl->otg.host = host; | ||
371 | if (!host) | ||
372 | twl->otg.state = OTG_STATE_UNDEFINED; | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static int __devinit twl6030_usb_probe(struct platform_device *pdev) | ||
377 | { | ||
378 | struct twl6030_usb *twl; | ||
379 | int status, err; | ||
380 | struct twl4030_usb_data *pdata; | ||
381 | struct device *dev = &pdev->dev; | ||
382 | pdata = dev->platform_data; | ||
383 | |||
384 | twl = kzalloc(sizeof *twl, GFP_KERNEL); | ||
385 | if (!twl) | ||
386 | return -ENOMEM; | ||
387 | |||
388 | twl->dev = &pdev->dev; | ||
389 | twl->irq1 = platform_get_irq(pdev, 0); | ||
390 | twl->irq2 = platform_get_irq(pdev, 1); | ||
391 | twl->otg.dev = twl->dev; | ||
392 | twl->otg.label = "twl6030"; | ||
393 | twl->otg.set_host = twl6030_set_host; | ||
394 | twl->otg.set_peripheral = twl6030_set_peripheral; | ||
395 | twl->otg.set_vbus = twl6030_set_vbus; | ||
396 | twl->otg.init = twl6030_phy_init; | ||
397 | twl->otg.shutdown = twl6030_phy_shutdown; | ||
398 | |||
399 | /* init spinlock for workqueue */ | ||
400 | spin_lock_init(&twl->lock); | ||
401 | |||
402 | err = twl6030_usb_ldo_init(twl); | ||
403 | if (err) { | ||
404 | dev_err(&pdev->dev, "ldo init failed\n"); | ||
405 | kfree(twl); | ||
406 | return err; | ||
407 | } | ||
408 | otg_set_transceiver(&twl->otg); | ||
409 | |||
410 | platform_set_drvdata(pdev, twl); | ||
411 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | ||
412 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | ||
413 | |||
414 | BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier); | ||
415 | |||
416 | twl->irq_enabled = true; | ||
417 | status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, | ||
418 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
419 | "twl6030_usb", twl); | ||
420 | if (status < 0) { | ||
421 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
422 | twl->irq1, status); | ||
423 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
424 | kfree(twl); | ||
425 | return status; | ||
426 | } | ||
427 | |||
428 | status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq, | ||
429 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
430 | "twl6030_usb", twl); | ||
431 | if (status < 0) { | ||
432 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
433 | twl->irq2, status); | ||
434 | free_irq(twl->irq1, twl); | ||
435 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
436 | kfree(twl); | ||
437 | return status; | ||
438 | } | ||
439 | |||
440 | pdata->phy_init(dev); | ||
441 | twl6030_enable_irq(&twl->otg); | ||
442 | dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int __exit twl6030_usb_remove(struct platform_device *pdev) | ||
448 | { | ||
449 | struct twl6030_usb *twl = platform_get_drvdata(pdev); | ||
450 | |||
451 | struct twl4030_usb_data *pdata; | ||
452 | struct device *dev = &pdev->dev; | ||
453 | pdata = dev->platform_data; | ||
454 | |||
455 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, | ||
456 | REG_INT_MSK_LINE_C); | ||
457 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, | ||
458 | REG_INT_MSK_STS_C); | ||
459 | free_irq(twl->irq1, twl); | ||
460 | free_irq(twl->irq2, twl); | ||
461 | regulator_put(twl->usb3v3); | ||
462 | pdata->phy_exit(twl->dev); | ||
463 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
464 | kfree(twl); | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static struct platform_driver twl6030_usb_driver = { | ||
470 | .probe = twl6030_usb_probe, | ||
471 | .remove = __exit_p(twl6030_usb_remove), | ||
472 | .driver = { | ||
473 | .name = "twl6030_usb", | ||
474 | .owner = THIS_MODULE, | ||
475 | }, | ||
476 | }; | ||
477 | |||
478 | static int __init twl6030_usb_init(void) | ||
479 | { | ||
480 | return platform_driver_register(&twl6030_usb_driver); | ||
481 | } | ||
482 | subsys_initcall(twl6030_usb_init); | ||
483 | |||
484 | static void __exit twl6030_usb_exit(void) | ||
485 | { | ||
486 | platform_driver_unregister(&twl6030_usb_driver); | ||
487 | } | ||
488 | module_exit(twl6030_usb_exit); | ||
489 | |||
490 | MODULE_ALIAS("platform:twl6030_usb"); | ||
491 | MODULE_AUTHOR("Hema HK <hemahk@ti.com>"); | ||
492 | MODULE_DESCRIPTION("TWL6030 USB transceiver driver"); | ||
493 | MODULE_LICENSE("GPL"); | ||