diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/usb/otg | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/usb/otg')
-rw-r--r-- | drivers/usb/otg/Kconfig | 63 | ||||
-rw-r--r-- | drivers/usb/otg/Makefile | 14 | ||||
-rw-r--r-- | drivers/usb/otg/ab8500-usb.c | 585 | ||||
-rw-r--r-- | drivers/usb/otg/fsl_otg.c | 1169 | ||||
-rw-r--r-- | drivers/usb/otg/fsl_otg.h | 406 | ||||
-rw-r--r-- | drivers/usb/otg/gpio_vbus.c | 14 | ||||
-rw-r--r-- | drivers/usb/otg/isp1301_omap.c | 32 | ||||
-rw-r--r-- | drivers/usb/otg/langwell_otg.c | 2347 | ||||
-rw-r--r-- | drivers/usb/otg/msm_otg.c | 1761 | ||||
-rw-r--r-- | drivers/usb/otg/nop-usb-xceiv.c | 2 | ||||
-rw-r--r-- | drivers/usb/otg/otg.c | 35 | ||||
-rw-r--r-- | drivers/usb/otg/otg_fsm.c | 349 | ||||
-rw-r--r-- | drivers/usb/otg/otg_fsm.h | 154 | ||||
-rw-r--r-- | drivers/usb/otg/twl4030-usb.c | 33 | ||||
-rw-r--r-- | drivers/usb/otg/twl6030-usb.c | 526 | ||||
-rw-r--r-- | drivers/usb/otg/ulpi.c | 60 | ||||
-rw-r--r-- | drivers/usb/otg/ulpi_viewport.c | 80 |
17 files changed, 7576 insertions, 54 deletions
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 3b1289572d72..c66481ad98d7 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -49,6 +49,13 @@ config USB_ULPI | |||
49 | Enable this to support ULPI connected USB OTG transceivers which | 49 | Enable this to support ULPI connected USB OTG transceivers which |
50 | are likely found on embedded boards. | 50 | are likely found on embedded boards. |
51 | 51 | ||
52 | config USB_ULPI_VIEWPORT | ||
53 | bool | ||
54 | depends on USB_ULPI | ||
55 | help | ||
56 | Provides read/write operations to the ULPI phy register set for | ||
57 | controllers with a viewport register (e.g. Chipidea/ARC controllers). | ||
58 | |||
52 | config TWL4030_USB | 59 | config TWL4030_USB |
53 | tristate "TWL4030 USB Transceiver Driver" | 60 | tristate "TWL4030 USB Transceiver Driver" |
54 | depends on TWL4030_CORE && REGULATOR_TWL4030 | 61 | depends on TWL4030_CORE && REGULATOR_TWL4030 |
@@ -59,6 +66,18 @@ config TWL4030_USB | |||
59 | This transceiver supports high and full speed devices plus, | 66 | This transceiver supports high and full speed devices plus, |
60 | in host mode, low speed. | 67 | in host mode, low speed. |
61 | 68 | ||
69 | config TWL6030_USB | ||
70 | tristate "TWL6030 USB Transceiver Driver" | ||
71 | depends on TWL4030_CORE | ||
72 | select USB_OTG_UTILS | ||
73 | help | ||
74 | Enable this to support the USB OTG transceiver on TWL6030 | ||
75 | family chips. This TWL6030 transceiver has the VBUS and ID GND | ||
76 | and OTG SRP events capabilities. For all other transceiver functionality | ||
77 | UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs | ||
78 | are hooked to this driver through platform_data structure. | ||
79 | The definition of internal PHY APIs are in the mach-omap2 layer. | ||
80 | |||
62 | config NOP_USB_XCEIV | 81 | config NOP_USB_XCEIV |
63 | tristate "NOP USB Transceiver Driver" | 82 | tristate "NOP USB Transceiver Driver" |
64 | select USB_OTG_UTILS | 83 | select USB_OTG_UTILS |
@@ -67,4 +86,48 @@ config NOP_USB_XCEIV | |||
67 | built-in with usb ip or which are autonomous and doesn't require any | 86 | built-in with usb ip or which are autonomous and doesn't require any |
68 | phy programming such as ISP1x04 etc. | 87 | phy programming such as ISP1x04 etc. |
69 | 88 | ||
89 | config USB_LANGWELL_OTG | ||
90 | tristate "Intel Langwell USB OTG dual-role support" | ||
91 | depends on USB && PCI && INTEL_SCU_IPC | ||
92 | select USB_OTG | ||
93 | select USB_OTG_UTILS | ||
94 | help | ||
95 | Say Y here if you want to build Intel Langwell USB OTG | ||
96 | transciever driver in kernel. This driver implements role | ||
97 | switch between EHCI host driver and Langwell USB OTG | ||
98 | client driver. | ||
99 | |||
100 | To compile this driver as a module, choose M here: the | ||
101 | module will be called langwell_otg. | ||
102 | |||
103 | config USB_MSM_OTG | ||
104 | tristate "OTG support for Qualcomm on-chip USB controller" | ||
105 | depends on (USB || USB_GADGET) && ARCH_MSM | ||
106 | select USB_OTG_UTILS | ||
107 | help | ||
108 | Enable this to support the USB OTG transceiver on MSM chips. It | ||
109 | handles PHY initialization, clock management, and workarounds | ||
110 | required after resetting the hardware and power management. | ||
111 | This driver is required even for peripheral only or host only | ||
112 | mode configurations. | ||
113 | This driver is not supported on boards like trout which | ||
114 | has an external PHY. | ||
115 | |||
116 | config AB8500_USB | ||
117 | tristate "AB8500 USB Transceiver Driver" | ||
118 | depends on AB8500_CORE | ||
119 | select USB_OTG_UTILS | ||
120 | help | ||
121 | Enable this to support the USB OTG transceiver in AB8500 chip. | ||
122 | This transceiver supports high and full speed devices plus, | ||
123 | in host mode, low speed. | ||
124 | |||
125 | config FSL_USB2_OTG | ||
126 | bool "Freescale USB OTG Transceiver Driver" | ||
127 | depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 | ||
128 | select USB_OTG | ||
129 | select USB_OTG_UTILS | ||
130 | help | ||
131 | Enable this to support Freescale USB OTG transceiver. | ||
132 | |||
70 | endif # USB || OTG | 133 | endif # USB || OTG |
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index aeb49a8ec412..566655c53331 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile | |||
@@ -2,6 +2,9 @@ | |||
2 | # OTG infrastructure and transceiver drivers | 2 | # OTG infrastructure and transceiver drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG | ||
6 | ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG | ||
7 | |||
5 | # infrastructure | 8 | # infrastructure |
6 | obj-$(CONFIG_USB_OTG_UTILS) += otg.o | 9 | obj-$(CONFIG_USB_OTG_UTILS) += otg.o |
7 | 10 | ||
@@ -9,9 +12,12 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o | |||
9 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o | 12 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o |
10 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o | 13 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o |
11 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o | 14 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o |
15 | obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o | ||
16 | obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o | ||
12 | obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o | 17 | obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o |
13 | obj-$(CONFIG_USB_ULPI) += ulpi.o | 18 | obj-$(CONFIG_USB_ULPI) += ulpi.o |
14 | 19 | obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o | |
15 | ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG | 20 | obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o |
16 | ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG | 21 | obj-$(CONFIG_AB8500_USB) += ab8500-usb.o |
17 | 22 | fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o | |
23 | obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o | ||
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c new file mode 100644 index 000000000000..07ccea9ada40 --- /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 | atomic_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 | atomic_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 | ATOMIC_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/fsl_otg.c b/drivers/usb/otg/fsl_otg.c new file mode 100644 index 000000000000..0f420b25e9a9 --- /dev/null +++ b/drivers/usb/otg/fsl_otg.c | |||
@@ -0,0 +1,1169 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007,2008 Freescale semiconductor, Inc. | ||
3 | * | ||
4 | * Author: Li Yang <LeoLi@freescale.com> | ||
5 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
6 | * | ||
7 | * Initialization based on code from Shlomi Gridish. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/proc_fs.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/io.h> | ||
33 | #include <linux/timer.h> | ||
34 | #include <linux/usb.h> | ||
35 | #include <linux/device.h> | ||
36 | #include <linux/usb/ch9.h> | ||
37 | #include <linux/usb/gadget.h> | ||
38 | #include <linux/workqueue.h> | ||
39 | #include <linux/time.h> | ||
40 | #include <linux/fsl_devices.h> | ||
41 | #include <linux/platform_device.h> | ||
42 | #include <linux/uaccess.h> | ||
43 | |||
44 | #include <asm/unaligned.h> | ||
45 | |||
46 | #include "fsl_otg.h" | ||
47 | |||
48 | #define DRIVER_VERSION "Rev. 1.55" | ||
49 | #define DRIVER_AUTHOR "Jerry Huang/Li Yang" | ||
50 | #define DRIVER_DESC "Freescale USB OTG Transceiver Driver" | ||
51 | #define DRIVER_INFO DRIVER_DESC " " DRIVER_VERSION | ||
52 | |||
53 | static const char driver_name[] = "fsl-usb2-otg"; | ||
54 | |||
55 | const pm_message_t otg_suspend_state = { | ||
56 | .event = 1, | ||
57 | }; | ||
58 | |||
59 | #define HA_DATA_PULSE | ||
60 | |||
61 | static struct usb_dr_mmap *usb_dr_regs; | ||
62 | static struct fsl_otg *fsl_otg_dev; | ||
63 | static int srp_wait_done; | ||
64 | |||
65 | /* FSM timers */ | ||
66 | struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr, | ||
67 | *b_ase0_brst_tmr, *b_se0_srp_tmr; | ||
68 | |||
69 | /* Driver specific timers */ | ||
70 | struct fsl_otg_timer *b_data_pulse_tmr, *b_vbus_pulse_tmr, *b_srp_fail_tmr, | ||
71 | *b_srp_wait_tmr, *a_wait_enum_tmr; | ||
72 | |||
73 | static struct list_head active_timers; | ||
74 | |||
75 | static struct fsl_otg_config fsl_otg_initdata = { | ||
76 | .otg_port = 1, | ||
77 | }; | ||
78 | |||
79 | #ifdef CONFIG_PPC32 | ||
80 | static u32 _fsl_readl_be(const unsigned __iomem *p) | ||
81 | { | ||
82 | return in_be32(p); | ||
83 | } | ||
84 | |||
85 | static u32 _fsl_readl_le(const unsigned __iomem *p) | ||
86 | { | ||
87 | return in_le32(p); | ||
88 | } | ||
89 | |||
90 | static void _fsl_writel_be(u32 v, unsigned __iomem *p) | ||
91 | { | ||
92 | out_be32(p, v); | ||
93 | } | ||
94 | |||
95 | static void _fsl_writel_le(u32 v, unsigned __iomem *p) | ||
96 | { | ||
97 | out_le32(p, v); | ||
98 | } | ||
99 | |||
100 | static u32 (*_fsl_readl)(const unsigned __iomem *p); | ||
101 | static void (*_fsl_writel)(u32 v, unsigned __iomem *p); | ||
102 | |||
103 | #define fsl_readl(p) (*_fsl_readl)((p)) | ||
104 | #define fsl_writel(v, p) (*_fsl_writel)((v), (p)) | ||
105 | |||
106 | #else | ||
107 | #define fsl_readl(addr) readl(addr) | ||
108 | #define fsl_writel(val, addr) writel(val, addr) | ||
109 | #endif /* CONFIG_PPC32 */ | ||
110 | |||
111 | /* Routines to access transceiver ULPI registers */ | ||
112 | u8 view_ulpi(u8 addr) | ||
113 | { | ||
114 | u32 temp; | ||
115 | |||
116 | temp = 0x40000000 | (addr << 16); | ||
117 | fsl_writel(temp, &usb_dr_regs->ulpiview); | ||
118 | udelay(1000); | ||
119 | while (temp & 0x40) | ||
120 | temp = fsl_readl(&usb_dr_regs->ulpiview); | ||
121 | return (le32_to_cpu(temp) & 0x0000ff00) >> 8; | ||
122 | } | ||
123 | |||
124 | int write_ulpi(u8 addr, u8 data) | ||
125 | { | ||
126 | u32 temp; | ||
127 | |||
128 | temp = 0x60000000 | (addr << 16) | data; | ||
129 | fsl_writel(temp, &usb_dr_regs->ulpiview); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | /* -------------------------------------------------------------*/ | ||
134 | /* Operations that will be called from OTG Finite State Machine */ | ||
135 | |||
136 | /* Charge vbus for vbus pulsing in SRP */ | ||
137 | void fsl_otg_chrg_vbus(int on) | ||
138 | { | ||
139 | u32 tmp; | ||
140 | |||
141 | tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; | ||
142 | |||
143 | if (on) | ||
144 | /* stop discharging, start charging */ | ||
145 | tmp = (tmp & ~OTGSC_CTRL_VBUS_DISCHARGE) | | ||
146 | OTGSC_CTRL_VBUS_CHARGE; | ||
147 | else | ||
148 | /* stop charging */ | ||
149 | tmp &= ~OTGSC_CTRL_VBUS_CHARGE; | ||
150 | |||
151 | fsl_writel(tmp, &usb_dr_regs->otgsc); | ||
152 | } | ||
153 | |||
154 | /* Discharge vbus through a resistor to ground */ | ||
155 | void fsl_otg_dischrg_vbus(int on) | ||
156 | { | ||
157 | u32 tmp; | ||
158 | |||
159 | tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; | ||
160 | |||
161 | if (on) | ||
162 | /* stop charging, start discharging */ | ||
163 | tmp = (tmp & ~OTGSC_CTRL_VBUS_CHARGE) | | ||
164 | OTGSC_CTRL_VBUS_DISCHARGE; | ||
165 | else | ||
166 | /* stop discharging */ | ||
167 | tmp &= ~OTGSC_CTRL_VBUS_DISCHARGE; | ||
168 | |||
169 | fsl_writel(tmp, &usb_dr_regs->otgsc); | ||
170 | } | ||
171 | |||
172 | /* A-device driver vbus, controlled through PP bit in PORTSC */ | ||
173 | void fsl_otg_drv_vbus(int on) | ||
174 | { | ||
175 | u32 tmp; | ||
176 | |||
177 | if (on) { | ||
178 | tmp = fsl_readl(&usb_dr_regs->portsc) & ~PORTSC_W1C_BITS; | ||
179 | fsl_writel(tmp | PORTSC_PORT_POWER, &usb_dr_regs->portsc); | ||
180 | } else { | ||
181 | tmp = fsl_readl(&usb_dr_regs->portsc) & | ||
182 | ~PORTSC_W1C_BITS & ~PORTSC_PORT_POWER; | ||
183 | fsl_writel(tmp, &usb_dr_regs->portsc); | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * Pull-up D+, signalling connect by periperal. Also used in | ||
189 | * data-line pulsing in SRP | ||
190 | */ | ||
191 | void fsl_otg_loc_conn(int on) | ||
192 | { | ||
193 | u32 tmp; | ||
194 | |||
195 | tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; | ||
196 | |||
197 | if (on) | ||
198 | tmp |= OTGSC_CTRL_DATA_PULSING; | ||
199 | else | ||
200 | tmp &= ~OTGSC_CTRL_DATA_PULSING; | ||
201 | |||
202 | fsl_writel(tmp, &usb_dr_regs->otgsc); | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * Generate SOF by host. This is controlled through suspend/resume the | ||
207 | * port. In host mode, controller will automatically send SOF. | ||
208 | * Suspend will block the data on the port. | ||
209 | */ | ||
210 | void fsl_otg_loc_sof(int on) | ||
211 | { | ||
212 | u32 tmp; | ||
213 | |||
214 | tmp = fsl_readl(&fsl_otg_dev->dr_mem_map->portsc) & ~PORTSC_W1C_BITS; | ||
215 | if (on) | ||
216 | tmp |= PORTSC_PORT_FORCE_RESUME; | ||
217 | else | ||
218 | tmp |= PORTSC_PORT_SUSPEND; | ||
219 | |||
220 | fsl_writel(tmp, &fsl_otg_dev->dr_mem_map->portsc); | ||
221 | |||
222 | } | ||
223 | |||
224 | /* Start SRP pulsing by data-line pulsing, followed with v-bus pulsing. */ | ||
225 | void fsl_otg_start_pulse(void) | ||
226 | { | ||
227 | u32 tmp; | ||
228 | |||
229 | srp_wait_done = 0; | ||
230 | #ifdef HA_DATA_PULSE | ||
231 | tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; | ||
232 | tmp |= OTGSC_HA_DATA_PULSE; | ||
233 | fsl_writel(tmp, &usb_dr_regs->otgsc); | ||
234 | #else | ||
235 | fsl_otg_loc_conn(1); | ||
236 | #endif | ||
237 | |||
238 | fsl_otg_add_timer(b_data_pulse_tmr); | ||
239 | } | ||
240 | |||
241 | void b_data_pulse_end(unsigned long foo) | ||
242 | { | ||
243 | #ifdef HA_DATA_PULSE | ||
244 | #else | ||
245 | fsl_otg_loc_conn(0); | ||
246 | #endif | ||
247 | |||
248 | /* Do VBUS pulse after data pulse */ | ||
249 | fsl_otg_pulse_vbus(); | ||
250 | } | ||
251 | |||
252 | void fsl_otg_pulse_vbus(void) | ||
253 | { | ||
254 | srp_wait_done = 0; | ||
255 | fsl_otg_chrg_vbus(1); | ||
256 | /* start the timer to end vbus charge */ | ||
257 | fsl_otg_add_timer(b_vbus_pulse_tmr); | ||
258 | } | ||
259 | |||
260 | void b_vbus_pulse_end(unsigned long foo) | ||
261 | { | ||
262 | fsl_otg_chrg_vbus(0); | ||
263 | |||
264 | /* | ||
265 | * As USB3300 using the same a_sess_vld and b_sess_vld voltage | ||
266 | * we need to discharge the bus for a while to distinguish | ||
267 | * residual voltage of vbus pulsing and A device pull up | ||
268 | */ | ||
269 | fsl_otg_dischrg_vbus(1); | ||
270 | fsl_otg_add_timer(b_srp_wait_tmr); | ||
271 | } | ||
272 | |||
273 | void b_srp_end(unsigned long foo) | ||
274 | { | ||
275 | fsl_otg_dischrg_vbus(0); | ||
276 | srp_wait_done = 1; | ||
277 | |||
278 | if ((fsl_otg_dev->otg.state == OTG_STATE_B_SRP_INIT) && | ||
279 | fsl_otg_dev->fsm.b_sess_vld) | ||
280 | fsl_otg_dev->fsm.b_srp_done = 1; | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * Workaround for a_host suspending too fast. When a_bus_req=0, | ||
285 | * a_host will start by SRP. It needs to set b_hnp_enable before | ||
286 | * actually suspending to start HNP | ||
287 | */ | ||
288 | void a_wait_enum(unsigned long foo) | ||
289 | { | ||
290 | VDBG("a_wait_enum timeout\n"); | ||
291 | if (!fsl_otg_dev->otg.host->b_hnp_enable) | ||
292 | fsl_otg_add_timer(a_wait_enum_tmr); | ||
293 | else | ||
294 | otg_statemachine(&fsl_otg_dev->fsm); | ||
295 | } | ||
296 | |||
297 | /* The timeout callback function to set time out bit */ | ||
298 | void set_tmout(unsigned long indicator) | ||
299 | { | ||
300 | *(int *)indicator = 1; | ||
301 | } | ||
302 | |||
303 | /* Initialize timers */ | ||
304 | int fsl_otg_init_timers(struct otg_fsm *fsm) | ||
305 | { | ||
306 | /* FSM used timers */ | ||
307 | a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, | ||
308 | (unsigned long)&fsm->a_wait_vrise_tmout); | ||
309 | if (!a_wait_vrise_tmr) | ||
310 | return -ENOMEM; | ||
311 | |||
312 | a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON, | ||
313 | (unsigned long)&fsm->a_wait_bcon_tmout); | ||
314 | if (!a_wait_bcon_tmr) | ||
315 | return -ENOMEM; | ||
316 | |||
317 | a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, | ||
318 | (unsigned long)&fsm->a_aidl_bdis_tmout); | ||
319 | if (!a_aidl_bdis_tmr) | ||
320 | return -ENOMEM; | ||
321 | |||
322 | b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST, | ||
323 | (unsigned long)&fsm->b_ase0_brst_tmout); | ||
324 | if (!b_ase0_brst_tmr) | ||
325 | return -ENOMEM; | ||
326 | |||
327 | b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, | ||
328 | (unsigned long)&fsm->b_se0_srp); | ||
329 | if (!b_se0_srp_tmr) | ||
330 | return -ENOMEM; | ||
331 | |||
332 | b_srp_fail_tmr = otg_timer_initializer(&set_tmout, TB_SRP_FAIL, | ||
333 | (unsigned long)&fsm->b_srp_done); | ||
334 | if (!b_srp_fail_tmr) | ||
335 | return -ENOMEM; | ||
336 | |||
337 | a_wait_enum_tmr = otg_timer_initializer(&a_wait_enum, 10, | ||
338 | (unsigned long)&fsm); | ||
339 | if (!a_wait_enum_tmr) | ||
340 | return -ENOMEM; | ||
341 | |||
342 | /* device driver used timers */ | ||
343 | b_srp_wait_tmr = otg_timer_initializer(&b_srp_end, TB_SRP_WAIT, 0); | ||
344 | if (!b_srp_wait_tmr) | ||
345 | return -ENOMEM; | ||
346 | |||
347 | b_data_pulse_tmr = otg_timer_initializer(&b_data_pulse_end, | ||
348 | TB_DATA_PLS, 0); | ||
349 | if (!b_data_pulse_tmr) | ||
350 | return -ENOMEM; | ||
351 | |||
352 | b_vbus_pulse_tmr = otg_timer_initializer(&b_vbus_pulse_end, | ||
353 | TB_VBUS_PLS, 0); | ||
354 | if (!b_vbus_pulse_tmr) | ||
355 | return -ENOMEM; | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | /* Uninitialize timers */ | ||
361 | void fsl_otg_uninit_timers(void) | ||
362 | { | ||
363 | /* FSM used timers */ | ||
364 | if (a_wait_vrise_tmr != NULL) | ||
365 | kfree(a_wait_vrise_tmr); | ||
366 | if (a_wait_bcon_tmr != NULL) | ||
367 | kfree(a_wait_bcon_tmr); | ||
368 | if (a_aidl_bdis_tmr != NULL) | ||
369 | kfree(a_aidl_bdis_tmr); | ||
370 | if (b_ase0_brst_tmr != NULL) | ||
371 | kfree(b_ase0_brst_tmr); | ||
372 | if (b_se0_srp_tmr != NULL) | ||
373 | kfree(b_se0_srp_tmr); | ||
374 | if (b_srp_fail_tmr != NULL) | ||
375 | kfree(b_srp_fail_tmr); | ||
376 | if (a_wait_enum_tmr != NULL) | ||
377 | kfree(a_wait_enum_tmr); | ||
378 | |||
379 | /* device driver used timers */ | ||
380 | if (b_srp_wait_tmr != NULL) | ||
381 | kfree(b_srp_wait_tmr); | ||
382 | if (b_data_pulse_tmr != NULL) | ||
383 | kfree(b_data_pulse_tmr); | ||
384 | if (b_vbus_pulse_tmr != NULL) | ||
385 | kfree(b_vbus_pulse_tmr); | ||
386 | } | ||
387 | |||
388 | /* Add timer to timer list */ | ||
389 | void fsl_otg_add_timer(void *gtimer) | ||
390 | { | ||
391 | struct fsl_otg_timer *timer = gtimer; | ||
392 | struct fsl_otg_timer *tmp_timer; | ||
393 | |||
394 | /* | ||
395 | * Check if the timer is already in the active list, | ||
396 | * if so update timer count | ||
397 | */ | ||
398 | list_for_each_entry(tmp_timer, &active_timers, list) | ||
399 | if (tmp_timer == timer) { | ||
400 | timer->count = timer->expires; | ||
401 | return; | ||
402 | } | ||
403 | timer->count = timer->expires; | ||
404 | list_add_tail(&timer->list, &active_timers); | ||
405 | } | ||
406 | |||
407 | /* Remove timer from the timer list; clear timeout status */ | ||
408 | void fsl_otg_del_timer(void *gtimer) | ||
409 | { | ||
410 | struct fsl_otg_timer *timer = gtimer; | ||
411 | struct fsl_otg_timer *tmp_timer, *del_tmp; | ||
412 | |||
413 | list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) | ||
414 | if (tmp_timer == timer) | ||
415 | list_del(&timer->list); | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | * Reduce timer count by 1, and find timeout conditions. | ||
420 | * Called by fsl_otg 1ms timer interrupt | ||
421 | */ | ||
422 | int fsl_otg_tick_timer(void) | ||
423 | { | ||
424 | struct fsl_otg_timer *tmp_timer, *del_tmp; | ||
425 | int expired = 0; | ||
426 | |||
427 | list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { | ||
428 | tmp_timer->count--; | ||
429 | /* check if timer expires */ | ||
430 | if (!tmp_timer->count) { | ||
431 | list_del(&tmp_timer->list); | ||
432 | tmp_timer->function(tmp_timer->data); | ||
433 | expired = 1; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | return expired; | ||
438 | } | ||
439 | |||
440 | /* Reset controller, not reset the bus */ | ||
441 | void otg_reset_controller(void) | ||
442 | { | ||
443 | u32 command; | ||
444 | |||
445 | command = fsl_readl(&usb_dr_regs->usbcmd); | ||
446 | command |= (1 << 1); | ||
447 | fsl_writel(command, &usb_dr_regs->usbcmd); | ||
448 | while (fsl_readl(&usb_dr_regs->usbcmd) & (1 << 1)) | ||
449 | ; | ||
450 | } | ||
451 | |||
452 | /* Call suspend/resume routines in host driver */ | ||
453 | int fsl_otg_start_host(struct otg_fsm *fsm, int on) | ||
454 | { | ||
455 | struct otg_transceiver *xceiv = fsm->transceiver; | ||
456 | struct device *dev; | ||
457 | struct fsl_otg *otg_dev = container_of(xceiv, struct fsl_otg, otg); | ||
458 | u32 retval = 0; | ||
459 | |||
460 | if (!xceiv->host) | ||
461 | return -ENODEV; | ||
462 | dev = xceiv->host->controller; | ||
463 | |||
464 | /* | ||
465 | * Update a_vbus_vld state as a_vbus_vld int is disabled | ||
466 | * in device mode | ||
467 | */ | ||
468 | fsm->a_vbus_vld = | ||
469 | !!(fsl_readl(&usb_dr_regs->otgsc) & OTGSC_STS_A_VBUS_VALID); | ||
470 | if (on) { | ||
471 | /* start fsl usb host controller */ | ||
472 | if (otg_dev->host_working) | ||
473 | goto end; | ||
474 | else { | ||
475 | otg_reset_controller(); | ||
476 | VDBG("host on......\n"); | ||
477 | if (dev->driver->pm && dev->driver->pm->resume) { | ||
478 | retval = dev->driver->pm->resume(dev); | ||
479 | if (fsm->id) { | ||
480 | /* default-b */ | ||
481 | fsl_otg_drv_vbus(1); | ||
482 | /* | ||
483 | * Workaround: b_host can't driver | ||
484 | * vbus, but PP in PORTSC needs to | ||
485 | * be 1 for host to work. | ||
486 | * So we set drv_vbus bit in | ||
487 | * transceiver to 0 thru ULPI. | ||
488 | */ | ||
489 | write_ulpi(0x0c, 0x20); | ||
490 | } | ||
491 | } | ||
492 | |||
493 | otg_dev->host_working = 1; | ||
494 | } | ||
495 | } else { | ||
496 | /* stop fsl usb host controller */ | ||
497 | if (!otg_dev->host_working) | ||
498 | goto end; | ||
499 | else { | ||
500 | VDBG("host off......\n"); | ||
501 | if (dev && dev->driver) { | ||
502 | if (dev->driver->pm && dev->driver->pm->suspend) | ||
503 | retval = dev->driver->pm->suspend(dev); | ||
504 | if (fsm->id) | ||
505 | /* default-b */ | ||
506 | fsl_otg_drv_vbus(0); | ||
507 | } | ||
508 | otg_dev->host_working = 0; | ||
509 | } | ||
510 | } | ||
511 | end: | ||
512 | return retval; | ||
513 | } | ||
514 | |||
515 | /* | ||
516 | * Call suspend and resume function in udc driver | ||
517 | * to stop and start udc driver. | ||
518 | */ | ||
519 | int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) | ||
520 | { | ||
521 | struct otg_transceiver *xceiv = fsm->transceiver; | ||
522 | struct device *dev; | ||
523 | |||
524 | if (!xceiv->gadget || !xceiv->gadget->dev.parent) | ||
525 | return -ENODEV; | ||
526 | |||
527 | VDBG("gadget %s\n", on ? "on" : "off"); | ||
528 | dev = xceiv->gadget->dev.parent; | ||
529 | |||
530 | if (on) { | ||
531 | if (dev->driver->resume) | ||
532 | dev->driver->resume(dev); | ||
533 | } else { | ||
534 | if (dev->driver->suspend) | ||
535 | dev->driver->suspend(dev, otg_suspend_state); | ||
536 | } | ||
537 | |||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | /* | ||
542 | * Called by initialization code of host driver. Register host controller | ||
543 | * to the OTG. Suspend host for OTG role detection. | ||
544 | */ | ||
545 | static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) | ||
546 | { | ||
547 | struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); | ||
548 | |||
549 | if (!otg_p || otg_dev != fsl_otg_dev) | ||
550 | return -ENODEV; | ||
551 | |||
552 | otg_p->host = host; | ||
553 | |||
554 | otg_dev->fsm.a_bus_drop = 0; | ||
555 | otg_dev->fsm.a_bus_req = 1; | ||
556 | |||
557 | if (host) { | ||
558 | VDBG("host off......\n"); | ||
559 | |||
560 | otg_p->host->otg_port = fsl_otg_initdata.otg_port; | ||
561 | otg_p->host->is_b_host = otg_dev->fsm.id; | ||
562 | /* | ||
563 | * must leave time for khubd to finish its thing | ||
564 | * before yanking the host driver out from under it, | ||
565 | * so suspend the host after a short delay. | ||
566 | */ | ||
567 | otg_dev->host_working = 1; | ||
568 | schedule_delayed_work(&otg_dev->otg_event, 100); | ||
569 | return 0; | ||
570 | } else { | ||
571 | /* host driver going away */ | ||
572 | if (!(fsl_readl(&otg_dev->dr_mem_map->otgsc) & | ||
573 | OTGSC_STS_USB_ID)) { | ||
574 | /* Mini-A cable connected */ | ||
575 | struct otg_fsm *fsm = &otg_dev->fsm; | ||
576 | |||
577 | otg_p->state = OTG_STATE_UNDEFINED; | ||
578 | fsm->protocol = PROTO_UNDEF; | ||
579 | } | ||
580 | } | ||
581 | |||
582 | otg_dev->host_working = 0; | ||
583 | |||
584 | otg_statemachine(&otg_dev->fsm); | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | /* Called by initialization code of udc. Register udc to OTG. */ | ||
590 | static int fsl_otg_set_peripheral(struct otg_transceiver *otg_p, | ||
591 | struct usb_gadget *gadget) | ||
592 | { | ||
593 | struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); | ||
594 | |||
595 | VDBG("otg_dev 0x%x\n", (int)otg_dev); | ||
596 | VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev); | ||
597 | |||
598 | if (!otg_p || otg_dev != fsl_otg_dev) | ||
599 | return -ENODEV; | ||
600 | |||
601 | if (!gadget) { | ||
602 | if (!otg_dev->otg.default_a) | ||
603 | otg_p->gadget->ops->vbus_draw(otg_p->gadget, 0); | ||
604 | usb_gadget_vbus_disconnect(otg_dev->otg.gadget); | ||
605 | otg_dev->otg.gadget = 0; | ||
606 | otg_dev->fsm.b_bus_req = 0; | ||
607 | otg_statemachine(&otg_dev->fsm); | ||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | otg_p->gadget = gadget; | ||
612 | otg_p->gadget->is_a_peripheral = !otg_dev->fsm.id; | ||
613 | |||
614 | otg_dev->fsm.b_bus_req = 1; | ||
615 | |||
616 | /* start the gadget right away if the ID pin says Mini-B */ | ||
617 | DBG("ID pin=%d\n", otg_dev->fsm.id); | ||
618 | if (otg_dev->fsm.id == 1) { | ||
619 | fsl_otg_start_host(&otg_dev->fsm, 0); | ||
620 | otg_drv_vbus(&otg_dev->fsm, 0); | ||
621 | fsl_otg_start_gadget(&otg_dev->fsm, 1); | ||
622 | } | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | /* Set OTG port power, only for B-device */ | ||
628 | static int fsl_otg_set_power(struct otg_transceiver *otg_p, unsigned mA) | ||
629 | { | ||
630 | if (!fsl_otg_dev) | ||
631 | return -ENODEV; | ||
632 | if (otg_p->state == OTG_STATE_B_PERIPHERAL) | ||
633 | pr_info("FSL OTG: Draw %d mA\n", mA); | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | /* | ||
639 | * Delayed pin detect interrupt processing. | ||
640 | * | ||
641 | * When the Mini-A cable is disconnected from the board, | ||
642 | * the pin-detect interrupt happens before the disconnnect | ||
643 | * interrupts for the connected device(s). In order to | ||
644 | * process the disconnect interrupt(s) prior to switching | ||
645 | * roles, the pin-detect interrupts are delayed, and handled | ||
646 | * by this routine. | ||
647 | */ | ||
648 | static void fsl_otg_event(struct work_struct *work) | ||
649 | { | ||
650 | struct fsl_otg *og = container_of(work, struct fsl_otg, otg_event.work); | ||
651 | struct otg_fsm *fsm = &og->fsm; | ||
652 | |||
653 | if (fsm->id) { /* switch to gadget */ | ||
654 | fsl_otg_start_host(fsm, 0); | ||
655 | otg_drv_vbus(fsm, 0); | ||
656 | fsl_otg_start_gadget(fsm, 1); | ||
657 | } | ||
658 | } | ||
659 | |||
660 | /* B-device start SRP */ | ||
661 | static int fsl_otg_start_srp(struct otg_transceiver *otg_p) | ||
662 | { | ||
663 | struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); | ||
664 | |||
665 | if (!otg_p || otg_dev != fsl_otg_dev | ||
666 | || otg_p->state != OTG_STATE_B_IDLE) | ||
667 | return -ENODEV; | ||
668 | |||
669 | otg_dev->fsm.b_bus_req = 1; | ||
670 | otg_statemachine(&otg_dev->fsm); | ||
671 | |||
672 | return 0; | ||
673 | } | ||
674 | |||
675 | /* A_host suspend will call this function to start hnp */ | ||
676 | static int fsl_otg_start_hnp(struct otg_transceiver *otg_p) | ||
677 | { | ||
678 | struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); | ||
679 | |||
680 | if (!otg_p || otg_dev != fsl_otg_dev) | ||
681 | return -ENODEV; | ||
682 | |||
683 | DBG("start_hnp...n"); | ||
684 | |||
685 | /* clear a_bus_req to enter a_suspend state */ | ||
686 | otg_dev->fsm.a_bus_req = 0; | ||
687 | otg_statemachine(&otg_dev->fsm); | ||
688 | |||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | /* | ||
693 | * Interrupt handler. OTG/host/peripheral share the same int line. | ||
694 | * OTG driver clears OTGSC interrupts and leaves USB interrupts | ||
695 | * intact. It needs to have knowledge of some USB interrupts | ||
696 | * such as port change. | ||
697 | */ | ||
698 | irqreturn_t fsl_otg_isr(int irq, void *dev_id) | ||
699 | { | ||
700 | struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm; | ||
701 | struct otg_transceiver *otg = &((struct fsl_otg *)dev_id)->otg; | ||
702 | u32 otg_int_src, otg_sc; | ||
703 | |||
704 | otg_sc = fsl_readl(&usb_dr_regs->otgsc); | ||
705 | otg_int_src = otg_sc & OTGSC_INTSTS_MASK & (otg_sc >> 8); | ||
706 | |||
707 | /* Only clear otg interrupts */ | ||
708 | fsl_writel(otg_sc, &usb_dr_regs->otgsc); | ||
709 | |||
710 | /*FIXME: ID change not generate when init to 0 */ | ||
711 | fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0; | ||
712 | otg->default_a = (fsm->id == 0); | ||
713 | |||
714 | /* process OTG interrupts */ | ||
715 | if (otg_int_src) { | ||
716 | if (otg_int_src & OTGSC_INTSTS_USB_ID) { | ||
717 | fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0; | ||
718 | otg->default_a = (fsm->id == 0); | ||
719 | /* clear conn information */ | ||
720 | if (fsm->id) | ||
721 | fsm->b_conn = 0; | ||
722 | else | ||
723 | fsm->a_conn = 0; | ||
724 | |||
725 | if (otg->host) | ||
726 | otg->host->is_b_host = fsm->id; | ||
727 | if (otg->gadget) | ||
728 | otg->gadget->is_a_peripheral = !fsm->id; | ||
729 | VDBG("ID int (ID is %d)\n", fsm->id); | ||
730 | |||
731 | if (fsm->id) { /* switch to gadget */ | ||
732 | schedule_delayed_work( | ||
733 | &((struct fsl_otg *)dev_id)->otg_event, | ||
734 | 100); | ||
735 | } else { /* switch to host */ | ||
736 | cancel_delayed_work(& | ||
737 | ((struct fsl_otg *)dev_id)-> | ||
738 | otg_event); | ||
739 | fsl_otg_start_gadget(fsm, 0); | ||
740 | otg_drv_vbus(fsm, 1); | ||
741 | fsl_otg_start_host(fsm, 1); | ||
742 | } | ||
743 | return IRQ_HANDLED; | ||
744 | } | ||
745 | } | ||
746 | return IRQ_NONE; | ||
747 | } | ||
748 | |||
749 | static struct otg_fsm_ops fsl_otg_ops = { | ||
750 | .chrg_vbus = fsl_otg_chrg_vbus, | ||
751 | .drv_vbus = fsl_otg_drv_vbus, | ||
752 | .loc_conn = fsl_otg_loc_conn, | ||
753 | .loc_sof = fsl_otg_loc_sof, | ||
754 | .start_pulse = fsl_otg_start_pulse, | ||
755 | |||
756 | .add_timer = fsl_otg_add_timer, | ||
757 | .del_timer = fsl_otg_del_timer, | ||
758 | |||
759 | .start_host = fsl_otg_start_host, | ||
760 | .start_gadget = fsl_otg_start_gadget, | ||
761 | }; | ||
762 | |||
763 | /* Initialize the global variable fsl_otg_dev and request IRQ for OTG */ | ||
764 | static int fsl_otg_conf(struct platform_device *pdev) | ||
765 | { | ||
766 | struct fsl_otg *fsl_otg_tc; | ||
767 | int status; | ||
768 | |||
769 | if (fsl_otg_dev) | ||
770 | return 0; | ||
771 | |||
772 | /* allocate space to fsl otg device */ | ||
773 | fsl_otg_tc = kzalloc(sizeof(struct fsl_otg), GFP_KERNEL); | ||
774 | if (!fsl_otg_tc) | ||
775 | return -ENOMEM; | ||
776 | |||
777 | INIT_DELAYED_WORK(&fsl_otg_tc->otg_event, fsl_otg_event); | ||
778 | |||
779 | INIT_LIST_HEAD(&active_timers); | ||
780 | status = fsl_otg_init_timers(&fsl_otg_tc->fsm); | ||
781 | if (status) { | ||
782 | pr_info("Couldn't init OTG timers\n"); | ||
783 | goto err; | ||
784 | } | ||
785 | spin_lock_init(&fsl_otg_tc->fsm.lock); | ||
786 | |||
787 | /* Set OTG state machine operations */ | ||
788 | fsl_otg_tc->fsm.ops = &fsl_otg_ops; | ||
789 | |||
790 | /* initialize the otg structure */ | ||
791 | fsl_otg_tc->otg.label = DRIVER_DESC; | ||
792 | fsl_otg_tc->otg.set_host = fsl_otg_set_host; | ||
793 | fsl_otg_tc->otg.set_peripheral = fsl_otg_set_peripheral; | ||
794 | fsl_otg_tc->otg.set_power = fsl_otg_set_power; | ||
795 | fsl_otg_tc->otg.start_hnp = fsl_otg_start_hnp; | ||
796 | fsl_otg_tc->otg.start_srp = fsl_otg_start_srp; | ||
797 | |||
798 | fsl_otg_dev = fsl_otg_tc; | ||
799 | |||
800 | /* Store the otg transceiver */ | ||
801 | status = otg_set_transceiver(&fsl_otg_tc->otg); | ||
802 | if (status) { | ||
803 | pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n"); | ||
804 | goto err; | ||
805 | } | ||
806 | |||
807 | return 0; | ||
808 | err: | ||
809 | fsl_otg_uninit_timers(); | ||
810 | kfree(fsl_otg_tc); | ||
811 | return status; | ||
812 | } | ||
813 | |||
814 | /* OTG Initialization */ | ||
815 | int usb_otg_start(struct platform_device *pdev) | ||
816 | { | ||
817 | struct fsl_otg *p_otg; | ||
818 | struct otg_transceiver *otg_trans = otg_get_transceiver(); | ||
819 | struct otg_fsm *fsm; | ||
820 | int status; | ||
821 | struct resource *res; | ||
822 | u32 temp; | ||
823 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; | ||
824 | |||
825 | p_otg = container_of(otg_trans, struct fsl_otg, otg); | ||
826 | fsm = &p_otg->fsm; | ||
827 | |||
828 | /* Initialize the state machine structure with default values */ | ||
829 | SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED); | ||
830 | fsm->transceiver = &p_otg->otg; | ||
831 | |||
832 | /* We don't require predefined MEM/IRQ resource index */ | ||
833 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
834 | if (!res) | ||
835 | return -ENXIO; | ||
836 | |||
837 | /* We don't request_mem_region here to enable resource sharing | ||
838 | * with host/device */ | ||
839 | |||
840 | usb_dr_regs = ioremap(res->start, sizeof(struct usb_dr_mmap)); | ||
841 | p_otg->dr_mem_map = (struct usb_dr_mmap *)usb_dr_regs; | ||
842 | pdata->regs = (void *)usb_dr_regs; | ||
843 | |||
844 | if (pdata->init && pdata->init(pdev) != 0) | ||
845 | return -EINVAL; | ||
846 | |||
847 | if (pdata->big_endian_mmio) { | ||
848 | _fsl_readl = _fsl_readl_be; | ||
849 | _fsl_writel = _fsl_writel_be; | ||
850 | } else { | ||
851 | _fsl_readl = _fsl_readl_le; | ||
852 | _fsl_writel = _fsl_writel_le; | ||
853 | } | ||
854 | |||
855 | /* request irq */ | ||
856 | p_otg->irq = platform_get_irq(pdev, 0); | ||
857 | status = request_irq(p_otg->irq, fsl_otg_isr, | ||
858 | IRQF_SHARED, driver_name, p_otg); | ||
859 | if (status) { | ||
860 | dev_dbg(p_otg->otg.dev, "can't get IRQ %d, error %d\n", | ||
861 | p_otg->irq, status); | ||
862 | iounmap(p_otg->dr_mem_map); | ||
863 | kfree(p_otg); | ||
864 | return status; | ||
865 | } | ||
866 | |||
867 | /* stop the controller */ | ||
868 | temp = fsl_readl(&p_otg->dr_mem_map->usbcmd); | ||
869 | temp &= ~USB_CMD_RUN_STOP; | ||
870 | fsl_writel(temp, &p_otg->dr_mem_map->usbcmd); | ||
871 | |||
872 | /* reset the controller */ | ||
873 | temp = fsl_readl(&p_otg->dr_mem_map->usbcmd); | ||
874 | temp |= USB_CMD_CTRL_RESET; | ||
875 | fsl_writel(temp, &p_otg->dr_mem_map->usbcmd); | ||
876 | |||
877 | /* wait reset completed */ | ||
878 | while (fsl_readl(&p_otg->dr_mem_map->usbcmd) & USB_CMD_CTRL_RESET) | ||
879 | ; | ||
880 | |||
881 | /* configure the VBUSHS as IDLE(both host and device) */ | ||
882 | temp = USB_MODE_STREAM_DISABLE | (pdata->es ? USB_MODE_ES : 0); | ||
883 | fsl_writel(temp, &p_otg->dr_mem_map->usbmode); | ||
884 | |||
885 | /* configure PHY interface */ | ||
886 | temp = fsl_readl(&p_otg->dr_mem_map->portsc); | ||
887 | temp &= ~(PORTSC_PHY_TYPE_SEL | PORTSC_PTW); | ||
888 | switch (pdata->phy_mode) { | ||
889 | case FSL_USB2_PHY_ULPI: | ||
890 | temp |= PORTSC_PTS_ULPI; | ||
891 | break; | ||
892 | case FSL_USB2_PHY_UTMI_WIDE: | ||
893 | temp |= PORTSC_PTW_16BIT; | ||
894 | /* fall through */ | ||
895 | case FSL_USB2_PHY_UTMI: | ||
896 | temp |= PORTSC_PTS_UTMI; | ||
897 | /* fall through */ | ||
898 | default: | ||
899 | break; | ||
900 | } | ||
901 | fsl_writel(temp, &p_otg->dr_mem_map->portsc); | ||
902 | |||
903 | if (pdata->have_sysif_regs) { | ||
904 | /* configure control enable IO output, big endian register */ | ||
905 | temp = __raw_readl(&p_otg->dr_mem_map->control); | ||
906 | temp |= USB_CTRL_IOENB; | ||
907 | __raw_writel(temp, &p_otg->dr_mem_map->control); | ||
908 | } | ||
909 | |||
910 | /* disable all interrupt and clear all OTGSC status */ | ||
911 | temp = fsl_readl(&p_otg->dr_mem_map->otgsc); | ||
912 | temp &= ~OTGSC_INTERRUPT_ENABLE_BITS_MASK; | ||
913 | temp |= OTGSC_INTERRUPT_STATUS_BITS_MASK | OTGSC_CTRL_VBUS_DISCHARGE; | ||
914 | fsl_writel(temp, &p_otg->dr_mem_map->otgsc); | ||
915 | |||
916 | /* | ||
917 | * The identification (id) input is FALSE when a Mini-A plug is inserted | ||
918 | * in the devices Mini-AB receptacle. Otherwise, this input is TRUE. | ||
919 | * Also: record initial state of ID pin | ||
920 | */ | ||
921 | if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) { | ||
922 | p_otg->otg.state = OTG_STATE_UNDEFINED; | ||
923 | p_otg->fsm.id = 1; | ||
924 | } else { | ||
925 | p_otg->otg.state = OTG_STATE_A_IDLE; | ||
926 | p_otg->fsm.id = 0; | ||
927 | } | ||
928 | |||
929 | DBG("initial ID pin=%d\n", p_otg->fsm.id); | ||
930 | |||
931 | /* enable OTG ID pin interrupt */ | ||
932 | temp = fsl_readl(&p_otg->dr_mem_map->otgsc); | ||
933 | temp |= OTGSC_INTR_USB_ID_EN; | ||
934 | temp &= ~(OTGSC_CTRL_VBUS_DISCHARGE | OTGSC_INTR_1MS_TIMER_EN); | ||
935 | fsl_writel(temp, &p_otg->dr_mem_map->otgsc); | ||
936 | |||
937 | return 0; | ||
938 | } | ||
939 | |||
940 | /* | ||
941 | * state file in sysfs | ||
942 | */ | ||
943 | static int show_fsl_usb2_otg_state(struct device *dev, | ||
944 | struct device_attribute *attr, char *buf) | ||
945 | { | ||
946 | struct otg_fsm *fsm = &fsl_otg_dev->fsm; | ||
947 | char *next = buf; | ||
948 | unsigned size = PAGE_SIZE; | ||
949 | unsigned long flags; | ||
950 | int t; | ||
951 | |||
952 | spin_lock_irqsave(&fsm->lock, flags); | ||
953 | |||
954 | /* basic driver infomation */ | ||
955 | t = scnprintf(next, size, | ||
956 | DRIVER_DESC "\n" "fsl_usb2_otg version: %s\n\n", | ||
957 | DRIVER_VERSION); | ||
958 | size -= t; | ||
959 | next += t; | ||
960 | |||
961 | /* Registers */ | ||
962 | t = scnprintf(next, size, | ||
963 | "OTGSC: 0x%08x\n" | ||
964 | "PORTSC: 0x%08x\n" | ||
965 | "USBMODE: 0x%08x\n" | ||
966 | "USBCMD: 0x%08x\n" | ||
967 | "USBSTS: 0x%08x\n" | ||
968 | "USBINTR: 0x%08x\n", | ||
969 | fsl_readl(&usb_dr_regs->otgsc), | ||
970 | fsl_readl(&usb_dr_regs->portsc), | ||
971 | fsl_readl(&usb_dr_regs->usbmode), | ||
972 | fsl_readl(&usb_dr_regs->usbcmd), | ||
973 | fsl_readl(&usb_dr_regs->usbsts), | ||
974 | fsl_readl(&usb_dr_regs->usbintr)); | ||
975 | size -= t; | ||
976 | next += t; | ||
977 | |||
978 | /* State */ | ||
979 | t = scnprintf(next, size, | ||
980 | "OTG state: %s\n\n", | ||
981 | otg_state_string(fsl_otg_dev->otg.state)); | ||
982 | size -= t; | ||
983 | next += t; | ||
984 | |||
985 | /* State Machine Variables */ | ||
986 | t = scnprintf(next, size, | ||
987 | "a_bus_req: %d\n" | ||
988 | "b_bus_req: %d\n" | ||
989 | "a_bus_resume: %d\n" | ||
990 | "a_bus_suspend: %d\n" | ||
991 | "a_conn: %d\n" | ||
992 | "a_sess_vld: %d\n" | ||
993 | "a_srp_det: %d\n" | ||
994 | "a_vbus_vld: %d\n" | ||
995 | "b_bus_resume: %d\n" | ||
996 | "b_bus_suspend: %d\n" | ||
997 | "b_conn: %d\n" | ||
998 | "b_se0_srp: %d\n" | ||
999 | "b_sess_end: %d\n" | ||
1000 | "b_sess_vld: %d\n" | ||
1001 | "id: %d\n", | ||
1002 | fsm->a_bus_req, | ||
1003 | fsm->b_bus_req, | ||
1004 | fsm->a_bus_resume, | ||
1005 | fsm->a_bus_suspend, | ||
1006 | fsm->a_conn, | ||
1007 | fsm->a_sess_vld, | ||
1008 | fsm->a_srp_det, | ||
1009 | fsm->a_vbus_vld, | ||
1010 | fsm->b_bus_resume, | ||
1011 | fsm->b_bus_suspend, | ||
1012 | fsm->b_conn, | ||
1013 | fsm->b_se0_srp, | ||
1014 | fsm->b_sess_end, | ||
1015 | fsm->b_sess_vld, | ||
1016 | fsm->id); | ||
1017 | size -= t; | ||
1018 | next += t; | ||
1019 | |||
1020 | spin_unlock_irqrestore(&fsm->lock, flags); | ||
1021 | |||
1022 | return PAGE_SIZE - size; | ||
1023 | } | ||
1024 | |||
1025 | static DEVICE_ATTR(fsl_usb2_otg_state, S_IRUGO, show_fsl_usb2_otg_state, NULL); | ||
1026 | |||
1027 | |||
1028 | /* Char driver interface to control some OTG input */ | ||
1029 | |||
1030 | /* | ||
1031 | * Handle some ioctl command, such as get otg | ||
1032 | * status and set host suspend | ||
1033 | */ | ||
1034 | static long fsl_otg_ioctl(struct file *file, unsigned int cmd, | ||
1035 | unsigned long arg) | ||
1036 | { | ||
1037 | u32 retval = 0; | ||
1038 | |||
1039 | switch (cmd) { | ||
1040 | case GET_OTG_STATUS: | ||
1041 | retval = fsl_otg_dev->host_working; | ||
1042 | break; | ||
1043 | |||
1044 | case SET_A_SUSPEND_REQ: | ||
1045 | fsl_otg_dev->fsm.a_suspend_req = arg; | ||
1046 | break; | ||
1047 | |||
1048 | case SET_A_BUS_DROP: | ||
1049 | fsl_otg_dev->fsm.a_bus_drop = arg; | ||
1050 | break; | ||
1051 | |||
1052 | case SET_A_BUS_REQ: | ||
1053 | fsl_otg_dev->fsm.a_bus_req = arg; | ||
1054 | break; | ||
1055 | |||
1056 | case SET_B_BUS_REQ: | ||
1057 | fsl_otg_dev->fsm.b_bus_req = arg; | ||
1058 | break; | ||
1059 | |||
1060 | default: | ||
1061 | break; | ||
1062 | } | ||
1063 | |||
1064 | otg_statemachine(&fsl_otg_dev->fsm); | ||
1065 | |||
1066 | return retval; | ||
1067 | } | ||
1068 | |||
1069 | static int fsl_otg_open(struct inode *inode, struct file *file) | ||
1070 | { | ||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
1074 | static int fsl_otg_release(struct inode *inode, struct file *file) | ||
1075 | { | ||
1076 | return 0; | ||
1077 | } | ||
1078 | |||
1079 | static const struct file_operations otg_fops = { | ||
1080 | .owner = THIS_MODULE, | ||
1081 | .llseek = NULL, | ||
1082 | .read = NULL, | ||
1083 | .write = NULL, | ||
1084 | .unlocked_ioctl = fsl_otg_ioctl, | ||
1085 | .open = fsl_otg_open, | ||
1086 | .release = fsl_otg_release, | ||
1087 | }; | ||
1088 | |||
1089 | static int __devinit fsl_otg_probe(struct platform_device *pdev) | ||
1090 | { | ||
1091 | int ret; | ||
1092 | |||
1093 | if (!pdev->dev.platform_data) | ||
1094 | return -ENODEV; | ||
1095 | |||
1096 | /* configure the OTG */ | ||
1097 | ret = fsl_otg_conf(pdev); | ||
1098 | if (ret) { | ||
1099 | dev_err(&pdev->dev, "Couldn't configure OTG module\n"); | ||
1100 | return ret; | ||
1101 | } | ||
1102 | |||
1103 | /* start OTG */ | ||
1104 | ret = usb_otg_start(pdev); | ||
1105 | if (ret) { | ||
1106 | dev_err(&pdev->dev, "Can't init FSL OTG device\n"); | ||
1107 | return ret; | ||
1108 | } | ||
1109 | |||
1110 | ret = register_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME, &otg_fops); | ||
1111 | if (ret) { | ||
1112 | dev_err(&pdev->dev, "unable to register FSL OTG device\n"); | ||
1113 | return ret; | ||
1114 | } | ||
1115 | |||
1116 | ret = device_create_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state); | ||
1117 | if (ret) | ||
1118 | dev_warn(&pdev->dev, "Can't register sysfs attribute\n"); | ||
1119 | |||
1120 | return ret; | ||
1121 | } | ||
1122 | |||
1123 | static int __devexit fsl_otg_remove(struct platform_device *pdev) | ||
1124 | { | ||
1125 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; | ||
1126 | |||
1127 | otg_set_transceiver(NULL); | ||
1128 | free_irq(fsl_otg_dev->irq, fsl_otg_dev); | ||
1129 | |||
1130 | iounmap((void *)usb_dr_regs); | ||
1131 | |||
1132 | fsl_otg_uninit_timers(); | ||
1133 | kfree(fsl_otg_dev); | ||
1134 | |||
1135 | device_remove_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state); | ||
1136 | |||
1137 | unregister_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME); | ||
1138 | |||
1139 | if (pdata->exit) | ||
1140 | pdata->exit(pdev); | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | struct platform_driver fsl_otg_driver = { | ||
1146 | .probe = fsl_otg_probe, | ||
1147 | .remove = __devexit_p(fsl_otg_remove), | ||
1148 | .driver = { | ||
1149 | .name = driver_name, | ||
1150 | .owner = THIS_MODULE, | ||
1151 | }, | ||
1152 | }; | ||
1153 | |||
1154 | static int __init fsl_usb_otg_init(void) | ||
1155 | { | ||
1156 | pr_info(DRIVER_INFO "\n"); | ||
1157 | return platform_driver_register(&fsl_otg_driver); | ||
1158 | } | ||
1159 | module_init(fsl_usb_otg_init); | ||
1160 | |||
1161 | static void __exit fsl_usb_otg_exit(void) | ||
1162 | { | ||
1163 | platform_driver_unregister(&fsl_otg_driver); | ||
1164 | } | ||
1165 | module_exit(fsl_usb_otg_exit); | ||
1166 | |||
1167 | MODULE_DESCRIPTION(DRIVER_INFO); | ||
1168 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1169 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/otg/fsl_otg.h new file mode 100644 index 000000000000..3f8ef731aac9 --- /dev/null +++ b/drivers/usb/otg/fsl_otg.h | |||
@@ -0,0 +1,406 @@ | |||
1 | /* Copyright (C) 2007,2008 Freescale Semiconductor, Inc. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License as published by the | ||
5 | * Free Software Foundation; either version 2 of the License, or (at your | ||
6 | * option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along | ||
14 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
16 | */ | ||
17 | |||
18 | #include "otg_fsm.h" | ||
19 | #include <linux/usb/otg.h> | ||
20 | #include <linux/ioctl.h> | ||
21 | |||
22 | /* USB Command Register Bit Masks */ | ||
23 | #define USB_CMD_RUN_STOP (0x1<<0) | ||
24 | #define USB_CMD_CTRL_RESET (0x1<<1) | ||
25 | #define USB_CMD_PERIODIC_SCHEDULE_EN (0x1<<4) | ||
26 | #define USB_CMD_ASYNC_SCHEDULE_EN (0x1<<5) | ||
27 | #define USB_CMD_INT_AA_DOORBELL (0x1<<6) | ||
28 | #define USB_CMD_ASP (0x3<<8) | ||
29 | #define USB_CMD_ASYNC_SCH_PARK_EN (0x1<<11) | ||
30 | #define USB_CMD_SUTW (0x1<<13) | ||
31 | #define USB_CMD_ATDTW (0x1<<14) | ||
32 | #define USB_CMD_ITC (0xFF<<16) | ||
33 | |||
34 | /* bit 15,3,2 are frame list size */ | ||
35 | #define USB_CMD_FRAME_SIZE_1024 (0x0<<15 | 0x0<<2) | ||
36 | #define USB_CMD_FRAME_SIZE_512 (0x0<<15 | 0x1<<2) | ||
37 | #define USB_CMD_FRAME_SIZE_256 (0x0<<15 | 0x2<<2) | ||
38 | #define USB_CMD_FRAME_SIZE_128 (0x0<<15 | 0x3<<2) | ||
39 | #define USB_CMD_FRAME_SIZE_64 (0x1<<15 | 0x0<<2) | ||
40 | #define USB_CMD_FRAME_SIZE_32 (0x1<<15 | 0x1<<2) | ||
41 | #define USB_CMD_FRAME_SIZE_16 (0x1<<15 | 0x2<<2) | ||
42 | #define USB_CMD_FRAME_SIZE_8 (0x1<<15 | 0x3<<2) | ||
43 | |||
44 | /* bit 9-8 are async schedule park mode count */ | ||
45 | #define USB_CMD_ASP_00 (0x0<<8) | ||
46 | #define USB_CMD_ASP_01 (0x1<<8) | ||
47 | #define USB_CMD_ASP_10 (0x2<<8) | ||
48 | #define USB_CMD_ASP_11 (0x3<<8) | ||
49 | #define USB_CMD_ASP_BIT_POS (8) | ||
50 | |||
51 | /* bit 23-16 are interrupt threshold control */ | ||
52 | #define USB_CMD_ITC_NO_THRESHOLD (0x00<<16) | ||
53 | #define USB_CMD_ITC_1_MICRO_FRM (0x01<<16) | ||
54 | #define USB_CMD_ITC_2_MICRO_FRM (0x02<<16) | ||
55 | #define USB_CMD_ITC_4_MICRO_FRM (0x04<<16) | ||
56 | #define USB_CMD_ITC_8_MICRO_FRM (0x08<<16) | ||
57 | #define USB_CMD_ITC_16_MICRO_FRM (0x10<<16) | ||
58 | #define USB_CMD_ITC_32_MICRO_FRM (0x20<<16) | ||
59 | #define USB_CMD_ITC_64_MICRO_FRM (0x40<<16) | ||
60 | #define USB_CMD_ITC_BIT_POS (16) | ||
61 | |||
62 | /* USB Status Register Bit Masks */ | ||
63 | #define USB_STS_INT (0x1<<0) | ||
64 | #define USB_STS_ERR (0x1<<1) | ||
65 | #define USB_STS_PORT_CHANGE (0x1<<2) | ||
66 | #define USB_STS_FRM_LST_ROLL (0x1<<3) | ||
67 | #define USB_STS_SYS_ERR (0x1<<4) | ||
68 | #define USB_STS_IAA (0x1<<5) | ||
69 | #define USB_STS_RESET_RECEIVED (0x1<<6) | ||
70 | #define USB_STS_SOF (0x1<<7) | ||
71 | #define USB_STS_DCSUSPEND (0x1<<8) | ||
72 | #define USB_STS_HC_HALTED (0x1<<12) | ||
73 | #define USB_STS_RCL (0x1<<13) | ||
74 | #define USB_STS_PERIODIC_SCHEDULE (0x1<<14) | ||
75 | #define USB_STS_ASYNC_SCHEDULE (0x1<<15) | ||
76 | |||
77 | /* USB Interrupt Enable Register Bit Masks */ | ||
78 | #define USB_INTR_INT_EN (0x1<<0) | ||
79 | #define USB_INTR_ERR_INT_EN (0x1<<1) | ||
80 | #define USB_INTR_PC_DETECT_EN (0x1<<2) | ||
81 | #define USB_INTR_FRM_LST_ROLL_EN (0x1<<3) | ||
82 | #define USB_INTR_SYS_ERR_EN (0x1<<4) | ||
83 | #define USB_INTR_ASYN_ADV_EN (0x1<<5) | ||
84 | #define USB_INTR_RESET_EN (0x1<<6) | ||
85 | #define USB_INTR_SOF_EN (0x1<<7) | ||
86 | #define USB_INTR_DEVICE_SUSPEND (0x1<<8) | ||
87 | |||
88 | /* Device Address bit masks */ | ||
89 | #define USB_DEVICE_ADDRESS_MASK (0x7F<<25) | ||
90 | #define USB_DEVICE_ADDRESS_BIT_POS (25) | ||
91 | /* PORTSC Register Bit Masks,Only one PORT in OTG mode*/ | ||
92 | #define PORTSC_CURRENT_CONNECT_STATUS (0x1<<0) | ||
93 | #define PORTSC_CONNECT_STATUS_CHANGE (0x1<<1) | ||
94 | #define PORTSC_PORT_ENABLE (0x1<<2) | ||
95 | #define PORTSC_PORT_EN_DIS_CHANGE (0x1<<3) | ||
96 | #define PORTSC_OVER_CURRENT_ACT (0x1<<4) | ||
97 | #define PORTSC_OVER_CUURENT_CHG (0x1<<5) | ||
98 | #define PORTSC_PORT_FORCE_RESUME (0x1<<6) | ||
99 | #define PORTSC_PORT_SUSPEND (0x1<<7) | ||
100 | #define PORTSC_PORT_RESET (0x1<<8) | ||
101 | #define PORTSC_LINE_STATUS_BITS (0x3<<10) | ||
102 | #define PORTSC_PORT_POWER (0x1<<12) | ||
103 | #define PORTSC_PORT_INDICTOR_CTRL (0x3<<14) | ||
104 | #define PORTSC_PORT_TEST_CTRL (0xF<<16) | ||
105 | #define PORTSC_WAKE_ON_CONNECT_EN (0x1<<20) | ||
106 | #define PORTSC_WAKE_ON_CONNECT_DIS (0x1<<21) | ||
107 | #define PORTSC_WAKE_ON_OVER_CURRENT (0x1<<22) | ||
108 | #define PORTSC_PHY_LOW_POWER_SPD (0x1<<23) | ||
109 | #define PORTSC_PORT_FORCE_FULL_SPEED (0x1<<24) | ||
110 | #define PORTSC_PORT_SPEED_MASK (0x3<<26) | ||
111 | #define PORTSC_TRANSCEIVER_WIDTH (0x1<<28) | ||
112 | #define PORTSC_PHY_TYPE_SEL (0x3<<30) | ||
113 | /* bit 11-10 are line status */ | ||
114 | #define PORTSC_LINE_STATUS_SE0 (0x0<<10) | ||
115 | #define PORTSC_LINE_STATUS_JSTATE (0x1<<10) | ||
116 | #define PORTSC_LINE_STATUS_KSTATE (0x2<<10) | ||
117 | #define PORTSC_LINE_STATUS_UNDEF (0x3<<10) | ||
118 | #define PORTSC_LINE_STATUS_BIT_POS (10) | ||
119 | |||
120 | /* bit 15-14 are port indicator control */ | ||
121 | #define PORTSC_PIC_OFF (0x0<<14) | ||
122 | #define PORTSC_PIC_AMBER (0x1<<14) | ||
123 | #define PORTSC_PIC_GREEN (0x2<<14) | ||
124 | #define PORTSC_PIC_UNDEF (0x3<<14) | ||
125 | #define PORTSC_PIC_BIT_POS (14) | ||
126 | |||
127 | /* bit 19-16 are port test control */ | ||
128 | #define PORTSC_PTC_DISABLE (0x0<<16) | ||
129 | #define PORTSC_PTC_JSTATE (0x1<<16) | ||
130 | #define PORTSC_PTC_KSTATE (0x2<<16) | ||
131 | #define PORTSC_PTC_SEQNAK (0x3<<16) | ||
132 | #define PORTSC_PTC_PACKET (0x4<<16) | ||
133 | #define PORTSC_PTC_FORCE_EN (0x5<<16) | ||
134 | #define PORTSC_PTC_BIT_POS (16) | ||
135 | |||
136 | /* bit 27-26 are port speed */ | ||
137 | #define PORTSC_PORT_SPEED_FULL (0x0<<26) | ||
138 | #define PORTSC_PORT_SPEED_LOW (0x1<<26) | ||
139 | #define PORTSC_PORT_SPEED_HIGH (0x2<<26) | ||
140 | #define PORTSC_PORT_SPEED_UNDEF (0x3<<26) | ||
141 | #define PORTSC_SPEED_BIT_POS (26) | ||
142 | |||
143 | /* bit 28 is parallel transceiver width for UTMI interface */ | ||
144 | #define PORTSC_PTW (0x1<<28) | ||
145 | #define PORTSC_PTW_8BIT (0x0<<28) | ||
146 | #define PORTSC_PTW_16BIT (0x1<<28) | ||
147 | |||
148 | /* bit 31-30 are port transceiver select */ | ||
149 | #define PORTSC_PTS_UTMI (0x0<<30) | ||
150 | #define PORTSC_PTS_ULPI (0x2<<30) | ||
151 | #define PORTSC_PTS_FSLS_SERIAL (0x3<<30) | ||
152 | #define PORTSC_PTS_BIT_POS (30) | ||
153 | |||
154 | #define PORTSC_W1C_BITS \ | ||
155 | (PORTSC_CONNECT_STATUS_CHANGE | \ | ||
156 | PORTSC_PORT_EN_DIS_CHANGE | \ | ||
157 | PORTSC_OVER_CUURENT_CHG) | ||
158 | |||
159 | /* OTG Status Control Register Bit Masks */ | ||
160 | #define OTGSC_CTRL_VBUS_DISCHARGE (0x1<<0) | ||
161 | #define OTGSC_CTRL_VBUS_CHARGE (0x1<<1) | ||
162 | #define OTGSC_CTRL_OTG_TERMINATION (0x1<<3) | ||
163 | #define OTGSC_CTRL_DATA_PULSING (0x1<<4) | ||
164 | #define OTGSC_CTRL_ID_PULL_EN (0x1<<5) | ||
165 | #define OTGSC_HA_DATA_PULSE (0x1<<6) | ||
166 | #define OTGSC_HA_BA (0x1<<7) | ||
167 | #define OTGSC_STS_USB_ID (0x1<<8) | ||
168 | #define OTGSC_STS_A_VBUS_VALID (0x1<<9) | ||
169 | #define OTGSC_STS_A_SESSION_VALID (0x1<<10) | ||
170 | #define OTGSC_STS_B_SESSION_VALID (0x1<<11) | ||
171 | #define OTGSC_STS_B_SESSION_END (0x1<<12) | ||
172 | #define OTGSC_STS_1MS_TOGGLE (0x1<<13) | ||
173 | #define OTGSC_STS_DATA_PULSING (0x1<<14) | ||
174 | #define OTGSC_INTSTS_USB_ID (0x1<<16) | ||
175 | #define OTGSC_INTSTS_A_VBUS_VALID (0x1<<17) | ||
176 | #define OTGSC_INTSTS_A_SESSION_VALID (0x1<<18) | ||
177 | #define OTGSC_INTSTS_B_SESSION_VALID (0x1<<19) | ||
178 | #define OTGSC_INTSTS_B_SESSION_END (0x1<<20) | ||
179 | #define OTGSC_INTSTS_1MS (0x1<<21) | ||
180 | #define OTGSC_INTSTS_DATA_PULSING (0x1<<22) | ||
181 | #define OTGSC_INTR_USB_ID_EN (0x1<<24) | ||
182 | #define OTGSC_INTR_A_VBUS_VALID_EN (0x1<<25) | ||
183 | #define OTGSC_INTR_A_SESSION_VALID_EN (0x1<<26) | ||
184 | #define OTGSC_INTR_B_SESSION_VALID_EN (0x1<<27) | ||
185 | #define OTGSC_INTR_B_SESSION_END_EN (0x1<<28) | ||
186 | #define OTGSC_INTR_1MS_TIMER_EN (0x1<<29) | ||
187 | #define OTGSC_INTR_DATA_PULSING_EN (0x1<<30) | ||
188 | #define OTGSC_INTSTS_MASK (0x00ff0000) | ||
189 | |||
190 | /* USB MODE Register Bit Masks */ | ||
191 | #define USB_MODE_CTRL_MODE_IDLE (0x0<<0) | ||
192 | #define USB_MODE_CTRL_MODE_DEVICE (0x2<<0) | ||
193 | #define USB_MODE_CTRL_MODE_HOST (0x3<<0) | ||
194 | #define USB_MODE_CTRL_MODE_RSV (0x1<<0) | ||
195 | #define USB_MODE_SETUP_LOCK_OFF (0x1<<3) | ||
196 | #define USB_MODE_STREAM_DISABLE (0x1<<4) | ||
197 | #define USB_MODE_ES (0x1<<2) /* Endian Select */ | ||
198 | |||
199 | /* control Register Bit Masks */ | ||
200 | #define USB_CTRL_IOENB (0x1<<2) | ||
201 | #define USB_CTRL_ULPI_INT0EN (0x1<<0) | ||
202 | |||
203 | /* BCSR5 */ | ||
204 | #define BCSR5_INT_USB (0x02) | ||
205 | |||
206 | /* USB module clk cfg */ | ||
207 | #define SCCR_OFFS (0xA08) | ||
208 | #define SCCR_USB_CLK_DISABLE (0x00000000) /* USB clk disable */ | ||
209 | #define SCCR_USB_MPHCM_11 (0x00c00000) | ||
210 | #define SCCR_USB_MPHCM_01 (0x00400000) | ||
211 | #define SCCR_USB_MPHCM_10 (0x00800000) | ||
212 | #define SCCR_USB_DRCM_11 (0x00300000) | ||
213 | #define SCCR_USB_DRCM_01 (0x00100000) | ||
214 | #define SCCR_USB_DRCM_10 (0x00200000) | ||
215 | |||
216 | #define SICRL_OFFS (0x114) | ||
217 | #define SICRL_USB0 (0x40000000) | ||
218 | #define SICRL_USB1 (0x20000000) | ||
219 | |||
220 | #define SICRH_OFFS (0x118) | ||
221 | #define SICRH_USB_UTMI (0x00020000) | ||
222 | |||
223 | /* OTG interrupt enable bit masks */ | ||
224 | #define OTGSC_INTERRUPT_ENABLE_BITS_MASK \ | ||
225 | (OTGSC_INTR_USB_ID_EN | \ | ||
226 | OTGSC_INTR_1MS_TIMER_EN | \ | ||
227 | OTGSC_INTR_A_VBUS_VALID_EN | \ | ||
228 | OTGSC_INTR_A_SESSION_VALID_EN | \ | ||
229 | OTGSC_INTR_B_SESSION_VALID_EN | \ | ||
230 | OTGSC_INTR_B_SESSION_END_EN | \ | ||
231 | OTGSC_INTR_DATA_PULSING_EN) | ||
232 | |||
233 | /* OTG interrupt status bit masks */ | ||
234 | #define OTGSC_INTERRUPT_STATUS_BITS_MASK \ | ||
235 | (OTGSC_INTSTS_USB_ID | \ | ||
236 | OTGSC_INTR_1MS_TIMER_EN | \ | ||
237 | OTGSC_INTSTS_A_VBUS_VALID | \ | ||
238 | OTGSC_INTSTS_A_SESSION_VALID | \ | ||
239 | OTGSC_INTSTS_B_SESSION_VALID | \ | ||
240 | OTGSC_INTSTS_B_SESSION_END | \ | ||
241 | OTGSC_INTSTS_DATA_PULSING) | ||
242 | |||
243 | /* | ||
244 | * A-DEVICE timing constants | ||
245 | */ | ||
246 | |||
247 | /* Wait for VBUS Rise */ | ||
248 | #define TA_WAIT_VRISE (100) /* a_wait_vrise 100 ms, section: 6.6.5.1 */ | ||
249 | |||
250 | /* Wait for B-Connect */ | ||
251 | #define TA_WAIT_BCON (10000) /* a_wait_bcon > 1 sec, section: 6.6.5.2 | ||
252 | * This is only used to get out of | ||
253 | * OTG_STATE_A_WAIT_BCON state if there was | ||
254 | * no connection for these many milliseconds | ||
255 | */ | ||
256 | |||
257 | /* A-Idle to B-Disconnect */ | ||
258 | /* It is necessary for this timer to be more than 750 ms because of a bug in OPT | ||
259 | * test 5.4 in which B OPT disconnects after 750 ms instead of 75ms as stated | ||
260 | * in the test description | ||
261 | */ | ||
262 | #define TA_AIDL_BDIS (5000) /* a_suspend minimum 200 ms, section: 6.6.5.3 */ | ||
263 | |||
264 | /* B-Idle to A-Disconnect */ | ||
265 | #define TA_BIDL_ADIS (12) /* 3 to 200 ms */ | ||
266 | |||
267 | /* B-device timing constants */ | ||
268 | |||
269 | |||
270 | /* Data-Line Pulse Time*/ | ||
271 | #define TB_DATA_PLS (10) /* b_srp_init,continue 5~10ms, section:5.3.3 */ | ||
272 | #define TB_DATA_PLS_MIN (5) /* minimum 5 ms */ | ||
273 | #define TB_DATA_PLS_MAX (10) /* maximum 10 ms */ | ||
274 | |||
275 | /* SRP Initiate Time */ | ||
276 | #define TB_SRP_INIT (100) /* b_srp_init,maximum 100 ms, section:5.3.8 */ | ||
277 | |||
278 | /* SRP Fail Time */ | ||
279 | #define TB_SRP_FAIL (7000) /* b_srp_init,Fail time 5~30s, section:6.8.2.2*/ | ||
280 | |||
281 | /* SRP result wait time */ | ||
282 | #define TB_SRP_WAIT (60) | ||
283 | |||
284 | /* VBus time */ | ||
285 | #define TB_VBUS_PLS (30) /* time to keep vbus pulsing asserted */ | ||
286 | |||
287 | /* Discharge time */ | ||
288 | /* This time should be less than 10ms. It varies from system to system. */ | ||
289 | #define TB_VBUS_DSCHRG (8) | ||
290 | |||
291 | /* A-SE0 to B-Reset */ | ||
292 | #define TB_ASE0_BRST (20) /* b_wait_acon, mini 3.125 ms,section:6.8.2.4 */ | ||
293 | |||
294 | /* A bus suspend timer before we can switch to b_wait_aconn */ | ||
295 | #define TB_A_SUSPEND (7) | ||
296 | #define TB_BUS_RESUME (12) | ||
297 | |||
298 | /* SE0 Time Before SRP */ | ||
299 | #define TB_SE0_SRP (2) /* b_idle,minimum 2 ms, section:5.3.2 */ | ||
300 | |||
301 | #define SET_OTG_STATE(otg_ptr, newstate) ((otg_ptr)->state = newstate) | ||
302 | |||
303 | struct usb_dr_mmap { | ||
304 | /* Capability register */ | ||
305 | u8 res1[256]; | ||
306 | u16 caplength; /* Capability Register Length */ | ||
307 | u16 hciversion; /* Host Controller Interface Version */ | ||
308 | u32 hcsparams; /* Host Controller Structual Parameters */ | ||
309 | u32 hccparams; /* Host Controller Capability Parameters */ | ||
310 | u8 res2[20]; | ||
311 | u32 dciversion; /* Device Controller Interface Version */ | ||
312 | u32 dccparams; /* Device Controller Capability Parameters */ | ||
313 | u8 res3[24]; | ||
314 | /* Operation register */ | ||
315 | u32 usbcmd; /* USB Command Register */ | ||
316 | u32 usbsts; /* USB Status Register */ | ||
317 | u32 usbintr; /* USB Interrupt Enable Register */ | ||
318 | u32 frindex; /* Frame Index Register */ | ||
319 | u8 res4[4]; | ||
320 | u32 deviceaddr; /* Device Address */ | ||
321 | u32 endpointlistaddr; /* Endpoint List Address Register */ | ||
322 | u8 res5[4]; | ||
323 | u32 burstsize; /* Master Interface Data Burst Size Register */ | ||
324 | u32 txttfilltuning; /* Transmit FIFO Tuning Controls Register */ | ||
325 | u8 res6[8]; | ||
326 | u32 ulpiview; /* ULPI register access */ | ||
327 | u8 res7[12]; | ||
328 | u32 configflag; /* Configure Flag Register */ | ||
329 | u32 portsc; /* Port 1 Status and Control Register */ | ||
330 | u8 res8[28]; | ||
331 | u32 otgsc; /* On-The-Go Status and Control */ | ||
332 | u32 usbmode; /* USB Mode Register */ | ||
333 | u32 endptsetupstat; /* Endpoint Setup Status Register */ | ||
334 | u32 endpointprime; /* Endpoint Initialization Register */ | ||
335 | u32 endptflush; /* Endpoint Flush Register */ | ||
336 | u32 endptstatus; /* Endpoint Status Register */ | ||
337 | u32 endptcomplete; /* Endpoint Complete Register */ | ||
338 | u32 endptctrl[6]; /* Endpoint Control Registers */ | ||
339 | u8 res9[552]; | ||
340 | u32 snoop1; | ||
341 | u32 snoop2; | ||
342 | u32 age_cnt_thresh; /* Age Count Threshold Register */ | ||
343 | u32 pri_ctrl; /* Priority Control Register */ | ||
344 | u32 si_ctrl; /* System Interface Control Register */ | ||
345 | u8 res10[236]; | ||
346 | u32 control; /* General Purpose Control Register */ | ||
347 | }; | ||
348 | |||
349 | struct fsl_otg_timer { | ||
350 | unsigned long expires; /* Number of count increase to timeout */ | ||
351 | unsigned long count; /* Tick counter */ | ||
352 | void (*function)(unsigned long); /* Timeout function */ | ||
353 | unsigned long data; /* Data passed to function */ | ||
354 | struct list_head list; | ||
355 | }; | ||
356 | |||
357 | inline struct fsl_otg_timer *otg_timer_initializer | ||
358 | (void (*function)(unsigned long), unsigned long expires, unsigned long data) | ||
359 | { | ||
360 | struct fsl_otg_timer *timer; | ||
361 | |||
362 | timer = kmalloc(sizeof(struct fsl_otg_timer), GFP_KERNEL); | ||
363 | if (!timer) | ||
364 | return NULL; | ||
365 | timer->function = function; | ||
366 | timer->expires = expires; | ||
367 | timer->data = data; | ||
368 | return timer; | ||
369 | } | ||
370 | |||
371 | struct fsl_otg { | ||
372 | struct otg_transceiver otg; | ||
373 | struct otg_fsm fsm; | ||
374 | struct usb_dr_mmap *dr_mem_map; | ||
375 | struct delayed_work otg_event; | ||
376 | |||
377 | /* used for usb host */ | ||
378 | struct work_struct work_wq; | ||
379 | u8 host_working; | ||
380 | |||
381 | int irq; | ||
382 | }; | ||
383 | |||
384 | struct fsl_otg_config { | ||
385 | u8 otg_port; | ||
386 | }; | ||
387 | |||
388 | /* For SRP and HNP handle */ | ||
389 | #define FSL_OTG_MAJOR 240 | ||
390 | #define FSL_OTG_NAME "fsl-usb2-otg" | ||
391 | /* Command to OTG driver ioctl */ | ||
392 | #define OTG_IOCTL_MAGIC FSL_OTG_MAJOR | ||
393 | /* if otg work as host, it should return 1, otherwise return 0 */ | ||
394 | #define GET_OTG_STATUS _IOR(OTG_IOCTL_MAGIC, 1, int) | ||
395 | #define SET_A_SUSPEND_REQ _IOW(OTG_IOCTL_MAGIC, 2, int) | ||
396 | #define SET_A_BUS_DROP _IOW(OTG_IOCTL_MAGIC, 3, int) | ||
397 | #define SET_A_BUS_REQ _IOW(OTG_IOCTL_MAGIC, 4, int) | ||
398 | #define SET_B_BUS_REQ _IOW(OTG_IOCTL_MAGIC, 5, int) | ||
399 | #define GET_A_SUSPEND_REQ _IOR(OTG_IOCTL_MAGIC, 6, int) | ||
400 | #define GET_A_BUS_DROP _IOR(OTG_IOCTL_MAGIC, 7, int) | ||
401 | #define GET_A_BUS_REQ _IOR(OTG_IOCTL_MAGIC, 8, int) | ||
402 | #define GET_B_BUS_REQ _IOR(OTG_IOCTL_MAGIC, 9, int) | ||
403 | |||
404 | void fsl_otg_add_timer(void *timer); | ||
405 | void fsl_otg_del_timer(void *timer); | ||
406 | void fsl_otg_pulse_vbus(void); | ||
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index 221c44444ec6..52733d9959b4 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c | |||
@@ -279,6 +279,13 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) | |||
279 | } | 279 | } |
280 | INIT_WORK(&gpio_vbus->work, gpio_vbus_work); | 280 | INIT_WORK(&gpio_vbus->work, gpio_vbus_work); |
281 | 281 | ||
282 | gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw"); | ||
283 | if (IS_ERR(gpio_vbus->vbus_draw)) { | ||
284 | dev_dbg(&pdev->dev, "can't get vbus_draw regulator, err: %ld\n", | ||
285 | PTR_ERR(gpio_vbus->vbus_draw)); | ||
286 | gpio_vbus->vbus_draw = NULL; | ||
287 | } | ||
288 | |||
282 | /* only active when a gadget is registered */ | 289 | /* only active when a gadget is registered */ |
283 | err = otg_set_transceiver(&gpio_vbus->otg); | 290 | err = otg_set_transceiver(&gpio_vbus->otg); |
284 | if (err) { | 291 | if (err) { |
@@ -287,13 +294,6 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) | |||
287 | goto err_otg; | 294 | goto err_otg; |
288 | } | 295 | } |
289 | 296 | ||
290 | gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw"); | ||
291 | if (IS_ERR(gpio_vbus->vbus_draw)) { | ||
292 | dev_dbg(&pdev->dev, "can't get vbus_draw regulator, err: %ld\n", | ||
293 | PTR_ERR(gpio_vbus->vbus_draw)); | ||
294 | gpio_vbus->vbus_draw = NULL; | ||
295 | } | ||
296 | |||
297 | return 0; | 297 | return 0; |
298 | err_otg: | 298 | err_otg: |
299 | free_irq(irq, &pdev->dev); | 299 | free_irq(irq, &pdev->dev); |
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index 456969492410..8c282258e1bd 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c | |||
@@ -234,29 +234,9 @@ isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits) | |||
234 | 234 | ||
235 | /*-------------------------------------------------------------------------*/ | 235 | /*-------------------------------------------------------------------------*/ |
236 | 236 | ||
237 | static const char *state_string(enum usb_otg_state state) | ||
238 | { | ||
239 | switch (state) { | ||
240 | case OTG_STATE_A_IDLE: return "a_idle"; | ||
241 | case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise"; | ||
242 | case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon"; | ||
243 | case OTG_STATE_A_HOST: return "a_host"; | ||
244 | case OTG_STATE_A_SUSPEND: return "a_suspend"; | ||
245 | case OTG_STATE_A_PERIPHERAL: return "a_peripheral"; | ||
246 | case OTG_STATE_A_WAIT_VFALL: return "a_wait_vfall"; | ||
247 | case OTG_STATE_A_VBUS_ERR: return "a_vbus_err"; | ||
248 | case OTG_STATE_B_IDLE: return "b_idle"; | ||
249 | case OTG_STATE_B_SRP_INIT: return "b_srp_init"; | ||
250 | case OTG_STATE_B_PERIPHERAL: return "b_peripheral"; | ||
251 | case OTG_STATE_B_WAIT_ACON: return "b_wait_acon"; | ||
252 | case OTG_STATE_B_HOST: return "b_host"; | ||
253 | default: return "UNDEFINED"; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | static inline const char *state_name(struct isp1301 *isp) | 237 | static inline const char *state_name(struct isp1301 *isp) |
258 | { | 238 | { |
259 | return state_string(isp->otg.state); | 239 | return otg_state_string(isp->otg.state); |
260 | } | 240 | } |
261 | 241 | ||
262 | /*-------------------------------------------------------------------------*/ | 242 | /*-------------------------------------------------------------------------*/ |
@@ -501,7 +481,7 @@ static void check_state(struct isp1301 *isp, const char *tag) | |||
501 | if (isp->otg.state == state && !extra) | 481 | if (isp->otg.state == state && !extra) |
502 | return; | 482 | return; |
503 | pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag, | 483 | pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag, |
504 | state_string(state), fsm, state_name(isp), | 484 | otg_state_string(state), fsm, state_name(isp), |
505 | omap_readl(OTG_CTRL)); | 485 | omap_readl(OTG_CTRL)); |
506 | } | 486 | } |
507 | 487 | ||
@@ -1095,7 +1075,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) | |||
1095 | 1075 | ||
1096 | if (state != isp->otg.state) | 1076 | if (state != isp->otg.state) |
1097 | pr_debug(" isp, %s -> %s\n", | 1077 | pr_debug(" isp, %s -> %s\n", |
1098 | state_string(state), state_name(isp)); | 1078 | otg_state_string(state), state_name(isp)); |
1099 | 1079 | ||
1100 | #ifdef CONFIG_USB_OTG | 1080 | #ifdef CONFIG_USB_OTG |
1101 | /* update the OTG controller state to match the isp1301; may | 1081 | /* update the OTG controller state to match the isp1301; may |
@@ -1247,7 +1227,7 @@ static int __exit isp1301_remove(struct i2c_client *i2c) | |||
1247 | isp->timer.data = 0; | 1227 | isp->timer.data = 0; |
1248 | set_bit(WORK_STOP, &isp->todo); | 1228 | set_bit(WORK_STOP, &isp->todo); |
1249 | del_timer_sync(&isp->timer); | 1229 | del_timer_sync(&isp->timer); |
1250 | flush_scheduled_work(); | 1230 | flush_work_sync(&isp->work); |
1251 | 1231 | ||
1252 | put_device(&i2c->dev); | 1232 | put_device(&i2c->dev); |
1253 | the_transceiver = NULL; | 1233 | the_transceiver = NULL; |
@@ -1510,7 +1490,7 @@ isp1301_start_hnp(struct otg_transceiver *dev) | |||
1510 | 1490 | ||
1511 | /*-------------------------------------------------------------------------*/ | 1491 | /*-------------------------------------------------------------------------*/ |
1512 | 1492 | ||
1513 | static int __init | 1493 | static int __devinit |
1514 | isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) | 1494 | isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) |
1515 | { | 1495 | { |
1516 | int status; | 1496 | int status; |
@@ -1531,7 +1511,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) | |||
1531 | i2c_set_clientdata(i2c, isp); | 1511 | i2c_set_clientdata(i2c, isp); |
1532 | isp->client = i2c; | 1512 | isp->client = i2c; |
1533 | 1513 | ||
1534 | /* verify the chip (shouldn't be necesary) */ | 1514 | /* verify the chip (shouldn't be necessary) */ |
1535 | status = isp1301_get_u16(isp, ISP1301_VENDOR_ID); | 1515 | status = isp1301_get_u16(isp, ISP1301_VENDOR_ID); |
1536 | if (status != I2C_VENDOR_ID_PHILIPS) { | 1516 | if (status != I2C_VENDOR_ID_PHILIPS) { |
1537 | dev_dbg(&i2c->dev, "not philips id: %d\n", status); | 1517 | dev_dbg(&i2c->dev, "not philips id: %d\n", status); |
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c new file mode 100644 index 000000000000..f08f784086f7 --- /dev/null +++ b/drivers/usb/otg/langwell_otg.c | |||
@@ -0,0 +1,2347 @@ | |||
1 | /* | ||
2 | * Intel Langwell USB OTG transceiver driver | ||
3 | * Copyright (C) 2008 - 2010, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | * | ||
18 | */ | ||
19 | /* This driver helps to switch Langwell OTG controller function between host | ||
20 | * and peripheral. It works with EHCI driver and Langwell client controller | ||
21 | * driver together. | ||
22 | */ | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/pci.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/moduleparam.h> | ||
31 | #include <linux/usb/ch9.h> | ||
32 | #include <linux/usb/gadget.h> | ||
33 | #include <linux/usb.h> | ||
34 | #include <linux/usb/otg.h> | ||
35 | #include <linux/usb/hcd.h> | ||
36 | #include <linux/notifier.h> | ||
37 | #include <linux/delay.h> | ||
38 | #include <asm/intel_scu_ipc.h> | ||
39 | |||
40 | #include <linux/usb/langwell_otg.h> | ||
41 | |||
42 | #define DRIVER_DESC "Intel Langwell USB OTG transceiver driver" | ||
43 | #define DRIVER_VERSION "July 10, 2010" | ||
44 | |||
45 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
46 | MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>"); | ||
47 | MODULE_VERSION(DRIVER_VERSION); | ||
48 | MODULE_LICENSE("GPL"); | ||
49 | |||
50 | static const char driver_name[] = "langwell_otg"; | ||
51 | |||
52 | static int langwell_otg_probe(struct pci_dev *pdev, | ||
53 | const struct pci_device_id *id); | ||
54 | static void langwell_otg_remove(struct pci_dev *pdev); | ||
55 | static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message); | ||
56 | static int langwell_otg_resume(struct pci_dev *pdev); | ||
57 | |||
58 | static int langwell_otg_set_host(struct otg_transceiver *otg, | ||
59 | struct usb_bus *host); | ||
60 | static int langwell_otg_set_peripheral(struct otg_transceiver *otg, | ||
61 | struct usb_gadget *gadget); | ||
62 | static int langwell_otg_start_srp(struct otg_transceiver *otg); | ||
63 | |||
64 | static const struct pci_device_id pci_ids[] = {{ | ||
65 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), | ||
66 | .class_mask = ~0, | ||
67 | .vendor = 0x8086, | ||
68 | .device = 0x0811, | ||
69 | .subvendor = PCI_ANY_ID, | ||
70 | .subdevice = PCI_ANY_ID, | ||
71 | }, { /* end: all zeroes */ } | ||
72 | }; | ||
73 | |||
74 | static struct pci_driver otg_pci_driver = { | ||
75 | .name = (char *) driver_name, | ||
76 | .id_table = pci_ids, | ||
77 | |||
78 | .probe = langwell_otg_probe, | ||
79 | .remove = langwell_otg_remove, | ||
80 | |||
81 | .suspend = langwell_otg_suspend, | ||
82 | .resume = langwell_otg_resume, | ||
83 | }; | ||
84 | |||
85 | /* HSM timers */ | ||
86 | static inline struct langwell_otg_timer *otg_timer_initializer | ||
87 | (void (*function)(unsigned long), unsigned long expires, unsigned long data) | ||
88 | { | ||
89 | struct langwell_otg_timer *timer; | ||
90 | timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL); | ||
91 | if (timer == NULL) | ||
92 | return timer; | ||
93 | |||
94 | timer->function = function; | ||
95 | timer->expires = expires; | ||
96 | timer->data = data; | ||
97 | return timer; | ||
98 | } | ||
99 | |||
100 | static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr, | ||
101 | *b_se0_srp_tmr, *b_srp_init_tmr; | ||
102 | |||
103 | static struct list_head active_timers; | ||
104 | |||
105 | static struct langwell_otg *the_transceiver; | ||
106 | |||
107 | /* host/client notify transceiver when event affects HNP state */ | ||
108 | void langwell_update_transceiver(void) | ||
109 | { | ||
110 | struct langwell_otg *lnw = the_transceiver; | ||
111 | |||
112 | dev_dbg(lnw->dev, "transceiver is updated\n"); | ||
113 | |||
114 | if (!lnw->qwork) | ||
115 | return ; | ||
116 | |||
117 | queue_work(lnw->qwork, &lnw->work); | ||
118 | } | ||
119 | EXPORT_SYMBOL(langwell_update_transceiver); | ||
120 | |||
121 | static int langwell_otg_set_host(struct otg_transceiver *otg, | ||
122 | struct usb_bus *host) | ||
123 | { | ||
124 | otg->host = host; | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int langwell_otg_set_peripheral(struct otg_transceiver *otg, | ||
130 | struct usb_gadget *gadget) | ||
131 | { | ||
132 | otg->gadget = gadget; | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int langwell_otg_set_power(struct otg_transceiver *otg, | ||
138 | unsigned mA) | ||
139 | { | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | /* A-device drives vbus, controlled through IPC commands */ | ||
144 | static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled) | ||
145 | { | ||
146 | struct langwell_otg *lnw = the_transceiver; | ||
147 | u8 sub_id; | ||
148 | |||
149 | dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off"); | ||
150 | |||
151 | if (enabled) | ||
152 | sub_id = 0x8; /* Turn on the VBus */ | ||
153 | else | ||
154 | sub_id = 0x9; /* Turn off the VBus */ | ||
155 | |||
156 | if (intel_scu_ipc_simple_command(0xef, sub_id)) { | ||
157 | dev_dbg(lnw->dev, "Failed to set Vbus via IPC commands\n"); | ||
158 | return -EBUSY; | ||
159 | } | ||
160 | |||
161 | dev_dbg(lnw->dev, "%s --->\n", __func__); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | /* charge vbus or discharge vbus through a resistor to ground */ | ||
167 | static void langwell_otg_chrg_vbus(int on) | ||
168 | { | ||
169 | struct langwell_otg *lnw = the_transceiver; | ||
170 | u32 val; | ||
171 | |||
172 | val = readl(lnw->iotg.base + CI_OTGSC); | ||
173 | |||
174 | if (on) | ||
175 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC, | ||
176 | lnw->iotg.base + CI_OTGSC); | ||
177 | else | ||
178 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD, | ||
179 | lnw->iotg.base + CI_OTGSC); | ||
180 | } | ||
181 | |||
182 | /* Start SRP */ | ||
183 | static int langwell_otg_start_srp(struct otg_transceiver *otg) | ||
184 | { | ||
185 | struct langwell_otg *lnw = the_transceiver; | ||
186 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
187 | u32 val; | ||
188 | |||
189 | dev_dbg(lnw->dev, "%s --->\n", __func__); | ||
190 | |||
191 | val = readl(iotg->base + CI_OTGSC); | ||
192 | |||
193 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, | ||
194 | iotg->base + CI_OTGSC); | ||
195 | |||
196 | /* Check if the data plus is finished or not */ | ||
197 | msleep(8); | ||
198 | val = readl(iotg->base + CI_OTGSC); | ||
199 | if (val & (OTGSC_HADP | OTGSC_DP)) | ||
200 | dev_dbg(lnw->dev, "DataLine SRP Error\n"); | ||
201 | |||
202 | /* Disable interrupt - b_sess_vld */ | ||
203 | val = readl(iotg->base + CI_OTGSC); | ||
204 | val &= (~(OTGSC_BSVIE | OTGSC_BSEIE)); | ||
205 | writel(val, iotg->base + CI_OTGSC); | ||
206 | |||
207 | /* Start VBus SRP, drive vbus to generate VBus pulse */ | ||
208 | iotg->otg.set_vbus(&iotg->otg, true); | ||
209 | msleep(15); | ||
210 | iotg->otg.set_vbus(&iotg->otg, false); | ||
211 | |||
212 | /* Enable interrupt - b_sess_vld*/ | ||
213 | val = readl(iotg->base + CI_OTGSC); | ||
214 | dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val); | ||
215 | |||
216 | val |= (OTGSC_BSVIE | OTGSC_BSEIE); | ||
217 | writel(val, iotg->base + CI_OTGSC); | ||
218 | |||
219 | /* If Vbus is valid, then update the hsm */ | ||
220 | if (val & OTGSC_BSV) { | ||
221 | dev_dbg(lnw->dev, "no b_sess_vld interrupt\n"); | ||
222 | |||
223 | lnw->iotg.hsm.b_sess_vld = 1; | ||
224 | langwell_update_transceiver(); | ||
225 | } | ||
226 | |||
227 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | /* stop SOF via bus_suspend */ | ||
232 | static void langwell_otg_loc_sof(int on) | ||
233 | { | ||
234 | struct langwell_otg *lnw = the_transceiver; | ||
235 | struct usb_hcd *hcd; | ||
236 | int err; | ||
237 | |||
238 | dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume"); | ||
239 | |||
240 | hcd = bus_to_hcd(lnw->iotg.otg.host); | ||
241 | if (on) | ||
242 | err = hcd->driver->bus_resume(hcd); | ||
243 | else | ||
244 | err = hcd->driver->bus_suspend(hcd); | ||
245 | |||
246 | if (err) | ||
247 | dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err); | ||
248 | |||
249 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
250 | } | ||
251 | |||
252 | static int langwell_otg_check_otgsc(void) | ||
253 | { | ||
254 | struct langwell_otg *lnw = the_transceiver; | ||
255 | u32 otgsc, usbcfg; | ||
256 | |||
257 | dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n"); | ||
258 | |||
259 | otgsc = readl(lnw->iotg.base + CI_OTGSC); | ||
260 | usbcfg = readl(lnw->usbcfg); | ||
261 | |||
262 | dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n", | ||
263 | otgsc, usbcfg); | ||
264 | dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV)); | ||
265 | dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n", | ||
266 | !!(usbcfg & USBCFG_VBUSVAL)); | ||
267 | dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV)); | ||
268 | dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n", | ||
269 | !!(usbcfg & USBCFG_AVALID)); | ||
270 | dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV)); | ||
271 | dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n", | ||
272 | !!(usbcfg & USBCFG_BVALID)); | ||
273 | dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE)); | ||
274 | dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n", | ||
275 | !!(usbcfg & USBCFG_SESEND)); | ||
276 | |||
277 | /* Check USBCFG VBusValid/AValid/BValid/SessEnd */ | ||
278 | if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) { | ||
279 | dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n"); | ||
280 | goto err; | ||
281 | } | ||
282 | if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) { | ||
283 | dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n"); | ||
284 | goto err; | ||
285 | } | ||
286 | if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) { | ||
287 | dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n"); | ||
288 | goto err; | ||
289 | } | ||
290 | if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) { | ||
291 | dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n"); | ||
292 | goto err; | ||
293 | } | ||
294 | |||
295 | dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n"); | ||
296 | |||
297 | return 0; | ||
298 | |||
299 | err: | ||
300 | dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n"); | ||
301 | return -EPIPE; | ||
302 | } | ||
303 | |||
304 | |||
305 | static void langwell_otg_phy_low_power(int on) | ||
306 | { | ||
307 | struct langwell_otg *lnw = the_transceiver; | ||
308 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
309 | u8 val, phcd; | ||
310 | int retval; | ||
311 | |||
312 | dev_dbg(lnw->dev, "%s ---> %s mode\n", | ||
313 | __func__, on ? "Low power" : "Normal"); | ||
314 | |||
315 | phcd = 0x40; | ||
316 | |||
317 | val = readb(iotg->base + CI_HOSTPC1 + 2); | ||
318 | |||
319 | if (on) { | ||
320 | /* Due to hardware issue, after set PHCD, sync will failed | ||
321 | * between USBCFG and OTGSC, so before set PHCD, check if | ||
322 | * sync is in process now. If the answer is "yes", then do | ||
323 | * not touch PHCD bit */ | ||
324 | retval = langwell_otg_check_otgsc(); | ||
325 | if (retval) { | ||
326 | dev_dbg(lnw->dev, "Skip PHCD programming..\n"); | ||
327 | return ; | ||
328 | } | ||
329 | |||
330 | writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2); | ||
331 | } else | ||
332 | writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2); | ||
333 | |||
334 | dev_dbg(lnw->dev, "%s <--- done\n", __func__); | ||
335 | } | ||
336 | |||
337 | /* After drv vbus, add 5 ms delay to set PHCD */ | ||
338 | static void langwell_otg_phy_low_power_wait(int on) | ||
339 | { | ||
340 | struct langwell_otg *lnw = the_transceiver; | ||
341 | |||
342 | dev_dbg(lnw->dev, "add 5ms delay before programing PHCD\n"); | ||
343 | |||
344 | mdelay(5); | ||
345 | langwell_otg_phy_low_power(on); | ||
346 | } | ||
347 | |||
348 | /* Enable/Disable OTG interrupt */ | ||
349 | static void langwell_otg_intr(int on) | ||
350 | { | ||
351 | struct langwell_otg *lnw = the_transceiver; | ||
352 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
353 | u32 val; | ||
354 | |||
355 | dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); | ||
356 | |||
357 | val = readl(iotg->base + CI_OTGSC); | ||
358 | |||
359 | /* OTGSC_INT_MASK doesn't contains 1msInt */ | ||
360 | if (on) { | ||
361 | val = val | (OTGSC_INT_MASK); | ||
362 | writel(val, iotg->base + CI_OTGSC); | ||
363 | } else { | ||
364 | val = val & ~(OTGSC_INT_MASK); | ||
365 | writel(val, iotg->base + CI_OTGSC); | ||
366 | } | ||
367 | |||
368 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
369 | } | ||
370 | |||
371 | /* set HAAR: Hardware Assist Auto-Reset */ | ||
372 | static void langwell_otg_HAAR(int on) | ||
373 | { | ||
374 | struct langwell_otg *lnw = the_transceiver; | ||
375 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
376 | u32 val; | ||
377 | |||
378 | dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); | ||
379 | |||
380 | val = readl(iotg->base + CI_OTGSC); | ||
381 | if (on) | ||
382 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR, | ||
383 | iotg->base + CI_OTGSC); | ||
384 | else | ||
385 | writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR, | ||
386 | iotg->base + CI_OTGSC); | ||
387 | |||
388 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
389 | } | ||
390 | |||
391 | /* set HABA: Hardware Assist B-Disconnect to A-Connect */ | ||
392 | static void langwell_otg_HABA(int on) | ||
393 | { | ||
394 | struct langwell_otg *lnw = the_transceiver; | ||
395 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
396 | u32 val; | ||
397 | |||
398 | dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); | ||
399 | |||
400 | val = readl(iotg->base + CI_OTGSC); | ||
401 | if (on) | ||
402 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA, | ||
403 | iotg->base + CI_OTGSC); | ||
404 | else | ||
405 | writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA, | ||
406 | iotg->base + CI_OTGSC); | ||
407 | |||
408 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
409 | } | ||
410 | |||
411 | static int langwell_otg_check_se0_srp(int on) | ||
412 | { | ||
413 | struct langwell_otg *lnw = the_transceiver; | ||
414 | int delay_time = TB_SE0_SRP * 10; | ||
415 | u32 val; | ||
416 | |||
417 | dev_dbg(lnw->dev, "%s --->\n", __func__); | ||
418 | |||
419 | do { | ||
420 | udelay(100); | ||
421 | if (!delay_time--) | ||
422 | break; | ||
423 | val = readl(lnw->iotg.base + CI_PORTSC1); | ||
424 | val &= PORTSC_LS; | ||
425 | } while (!val); | ||
426 | |||
427 | dev_dbg(lnw->dev, "%s <---\n", __func__); | ||
428 | return val; | ||
429 | } | ||
430 | |||
431 | /* The timeout callback function to set time out bit */ | ||
432 | static void set_tmout(unsigned long indicator) | ||
433 | { | ||
434 | *(int *)indicator = 1; | ||
435 | } | ||
436 | |||
437 | void langwell_otg_nsf_msg(unsigned long indicator) | ||
438 | { | ||
439 | struct langwell_otg *lnw = the_transceiver; | ||
440 | |||
441 | switch (indicator) { | ||
442 | case 2: | ||
443 | case 4: | ||
444 | case 6: | ||
445 | case 7: | ||
446 | dev_warn(lnw->dev, | ||
447 | "OTG:NSF-%lu - deivce not responding\n", indicator); | ||
448 | break; | ||
449 | case 3: | ||
450 | dev_warn(lnw->dev, | ||
451 | "OTG:NSF-%lu - deivce not supported\n", indicator); | ||
452 | break; | ||
453 | default: | ||
454 | dev_warn(lnw->dev, "Do not have this kind of NSF\n"); | ||
455 | break; | ||
456 | } | ||
457 | } | ||
458 | |||
459 | /* Initialize timers */ | ||
460 | static int langwell_otg_init_timers(struct otg_hsm *hsm) | ||
461 | { | ||
462 | /* HSM used timers */ | ||
463 | a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, | ||
464 | (unsigned long)&hsm->a_wait_vrise_tmout); | ||
465 | if (a_wait_vrise_tmr == NULL) | ||
466 | return -ENOMEM; | ||
467 | a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, | ||
468 | (unsigned long)&hsm->a_aidl_bdis_tmout); | ||
469 | if (a_aidl_bdis_tmr == NULL) | ||
470 | return -ENOMEM; | ||
471 | b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, | ||
472 | (unsigned long)&hsm->b_se0_srp); | ||
473 | if (b_se0_srp_tmr == NULL) | ||
474 | return -ENOMEM; | ||
475 | b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT, | ||
476 | (unsigned long)&hsm->b_srp_init_tmout); | ||
477 | if (b_srp_init_tmr == NULL) | ||
478 | return -ENOMEM; | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | /* Free timers */ | ||
484 | static void langwell_otg_free_timers(void) | ||
485 | { | ||
486 | kfree(a_wait_vrise_tmr); | ||
487 | kfree(a_aidl_bdis_tmr); | ||
488 | kfree(b_se0_srp_tmr); | ||
489 | kfree(b_srp_init_tmr); | ||
490 | } | ||
491 | |||
492 | /* The timeout callback function to set time out bit */ | ||
493 | static void langwell_otg_timer_fn(unsigned long indicator) | ||
494 | { | ||
495 | struct langwell_otg *lnw = the_transceiver; | ||
496 | |||
497 | *(int *)indicator = 1; | ||
498 | |||
499 | dev_dbg(lnw->dev, "kernel timer - timeout\n"); | ||
500 | |||
501 | langwell_update_transceiver(); | ||
502 | } | ||
503 | |||
504 | /* kernel timer used instead of HW based interrupt */ | ||
505 | static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers) | ||
506 | { | ||
507 | struct langwell_otg *lnw = the_transceiver; | ||
508 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
509 | unsigned long j = jiffies; | ||
510 | unsigned long data, time; | ||
511 | |||
512 | switch (timers) { | ||
513 | case TA_WAIT_VRISE_TMR: | ||
514 | iotg->hsm.a_wait_vrise_tmout = 0; | ||
515 | data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout; | ||
516 | time = TA_WAIT_VRISE; | ||
517 | break; | ||
518 | case TA_WAIT_BCON_TMR: | ||
519 | iotg->hsm.a_wait_bcon_tmout = 0; | ||
520 | data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout; | ||
521 | time = TA_WAIT_BCON; | ||
522 | break; | ||
523 | case TA_AIDL_BDIS_TMR: | ||
524 | iotg->hsm.a_aidl_bdis_tmout = 0; | ||
525 | data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout; | ||
526 | time = TA_AIDL_BDIS; | ||
527 | break; | ||
528 | case TB_ASE0_BRST_TMR: | ||
529 | iotg->hsm.b_ase0_brst_tmout = 0; | ||
530 | data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout; | ||
531 | time = TB_ASE0_BRST; | ||
532 | break; | ||
533 | case TB_SRP_INIT_TMR: | ||
534 | iotg->hsm.b_srp_init_tmout = 0; | ||
535 | data = (unsigned long)&iotg->hsm.b_srp_init_tmout; | ||
536 | time = TB_SRP_INIT; | ||
537 | break; | ||
538 | case TB_SRP_FAIL_TMR: | ||
539 | iotg->hsm.b_srp_fail_tmout = 0; | ||
540 | data = (unsigned long)&iotg->hsm.b_srp_fail_tmout; | ||
541 | time = TB_SRP_FAIL; | ||
542 | break; | ||
543 | case TB_BUS_SUSPEND_TMR: | ||
544 | iotg->hsm.b_bus_suspend_tmout = 0; | ||
545 | data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout; | ||
546 | time = TB_BUS_SUSPEND; | ||
547 | break; | ||
548 | default: | ||
549 | dev_dbg(lnw->dev, "unknown timer, cannot enable it\n"); | ||
550 | return; | ||
551 | } | ||
552 | |||
553 | lnw->hsm_timer.data = data; | ||
554 | lnw->hsm_timer.function = langwell_otg_timer_fn; | ||
555 | lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */ | ||
556 | |||
557 | add_timer(&lnw->hsm_timer); | ||
558 | |||
559 | dev_dbg(lnw->dev, "add timer successfully\n"); | ||
560 | } | ||
561 | |||
562 | /* Add timer to timer list */ | ||
563 | static void langwell_otg_add_timer(void *gtimer) | ||
564 | { | ||
565 | struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; | ||
566 | struct langwell_otg_timer *tmp_timer; | ||
567 | struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg; | ||
568 | u32 val32; | ||
569 | |||
570 | /* Check if the timer is already in the active list, | ||
571 | * if so update timer count | ||
572 | */ | ||
573 | list_for_each_entry(tmp_timer, &active_timers, list) | ||
574 | if (tmp_timer == timer) { | ||
575 | timer->count = timer->expires; | ||
576 | return; | ||
577 | } | ||
578 | timer->count = timer->expires; | ||
579 | |||
580 | if (list_empty(&active_timers)) { | ||
581 | val32 = readl(iotg->base + CI_OTGSC); | ||
582 | writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC); | ||
583 | } | ||
584 | |||
585 | list_add_tail(&timer->list, &active_timers); | ||
586 | } | ||
587 | |||
588 | /* Remove timer from the timer list; clear timeout status */ | ||
589 | static void langwell_otg_del_timer(void *gtimer) | ||
590 | { | ||
591 | struct langwell_otg *lnw = the_transceiver; | ||
592 | struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; | ||
593 | struct langwell_otg_timer *tmp_timer, *del_tmp; | ||
594 | u32 val32; | ||
595 | |||
596 | list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) | ||
597 | if (tmp_timer == timer) | ||
598 | list_del(&timer->list); | ||
599 | |||
600 | if (list_empty(&active_timers)) { | ||
601 | val32 = readl(lnw->iotg.base + CI_OTGSC); | ||
602 | writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC); | ||
603 | } | ||
604 | } | ||
605 | |||
606 | /* Reduce timer count by 1, and find timeout conditions.*/ | ||
607 | static int langwell_otg_tick_timer(u32 *int_sts) | ||
608 | { | ||
609 | struct langwell_otg *lnw = the_transceiver; | ||
610 | struct langwell_otg_timer *tmp_timer, *del_tmp; | ||
611 | int expired = 0; | ||
612 | |||
613 | list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { | ||
614 | tmp_timer->count--; | ||
615 | /* check if timer expires */ | ||
616 | if (!tmp_timer->count) { | ||
617 | list_del(&tmp_timer->list); | ||
618 | tmp_timer->function(tmp_timer->data); | ||
619 | expired = 1; | ||
620 | } | ||
621 | } | ||
622 | |||
623 | if (list_empty(&active_timers)) { | ||
624 | dev_dbg(lnw->dev, "tick timer: disable 1ms int\n"); | ||
625 | *int_sts = *int_sts & ~OTGSC_1MSE; | ||
626 | } | ||
627 | return expired; | ||
628 | } | ||
629 | |||
630 | static void reset_otg(void) | ||
631 | { | ||
632 | struct langwell_otg *lnw = the_transceiver; | ||
633 | int delay_time = 1000; | ||
634 | u32 val; | ||
635 | |||
636 | dev_dbg(lnw->dev, "reseting OTG controller ...\n"); | ||
637 | val = readl(lnw->iotg.base + CI_USBCMD); | ||
638 | writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD); | ||
639 | do { | ||
640 | udelay(100); | ||
641 | if (!delay_time--) | ||
642 | dev_dbg(lnw->dev, "reset timeout\n"); | ||
643 | val = readl(lnw->iotg.base + CI_USBCMD); | ||
644 | val &= USBCMD_RST; | ||
645 | } while (val != 0); | ||
646 | dev_dbg(lnw->dev, "reset done.\n"); | ||
647 | } | ||
648 | |||
649 | static void set_host_mode(void) | ||
650 | { | ||
651 | struct langwell_otg *lnw = the_transceiver; | ||
652 | u32 val; | ||
653 | |||
654 | reset_otg(); | ||
655 | val = readl(lnw->iotg.base + CI_USBMODE); | ||
656 | val = (val & (~USBMODE_CM)) | USBMODE_HOST; | ||
657 | writel(val, lnw->iotg.base + CI_USBMODE); | ||
658 | } | ||
659 | |||
660 | static void set_client_mode(void) | ||
661 | { | ||
662 | struct langwell_otg *lnw = the_transceiver; | ||
663 | u32 val; | ||
664 | |||
665 | reset_otg(); | ||
666 | val = readl(lnw->iotg.base + CI_USBMODE); | ||
667 | val = (val & (~USBMODE_CM)) | USBMODE_DEVICE; | ||
668 | writel(val, lnw->iotg.base + CI_USBMODE); | ||
669 | } | ||
670 | |||
671 | static void init_hsm(void) | ||
672 | { | ||
673 | struct langwell_otg *lnw = the_transceiver; | ||
674 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
675 | u32 val32; | ||
676 | |||
677 | /* read OTGSC after reset */ | ||
678 | val32 = readl(lnw->iotg.base + CI_OTGSC); | ||
679 | dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32); | ||
680 | |||
681 | /* set init state */ | ||
682 | if (val32 & OTGSC_ID) { | ||
683 | iotg->hsm.id = 1; | ||
684 | iotg->otg.default_a = 0; | ||
685 | set_client_mode(); | ||
686 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
687 | } else { | ||
688 | iotg->hsm.id = 0; | ||
689 | iotg->otg.default_a = 1; | ||
690 | set_host_mode(); | ||
691 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
692 | } | ||
693 | |||
694 | /* set session indicator */ | ||
695 | if (val32 & OTGSC_BSE) | ||
696 | iotg->hsm.b_sess_end = 1; | ||
697 | if (val32 & OTGSC_BSV) | ||
698 | iotg->hsm.b_sess_vld = 1; | ||
699 | if (val32 & OTGSC_ASV) | ||
700 | iotg->hsm.a_sess_vld = 1; | ||
701 | if (val32 & OTGSC_AVV) | ||
702 | iotg->hsm.a_vbus_vld = 1; | ||
703 | |||
704 | /* defautly power the bus */ | ||
705 | iotg->hsm.a_bus_req = 1; | ||
706 | iotg->hsm.a_bus_drop = 0; | ||
707 | /* defautly don't request bus as B device */ | ||
708 | iotg->hsm.b_bus_req = 0; | ||
709 | /* no system error */ | ||
710 | iotg->hsm.a_clr_err = 0; | ||
711 | |||
712 | langwell_otg_phy_low_power_wait(1); | ||
713 | } | ||
714 | |||
715 | static void update_hsm(void) | ||
716 | { | ||
717 | struct langwell_otg *lnw = the_transceiver; | ||
718 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
719 | u32 val32; | ||
720 | |||
721 | /* read OTGSC */ | ||
722 | val32 = readl(lnw->iotg.base + CI_OTGSC); | ||
723 | dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32); | ||
724 | |||
725 | iotg->hsm.id = !!(val32 & OTGSC_ID); | ||
726 | iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE); | ||
727 | iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV); | ||
728 | iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV); | ||
729 | iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV); | ||
730 | } | ||
731 | |||
732 | static irqreturn_t otg_dummy_irq(int irq, void *_dev) | ||
733 | { | ||
734 | struct langwell_otg *lnw = the_transceiver; | ||
735 | void __iomem *reg_base = _dev; | ||
736 | u32 val; | ||
737 | u32 int_mask = 0; | ||
738 | |||
739 | val = readl(reg_base + CI_USBMODE); | ||
740 | if ((val & USBMODE_CM) != USBMODE_DEVICE) | ||
741 | return IRQ_NONE; | ||
742 | |||
743 | val = readl(reg_base + CI_USBSTS); | ||
744 | int_mask = val & INTR_DUMMY_MASK; | ||
745 | |||
746 | if (int_mask == 0) | ||
747 | return IRQ_NONE; | ||
748 | |||
749 | /* clear hsm.b_conn here since host driver can't detect it | ||
750 | * otg_dummy_irq called means B-disconnect happened. | ||
751 | */ | ||
752 | if (lnw->iotg.hsm.b_conn) { | ||
753 | lnw->iotg.hsm.b_conn = 0; | ||
754 | if (spin_trylock(&lnw->wq_lock)) { | ||
755 | langwell_update_transceiver(); | ||
756 | spin_unlock(&lnw->wq_lock); | ||
757 | } | ||
758 | } | ||
759 | |||
760 | /* Clear interrupts */ | ||
761 | writel(int_mask, reg_base + CI_USBSTS); | ||
762 | return IRQ_HANDLED; | ||
763 | } | ||
764 | |||
765 | static irqreturn_t otg_irq(int irq, void *_dev) | ||
766 | { | ||
767 | struct langwell_otg *lnw = _dev; | ||
768 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
769 | u32 int_sts, int_en; | ||
770 | u32 int_mask = 0; | ||
771 | int flag = 0; | ||
772 | |||
773 | int_sts = readl(lnw->iotg.base + CI_OTGSC); | ||
774 | int_en = (int_sts & OTGSC_INTEN_MASK) >> 8; | ||
775 | int_mask = int_sts & int_en; | ||
776 | if (int_mask == 0) | ||
777 | return IRQ_NONE; | ||
778 | |||
779 | if (int_mask & OTGSC_IDIS) { | ||
780 | dev_dbg(lnw->dev, "%s: id change int\n", __func__); | ||
781 | iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; | ||
782 | dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id); | ||
783 | flag = 1; | ||
784 | } | ||
785 | if (int_mask & OTGSC_DPIS) { | ||
786 | dev_dbg(lnw->dev, "%s: data pulse int\n", __func__); | ||
787 | iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; | ||
788 | dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det); | ||
789 | flag = 1; | ||
790 | } | ||
791 | if (int_mask & OTGSC_BSEIS) { | ||
792 | dev_dbg(lnw->dev, "%s: b session end int\n", __func__); | ||
793 | iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; | ||
794 | dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end); | ||
795 | flag = 1; | ||
796 | } | ||
797 | if (int_mask & OTGSC_BSVIS) { | ||
798 | dev_dbg(lnw->dev, "%s: b session valid int\n", __func__); | ||
799 | iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; | ||
800 | dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end); | ||
801 | flag = 1; | ||
802 | } | ||
803 | if (int_mask & OTGSC_ASVIS) { | ||
804 | dev_dbg(lnw->dev, "%s: a session valid int\n", __func__); | ||
805 | iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; | ||
806 | dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld); | ||
807 | flag = 1; | ||
808 | } | ||
809 | if (int_mask & OTGSC_AVVIS) { | ||
810 | dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__); | ||
811 | iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; | ||
812 | dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld); | ||
813 | flag = 1; | ||
814 | } | ||
815 | |||
816 | if (int_mask & OTGSC_1MSS) { | ||
817 | /* need to schedule otg_work if any timer is expired */ | ||
818 | if (langwell_otg_tick_timer(&int_sts)) | ||
819 | flag = 1; | ||
820 | } | ||
821 | |||
822 | writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, | ||
823 | lnw->iotg.base + CI_OTGSC); | ||
824 | if (flag) | ||
825 | langwell_update_transceiver(); | ||
826 | |||
827 | return IRQ_HANDLED; | ||
828 | } | ||
829 | |||
830 | static int langwell_otg_iotg_notify(struct notifier_block *nb, | ||
831 | unsigned long action, void *data) | ||
832 | { | ||
833 | struct langwell_otg *lnw = the_transceiver; | ||
834 | struct intel_mid_otg_xceiv *iotg = data; | ||
835 | int flag = 0; | ||
836 | |||
837 | if (iotg == NULL) | ||
838 | return NOTIFY_BAD; | ||
839 | |||
840 | if (lnw == NULL) | ||
841 | return NOTIFY_BAD; | ||
842 | |||
843 | switch (action) { | ||
844 | case MID_OTG_NOTIFY_CONNECT: | ||
845 | dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n"); | ||
846 | if (iotg->otg.default_a == 1) | ||
847 | iotg->hsm.b_conn = 1; | ||
848 | else | ||
849 | iotg->hsm.a_conn = 1; | ||
850 | flag = 1; | ||
851 | break; | ||
852 | case MID_OTG_NOTIFY_DISCONN: | ||
853 | dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n"); | ||
854 | if (iotg->otg.default_a == 1) | ||
855 | iotg->hsm.b_conn = 0; | ||
856 | else | ||
857 | iotg->hsm.a_conn = 0; | ||
858 | flag = 1; | ||
859 | break; | ||
860 | case MID_OTG_NOTIFY_HSUSPEND: | ||
861 | dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n"); | ||
862 | if (iotg->otg.default_a == 1) | ||
863 | iotg->hsm.a_suspend_req = 1; | ||
864 | else | ||
865 | iotg->hsm.b_bus_req = 0; | ||
866 | flag = 1; | ||
867 | break; | ||
868 | case MID_OTG_NOTIFY_HRESUME: | ||
869 | dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n"); | ||
870 | if (iotg->otg.default_a == 1) | ||
871 | iotg->hsm.b_bus_resume = 1; | ||
872 | flag = 1; | ||
873 | break; | ||
874 | case MID_OTG_NOTIFY_CSUSPEND: | ||
875 | dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n"); | ||
876 | if (iotg->otg.default_a == 1) { | ||
877 | if (iotg->hsm.b_bus_suspend_vld == 2) { | ||
878 | iotg->hsm.b_bus_suspend = 1; | ||
879 | iotg->hsm.b_bus_suspend_vld = 0; | ||
880 | flag = 1; | ||
881 | } else { | ||
882 | iotg->hsm.b_bus_suspend_vld++; | ||
883 | flag = 0; | ||
884 | } | ||
885 | } else { | ||
886 | if (iotg->hsm.a_bus_suspend == 0) { | ||
887 | iotg->hsm.a_bus_suspend = 1; | ||
888 | flag = 1; | ||
889 | } | ||
890 | } | ||
891 | break; | ||
892 | case MID_OTG_NOTIFY_CRESUME: | ||
893 | dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n"); | ||
894 | if (iotg->otg.default_a == 0) | ||
895 | iotg->hsm.a_bus_suspend = 0; | ||
896 | flag = 0; | ||
897 | break; | ||
898 | case MID_OTG_NOTIFY_HOSTADD: | ||
899 | dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n"); | ||
900 | flag = 1; | ||
901 | break; | ||
902 | case MID_OTG_NOTIFY_HOSTREMOVE: | ||
903 | dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n"); | ||
904 | flag = 1; | ||
905 | break; | ||
906 | case MID_OTG_NOTIFY_CLIENTADD: | ||
907 | dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n"); | ||
908 | flag = 1; | ||
909 | break; | ||
910 | case MID_OTG_NOTIFY_CLIENTREMOVE: | ||
911 | dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n"); | ||
912 | flag = 1; | ||
913 | break; | ||
914 | default: | ||
915 | dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n"); | ||
916 | return NOTIFY_DONE; | ||
917 | } | ||
918 | |||
919 | if (flag) | ||
920 | langwell_update_transceiver(); | ||
921 | |||
922 | return NOTIFY_OK; | ||
923 | } | ||
924 | |||
925 | static void langwell_otg_work(struct work_struct *work) | ||
926 | { | ||
927 | struct langwell_otg *lnw; | ||
928 | struct intel_mid_otg_xceiv *iotg; | ||
929 | int retval; | ||
930 | struct pci_dev *pdev; | ||
931 | |||
932 | lnw = container_of(work, struct langwell_otg, work); | ||
933 | iotg = &lnw->iotg; | ||
934 | pdev = to_pci_dev(lnw->dev); | ||
935 | |||
936 | dev_dbg(lnw->dev, "%s: old state = %s\n", __func__, | ||
937 | otg_state_string(iotg->otg.state)); | ||
938 | |||
939 | switch (iotg->otg.state) { | ||
940 | case OTG_STATE_UNDEFINED: | ||
941 | case OTG_STATE_B_IDLE: | ||
942 | if (!iotg->hsm.id) { | ||
943 | langwell_otg_del_timer(b_srp_init_tmr); | ||
944 | del_timer_sync(&lnw->hsm_timer); | ||
945 | |||
946 | iotg->otg.default_a = 1; | ||
947 | iotg->hsm.a_srp_det = 0; | ||
948 | |||
949 | langwell_otg_chrg_vbus(0); | ||
950 | set_host_mode(); | ||
951 | langwell_otg_phy_low_power(1); | ||
952 | |||
953 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
954 | langwell_update_transceiver(); | ||
955 | } else if (iotg->hsm.b_sess_vld) { | ||
956 | langwell_otg_del_timer(b_srp_init_tmr); | ||
957 | del_timer_sync(&lnw->hsm_timer); | ||
958 | iotg->hsm.b_sess_end = 0; | ||
959 | iotg->hsm.a_bus_suspend = 0; | ||
960 | langwell_otg_chrg_vbus(0); | ||
961 | |||
962 | if (lnw->iotg.start_peripheral) { | ||
963 | lnw->iotg.start_peripheral(&lnw->iotg); | ||
964 | iotg->otg.state = OTG_STATE_B_PERIPHERAL; | ||
965 | } else | ||
966 | dev_dbg(lnw->dev, "client driver not loaded\n"); | ||
967 | |||
968 | } else if (iotg->hsm.b_srp_init_tmout) { | ||
969 | iotg->hsm.b_srp_init_tmout = 0; | ||
970 | dev_warn(lnw->dev, "SRP init timeout\n"); | ||
971 | } else if (iotg->hsm.b_srp_fail_tmout) { | ||
972 | iotg->hsm.b_srp_fail_tmout = 0; | ||
973 | iotg->hsm.b_bus_req = 0; | ||
974 | |||
975 | /* No silence failure */ | ||
976 | langwell_otg_nsf_msg(6); | ||
977 | } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) { | ||
978 | del_timer_sync(&lnw->hsm_timer); | ||
979 | /* workaround for b_se0_srp detection */ | ||
980 | retval = langwell_otg_check_se0_srp(0); | ||
981 | if (retval) { | ||
982 | iotg->hsm.b_bus_req = 0; | ||
983 | dev_dbg(lnw->dev, "LS isn't SE0, try later\n"); | ||
984 | } else { | ||
985 | /* clear the PHCD before start srp */ | ||
986 | langwell_otg_phy_low_power(0); | ||
987 | |||
988 | /* Start SRP */ | ||
989 | langwell_otg_add_timer(b_srp_init_tmr); | ||
990 | iotg->otg.start_srp(&iotg->otg); | ||
991 | langwell_otg_del_timer(b_srp_init_tmr); | ||
992 | langwell_otg_add_ktimer(TB_SRP_FAIL_TMR); | ||
993 | |||
994 | /* reset PHY low power mode here */ | ||
995 | langwell_otg_phy_low_power_wait(1); | ||
996 | } | ||
997 | } | ||
998 | break; | ||
999 | case OTG_STATE_B_SRP_INIT: | ||
1000 | if (!iotg->hsm.id) { | ||
1001 | iotg->otg.default_a = 1; | ||
1002 | iotg->hsm.a_srp_det = 0; | ||
1003 | |||
1004 | /* Turn off VBus */ | ||
1005 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1006 | langwell_otg_chrg_vbus(0); | ||
1007 | set_host_mode(); | ||
1008 | langwell_otg_phy_low_power(1); | ||
1009 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
1010 | langwell_update_transceiver(); | ||
1011 | } else if (iotg->hsm.b_sess_vld) { | ||
1012 | langwell_otg_chrg_vbus(0); | ||
1013 | if (lnw->iotg.start_peripheral) { | ||
1014 | lnw->iotg.start_peripheral(&lnw->iotg); | ||
1015 | iotg->otg.state = OTG_STATE_B_PERIPHERAL; | ||
1016 | } else | ||
1017 | dev_dbg(lnw->dev, "client driver not loaded\n"); | ||
1018 | } | ||
1019 | break; | ||
1020 | case OTG_STATE_B_PERIPHERAL: | ||
1021 | if (!iotg->hsm.id) { | ||
1022 | iotg->otg.default_a = 1; | ||
1023 | iotg->hsm.a_srp_det = 0; | ||
1024 | |||
1025 | langwell_otg_chrg_vbus(0); | ||
1026 | |||
1027 | if (lnw->iotg.stop_peripheral) | ||
1028 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
1029 | else | ||
1030 | dev_dbg(lnw->dev, | ||
1031 | "client driver has been removed.\n"); | ||
1032 | |||
1033 | set_host_mode(); | ||
1034 | langwell_otg_phy_low_power(1); | ||
1035 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
1036 | langwell_update_transceiver(); | ||
1037 | } else if (!iotg->hsm.b_sess_vld) { | ||
1038 | iotg->hsm.b_hnp_enable = 0; | ||
1039 | |||
1040 | if (lnw->iotg.stop_peripheral) | ||
1041 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
1042 | else | ||
1043 | dev_dbg(lnw->dev, | ||
1044 | "client driver has been removed.\n"); | ||
1045 | |||
1046 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1047 | } else if (iotg->hsm.b_bus_req && iotg->otg.gadget && | ||
1048 | iotg->otg.gadget->b_hnp_enable && | ||
1049 | iotg->hsm.a_bus_suspend) { | ||
1050 | |||
1051 | if (lnw->iotg.stop_peripheral) | ||
1052 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
1053 | else | ||
1054 | dev_dbg(lnw->dev, | ||
1055 | "client driver has been removed.\n"); | ||
1056 | |||
1057 | langwell_otg_HAAR(1); | ||
1058 | iotg->hsm.a_conn = 0; | ||
1059 | |||
1060 | if (lnw->iotg.start_host) { | ||
1061 | lnw->iotg.start_host(&lnw->iotg); | ||
1062 | iotg->otg.state = OTG_STATE_B_WAIT_ACON; | ||
1063 | } else | ||
1064 | dev_dbg(lnw->dev, | ||
1065 | "host driver not loaded.\n"); | ||
1066 | |||
1067 | iotg->hsm.a_bus_resume = 0; | ||
1068 | langwell_otg_add_ktimer(TB_ASE0_BRST_TMR); | ||
1069 | } | ||
1070 | break; | ||
1071 | |||
1072 | case OTG_STATE_B_WAIT_ACON: | ||
1073 | if (!iotg->hsm.id) { | ||
1074 | /* delete hsm timer for b_ase0_brst_tmr */ | ||
1075 | del_timer_sync(&lnw->hsm_timer); | ||
1076 | |||
1077 | iotg->otg.default_a = 1; | ||
1078 | iotg->hsm.a_srp_det = 0; | ||
1079 | |||
1080 | langwell_otg_chrg_vbus(0); | ||
1081 | |||
1082 | langwell_otg_HAAR(0); | ||
1083 | if (lnw->iotg.stop_host) | ||
1084 | lnw->iotg.stop_host(&lnw->iotg); | ||
1085 | else | ||
1086 | dev_dbg(lnw->dev, | ||
1087 | "host driver has been removed.\n"); | ||
1088 | |||
1089 | set_host_mode(); | ||
1090 | langwell_otg_phy_low_power(1); | ||
1091 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
1092 | langwell_update_transceiver(); | ||
1093 | } else if (!iotg->hsm.b_sess_vld) { | ||
1094 | /* delete hsm timer for b_ase0_brst_tmr */ | ||
1095 | del_timer_sync(&lnw->hsm_timer); | ||
1096 | |||
1097 | iotg->hsm.b_hnp_enable = 0; | ||
1098 | iotg->hsm.b_bus_req = 0; | ||
1099 | |||
1100 | langwell_otg_chrg_vbus(0); | ||
1101 | langwell_otg_HAAR(0); | ||
1102 | |||
1103 | if (lnw->iotg.stop_host) | ||
1104 | lnw->iotg.stop_host(&lnw->iotg); | ||
1105 | else | ||
1106 | dev_dbg(lnw->dev, | ||
1107 | "host driver has been removed.\n"); | ||
1108 | |||
1109 | set_client_mode(); | ||
1110 | langwell_otg_phy_low_power(1); | ||
1111 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1112 | } else if (iotg->hsm.a_conn) { | ||
1113 | /* delete hsm timer for b_ase0_brst_tmr */ | ||
1114 | del_timer_sync(&lnw->hsm_timer); | ||
1115 | |||
1116 | langwell_otg_HAAR(0); | ||
1117 | iotg->otg.state = OTG_STATE_B_HOST; | ||
1118 | langwell_update_transceiver(); | ||
1119 | } else if (iotg->hsm.a_bus_resume || | ||
1120 | iotg->hsm.b_ase0_brst_tmout) { | ||
1121 | /* delete hsm timer for b_ase0_brst_tmr */ | ||
1122 | del_timer_sync(&lnw->hsm_timer); | ||
1123 | |||
1124 | langwell_otg_HAAR(0); | ||
1125 | langwell_otg_nsf_msg(7); | ||
1126 | |||
1127 | if (lnw->iotg.stop_host) | ||
1128 | lnw->iotg.stop_host(&lnw->iotg); | ||
1129 | else | ||
1130 | dev_dbg(lnw->dev, | ||
1131 | "host driver has been removed.\n"); | ||
1132 | |||
1133 | iotg->hsm.a_bus_suspend = 0; | ||
1134 | iotg->hsm.b_bus_req = 0; | ||
1135 | |||
1136 | if (lnw->iotg.start_peripheral) | ||
1137 | lnw->iotg.start_peripheral(&lnw->iotg); | ||
1138 | else | ||
1139 | dev_dbg(lnw->dev, | ||
1140 | "client driver not loaded.\n"); | ||
1141 | |||
1142 | iotg->otg.state = OTG_STATE_B_PERIPHERAL; | ||
1143 | } | ||
1144 | break; | ||
1145 | |||
1146 | case OTG_STATE_B_HOST: | ||
1147 | if (!iotg->hsm.id) { | ||
1148 | iotg->otg.default_a = 1; | ||
1149 | iotg->hsm.a_srp_det = 0; | ||
1150 | |||
1151 | langwell_otg_chrg_vbus(0); | ||
1152 | |||
1153 | if (lnw->iotg.stop_host) | ||
1154 | lnw->iotg.stop_host(&lnw->iotg); | ||
1155 | else | ||
1156 | dev_dbg(lnw->dev, | ||
1157 | "host driver has been removed.\n"); | ||
1158 | |||
1159 | set_host_mode(); | ||
1160 | langwell_otg_phy_low_power(1); | ||
1161 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
1162 | langwell_update_transceiver(); | ||
1163 | } else if (!iotg->hsm.b_sess_vld) { | ||
1164 | iotg->hsm.b_hnp_enable = 0; | ||
1165 | iotg->hsm.b_bus_req = 0; | ||
1166 | |||
1167 | langwell_otg_chrg_vbus(0); | ||
1168 | if (lnw->iotg.stop_host) | ||
1169 | lnw->iotg.stop_host(&lnw->iotg); | ||
1170 | else | ||
1171 | dev_dbg(lnw->dev, | ||
1172 | "host driver has been removed.\n"); | ||
1173 | |||
1174 | set_client_mode(); | ||
1175 | langwell_otg_phy_low_power(1); | ||
1176 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1177 | } else if ((!iotg->hsm.b_bus_req) || | ||
1178 | (!iotg->hsm.a_conn)) { | ||
1179 | iotg->hsm.b_bus_req = 0; | ||
1180 | langwell_otg_loc_sof(0); | ||
1181 | |||
1182 | if (lnw->iotg.stop_host) | ||
1183 | lnw->iotg.stop_host(&lnw->iotg); | ||
1184 | else | ||
1185 | dev_dbg(lnw->dev, | ||
1186 | "host driver has been removed.\n"); | ||
1187 | |||
1188 | iotg->hsm.a_bus_suspend = 0; | ||
1189 | |||
1190 | if (lnw->iotg.start_peripheral) | ||
1191 | lnw->iotg.start_peripheral(&lnw->iotg); | ||
1192 | else | ||
1193 | dev_dbg(lnw->dev, | ||
1194 | "client driver not loaded.\n"); | ||
1195 | |||
1196 | iotg->otg.state = OTG_STATE_B_PERIPHERAL; | ||
1197 | } | ||
1198 | break; | ||
1199 | |||
1200 | case OTG_STATE_A_IDLE: | ||
1201 | iotg->otg.default_a = 1; | ||
1202 | if (iotg->hsm.id) { | ||
1203 | iotg->otg.default_a = 0; | ||
1204 | iotg->hsm.b_bus_req = 0; | ||
1205 | iotg->hsm.vbus_srp_up = 0; | ||
1206 | |||
1207 | langwell_otg_chrg_vbus(0); | ||
1208 | set_client_mode(); | ||
1209 | langwell_otg_phy_low_power(1); | ||
1210 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1211 | langwell_update_transceiver(); | ||
1212 | } else if (!iotg->hsm.a_bus_drop && | ||
1213 | (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) { | ||
1214 | langwell_otg_phy_low_power(0); | ||
1215 | |||
1216 | /* Turn on VBus */ | ||
1217 | iotg->otg.set_vbus(&iotg->otg, true); | ||
1218 | |||
1219 | iotg->hsm.vbus_srp_up = 0; | ||
1220 | iotg->hsm.a_wait_vrise_tmout = 0; | ||
1221 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
1222 | iotg->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
1223 | langwell_update_transceiver(); | ||
1224 | } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) { | ||
1225 | iotg->hsm.vbus_srp_up = 1; | ||
1226 | } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) { | ||
1227 | msleep(10); | ||
1228 | langwell_otg_phy_low_power(0); | ||
1229 | |||
1230 | /* Turn on VBus */ | ||
1231 | iotg->otg.set_vbus(&iotg->otg, true); | ||
1232 | iotg->hsm.a_srp_det = 1; | ||
1233 | iotg->hsm.vbus_srp_up = 0; | ||
1234 | iotg->hsm.a_wait_vrise_tmout = 0; | ||
1235 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
1236 | iotg->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
1237 | langwell_update_transceiver(); | ||
1238 | } else if (!iotg->hsm.a_sess_vld && | ||
1239 | !iotg->hsm.vbus_srp_up) { | ||
1240 | langwell_otg_phy_low_power(1); | ||
1241 | } | ||
1242 | break; | ||
1243 | case OTG_STATE_A_WAIT_VRISE: | ||
1244 | if (iotg->hsm.id) { | ||
1245 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
1246 | iotg->hsm.b_bus_req = 0; | ||
1247 | iotg->otg.default_a = 0; | ||
1248 | |||
1249 | /* Turn off VBus */ | ||
1250 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1251 | set_client_mode(); | ||
1252 | langwell_otg_phy_low_power_wait(1); | ||
1253 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1254 | } else if (iotg->hsm.a_vbus_vld) { | ||
1255 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
1256 | iotg->hsm.b_conn = 0; | ||
1257 | if (lnw->iotg.start_host) | ||
1258 | lnw->iotg.start_host(&lnw->iotg); | ||
1259 | else { | ||
1260 | dev_dbg(lnw->dev, "host driver not loaded.\n"); | ||
1261 | break; | ||
1262 | } | ||
1263 | |||
1264 | langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); | ||
1265 | iotg->otg.state = OTG_STATE_A_WAIT_BCON; | ||
1266 | } else if (iotg->hsm.a_wait_vrise_tmout) { | ||
1267 | iotg->hsm.b_conn = 0; | ||
1268 | if (iotg->hsm.a_vbus_vld) { | ||
1269 | if (lnw->iotg.start_host) | ||
1270 | lnw->iotg.start_host(&lnw->iotg); | ||
1271 | else { | ||
1272 | dev_dbg(lnw->dev, | ||
1273 | "host driver not loaded.\n"); | ||
1274 | break; | ||
1275 | } | ||
1276 | langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); | ||
1277 | iotg->otg.state = OTG_STATE_A_WAIT_BCON; | ||
1278 | } else { | ||
1279 | |||
1280 | /* Turn off VBus */ | ||
1281 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1282 | langwell_otg_phy_low_power_wait(1); | ||
1283 | iotg->otg.state = OTG_STATE_A_VBUS_ERR; | ||
1284 | } | ||
1285 | } | ||
1286 | break; | ||
1287 | case OTG_STATE_A_WAIT_BCON: | ||
1288 | if (iotg->hsm.id) { | ||
1289 | /* delete hsm timer for a_wait_bcon_tmr */ | ||
1290 | del_timer_sync(&lnw->hsm_timer); | ||
1291 | |||
1292 | iotg->otg.default_a = 0; | ||
1293 | iotg->hsm.b_bus_req = 0; | ||
1294 | |||
1295 | if (lnw->iotg.stop_host) | ||
1296 | lnw->iotg.stop_host(&lnw->iotg); | ||
1297 | else | ||
1298 | dev_dbg(lnw->dev, | ||
1299 | "host driver has been removed.\n"); | ||
1300 | |||
1301 | /* Turn off VBus */ | ||
1302 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1303 | set_client_mode(); | ||
1304 | langwell_otg_phy_low_power_wait(1); | ||
1305 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1306 | langwell_update_transceiver(); | ||
1307 | } else if (!iotg->hsm.a_vbus_vld) { | ||
1308 | /* delete hsm timer for a_wait_bcon_tmr */ | ||
1309 | del_timer_sync(&lnw->hsm_timer); | ||
1310 | |||
1311 | if (lnw->iotg.stop_host) | ||
1312 | lnw->iotg.stop_host(&lnw->iotg); | ||
1313 | else | ||
1314 | dev_dbg(lnw->dev, | ||
1315 | "host driver has been removed.\n"); | ||
1316 | |||
1317 | /* Turn off VBus */ | ||
1318 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1319 | langwell_otg_phy_low_power_wait(1); | ||
1320 | iotg->otg.state = OTG_STATE_A_VBUS_ERR; | ||
1321 | } else if (iotg->hsm.a_bus_drop || | ||
1322 | (iotg->hsm.a_wait_bcon_tmout && | ||
1323 | !iotg->hsm.a_bus_req)) { | ||
1324 | /* delete hsm timer for a_wait_bcon_tmr */ | ||
1325 | del_timer_sync(&lnw->hsm_timer); | ||
1326 | |||
1327 | if (lnw->iotg.stop_host) | ||
1328 | lnw->iotg.stop_host(&lnw->iotg); | ||
1329 | else | ||
1330 | dev_dbg(lnw->dev, | ||
1331 | "host driver has been removed.\n"); | ||
1332 | |||
1333 | /* Turn off VBus */ | ||
1334 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1335 | iotg->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1336 | } else if (iotg->hsm.b_conn) { | ||
1337 | /* delete hsm timer for a_wait_bcon_tmr */ | ||
1338 | del_timer_sync(&lnw->hsm_timer); | ||
1339 | |||
1340 | iotg->hsm.a_suspend_req = 0; | ||
1341 | iotg->otg.state = OTG_STATE_A_HOST; | ||
1342 | if (iotg->hsm.a_srp_det && iotg->otg.host && | ||
1343 | !iotg->otg.host->b_hnp_enable) { | ||
1344 | /* SRP capable peripheral-only device */ | ||
1345 | iotg->hsm.a_bus_req = 1; | ||
1346 | iotg->hsm.a_srp_det = 0; | ||
1347 | } else if (!iotg->hsm.a_bus_req && iotg->otg.host && | ||
1348 | iotg->otg.host->b_hnp_enable) { | ||
1349 | /* It is not safe enough to do a fast | ||
1350 | * transition from A_WAIT_BCON to | ||
1351 | * A_SUSPEND */ | ||
1352 | msleep(10000); | ||
1353 | if (iotg->hsm.a_bus_req) | ||
1354 | break; | ||
1355 | |||
1356 | if (request_irq(pdev->irq, | ||
1357 | otg_dummy_irq, IRQF_SHARED, | ||
1358 | driver_name, iotg->base) != 0) { | ||
1359 | dev_dbg(lnw->dev, | ||
1360 | "request interrupt %d fail\n", | ||
1361 | pdev->irq); | ||
1362 | } | ||
1363 | |||
1364 | langwell_otg_HABA(1); | ||
1365 | iotg->hsm.b_bus_resume = 0; | ||
1366 | iotg->hsm.a_aidl_bdis_tmout = 0; | ||
1367 | |||
1368 | langwell_otg_loc_sof(0); | ||
1369 | /* clear PHCD to enable HW timer */ | ||
1370 | langwell_otg_phy_low_power(0); | ||
1371 | langwell_otg_add_timer(a_aidl_bdis_tmr); | ||
1372 | iotg->otg.state = OTG_STATE_A_SUSPEND; | ||
1373 | } else if (!iotg->hsm.a_bus_req && iotg->otg.host && | ||
1374 | !iotg->otg.host->b_hnp_enable) { | ||
1375 | if (lnw->iotg.stop_host) | ||
1376 | lnw->iotg.stop_host(&lnw->iotg); | ||
1377 | else | ||
1378 | dev_dbg(lnw->dev, | ||
1379 | "host driver removed.\n"); | ||
1380 | |||
1381 | /* Turn off VBus */ | ||
1382 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1383 | iotg->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1384 | } | ||
1385 | } | ||
1386 | break; | ||
1387 | case OTG_STATE_A_HOST: | ||
1388 | if (iotg->hsm.id) { | ||
1389 | iotg->otg.default_a = 0; | ||
1390 | iotg->hsm.b_bus_req = 0; | ||
1391 | |||
1392 | if (lnw->iotg.stop_host) | ||
1393 | lnw->iotg.stop_host(&lnw->iotg); | ||
1394 | else | ||
1395 | dev_dbg(lnw->dev, | ||
1396 | "host driver has been removed.\n"); | ||
1397 | |||
1398 | /* Turn off VBus */ | ||
1399 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1400 | set_client_mode(); | ||
1401 | langwell_otg_phy_low_power_wait(1); | ||
1402 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1403 | langwell_update_transceiver(); | ||
1404 | } else if (iotg->hsm.a_bus_drop || | ||
1405 | (iotg->otg.host && | ||
1406 | !iotg->otg.host->b_hnp_enable && | ||
1407 | !iotg->hsm.a_bus_req)) { | ||
1408 | if (lnw->iotg.stop_host) | ||
1409 | lnw->iotg.stop_host(&lnw->iotg); | ||
1410 | else | ||
1411 | dev_dbg(lnw->dev, | ||
1412 | "host driver has been removed.\n"); | ||
1413 | |||
1414 | /* Turn off VBus */ | ||
1415 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1416 | iotg->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1417 | } else if (!iotg->hsm.a_vbus_vld) { | ||
1418 | if (lnw->iotg.stop_host) | ||
1419 | lnw->iotg.stop_host(&lnw->iotg); | ||
1420 | else | ||
1421 | dev_dbg(lnw->dev, | ||
1422 | "host driver has been removed.\n"); | ||
1423 | |||
1424 | /* Turn off VBus */ | ||
1425 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1426 | langwell_otg_phy_low_power_wait(1); | ||
1427 | iotg->otg.state = OTG_STATE_A_VBUS_ERR; | ||
1428 | } else if (iotg->otg.host && | ||
1429 | iotg->otg.host->b_hnp_enable && | ||
1430 | !iotg->hsm.a_bus_req) { | ||
1431 | /* Set HABA to enable hardware assistance to signal | ||
1432 | * A-connect after receiver B-disconnect. Hardware | ||
1433 | * will then set client mode and enable URE, SLE and | ||
1434 | * PCE after the assistance. otg_dummy_irq is used to | ||
1435 | * clean these ints when client driver is not resumed. | ||
1436 | */ | ||
1437 | if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED, | ||
1438 | driver_name, iotg->base) != 0) { | ||
1439 | dev_dbg(lnw->dev, | ||
1440 | "request interrupt %d failed\n", | ||
1441 | pdev->irq); | ||
1442 | } | ||
1443 | |||
1444 | /* set HABA */ | ||
1445 | langwell_otg_HABA(1); | ||
1446 | iotg->hsm.b_bus_resume = 0; | ||
1447 | iotg->hsm.a_aidl_bdis_tmout = 0; | ||
1448 | langwell_otg_loc_sof(0); | ||
1449 | /* clear PHCD to enable HW timer */ | ||
1450 | langwell_otg_phy_low_power(0); | ||
1451 | langwell_otg_add_timer(a_aidl_bdis_tmr); | ||
1452 | iotg->otg.state = OTG_STATE_A_SUSPEND; | ||
1453 | } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) { | ||
1454 | langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); | ||
1455 | iotg->otg.state = OTG_STATE_A_WAIT_BCON; | ||
1456 | } | ||
1457 | break; | ||
1458 | case OTG_STATE_A_SUSPEND: | ||
1459 | if (iotg->hsm.id) { | ||
1460 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1461 | langwell_otg_HABA(0); | ||
1462 | free_irq(pdev->irq, iotg->base); | ||
1463 | iotg->otg.default_a = 0; | ||
1464 | iotg->hsm.b_bus_req = 0; | ||
1465 | |||
1466 | if (lnw->iotg.stop_host) | ||
1467 | lnw->iotg.stop_host(&lnw->iotg); | ||
1468 | else | ||
1469 | dev_dbg(lnw->dev, | ||
1470 | "host driver has been removed.\n"); | ||
1471 | |||
1472 | /* Turn off VBus */ | ||
1473 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1474 | set_client_mode(); | ||
1475 | langwell_otg_phy_low_power(1); | ||
1476 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1477 | langwell_update_transceiver(); | ||
1478 | } else if (iotg->hsm.a_bus_req || | ||
1479 | iotg->hsm.b_bus_resume) { | ||
1480 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1481 | langwell_otg_HABA(0); | ||
1482 | free_irq(pdev->irq, iotg->base); | ||
1483 | iotg->hsm.a_suspend_req = 0; | ||
1484 | langwell_otg_loc_sof(1); | ||
1485 | iotg->otg.state = OTG_STATE_A_HOST; | ||
1486 | } else if (iotg->hsm.a_aidl_bdis_tmout || | ||
1487 | iotg->hsm.a_bus_drop) { | ||
1488 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1489 | langwell_otg_HABA(0); | ||
1490 | free_irq(pdev->irq, iotg->base); | ||
1491 | if (lnw->iotg.stop_host) | ||
1492 | lnw->iotg.stop_host(&lnw->iotg); | ||
1493 | else | ||
1494 | dev_dbg(lnw->dev, | ||
1495 | "host driver has been removed.\n"); | ||
1496 | |||
1497 | /* Turn off VBus */ | ||
1498 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1499 | iotg->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1500 | } else if (!iotg->hsm.b_conn && iotg->otg.host && | ||
1501 | iotg->otg.host->b_hnp_enable) { | ||
1502 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1503 | langwell_otg_HABA(0); | ||
1504 | free_irq(pdev->irq, iotg->base); | ||
1505 | |||
1506 | if (lnw->iotg.stop_host) | ||
1507 | lnw->iotg.stop_host(&lnw->iotg); | ||
1508 | else | ||
1509 | dev_dbg(lnw->dev, | ||
1510 | "host driver has been removed.\n"); | ||
1511 | |||
1512 | iotg->hsm.b_bus_suspend = 0; | ||
1513 | iotg->hsm.b_bus_suspend_vld = 0; | ||
1514 | |||
1515 | /* msleep(200); */ | ||
1516 | if (lnw->iotg.start_peripheral) | ||
1517 | lnw->iotg.start_peripheral(&lnw->iotg); | ||
1518 | else | ||
1519 | dev_dbg(lnw->dev, | ||
1520 | "client driver not loaded.\n"); | ||
1521 | |||
1522 | langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR); | ||
1523 | iotg->otg.state = OTG_STATE_A_PERIPHERAL; | ||
1524 | break; | ||
1525 | } else if (!iotg->hsm.a_vbus_vld) { | ||
1526 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1527 | langwell_otg_HABA(0); | ||
1528 | free_irq(pdev->irq, iotg->base); | ||
1529 | if (lnw->iotg.stop_host) | ||
1530 | lnw->iotg.stop_host(&lnw->iotg); | ||
1531 | else | ||
1532 | dev_dbg(lnw->dev, | ||
1533 | "host driver has been removed.\n"); | ||
1534 | |||
1535 | /* Turn off VBus */ | ||
1536 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1537 | langwell_otg_phy_low_power_wait(1); | ||
1538 | iotg->otg.state = OTG_STATE_A_VBUS_ERR; | ||
1539 | } | ||
1540 | break; | ||
1541 | case OTG_STATE_A_PERIPHERAL: | ||
1542 | if (iotg->hsm.id) { | ||
1543 | /* delete hsm timer for b_bus_suspend_tmr */ | ||
1544 | del_timer_sync(&lnw->hsm_timer); | ||
1545 | iotg->otg.default_a = 0; | ||
1546 | iotg->hsm.b_bus_req = 0; | ||
1547 | if (lnw->iotg.stop_peripheral) | ||
1548 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
1549 | else | ||
1550 | dev_dbg(lnw->dev, | ||
1551 | "client driver has been removed.\n"); | ||
1552 | |||
1553 | /* Turn off VBus */ | ||
1554 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1555 | set_client_mode(); | ||
1556 | langwell_otg_phy_low_power_wait(1); | ||
1557 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1558 | langwell_update_transceiver(); | ||
1559 | } else if (!iotg->hsm.a_vbus_vld) { | ||
1560 | /* delete hsm timer for b_bus_suspend_tmr */ | ||
1561 | del_timer_sync(&lnw->hsm_timer); | ||
1562 | |||
1563 | if (lnw->iotg.stop_peripheral) | ||
1564 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
1565 | else | ||
1566 | dev_dbg(lnw->dev, | ||
1567 | "client driver has been removed.\n"); | ||
1568 | |||
1569 | /* Turn off VBus */ | ||
1570 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1571 | langwell_otg_phy_low_power_wait(1); | ||
1572 | iotg->otg.state = OTG_STATE_A_VBUS_ERR; | ||
1573 | } else if (iotg->hsm.a_bus_drop) { | ||
1574 | /* delete hsm timer for b_bus_suspend_tmr */ | ||
1575 | del_timer_sync(&lnw->hsm_timer); | ||
1576 | |||
1577 | if (lnw->iotg.stop_peripheral) | ||
1578 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
1579 | else | ||
1580 | dev_dbg(lnw->dev, | ||
1581 | "client driver has been removed.\n"); | ||
1582 | |||
1583 | /* Turn off VBus */ | ||
1584 | iotg->otg.set_vbus(&iotg->otg, false); | ||
1585 | iotg->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1586 | } else if (iotg->hsm.b_bus_suspend) { | ||
1587 | /* delete hsm timer for b_bus_suspend_tmr */ | ||
1588 | del_timer_sync(&lnw->hsm_timer); | ||
1589 | |||
1590 | if (lnw->iotg.stop_peripheral) | ||
1591 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
1592 | else | ||
1593 | dev_dbg(lnw->dev, | ||
1594 | "client driver has been removed.\n"); | ||
1595 | |||
1596 | if (lnw->iotg.start_host) | ||
1597 | lnw->iotg.start_host(&lnw->iotg); | ||
1598 | else | ||
1599 | dev_dbg(lnw->dev, | ||
1600 | "host driver not loaded.\n"); | ||
1601 | langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); | ||
1602 | iotg->otg.state = OTG_STATE_A_WAIT_BCON; | ||
1603 | } else if (iotg->hsm.b_bus_suspend_tmout) { | ||
1604 | u32 val; | ||
1605 | val = readl(lnw->iotg.base + CI_PORTSC1); | ||
1606 | if (!(val & PORTSC_SUSP)) | ||
1607 | break; | ||
1608 | |||
1609 | if (lnw->iotg.stop_peripheral) | ||
1610 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
1611 | else | ||
1612 | dev_dbg(lnw->dev, | ||
1613 | "client driver has been removed.\n"); | ||
1614 | |||
1615 | if (lnw->iotg.start_host) | ||
1616 | lnw->iotg.start_host(&lnw->iotg); | ||
1617 | else | ||
1618 | dev_dbg(lnw->dev, | ||
1619 | "host driver not loaded.\n"); | ||
1620 | langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); | ||
1621 | iotg->otg.state = OTG_STATE_A_WAIT_BCON; | ||
1622 | } | ||
1623 | break; | ||
1624 | case OTG_STATE_A_VBUS_ERR: | ||
1625 | if (iotg->hsm.id) { | ||
1626 | iotg->otg.default_a = 0; | ||
1627 | iotg->hsm.a_clr_err = 0; | ||
1628 | iotg->hsm.a_srp_det = 0; | ||
1629 | set_client_mode(); | ||
1630 | langwell_otg_phy_low_power(1); | ||
1631 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1632 | langwell_update_transceiver(); | ||
1633 | } else if (iotg->hsm.a_clr_err) { | ||
1634 | iotg->hsm.a_clr_err = 0; | ||
1635 | iotg->hsm.a_srp_det = 0; | ||
1636 | reset_otg(); | ||
1637 | init_hsm(); | ||
1638 | if (iotg->otg.state == OTG_STATE_A_IDLE) | ||
1639 | langwell_update_transceiver(); | ||
1640 | } else { | ||
1641 | /* FW will clear PHCD bit when any VBus | ||
1642 | * event detected. Reset PHCD to 1 again */ | ||
1643 | langwell_otg_phy_low_power(1); | ||
1644 | } | ||
1645 | break; | ||
1646 | case OTG_STATE_A_WAIT_VFALL: | ||
1647 | if (iotg->hsm.id) { | ||
1648 | iotg->otg.default_a = 0; | ||
1649 | set_client_mode(); | ||
1650 | langwell_otg_phy_low_power(1); | ||
1651 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
1652 | langwell_update_transceiver(); | ||
1653 | } else if (iotg->hsm.a_bus_req) { | ||
1654 | |||
1655 | /* Turn on VBus */ | ||
1656 | iotg->otg.set_vbus(&iotg->otg, true); | ||
1657 | iotg->hsm.a_wait_vrise_tmout = 0; | ||
1658 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
1659 | iotg->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
1660 | } else if (!iotg->hsm.a_sess_vld) { | ||
1661 | iotg->hsm.a_srp_det = 0; | ||
1662 | set_host_mode(); | ||
1663 | langwell_otg_phy_low_power(1); | ||
1664 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
1665 | } | ||
1666 | break; | ||
1667 | default: | ||
1668 | ; | ||
1669 | } | ||
1670 | |||
1671 | dev_dbg(lnw->dev, "%s: new state = %s\n", __func__, | ||
1672 | otg_state_string(iotg->otg.state)); | ||
1673 | } | ||
1674 | |||
1675 | static ssize_t | ||
1676 | show_registers(struct device *_dev, struct device_attribute *attr, char *buf) | ||
1677 | { | ||
1678 | struct langwell_otg *lnw = the_transceiver; | ||
1679 | char *next; | ||
1680 | unsigned size, t; | ||
1681 | |||
1682 | next = buf; | ||
1683 | size = PAGE_SIZE; | ||
1684 | |||
1685 | t = scnprintf(next, size, | ||
1686 | "\n" | ||
1687 | "USBCMD = 0x%08x\n" | ||
1688 | "USBSTS = 0x%08x\n" | ||
1689 | "USBINTR = 0x%08x\n" | ||
1690 | "ASYNCLISTADDR = 0x%08x\n" | ||
1691 | "PORTSC1 = 0x%08x\n" | ||
1692 | "HOSTPC1 = 0x%08x\n" | ||
1693 | "OTGSC = 0x%08x\n" | ||
1694 | "USBMODE = 0x%08x\n", | ||
1695 | readl(lnw->iotg.base + 0x30), | ||
1696 | readl(lnw->iotg.base + 0x34), | ||
1697 | readl(lnw->iotg.base + 0x38), | ||
1698 | readl(lnw->iotg.base + 0x48), | ||
1699 | readl(lnw->iotg.base + 0x74), | ||
1700 | readl(lnw->iotg.base + 0xb4), | ||
1701 | readl(lnw->iotg.base + 0xf4), | ||
1702 | readl(lnw->iotg.base + 0xf8) | ||
1703 | ); | ||
1704 | size -= t; | ||
1705 | next += t; | ||
1706 | |||
1707 | return PAGE_SIZE - size; | ||
1708 | } | ||
1709 | static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); | ||
1710 | |||
1711 | static ssize_t | ||
1712 | show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) | ||
1713 | { | ||
1714 | struct langwell_otg *lnw = the_transceiver; | ||
1715 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
1716 | char *next; | ||
1717 | unsigned size, t; | ||
1718 | |||
1719 | next = buf; | ||
1720 | size = PAGE_SIZE; | ||
1721 | |||
1722 | if (iotg->otg.host) | ||
1723 | iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable; | ||
1724 | |||
1725 | if (iotg->otg.gadget) | ||
1726 | iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable; | ||
1727 | |||
1728 | t = scnprintf(next, size, | ||
1729 | "\n" | ||
1730 | "current state = %s\n" | ||
1731 | "a_bus_resume = \t%d\n" | ||
1732 | "a_bus_suspend = \t%d\n" | ||
1733 | "a_conn = \t%d\n" | ||
1734 | "a_sess_vld = \t%d\n" | ||
1735 | "a_srp_det = \t%d\n" | ||
1736 | "a_vbus_vld = \t%d\n" | ||
1737 | "b_bus_resume = \t%d\n" | ||
1738 | "b_bus_suspend = \t%d\n" | ||
1739 | "b_conn = \t%d\n" | ||
1740 | "b_se0_srp = \t%d\n" | ||
1741 | "b_sess_end = \t%d\n" | ||
1742 | "b_sess_vld = \t%d\n" | ||
1743 | "id = \t%d\n" | ||
1744 | "a_set_b_hnp_en = \t%d\n" | ||
1745 | "b_srp_done = \t%d\n" | ||
1746 | "b_hnp_enable = \t%d\n" | ||
1747 | "a_wait_vrise_tmout = \t%d\n" | ||
1748 | "a_wait_bcon_tmout = \t%d\n" | ||
1749 | "a_aidl_bdis_tmout = \t%d\n" | ||
1750 | "b_ase0_brst_tmout = \t%d\n" | ||
1751 | "a_bus_drop = \t%d\n" | ||
1752 | "a_bus_req = \t%d\n" | ||
1753 | "a_clr_err = \t%d\n" | ||
1754 | "a_suspend_req = \t%d\n" | ||
1755 | "b_bus_req = \t%d\n" | ||
1756 | "b_bus_suspend_tmout = \t%d\n" | ||
1757 | "b_bus_suspend_vld = \t%d\n", | ||
1758 | otg_state_string(iotg->otg.state), | ||
1759 | iotg->hsm.a_bus_resume, | ||
1760 | iotg->hsm.a_bus_suspend, | ||
1761 | iotg->hsm.a_conn, | ||
1762 | iotg->hsm.a_sess_vld, | ||
1763 | iotg->hsm.a_srp_det, | ||
1764 | iotg->hsm.a_vbus_vld, | ||
1765 | iotg->hsm.b_bus_resume, | ||
1766 | iotg->hsm.b_bus_suspend, | ||
1767 | iotg->hsm.b_conn, | ||
1768 | iotg->hsm.b_se0_srp, | ||
1769 | iotg->hsm.b_sess_end, | ||
1770 | iotg->hsm.b_sess_vld, | ||
1771 | iotg->hsm.id, | ||
1772 | iotg->hsm.a_set_b_hnp_en, | ||
1773 | iotg->hsm.b_srp_done, | ||
1774 | iotg->hsm.b_hnp_enable, | ||
1775 | iotg->hsm.a_wait_vrise_tmout, | ||
1776 | iotg->hsm.a_wait_bcon_tmout, | ||
1777 | iotg->hsm.a_aidl_bdis_tmout, | ||
1778 | iotg->hsm.b_ase0_brst_tmout, | ||
1779 | iotg->hsm.a_bus_drop, | ||
1780 | iotg->hsm.a_bus_req, | ||
1781 | iotg->hsm.a_clr_err, | ||
1782 | iotg->hsm.a_suspend_req, | ||
1783 | iotg->hsm.b_bus_req, | ||
1784 | iotg->hsm.b_bus_suspend_tmout, | ||
1785 | iotg->hsm.b_bus_suspend_vld | ||
1786 | ); | ||
1787 | size -= t; | ||
1788 | next += t; | ||
1789 | |||
1790 | return PAGE_SIZE - size; | ||
1791 | } | ||
1792 | static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL); | ||
1793 | |||
1794 | static ssize_t | ||
1795 | get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | ||
1796 | { | ||
1797 | struct langwell_otg *lnw = the_transceiver; | ||
1798 | char *next; | ||
1799 | unsigned size, t; | ||
1800 | |||
1801 | next = buf; | ||
1802 | size = PAGE_SIZE; | ||
1803 | |||
1804 | t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req); | ||
1805 | size -= t; | ||
1806 | next += t; | ||
1807 | |||
1808 | return PAGE_SIZE - size; | ||
1809 | } | ||
1810 | |||
1811 | static ssize_t | ||
1812 | set_a_bus_req(struct device *dev, struct device_attribute *attr, | ||
1813 | const char *buf, size_t count) | ||
1814 | { | ||
1815 | struct langwell_otg *lnw = the_transceiver; | ||
1816 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
1817 | |||
1818 | if (!iotg->otg.default_a) | ||
1819 | return -1; | ||
1820 | if (count > 2) | ||
1821 | return -1; | ||
1822 | |||
1823 | if (buf[0] == '0') { | ||
1824 | iotg->hsm.a_bus_req = 0; | ||
1825 | dev_dbg(lnw->dev, "User request: a_bus_req = 0\n"); | ||
1826 | } else if (buf[0] == '1') { | ||
1827 | /* If a_bus_drop is TRUE, a_bus_req can't be set */ | ||
1828 | if (iotg->hsm.a_bus_drop) | ||
1829 | return -1; | ||
1830 | iotg->hsm.a_bus_req = 1; | ||
1831 | dev_dbg(lnw->dev, "User request: a_bus_req = 1\n"); | ||
1832 | } | ||
1833 | if (spin_trylock(&lnw->wq_lock)) { | ||
1834 | langwell_update_transceiver(); | ||
1835 | spin_unlock(&lnw->wq_lock); | ||
1836 | } | ||
1837 | return count; | ||
1838 | } | ||
1839 | static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req); | ||
1840 | |||
1841 | static ssize_t | ||
1842 | get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf) | ||
1843 | { | ||
1844 | struct langwell_otg *lnw = the_transceiver; | ||
1845 | char *next; | ||
1846 | unsigned size, t; | ||
1847 | |||
1848 | next = buf; | ||
1849 | size = PAGE_SIZE; | ||
1850 | |||
1851 | t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop); | ||
1852 | size -= t; | ||
1853 | next += t; | ||
1854 | |||
1855 | return PAGE_SIZE - size; | ||
1856 | } | ||
1857 | |||
1858 | static ssize_t | ||
1859 | set_a_bus_drop(struct device *dev, struct device_attribute *attr, | ||
1860 | const char *buf, size_t count) | ||
1861 | { | ||
1862 | struct langwell_otg *lnw = the_transceiver; | ||
1863 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
1864 | |||
1865 | if (!iotg->otg.default_a) | ||
1866 | return -1; | ||
1867 | if (count > 2) | ||
1868 | return -1; | ||
1869 | |||
1870 | if (buf[0] == '0') { | ||
1871 | iotg->hsm.a_bus_drop = 0; | ||
1872 | dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n"); | ||
1873 | } else if (buf[0] == '1') { | ||
1874 | iotg->hsm.a_bus_drop = 1; | ||
1875 | iotg->hsm.a_bus_req = 0; | ||
1876 | dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n"); | ||
1877 | dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n"); | ||
1878 | } | ||
1879 | if (spin_trylock(&lnw->wq_lock)) { | ||
1880 | langwell_update_transceiver(); | ||
1881 | spin_unlock(&lnw->wq_lock); | ||
1882 | } | ||
1883 | return count; | ||
1884 | } | ||
1885 | static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, set_a_bus_drop); | ||
1886 | |||
1887 | static ssize_t | ||
1888 | get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | ||
1889 | { | ||
1890 | struct langwell_otg *lnw = the_transceiver; | ||
1891 | char *next; | ||
1892 | unsigned size, t; | ||
1893 | |||
1894 | next = buf; | ||
1895 | size = PAGE_SIZE; | ||
1896 | |||
1897 | t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req); | ||
1898 | size -= t; | ||
1899 | next += t; | ||
1900 | |||
1901 | return PAGE_SIZE - size; | ||
1902 | } | ||
1903 | |||
1904 | static ssize_t | ||
1905 | set_b_bus_req(struct device *dev, struct device_attribute *attr, | ||
1906 | const char *buf, size_t count) | ||
1907 | { | ||
1908 | struct langwell_otg *lnw = the_transceiver; | ||
1909 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
1910 | |||
1911 | if (iotg->otg.default_a) | ||
1912 | return -1; | ||
1913 | |||
1914 | if (count > 2) | ||
1915 | return -1; | ||
1916 | |||
1917 | if (buf[0] == '0') { | ||
1918 | iotg->hsm.b_bus_req = 0; | ||
1919 | dev_dbg(lnw->dev, "User request: b_bus_req = 0\n"); | ||
1920 | } else if (buf[0] == '1') { | ||
1921 | iotg->hsm.b_bus_req = 1; | ||
1922 | dev_dbg(lnw->dev, "User request: b_bus_req = 1\n"); | ||
1923 | } | ||
1924 | if (spin_trylock(&lnw->wq_lock)) { | ||
1925 | langwell_update_transceiver(); | ||
1926 | spin_unlock(&lnw->wq_lock); | ||
1927 | } | ||
1928 | return count; | ||
1929 | } | ||
1930 | static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req); | ||
1931 | |||
1932 | static ssize_t | ||
1933 | set_a_clr_err(struct device *dev, struct device_attribute *attr, | ||
1934 | const char *buf, size_t count) | ||
1935 | { | ||
1936 | struct langwell_otg *lnw = the_transceiver; | ||
1937 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
1938 | |||
1939 | if (!iotg->otg.default_a) | ||
1940 | return -1; | ||
1941 | if (count > 2) | ||
1942 | return -1; | ||
1943 | |||
1944 | if (buf[0] == '1') { | ||
1945 | iotg->hsm.a_clr_err = 1; | ||
1946 | dev_dbg(lnw->dev, "User request: a_clr_err = 1\n"); | ||
1947 | } | ||
1948 | if (spin_trylock(&lnw->wq_lock)) { | ||
1949 | langwell_update_transceiver(); | ||
1950 | spin_unlock(&lnw->wq_lock); | ||
1951 | } | ||
1952 | return count; | ||
1953 | } | ||
1954 | static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err); | ||
1955 | |||
1956 | static struct attribute *inputs_attrs[] = { | ||
1957 | &dev_attr_a_bus_req.attr, | ||
1958 | &dev_attr_a_bus_drop.attr, | ||
1959 | &dev_attr_b_bus_req.attr, | ||
1960 | &dev_attr_a_clr_err.attr, | ||
1961 | NULL, | ||
1962 | }; | ||
1963 | |||
1964 | static struct attribute_group debug_dev_attr_group = { | ||
1965 | .name = "inputs", | ||
1966 | .attrs = inputs_attrs, | ||
1967 | }; | ||
1968 | |||
1969 | static int langwell_otg_probe(struct pci_dev *pdev, | ||
1970 | const struct pci_device_id *id) | ||
1971 | { | ||
1972 | unsigned long resource, len; | ||
1973 | void __iomem *base = NULL; | ||
1974 | int retval; | ||
1975 | u32 val32; | ||
1976 | struct langwell_otg *lnw; | ||
1977 | char qname[] = "langwell_otg_queue"; | ||
1978 | |||
1979 | retval = 0; | ||
1980 | dev_dbg(&pdev->dev, "\notg controller is detected.\n"); | ||
1981 | if (pci_enable_device(pdev) < 0) { | ||
1982 | retval = -ENODEV; | ||
1983 | goto done; | ||
1984 | } | ||
1985 | |||
1986 | lnw = kzalloc(sizeof *lnw, GFP_KERNEL); | ||
1987 | if (lnw == NULL) { | ||
1988 | retval = -ENOMEM; | ||
1989 | goto done; | ||
1990 | } | ||
1991 | the_transceiver = lnw; | ||
1992 | |||
1993 | /* control register: BAR 0 */ | ||
1994 | resource = pci_resource_start(pdev, 0); | ||
1995 | len = pci_resource_len(pdev, 0); | ||
1996 | if (!request_mem_region(resource, len, driver_name)) { | ||
1997 | retval = -EBUSY; | ||
1998 | goto err; | ||
1999 | } | ||
2000 | lnw->region = 1; | ||
2001 | |||
2002 | base = ioremap_nocache(resource, len); | ||
2003 | if (base == NULL) { | ||
2004 | retval = -EFAULT; | ||
2005 | goto err; | ||
2006 | } | ||
2007 | lnw->iotg.base = base; | ||
2008 | |||
2009 | if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) { | ||
2010 | retval = -EBUSY; | ||
2011 | goto err; | ||
2012 | } | ||
2013 | lnw->cfg_region = 1; | ||
2014 | |||
2015 | /* For the SCCB.USBCFG register */ | ||
2016 | base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN); | ||
2017 | if (base == NULL) { | ||
2018 | retval = -EFAULT; | ||
2019 | goto err; | ||
2020 | } | ||
2021 | lnw->usbcfg = base; | ||
2022 | |||
2023 | if (!pdev->irq) { | ||
2024 | dev_dbg(&pdev->dev, "No IRQ.\n"); | ||
2025 | retval = -ENODEV; | ||
2026 | goto err; | ||
2027 | } | ||
2028 | |||
2029 | lnw->qwork = create_singlethread_workqueue(qname); | ||
2030 | if (!lnw->qwork) { | ||
2031 | dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname); | ||
2032 | retval = -ENOMEM; | ||
2033 | goto err; | ||
2034 | } | ||
2035 | INIT_WORK(&lnw->work, langwell_otg_work); | ||
2036 | |||
2037 | /* OTG common part */ | ||
2038 | lnw->dev = &pdev->dev; | ||
2039 | lnw->iotg.otg.dev = lnw->dev; | ||
2040 | lnw->iotg.otg.label = driver_name; | ||
2041 | lnw->iotg.otg.set_host = langwell_otg_set_host; | ||
2042 | lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral; | ||
2043 | lnw->iotg.otg.set_power = langwell_otg_set_power; | ||
2044 | lnw->iotg.otg.set_vbus = langwell_otg_set_vbus; | ||
2045 | lnw->iotg.otg.start_srp = langwell_otg_start_srp; | ||
2046 | lnw->iotg.otg.state = OTG_STATE_UNDEFINED; | ||
2047 | |||
2048 | if (otg_set_transceiver(&lnw->iotg.otg)) { | ||
2049 | dev_dbg(lnw->dev, "can't set transceiver\n"); | ||
2050 | retval = -EBUSY; | ||
2051 | goto err; | ||
2052 | } | ||
2053 | |||
2054 | reset_otg(); | ||
2055 | init_hsm(); | ||
2056 | |||
2057 | spin_lock_init(&lnw->lock); | ||
2058 | spin_lock_init(&lnw->wq_lock); | ||
2059 | INIT_LIST_HEAD(&active_timers); | ||
2060 | retval = langwell_otg_init_timers(&lnw->iotg.hsm); | ||
2061 | if (retval) { | ||
2062 | dev_dbg(&pdev->dev, "Failed to init timers\n"); | ||
2063 | goto err; | ||
2064 | } | ||
2065 | |||
2066 | init_timer(&lnw->hsm_timer); | ||
2067 | ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier); | ||
2068 | |||
2069 | lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify; | ||
2070 | |||
2071 | retval = intel_mid_otg_register_notifier(&lnw->iotg, | ||
2072 | &lnw->iotg_notifier); | ||
2073 | if (retval) { | ||
2074 | dev_dbg(lnw->dev, "Failed to register notifier\n"); | ||
2075 | goto err; | ||
2076 | } | ||
2077 | |||
2078 | if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, | ||
2079 | driver_name, lnw) != 0) { | ||
2080 | dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq); | ||
2081 | retval = -EBUSY; | ||
2082 | goto err; | ||
2083 | } | ||
2084 | |||
2085 | /* enable OTGSC int */ | ||
2086 | val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE | | ||
2087 | OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU; | ||
2088 | writel(val32, lnw->iotg.base + CI_OTGSC); | ||
2089 | |||
2090 | retval = device_create_file(&pdev->dev, &dev_attr_registers); | ||
2091 | if (retval < 0) { | ||
2092 | dev_dbg(lnw->dev, | ||
2093 | "Can't register sysfs attribute: %d\n", retval); | ||
2094 | goto err; | ||
2095 | } | ||
2096 | |||
2097 | retval = device_create_file(&pdev->dev, &dev_attr_hsm); | ||
2098 | if (retval < 0) { | ||
2099 | dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval); | ||
2100 | goto err; | ||
2101 | } | ||
2102 | |||
2103 | retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group); | ||
2104 | if (retval < 0) { | ||
2105 | dev_dbg(lnw->dev, | ||
2106 | "Can't register sysfs attr group: %d\n", retval); | ||
2107 | goto err; | ||
2108 | } | ||
2109 | |||
2110 | if (lnw->iotg.otg.state == OTG_STATE_A_IDLE) | ||
2111 | langwell_update_transceiver(); | ||
2112 | |||
2113 | return 0; | ||
2114 | |||
2115 | err: | ||
2116 | if (the_transceiver) | ||
2117 | langwell_otg_remove(pdev); | ||
2118 | done: | ||
2119 | return retval; | ||
2120 | } | ||
2121 | |||
2122 | static void langwell_otg_remove(struct pci_dev *pdev) | ||
2123 | { | ||
2124 | struct langwell_otg *lnw = the_transceiver; | ||
2125 | |||
2126 | if (lnw->qwork) { | ||
2127 | flush_workqueue(lnw->qwork); | ||
2128 | destroy_workqueue(lnw->qwork); | ||
2129 | } | ||
2130 | intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier); | ||
2131 | langwell_otg_free_timers(); | ||
2132 | |||
2133 | /* disable OTGSC interrupt as OTGSC doesn't change in reset */ | ||
2134 | writel(0, lnw->iotg.base + CI_OTGSC); | ||
2135 | |||
2136 | if (pdev->irq) | ||
2137 | free_irq(pdev->irq, lnw); | ||
2138 | if (lnw->usbcfg) | ||
2139 | iounmap(lnw->usbcfg); | ||
2140 | if (lnw->cfg_region) | ||
2141 | release_mem_region(USBCFG_ADDR, USBCFG_LEN); | ||
2142 | if (lnw->iotg.base) | ||
2143 | iounmap(lnw->iotg.base); | ||
2144 | if (lnw->region) | ||
2145 | release_mem_region(pci_resource_start(pdev, 0), | ||
2146 | pci_resource_len(pdev, 0)); | ||
2147 | |||
2148 | otg_set_transceiver(NULL); | ||
2149 | pci_disable_device(pdev); | ||
2150 | sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group); | ||
2151 | device_remove_file(&pdev->dev, &dev_attr_hsm); | ||
2152 | device_remove_file(&pdev->dev, &dev_attr_registers); | ||
2153 | kfree(lnw); | ||
2154 | lnw = NULL; | ||
2155 | } | ||
2156 | |||
2157 | static void transceiver_suspend(struct pci_dev *pdev) | ||
2158 | { | ||
2159 | pci_save_state(pdev); | ||
2160 | pci_set_power_state(pdev, PCI_D3hot); | ||
2161 | langwell_otg_phy_low_power(1); | ||
2162 | } | ||
2163 | |||
2164 | static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) | ||
2165 | { | ||
2166 | struct langwell_otg *lnw = the_transceiver; | ||
2167 | struct intel_mid_otg_xceiv *iotg = &lnw->iotg; | ||
2168 | int ret = 0; | ||
2169 | |||
2170 | /* Disbale OTG interrupts */ | ||
2171 | langwell_otg_intr(0); | ||
2172 | |||
2173 | if (pdev->irq) | ||
2174 | free_irq(pdev->irq, lnw); | ||
2175 | |||
2176 | /* Prevent more otg_work */ | ||
2177 | flush_workqueue(lnw->qwork); | ||
2178 | destroy_workqueue(lnw->qwork); | ||
2179 | lnw->qwork = NULL; | ||
2180 | |||
2181 | /* start actions */ | ||
2182 | switch (iotg->otg.state) { | ||
2183 | case OTG_STATE_A_WAIT_VFALL: | ||
2184 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
2185 | case OTG_STATE_A_IDLE: | ||
2186 | case OTG_STATE_B_IDLE: | ||
2187 | case OTG_STATE_A_VBUS_ERR: | ||
2188 | transceiver_suspend(pdev); | ||
2189 | break; | ||
2190 | case OTG_STATE_A_WAIT_VRISE: | ||
2191 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
2192 | iotg->hsm.a_srp_det = 0; | ||
2193 | |||
2194 | /* Turn off VBus */ | ||
2195 | iotg->otg.set_vbus(&iotg->otg, false); | ||
2196 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
2197 | transceiver_suspend(pdev); | ||
2198 | break; | ||
2199 | case OTG_STATE_A_WAIT_BCON: | ||
2200 | del_timer_sync(&lnw->hsm_timer); | ||
2201 | if (lnw->iotg.stop_host) | ||
2202 | lnw->iotg.stop_host(&lnw->iotg); | ||
2203 | else | ||
2204 | dev_dbg(&pdev->dev, "host driver has been removed.\n"); | ||
2205 | |||
2206 | iotg->hsm.a_srp_det = 0; | ||
2207 | |||
2208 | /* Turn off VBus */ | ||
2209 | iotg->otg.set_vbus(&iotg->otg, false); | ||
2210 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
2211 | transceiver_suspend(pdev); | ||
2212 | break; | ||
2213 | case OTG_STATE_A_HOST: | ||
2214 | if (lnw->iotg.stop_host) | ||
2215 | lnw->iotg.stop_host(&lnw->iotg); | ||
2216 | else | ||
2217 | dev_dbg(&pdev->dev, "host driver has been removed.\n"); | ||
2218 | |||
2219 | iotg->hsm.a_srp_det = 0; | ||
2220 | |||
2221 | /* Turn off VBus */ | ||
2222 | iotg->otg.set_vbus(&iotg->otg, false); | ||
2223 | |||
2224 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
2225 | transceiver_suspend(pdev); | ||
2226 | break; | ||
2227 | case OTG_STATE_A_SUSPEND: | ||
2228 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
2229 | langwell_otg_HABA(0); | ||
2230 | if (lnw->iotg.stop_host) | ||
2231 | lnw->iotg.stop_host(&lnw->iotg); | ||
2232 | else | ||
2233 | dev_dbg(lnw->dev, "host driver has been removed.\n"); | ||
2234 | iotg->hsm.a_srp_det = 0; | ||
2235 | |||
2236 | /* Turn off VBus */ | ||
2237 | iotg->otg.set_vbus(&iotg->otg, false); | ||
2238 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
2239 | transceiver_suspend(pdev); | ||
2240 | break; | ||
2241 | case OTG_STATE_A_PERIPHERAL: | ||
2242 | del_timer_sync(&lnw->hsm_timer); | ||
2243 | |||
2244 | if (lnw->iotg.stop_peripheral) | ||
2245 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
2246 | else | ||
2247 | dev_dbg(&pdev->dev, | ||
2248 | "client driver has been removed.\n"); | ||
2249 | iotg->hsm.a_srp_det = 0; | ||
2250 | |||
2251 | /* Turn off VBus */ | ||
2252 | iotg->otg.set_vbus(&iotg->otg, false); | ||
2253 | iotg->otg.state = OTG_STATE_A_IDLE; | ||
2254 | transceiver_suspend(pdev); | ||
2255 | break; | ||
2256 | case OTG_STATE_B_HOST: | ||
2257 | if (lnw->iotg.stop_host) | ||
2258 | lnw->iotg.stop_host(&lnw->iotg); | ||
2259 | else | ||
2260 | dev_dbg(&pdev->dev, "host driver has been removed.\n"); | ||
2261 | iotg->hsm.b_bus_req = 0; | ||
2262 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
2263 | transceiver_suspend(pdev); | ||
2264 | break; | ||
2265 | case OTG_STATE_B_PERIPHERAL: | ||
2266 | if (lnw->iotg.stop_peripheral) | ||
2267 | lnw->iotg.stop_peripheral(&lnw->iotg); | ||
2268 | else | ||
2269 | dev_dbg(&pdev->dev, | ||
2270 | "client driver has been removed.\n"); | ||
2271 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
2272 | transceiver_suspend(pdev); | ||
2273 | break; | ||
2274 | case OTG_STATE_B_WAIT_ACON: | ||
2275 | /* delete hsm timer for b_ase0_brst_tmr */ | ||
2276 | del_timer_sync(&lnw->hsm_timer); | ||
2277 | |||
2278 | langwell_otg_HAAR(0); | ||
2279 | |||
2280 | if (lnw->iotg.stop_host) | ||
2281 | lnw->iotg.stop_host(&lnw->iotg); | ||
2282 | else | ||
2283 | dev_dbg(&pdev->dev, "host driver has been removed.\n"); | ||
2284 | iotg->hsm.b_bus_req = 0; | ||
2285 | iotg->otg.state = OTG_STATE_B_IDLE; | ||
2286 | transceiver_suspend(pdev); | ||
2287 | break; | ||
2288 | default: | ||
2289 | dev_dbg(lnw->dev, "error state before suspend\n"); | ||
2290 | break; | ||
2291 | } | ||
2292 | |||
2293 | return ret; | ||
2294 | } | ||
2295 | |||
2296 | static void transceiver_resume(struct pci_dev *pdev) | ||
2297 | { | ||
2298 | pci_restore_state(pdev); | ||
2299 | pci_set_power_state(pdev, PCI_D0); | ||
2300 | } | ||
2301 | |||
2302 | static int langwell_otg_resume(struct pci_dev *pdev) | ||
2303 | { | ||
2304 | struct langwell_otg *lnw = the_transceiver; | ||
2305 | int ret = 0; | ||
2306 | |||
2307 | transceiver_resume(pdev); | ||
2308 | |||
2309 | lnw->qwork = create_singlethread_workqueue("langwell_otg_queue"); | ||
2310 | if (!lnw->qwork) { | ||
2311 | dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen"); | ||
2312 | ret = -ENOMEM; | ||
2313 | goto error; | ||
2314 | } | ||
2315 | |||
2316 | if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, | ||
2317 | driver_name, lnw) != 0) { | ||
2318 | dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq); | ||
2319 | ret = -EBUSY; | ||
2320 | goto error; | ||
2321 | } | ||
2322 | |||
2323 | /* enable OTG interrupts */ | ||
2324 | langwell_otg_intr(1); | ||
2325 | |||
2326 | update_hsm(); | ||
2327 | |||
2328 | langwell_update_transceiver(); | ||
2329 | |||
2330 | return ret; | ||
2331 | error: | ||
2332 | langwell_otg_intr(0); | ||
2333 | transceiver_suspend(pdev); | ||
2334 | return ret; | ||
2335 | } | ||
2336 | |||
2337 | static int __init langwell_otg_init(void) | ||
2338 | { | ||
2339 | return pci_register_driver(&otg_pci_driver); | ||
2340 | } | ||
2341 | module_init(langwell_otg_init); | ||
2342 | |||
2343 | static void __exit langwell_otg_cleanup(void) | ||
2344 | { | ||
2345 | pci_unregister_driver(&otg_pci_driver); | ||
2346 | } | ||
2347 | module_exit(langwell_otg_cleanup); | ||
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c new file mode 100644 index 000000000000..b276f8fcdeba --- /dev/null +++ b/drivers/usb/otg/msm_otg.c | |||
@@ -0,0 +1,1761 @@ | |||
1 | /* Copyright (c) 2009-2011, 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 | #include <linux/regulator/consumer.h> | ||
42 | |||
43 | #include <mach/clk.h> | ||
44 | |||
45 | #define MSM_USB_BASE (motg->regs) | ||
46 | #define DRIVER_NAME "msm_otg" | ||
47 | |||
48 | #define ULPI_IO_TIMEOUT_USEC (10 * 1000) | ||
49 | |||
50 | #define USB_PHY_3P3_VOL_MIN 3050000 /* uV */ | ||
51 | #define USB_PHY_3P3_VOL_MAX 3300000 /* uV */ | ||
52 | #define USB_PHY_3P3_HPM_LOAD 50000 /* uA */ | ||
53 | #define USB_PHY_3P3_LPM_LOAD 4000 /* uA */ | ||
54 | |||
55 | #define USB_PHY_1P8_VOL_MIN 1800000 /* uV */ | ||
56 | #define USB_PHY_1P8_VOL_MAX 1800000 /* uV */ | ||
57 | #define USB_PHY_1P8_HPM_LOAD 50000 /* uA */ | ||
58 | #define USB_PHY_1P8_LPM_LOAD 4000 /* uA */ | ||
59 | |||
60 | #define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */ | ||
61 | #define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */ | ||
62 | |||
63 | static struct regulator *hsusb_3p3; | ||
64 | static struct regulator *hsusb_1p8; | ||
65 | static struct regulator *hsusb_vddcx; | ||
66 | |||
67 | static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) | ||
68 | { | ||
69 | int ret = 0; | ||
70 | |||
71 | if (init) { | ||
72 | hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX"); | ||
73 | if (IS_ERR(hsusb_vddcx)) { | ||
74 | dev_err(motg->otg.dev, "unable to get hsusb vddcx\n"); | ||
75 | return PTR_ERR(hsusb_vddcx); | ||
76 | } | ||
77 | |||
78 | ret = regulator_set_voltage(hsusb_vddcx, | ||
79 | USB_PHY_VDD_DIG_VOL_MIN, | ||
80 | USB_PHY_VDD_DIG_VOL_MAX); | ||
81 | if (ret) { | ||
82 | dev_err(motg->otg.dev, "unable to set the voltage " | ||
83 | "for hsusb vddcx\n"); | ||
84 | regulator_put(hsusb_vddcx); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | ret = regulator_enable(hsusb_vddcx); | ||
89 | if (ret) { | ||
90 | dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n"); | ||
91 | regulator_put(hsusb_vddcx); | ||
92 | } | ||
93 | } else { | ||
94 | ret = regulator_set_voltage(hsusb_vddcx, 0, | ||
95 | USB_PHY_VDD_DIG_VOL_MAX); | ||
96 | if (ret) | ||
97 | dev_err(motg->otg.dev, "unable to set the voltage " | ||
98 | "for hsusb vddcx\n"); | ||
99 | ret = regulator_disable(hsusb_vddcx); | ||
100 | if (ret) | ||
101 | dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n"); | ||
102 | |||
103 | regulator_put(hsusb_vddcx); | ||
104 | } | ||
105 | |||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | static int msm_hsusb_ldo_init(struct msm_otg *motg, int init) | ||
110 | { | ||
111 | int rc = 0; | ||
112 | |||
113 | if (init) { | ||
114 | hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3"); | ||
115 | if (IS_ERR(hsusb_3p3)) { | ||
116 | dev_err(motg->otg.dev, "unable to get hsusb 3p3\n"); | ||
117 | return PTR_ERR(hsusb_3p3); | ||
118 | } | ||
119 | |||
120 | rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN, | ||
121 | USB_PHY_3P3_VOL_MAX); | ||
122 | if (rc) { | ||
123 | dev_err(motg->otg.dev, "unable to set voltage level " | ||
124 | "for hsusb 3p3\n"); | ||
125 | goto put_3p3; | ||
126 | } | ||
127 | rc = regulator_enable(hsusb_3p3); | ||
128 | if (rc) { | ||
129 | dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n"); | ||
130 | goto put_3p3; | ||
131 | } | ||
132 | hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8"); | ||
133 | if (IS_ERR(hsusb_1p8)) { | ||
134 | dev_err(motg->otg.dev, "unable to get hsusb 1p8\n"); | ||
135 | rc = PTR_ERR(hsusb_1p8); | ||
136 | goto disable_3p3; | ||
137 | } | ||
138 | rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN, | ||
139 | USB_PHY_1P8_VOL_MAX); | ||
140 | if (rc) { | ||
141 | dev_err(motg->otg.dev, "unable to set voltage level " | ||
142 | "for hsusb 1p8\n"); | ||
143 | goto put_1p8; | ||
144 | } | ||
145 | rc = regulator_enable(hsusb_1p8); | ||
146 | if (rc) { | ||
147 | dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n"); | ||
148 | goto put_1p8; | ||
149 | } | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | regulator_disable(hsusb_1p8); | ||
155 | put_1p8: | ||
156 | regulator_put(hsusb_1p8); | ||
157 | disable_3p3: | ||
158 | regulator_disable(hsusb_3p3); | ||
159 | put_3p3: | ||
160 | regulator_put(hsusb_3p3); | ||
161 | return rc; | ||
162 | } | ||
163 | |||
164 | #ifdef CONFIG_PM_SLEEP | ||
165 | #define USB_PHY_SUSP_DIG_VOL 500000 | ||
166 | static int msm_hsusb_config_vddcx(int high) | ||
167 | { | ||
168 | int max_vol = USB_PHY_VDD_DIG_VOL_MAX; | ||
169 | int min_vol; | ||
170 | int ret; | ||
171 | |||
172 | if (high) | ||
173 | min_vol = USB_PHY_VDD_DIG_VOL_MIN; | ||
174 | else | ||
175 | min_vol = USB_PHY_SUSP_DIG_VOL; | ||
176 | |||
177 | ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol); | ||
178 | if (ret) { | ||
179 | pr_err("%s: unable to set the voltage for regulator " | ||
180 | "HSUSB_VDDCX\n", __func__); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol); | ||
185 | |||
186 | return ret; | ||
187 | } | ||
188 | #endif | ||
189 | |||
190 | static int msm_hsusb_ldo_set_mode(int on) | ||
191 | { | ||
192 | int ret = 0; | ||
193 | |||
194 | if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) { | ||
195 | pr_err("%s: HSUSB_1p8 is not initialized\n", __func__); | ||
196 | return -ENODEV; | ||
197 | } | ||
198 | |||
199 | if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) { | ||
200 | pr_err("%s: HSUSB_3p3 is not initialized\n", __func__); | ||
201 | return -ENODEV; | ||
202 | } | ||
203 | |||
204 | if (on) { | ||
205 | ret = regulator_set_optimum_mode(hsusb_1p8, | ||
206 | USB_PHY_1P8_HPM_LOAD); | ||
207 | if (ret < 0) { | ||
208 | pr_err("%s: Unable to set HPM of the regulator " | ||
209 | "HSUSB_1p8\n", __func__); | ||
210 | return ret; | ||
211 | } | ||
212 | ret = regulator_set_optimum_mode(hsusb_3p3, | ||
213 | USB_PHY_3P3_HPM_LOAD); | ||
214 | if (ret < 0) { | ||
215 | pr_err("%s: Unable to set HPM of the regulator " | ||
216 | "HSUSB_3p3\n", __func__); | ||
217 | regulator_set_optimum_mode(hsusb_1p8, | ||
218 | USB_PHY_1P8_LPM_LOAD); | ||
219 | return ret; | ||
220 | } | ||
221 | } else { | ||
222 | ret = regulator_set_optimum_mode(hsusb_1p8, | ||
223 | USB_PHY_1P8_LPM_LOAD); | ||
224 | if (ret < 0) | ||
225 | pr_err("%s: Unable to set LPM of the regulator " | ||
226 | "HSUSB_1p8\n", __func__); | ||
227 | ret = regulator_set_optimum_mode(hsusb_3p3, | ||
228 | USB_PHY_3P3_LPM_LOAD); | ||
229 | if (ret < 0) | ||
230 | pr_err("%s: Unable to set LPM of the regulator " | ||
231 | "HSUSB_3p3\n", __func__); | ||
232 | } | ||
233 | |||
234 | pr_debug("reg (%s)\n", on ? "HPM" : "LPM"); | ||
235 | return ret < 0 ? ret : 0; | ||
236 | } | ||
237 | |||
238 | static int ulpi_read(struct otg_transceiver *otg, u32 reg) | ||
239 | { | ||
240 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
241 | int cnt = 0; | ||
242 | |||
243 | /* initiate read operation */ | ||
244 | writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg), | ||
245 | USB_ULPI_VIEWPORT); | ||
246 | |||
247 | /* wait for completion */ | ||
248 | while (cnt < ULPI_IO_TIMEOUT_USEC) { | ||
249 | if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN)) | ||
250 | break; | ||
251 | udelay(1); | ||
252 | cnt++; | ||
253 | } | ||
254 | |||
255 | if (cnt >= ULPI_IO_TIMEOUT_USEC) { | ||
256 | dev_err(otg->dev, "ulpi_read: timeout %08x\n", | ||
257 | readl(USB_ULPI_VIEWPORT)); | ||
258 | return -ETIMEDOUT; | ||
259 | } | ||
260 | return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT)); | ||
261 | } | ||
262 | |||
263 | static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg) | ||
264 | { | ||
265 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
266 | int cnt = 0; | ||
267 | |||
268 | /* initiate write operation */ | ||
269 | writel(ULPI_RUN | ULPI_WRITE | | ||
270 | ULPI_ADDR(reg) | ULPI_DATA(val), | ||
271 | USB_ULPI_VIEWPORT); | ||
272 | |||
273 | /* wait for completion */ | ||
274 | while (cnt < ULPI_IO_TIMEOUT_USEC) { | ||
275 | if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN)) | ||
276 | break; | ||
277 | udelay(1); | ||
278 | cnt++; | ||
279 | } | ||
280 | |||
281 | if (cnt >= ULPI_IO_TIMEOUT_USEC) { | ||
282 | dev_err(otg->dev, "ulpi_write: timeout\n"); | ||
283 | return -ETIMEDOUT; | ||
284 | } | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static struct otg_io_access_ops msm_otg_io_ops = { | ||
289 | .read = ulpi_read, | ||
290 | .write = ulpi_write, | ||
291 | }; | ||
292 | |||
293 | static void ulpi_init(struct msm_otg *motg) | ||
294 | { | ||
295 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
296 | int *seq = pdata->phy_init_seq; | ||
297 | |||
298 | if (!seq) | ||
299 | return; | ||
300 | |||
301 | while (seq[0] >= 0) { | ||
302 | dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n", | ||
303 | seq[0], seq[1]); | ||
304 | ulpi_write(&motg->otg, seq[0], seq[1]); | ||
305 | seq += 2; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) | ||
310 | { | ||
311 | int ret; | ||
312 | |||
313 | if (assert) { | ||
314 | ret = clk_reset(motg->clk, CLK_RESET_ASSERT); | ||
315 | if (ret) | ||
316 | dev_err(motg->otg.dev, "usb hs_clk assert failed\n"); | ||
317 | } else { | ||
318 | ret = clk_reset(motg->clk, CLK_RESET_DEASSERT); | ||
319 | if (ret) | ||
320 | dev_err(motg->otg.dev, "usb hs_clk deassert failed\n"); | ||
321 | } | ||
322 | return ret; | ||
323 | } | ||
324 | |||
325 | static int msm_otg_phy_clk_reset(struct msm_otg *motg) | ||
326 | { | ||
327 | int ret; | ||
328 | |||
329 | ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT); | ||
330 | if (ret) { | ||
331 | dev_err(motg->otg.dev, "usb phy clk assert failed\n"); | ||
332 | return ret; | ||
333 | } | ||
334 | usleep_range(10000, 12000); | ||
335 | ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT); | ||
336 | if (ret) | ||
337 | dev_err(motg->otg.dev, "usb phy clk deassert failed\n"); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | static int msm_otg_phy_reset(struct msm_otg *motg) | ||
342 | { | ||
343 | u32 val; | ||
344 | int ret; | ||
345 | int retries; | ||
346 | |||
347 | ret = msm_otg_link_clk_reset(motg, 1); | ||
348 | if (ret) | ||
349 | return ret; | ||
350 | ret = msm_otg_phy_clk_reset(motg); | ||
351 | if (ret) | ||
352 | return ret; | ||
353 | ret = msm_otg_link_clk_reset(motg, 0); | ||
354 | if (ret) | ||
355 | return ret; | ||
356 | |||
357 | val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK; | ||
358 | writel(val | PORTSC_PTS_ULPI, USB_PORTSC); | ||
359 | |||
360 | for (retries = 3; retries > 0; retries--) { | ||
361 | ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM, | ||
362 | ULPI_CLR(ULPI_FUNC_CTRL)); | ||
363 | if (!ret) | ||
364 | break; | ||
365 | ret = msm_otg_phy_clk_reset(motg); | ||
366 | if (ret) | ||
367 | return ret; | ||
368 | } | ||
369 | if (!retries) | ||
370 | return -ETIMEDOUT; | ||
371 | |||
372 | /* This reset calibrates the phy, if the above write succeeded */ | ||
373 | ret = msm_otg_phy_clk_reset(motg); | ||
374 | if (ret) | ||
375 | return ret; | ||
376 | |||
377 | for (retries = 3; retries > 0; retries--) { | ||
378 | ret = ulpi_read(&motg->otg, ULPI_DEBUG); | ||
379 | if (ret != -ETIMEDOUT) | ||
380 | break; | ||
381 | ret = msm_otg_phy_clk_reset(motg); | ||
382 | if (ret) | ||
383 | return ret; | ||
384 | } | ||
385 | if (!retries) | ||
386 | return -ETIMEDOUT; | ||
387 | |||
388 | dev_info(motg->otg.dev, "phy_reset: success\n"); | ||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | #define LINK_RESET_TIMEOUT_USEC (250 * 1000) | ||
393 | static int msm_otg_reset(struct otg_transceiver *otg) | ||
394 | { | ||
395 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
396 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
397 | int cnt = 0; | ||
398 | int ret; | ||
399 | u32 val = 0; | ||
400 | u32 ulpi_val = 0; | ||
401 | |||
402 | ret = msm_otg_phy_reset(motg); | ||
403 | if (ret) { | ||
404 | dev_err(otg->dev, "phy_reset failed\n"); | ||
405 | return ret; | ||
406 | } | ||
407 | |||
408 | ulpi_init(motg); | ||
409 | |||
410 | writel(USBCMD_RESET, USB_USBCMD); | ||
411 | while (cnt < LINK_RESET_TIMEOUT_USEC) { | ||
412 | if (!(readl(USB_USBCMD) & USBCMD_RESET)) | ||
413 | break; | ||
414 | udelay(1); | ||
415 | cnt++; | ||
416 | } | ||
417 | if (cnt >= LINK_RESET_TIMEOUT_USEC) | ||
418 | return -ETIMEDOUT; | ||
419 | |||
420 | /* select ULPI phy */ | ||
421 | writel(0x80000000, USB_PORTSC); | ||
422 | |||
423 | msleep(100); | ||
424 | |||
425 | writel(0x0, USB_AHBBURST); | ||
426 | writel(0x00, USB_AHBMODE); | ||
427 | |||
428 | if (pdata->otg_control == OTG_PHY_CONTROL) { | ||
429 | val = readl(USB_OTGSC); | ||
430 | if (pdata->mode == USB_OTG) { | ||
431 | ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID; | ||
432 | val |= OTGSC_IDIE | OTGSC_BSVIE; | ||
433 | } else if (pdata->mode == USB_PERIPHERAL) { | ||
434 | ulpi_val = ULPI_INT_SESS_VALID; | ||
435 | val |= OTGSC_BSVIE; | ||
436 | } | ||
437 | writel(val, USB_OTGSC); | ||
438 | ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE); | ||
439 | ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL); | ||
440 | } | ||
441 | |||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | #define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000) | ||
446 | #define PHY_RESUME_TIMEOUT_USEC (100 * 1000) | ||
447 | |||
448 | #ifdef CONFIG_PM_SLEEP | ||
449 | static int msm_otg_suspend(struct msm_otg *motg) | ||
450 | { | ||
451 | struct otg_transceiver *otg = &motg->otg; | ||
452 | struct usb_bus *bus = otg->host; | ||
453 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
454 | int cnt = 0; | ||
455 | |||
456 | if (atomic_read(&motg->in_lpm)) | ||
457 | return 0; | ||
458 | |||
459 | disable_irq(motg->irq); | ||
460 | /* | ||
461 | * Chipidea 45-nm PHY suspend sequence: | ||
462 | * | ||
463 | * Interrupt Latch Register auto-clear feature is not present | ||
464 | * in all PHY versions. Latch register is clear on read type. | ||
465 | * Clear latch register to avoid spurious wakeup from | ||
466 | * low power mode (LPM). | ||
467 | * | ||
468 | * PHY comparators are disabled when PHY enters into low power | ||
469 | * mode (LPM). Keep PHY comparators ON in LPM only when we expect | ||
470 | * VBUS/Id notifications from USB PHY. Otherwise turn off USB | ||
471 | * PHY comparators. This save significant amount of power. | ||
472 | * | ||
473 | * PLL is not turned off when PHY enters into low power mode (LPM). | ||
474 | * Disable PLL for maximum power savings. | ||
475 | */ | ||
476 | |||
477 | if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) { | ||
478 | ulpi_read(otg, 0x14); | ||
479 | if (pdata->otg_control == OTG_PHY_CONTROL) | ||
480 | ulpi_write(otg, 0x01, 0x30); | ||
481 | ulpi_write(otg, 0x08, 0x09); | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | * PHY may take some time or even fail to enter into low power | ||
486 | * mode (LPM). Hence poll for 500 msec and reset the PHY and link | ||
487 | * in failure case. | ||
488 | */ | ||
489 | writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); | ||
490 | while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { | ||
491 | if (readl(USB_PORTSC) & PORTSC_PHCD) | ||
492 | break; | ||
493 | udelay(1); | ||
494 | cnt++; | ||
495 | } | ||
496 | |||
497 | if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) { | ||
498 | dev_err(otg->dev, "Unable to suspend PHY\n"); | ||
499 | msm_otg_reset(otg); | ||
500 | enable_irq(motg->irq); | ||
501 | return -ETIMEDOUT; | ||
502 | } | ||
503 | |||
504 | /* | ||
505 | * PHY has capability to generate interrupt asynchronously in low | ||
506 | * power mode (LPM). This interrupt is level triggered. So USB IRQ | ||
507 | * line must be disabled till async interrupt enable bit is cleared | ||
508 | * in USBCMD register. Assert STP (ULPI interface STOP signal) to | ||
509 | * block data communication from PHY. | ||
510 | */ | ||
511 | writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); | ||
512 | |||
513 | if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && | ||
514 | motg->pdata->otg_control == OTG_PMIC_CONTROL) | ||
515 | writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL); | ||
516 | |||
517 | clk_disable(motg->pclk); | ||
518 | clk_disable(motg->clk); | ||
519 | if (motg->core_clk) | ||
520 | clk_disable(motg->core_clk); | ||
521 | |||
522 | if (!IS_ERR(motg->pclk_src)) | ||
523 | clk_disable(motg->pclk_src); | ||
524 | |||
525 | if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && | ||
526 | motg->pdata->otg_control == OTG_PMIC_CONTROL) { | ||
527 | msm_hsusb_ldo_set_mode(0); | ||
528 | msm_hsusb_config_vddcx(0); | ||
529 | } | ||
530 | |||
531 | if (device_may_wakeup(otg->dev)) | ||
532 | enable_irq_wake(motg->irq); | ||
533 | if (bus) | ||
534 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); | ||
535 | |||
536 | atomic_set(&motg->in_lpm, 1); | ||
537 | enable_irq(motg->irq); | ||
538 | |||
539 | dev_info(otg->dev, "USB in low power mode\n"); | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static int msm_otg_resume(struct msm_otg *motg) | ||
545 | { | ||
546 | struct otg_transceiver *otg = &motg->otg; | ||
547 | struct usb_bus *bus = otg->host; | ||
548 | int cnt = 0; | ||
549 | unsigned temp; | ||
550 | |||
551 | if (!atomic_read(&motg->in_lpm)) | ||
552 | return 0; | ||
553 | |||
554 | if (!IS_ERR(motg->pclk_src)) | ||
555 | clk_enable(motg->pclk_src); | ||
556 | |||
557 | clk_enable(motg->pclk); | ||
558 | clk_enable(motg->clk); | ||
559 | if (motg->core_clk) | ||
560 | clk_enable(motg->core_clk); | ||
561 | |||
562 | if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && | ||
563 | motg->pdata->otg_control == OTG_PMIC_CONTROL) { | ||
564 | msm_hsusb_ldo_set_mode(1); | ||
565 | msm_hsusb_config_vddcx(1); | ||
566 | writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL); | ||
567 | } | ||
568 | |||
569 | temp = readl(USB_USBCMD); | ||
570 | temp &= ~ASYNC_INTR_CTRL; | ||
571 | temp &= ~ULPI_STP_CTRL; | ||
572 | writel(temp, USB_USBCMD); | ||
573 | |||
574 | /* | ||
575 | * PHY comes out of low power mode (LPM) in case of wakeup | ||
576 | * from asynchronous interrupt. | ||
577 | */ | ||
578 | if (!(readl(USB_PORTSC) & PORTSC_PHCD)) | ||
579 | goto skip_phy_resume; | ||
580 | |||
581 | writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC); | ||
582 | while (cnt < PHY_RESUME_TIMEOUT_USEC) { | ||
583 | if (!(readl(USB_PORTSC) & PORTSC_PHCD)) | ||
584 | break; | ||
585 | udelay(1); | ||
586 | cnt++; | ||
587 | } | ||
588 | |||
589 | if (cnt >= PHY_RESUME_TIMEOUT_USEC) { | ||
590 | /* | ||
591 | * This is a fatal error. Reset the link and | ||
592 | * PHY. USB state can not be restored. Re-insertion | ||
593 | * of USB cable is the only way to get USB working. | ||
594 | */ | ||
595 | dev_err(otg->dev, "Unable to resume USB." | ||
596 | "Re-plugin the cable\n"); | ||
597 | msm_otg_reset(otg); | ||
598 | } | ||
599 | |||
600 | skip_phy_resume: | ||
601 | if (device_may_wakeup(otg->dev)) | ||
602 | disable_irq_wake(motg->irq); | ||
603 | if (bus) | ||
604 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); | ||
605 | |||
606 | atomic_set(&motg->in_lpm, 0); | ||
607 | |||
608 | if (motg->async_int) { | ||
609 | motg->async_int = 0; | ||
610 | pm_runtime_put(otg->dev); | ||
611 | enable_irq(motg->irq); | ||
612 | } | ||
613 | |||
614 | dev_info(otg->dev, "USB exited from low power mode\n"); | ||
615 | |||
616 | return 0; | ||
617 | } | ||
618 | #endif | ||
619 | |||
620 | static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA) | ||
621 | { | ||
622 | if (motg->cur_power == mA) | ||
623 | return; | ||
624 | |||
625 | /* TODO: Notify PMIC about available current */ | ||
626 | dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA); | ||
627 | motg->cur_power = mA; | ||
628 | } | ||
629 | |||
630 | static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA) | ||
631 | { | ||
632 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
633 | |||
634 | /* | ||
635 | * Gadget driver uses set_power method to notify about the | ||
636 | * available current based on suspend/configured states. | ||
637 | * | ||
638 | * IDEV_CHG can be drawn irrespective of suspend/un-configured | ||
639 | * states when CDP/ACA is connected. | ||
640 | */ | ||
641 | if (motg->chg_type == USB_SDP_CHARGER) | ||
642 | msm_otg_notify_charger(motg, mA); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static void msm_otg_start_host(struct otg_transceiver *otg, int on) | ||
648 | { | ||
649 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
650 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
651 | struct usb_hcd *hcd; | ||
652 | |||
653 | if (!otg->host) | ||
654 | return; | ||
655 | |||
656 | hcd = bus_to_hcd(otg->host); | ||
657 | |||
658 | if (on) { | ||
659 | dev_dbg(otg->dev, "host on\n"); | ||
660 | |||
661 | if (pdata->vbus_power) | ||
662 | pdata->vbus_power(1); | ||
663 | /* | ||
664 | * Some boards have a switch cotrolled by gpio | ||
665 | * to enable/disable internal HUB. Enable internal | ||
666 | * HUB before kicking the host. | ||
667 | */ | ||
668 | if (pdata->setup_gpio) | ||
669 | pdata->setup_gpio(OTG_STATE_A_HOST); | ||
670 | #ifdef CONFIG_USB | ||
671 | usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); | ||
672 | #endif | ||
673 | } else { | ||
674 | dev_dbg(otg->dev, "host off\n"); | ||
675 | |||
676 | #ifdef CONFIG_USB | ||
677 | usb_remove_hcd(hcd); | ||
678 | #endif | ||
679 | if (pdata->setup_gpio) | ||
680 | pdata->setup_gpio(OTG_STATE_UNDEFINED); | ||
681 | if (pdata->vbus_power) | ||
682 | pdata->vbus_power(0); | ||
683 | } | ||
684 | } | ||
685 | |||
686 | static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) | ||
687 | { | ||
688 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
689 | struct usb_hcd *hcd; | ||
690 | |||
691 | /* | ||
692 | * Fail host registration if this board can support | ||
693 | * only peripheral configuration. | ||
694 | */ | ||
695 | if (motg->pdata->mode == USB_PERIPHERAL) { | ||
696 | dev_info(otg->dev, "Host mode is not supported\n"); | ||
697 | return -ENODEV; | ||
698 | } | ||
699 | |||
700 | if (!host) { | ||
701 | if (otg->state == OTG_STATE_A_HOST) { | ||
702 | pm_runtime_get_sync(otg->dev); | ||
703 | msm_otg_start_host(otg, 0); | ||
704 | otg->host = NULL; | ||
705 | otg->state = OTG_STATE_UNDEFINED; | ||
706 | schedule_work(&motg->sm_work); | ||
707 | } else { | ||
708 | otg->host = NULL; | ||
709 | } | ||
710 | |||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | hcd = bus_to_hcd(host); | ||
715 | hcd->power_budget = motg->pdata->power_budget; | ||
716 | |||
717 | otg->host = host; | ||
718 | dev_dbg(otg->dev, "host driver registered w/ tranceiver\n"); | ||
719 | |||
720 | /* | ||
721 | * Kick the state machine work, if peripheral is not supported | ||
722 | * or peripheral is already registered with us. | ||
723 | */ | ||
724 | if (motg->pdata->mode == USB_HOST || otg->gadget) { | ||
725 | pm_runtime_get_sync(otg->dev); | ||
726 | schedule_work(&motg->sm_work); | ||
727 | } | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on) | ||
733 | { | ||
734 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
735 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
736 | |||
737 | if (!otg->gadget) | ||
738 | return; | ||
739 | |||
740 | if (on) { | ||
741 | dev_dbg(otg->dev, "gadget on\n"); | ||
742 | /* | ||
743 | * Some boards have a switch cotrolled by gpio | ||
744 | * to enable/disable internal HUB. Disable internal | ||
745 | * HUB before kicking the gadget. | ||
746 | */ | ||
747 | if (pdata->setup_gpio) | ||
748 | pdata->setup_gpio(OTG_STATE_B_PERIPHERAL); | ||
749 | usb_gadget_vbus_connect(otg->gadget); | ||
750 | } else { | ||
751 | dev_dbg(otg->dev, "gadget off\n"); | ||
752 | usb_gadget_vbus_disconnect(otg->gadget); | ||
753 | if (pdata->setup_gpio) | ||
754 | pdata->setup_gpio(OTG_STATE_UNDEFINED); | ||
755 | } | ||
756 | |||
757 | } | ||
758 | |||
759 | static int msm_otg_set_peripheral(struct otg_transceiver *otg, | ||
760 | struct usb_gadget *gadget) | ||
761 | { | ||
762 | struct msm_otg *motg = container_of(otg, struct msm_otg, otg); | ||
763 | |||
764 | /* | ||
765 | * Fail peripheral registration if this board can support | ||
766 | * only host configuration. | ||
767 | */ | ||
768 | if (motg->pdata->mode == USB_HOST) { | ||
769 | dev_info(otg->dev, "Peripheral mode is not supported\n"); | ||
770 | return -ENODEV; | ||
771 | } | ||
772 | |||
773 | if (!gadget) { | ||
774 | if (otg->state == OTG_STATE_B_PERIPHERAL) { | ||
775 | pm_runtime_get_sync(otg->dev); | ||
776 | msm_otg_start_peripheral(otg, 0); | ||
777 | otg->gadget = NULL; | ||
778 | otg->state = OTG_STATE_UNDEFINED; | ||
779 | schedule_work(&motg->sm_work); | ||
780 | } else { | ||
781 | otg->gadget = NULL; | ||
782 | } | ||
783 | |||
784 | return 0; | ||
785 | } | ||
786 | otg->gadget = gadget; | ||
787 | dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n"); | ||
788 | |||
789 | /* | ||
790 | * Kick the state machine work, if host is not supported | ||
791 | * or host is already registered with us. | ||
792 | */ | ||
793 | if (motg->pdata->mode == USB_PERIPHERAL || otg->host) { | ||
794 | pm_runtime_get_sync(otg->dev); | ||
795 | schedule_work(&motg->sm_work); | ||
796 | } | ||
797 | |||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | static bool msm_chg_check_secondary_det(struct msm_otg *motg) | ||
802 | { | ||
803 | struct otg_transceiver *otg = &motg->otg; | ||
804 | u32 chg_det; | ||
805 | bool ret = false; | ||
806 | |||
807 | switch (motg->pdata->phy_type) { | ||
808 | case CI_45NM_INTEGRATED_PHY: | ||
809 | chg_det = ulpi_read(otg, 0x34); | ||
810 | ret = chg_det & (1 << 4); | ||
811 | break; | ||
812 | case SNPS_28NM_INTEGRATED_PHY: | ||
813 | chg_det = ulpi_read(otg, 0x87); | ||
814 | ret = chg_det & 1; | ||
815 | break; | ||
816 | default: | ||
817 | break; | ||
818 | } | ||
819 | return ret; | ||
820 | } | ||
821 | |||
822 | static void msm_chg_enable_secondary_det(struct msm_otg *motg) | ||
823 | { | ||
824 | struct otg_transceiver *otg = &motg->otg; | ||
825 | u32 chg_det; | ||
826 | |||
827 | switch (motg->pdata->phy_type) { | ||
828 | case CI_45NM_INTEGRATED_PHY: | ||
829 | chg_det = ulpi_read(otg, 0x34); | ||
830 | /* Turn off charger block */ | ||
831 | chg_det |= ~(1 << 1); | ||
832 | ulpi_write(otg, chg_det, 0x34); | ||
833 | udelay(20); | ||
834 | /* control chg block via ULPI */ | ||
835 | chg_det &= ~(1 << 3); | ||
836 | ulpi_write(otg, chg_det, 0x34); | ||
837 | /* put it in host mode for enabling D- source */ | ||
838 | chg_det &= ~(1 << 2); | ||
839 | ulpi_write(otg, chg_det, 0x34); | ||
840 | /* Turn on chg detect block */ | ||
841 | chg_det &= ~(1 << 1); | ||
842 | ulpi_write(otg, chg_det, 0x34); | ||
843 | udelay(20); | ||
844 | /* enable chg detection */ | ||
845 | chg_det &= ~(1 << 0); | ||
846 | ulpi_write(otg, chg_det, 0x34); | ||
847 | break; | ||
848 | case SNPS_28NM_INTEGRATED_PHY: | ||
849 | /* | ||
850 | * Configure DM as current source, DP as current sink | ||
851 | * and enable battery charging comparators. | ||
852 | */ | ||
853 | ulpi_write(otg, 0x8, 0x85); | ||
854 | ulpi_write(otg, 0x2, 0x85); | ||
855 | ulpi_write(otg, 0x1, 0x85); | ||
856 | break; | ||
857 | default: | ||
858 | break; | ||
859 | } | ||
860 | } | ||
861 | |||
862 | static bool msm_chg_check_primary_det(struct msm_otg *motg) | ||
863 | { | ||
864 | struct otg_transceiver *otg = &motg->otg; | ||
865 | u32 chg_det; | ||
866 | bool ret = false; | ||
867 | |||
868 | switch (motg->pdata->phy_type) { | ||
869 | case CI_45NM_INTEGRATED_PHY: | ||
870 | chg_det = ulpi_read(otg, 0x34); | ||
871 | ret = chg_det & (1 << 4); | ||
872 | break; | ||
873 | case SNPS_28NM_INTEGRATED_PHY: | ||
874 | chg_det = ulpi_read(otg, 0x87); | ||
875 | ret = chg_det & 1; | ||
876 | break; | ||
877 | default: | ||
878 | break; | ||
879 | } | ||
880 | return ret; | ||
881 | } | ||
882 | |||
883 | static void msm_chg_enable_primary_det(struct msm_otg *motg) | ||
884 | { | ||
885 | struct otg_transceiver *otg = &motg->otg; | ||
886 | u32 chg_det; | ||
887 | |||
888 | switch (motg->pdata->phy_type) { | ||
889 | case CI_45NM_INTEGRATED_PHY: | ||
890 | chg_det = ulpi_read(otg, 0x34); | ||
891 | /* enable chg detection */ | ||
892 | chg_det &= ~(1 << 0); | ||
893 | ulpi_write(otg, chg_det, 0x34); | ||
894 | break; | ||
895 | case SNPS_28NM_INTEGRATED_PHY: | ||
896 | /* | ||
897 | * Configure DP as current source, DM as current sink | ||
898 | * and enable battery charging comparators. | ||
899 | */ | ||
900 | ulpi_write(otg, 0x2, 0x85); | ||
901 | ulpi_write(otg, 0x1, 0x85); | ||
902 | break; | ||
903 | default: | ||
904 | break; | ||
905 | } | ||
906 | } | ||
907 | |||
908 | static bool msm_chg_check_dcd(struct msm_otg *motg) | ||
909 | { | ||
910 | struct otg_transceiver *otg = &motg->otg; | ||
911 | u32 line_state; | ||
912 | bool ret = false; | ||
913 | |||
914 | switch (motg->pdata->phy_type) { | ||
915 | case CI_45NM_INTEGRATED_PHY: | ||
916 | line_state = ulpi_read(otg, 0x15); | ||
917 | ret = !(line_state & 1); | ||
918 | break; | ||
919 | case SNPS_28NM_INTEGRATED_PHY: | ||
920 | line_state = ulpi_read(otg, 0x87); | ||
921 | ret = line_state & 2; | ||
922 | break; | ||
923 | default: | ||
924 | break; | ||
925 | } | ||
926 | return ret; | ||
927 | } | ||
928 | |||
929 | static void msm_chg_disable_dcd(struct msm_otg *motg) | ||
930 | { | ||
931 | struct otg_transceiver *otg = &motg->otg; | ||
932 | u32 chg_det; | ||
933 | |||
934 | switch (motg->pdata->phy_type) { | ||
935 | case CI_45NM_INTEGRATED_PHY: | ||
936 | chg_det = ulpi_read(otg, 0x34); | ||
937 | chg_det &= ~(1 << 5); | ||
938 | ulpi_write(otg, chg_det, 0x34); | ||
939 | break; | ||
940 | case SNPS_28NM_INTEGRATED_PHY: | ||
941 | ulpi_write(otg, 0x10, 0x86); | ||
942 | break; | ||
943 | default: | ||
944 | break; | ||
945 | } | ||
946 | } | ||
947 | |||
948 | static void msm_chg_enable_dcd(struct msm_otg *motg) | ||
949 | { | ||
950 | struct otg_transceiver *otg = &motg->otg; | ||
951 | u32 chg_det; | ||
952 | |||
953 | switch (motg->pdata->phy_type) { | ||
954 | case CI_45NM_INTEGRATED_PHY: | ||
955 | chg_det = ulpi_read(otg, 0x34); | ||
956 | /* Turn on D+ current source */ | ||
957 | chg_det |= (1 << 5); | ||
958 | ulpi_write(otg, chg_det, 0x34); | ||
959 | break; | ||
960 | case SNPS_28NM_INTEGRATED_PHY: | ||
961 | /* Data contact detection enable */ | ||
962 | ulpi_write(otg, 0x10, 0x85); | ||
963 | break; | ||
964 | default: | ||
965 | break; | ||
966 | } | ||
967 | } | ||
968 | |||
969 | static void msm_chg_block_on(struct msm_otg *motg) | ||
970 | { | ||
971 | struct otg_transceiver *otg = &motg->otg; | ||
972 | u32 func_ctrl, chg_det; | ||
973 | |||
974 | /* put the controller in non-driving mode */ | ||
975 | func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL); | ||
976 | func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; | ||
977 | func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; | ||
978 | ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL); | ||
979 | |||
980 | switch (motg->pdata->phy_type) { | ||
981 | case CI_45NM_INTEGRATED_PHY: | ||
982 | chg_det = ulpi_read(otg, 0x34); | ||
983 | /* control chg block via ULPI */ | ||
984 | chg_det &= ~(1 << 3); | ||
985 | ulpi_write(otg, chg_det, 0x34); | ||
986 | /* Turn on chg detect block */ | ||
987 | chg_det &= ~(1 << 1); | ||
988 | ulpi_write(otg, chg_det, 0x34); | ||
989 | udelay(20); | ||
990 | break; | ||
991 | case SNPS_28NM_INTEGRATED_PHY: | ||
992 | /* Clear charger detecting control bits */ | ||
993 | ulpi_write(otg, 0x3F, 0x86); | ||
994 | /* Clear alt interrupt latch and enable bits */ | ||
995 | ulpi_write(otg, 0x1F, 0x92); | ||
996 | ulpi_write(otg, 0x1F, 0x95); | ||
997 | udelay(100); | ||
998 | break; | ||
999 | default: | ||
1000 | break; | ||
1001 | } | ||
1002 | } | ||
1003 | |||
1004 | static void msm_chg_block_off(struct msm_otg *motg) | ||
1005 | { | ||
1006 | struct otg_transceiver *otg = &motg->otg; | ||
1007 | u32 func_ctrl, chg_det; | ||
1008 | |||
1009 | switch (motg->pdata->phy_type) { | ||
1010 | case CI_45NM_INTEGRATED_PHY: | ||
1011 | chg_det = ulpi_read(otg, 0x34); | ||
1012 | /* Turn off charger block */ | ||
1013 | chg_det |= ~(1 << 1); | ||
1014 | ulpi_write(otg, chg_det, 0x34); | ||
1015 | break; | ||
1016 | case SNPS_28NM_INTEGRATED_PHY: | ||
1017 | /* Clear charger detecting control bits */ | ||
1018 | ulpi_write(otg, 0x3F, 0x86); | ||
1019 | /* Clear alt interrupt latch and enable bits */ | ||
1020 | ulpi_write(otg, 0x1F, 0x92); | ||
1021 | ulpi_write(otg, 0x1F, 0x95); | ||
1022 | break; | ||
1023 | default: | ||
1024 | break; | ||
1025 | } | ||
1026 | |||
1027 | /* put the controller in normal mode */ | ||
1028 | func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL); | ||
1029 | func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; | ||
1030 | func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL; | ||
1031 | ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL); | ||
1032 | } | ||
1033 | |||
1034 | #define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */ | ||
1035 | #define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */ | ||
1036 | #define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */ | ||
1037 | #define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */ | ||
1038 | static void msm_chg_detect_work(struct work_struct *w) | ||
1039 | { | ||
1040 | struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work); | ||
1041 | struct otg_transceiver *otg = &motg->otg; | ||
1042 | bool is_dcd, tmout, vout; | ||
1043 | unsigned long delay; | ||
1044 | |||
1045 | dev_dbg(otg->dev, "chg detection work\n"); | ||
1046 | switch (motg->chg_state) { | ||
1047 | case USB_CHG_STATE_UNDEFINED: | ||
1048 | pm_runtime_get_sync(otg->dev); | ||
1049 | msm_chg_block_on(motg); | ||
1050 | msm_chg_enable_dcd(motg); | ||
1051 | motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; | ||
1052 | motg->dcd_retries = 0; | ||
1053 | delay = MSM_CHG_DCD_POLL_TIME; | ||
1054 | break; | ||
1055 | case USB_CHG_STATE_WAIT_FOR_DCD: | ||
1056 | is_dcd = msm_chg_check_dcd(motg); | ||
1057 | tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES; | ||
1058 | if (is_dcd || tmout) { | ||
1059 | msm_chg_disable_dcd(motg); | ||
1060 | msm_chg_enable_primary_det(motg); | ||
1061 | delay = MSM_CHG_PRIMARY_DET_TIME; | ||
1062 | motg->chg_state = USB_CHG_STATE_DCD_DONE; | ||
1063 | } else { | ||
1064 | delay = MSM_CHG_DCD_POLL_TIME; | ||
1065 | } | ||
1066 | break; | ||
1067 | case USB_CHG_STATE_DCD_DONE: | ||
1068 | vout = msm_chg_check_primary_det(motg); | ||
1069 | if (vout) { | ||
1070 | msm_chg_enable_secondary_det(motg); | ||
1071 | delay = MSM_CHG_SECONDARY_DET_TIME; | ||
1072 | motg->chg_state = USB_CHG_STATE_PRIMARY_DONE; | ||
1073 | } else { | ||
1074 | motg->chg_type = USB_SDP_CHARGER; | ||
1075 | motg->chg_state = USB_CHG_STATE_DETECTED; | ||
1076 | delay = 0; | ||
1077 | } | ||
1078 | break; | ||
1079 | case USB_CHG_STATE_PRIMARY_DONE: | ||
1080 | vout = msm_chg_check_secondary_det(motg); | ||
1081 | if (vout) | ||
1082 | motg->chg_type = USB_DCP_CHARGER; | ||
1083 | else | ||
1084 | motg->chg_type = USB_CDP_CHARGER; | ||
1085 | motg->chg_state = USB_CHG_STATE_SECONDARY_DONE; | ||
1086 | /* fall through */ | ||
1087 | case USB_CHG_STATE_SECONDARY_DONE: | ||
1088 | motg->chg_state = USB_CHG_STATE_DETECTED; | ||
1089 | case USB_CHG_STATE_DETECTED: | ||
1090 | msm_chg_block_off(motg); | ||
1091 | dev_dbg(otg->dev, "charger = %d\n", motg->chg_type); | ||
1092 | schedule_work(&motg->sm_work); | ||
1093 | return; | ||
1094 | default: | ||
1095 | return; | ||
1096 | } | ||
1097 | |||
1098 | schedule_delayed_work(&motg->chg_work, delay); | ||
1099 | } | ||
1100 | |||
1101 | /* | ||
1102 | * We support OTG, Peripheral only and Host only configurations. In case | ||
1103 | * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen | ||
1104 | * via Id pin status or user request (debugfs). Id/BSV interrupts are not | ||
1105 | * enabled when switch is controlled by user and default mode is supplied | ||
1106 | * by board file, which can be changed by userspace later. | ||
1107 | */ | ||
1108 | static void msm_otg_init_sm(struct msm_otg *motg) | ||
1109 | { | ||
1110 | struct msm_otg_platform_data *pdata = motg->pdata; | ||
1111 | u32 otgsc = readl(USB_OTGSC); | ||
1112 | |||
1113 | switch (pdata->mode) { | ||
1114 | case USB_OTG: | ||
1115 | if (pdata->otg_control == OTG_PHY_CONTROL) { | ||
1116 | if (otgsc & OTGSC_ID) | ||
1117 | set_bit(ID, &motg->inputs); | ||
1118 | else | ||
1119 | clear_bit(ID, &motg->inputs); | ||
1120 | |||
1121 | if (otgsc & OTGSC_BSV) | ||
1122 | set_bit(B_SESS_VLD, &motg->inputs); | ||
1123 | else | ||
1124 | clear_bit(B_SESS_VLD, &motg->inputs); | ||
1125 | } else if (pdata->otg_control == OTG_USER_CONTROL) { | ||
1126 | if (pdata->default_mode == USB_HOST) { | ||
1127 | clear_bit(ID, &motg->inputs); | ||
1128 | } else if (pdata->default_mode == USB_PERIPHERAL) { | ||
1129 | set_bit(ID, &motg->inputs); | ||
1130 | set_bit(B_SESS_VLD, &motg->inputs); | ||
1131 | } else { | ||
1132 | set_bit(ID, &motg->inputs); | ||
1133 | clear_bit(B_SESS_VLD, &motg->inputs); | ||
1134 | } | ||
1135 | } | ||
1136 | break; | ||
1137 | case USB_HOST: | ||
1138 | clear_bit(ID, &motg->inputs); | ||
1139 | break; | ||
1140 | case USB_PERIPHERAL: | ||
1141 | set_bit(ID, &motg->inputs); | ||
1142 | if (otgsc & OTGSC_BSV) | ||
1143 | set_bit(B_SESS_VLD, &motg->inputs); | ||
1144 | else | ||
1145 | clear_bit(B_SESS_VLD, &motg->inputs); | ||
1146 | break; | ||
1147 | default: | ||
1148 | break; | ||
1149 | } | ||
1150 | } | ||
1151 | |||
1152 | static void msm_otg_sm_work(struct work_struct *w) | ||
1153 | { | ||
1154 | struct msm_otg *motg = container_of(w, struct msm_otg, sm_work); | ||
1155 | struct otg_transceiver *otg = &motg->otg; | ||
1156 | |||
1157 | switch (otg->state) { | ||
1158 | case OTG_STATE_UNDEFINED: | ||
1159 | dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n"); | ||
1160 | msm_otg_reset(otg); | ||
1161 | msm_otg_init_sm(motg); | ||
1162 | otg->state = OTG_STATE_B_IDLE; | ||
1163 | /* FALL THROUGH */ | ||
1164 | case OTG_STATE_B_IDLE: | ||
1165 | dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n"); | ||
1166 | if (!test_bit(ID, &motg->inputs) && otg->host) { | ||
1167 | /* disable BSV bit */ | ||
1168 | writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC); | ||
1169 | msm_otg_start_host(otg, 1); | ||
1170 | otg->state = OTG_STATE_A_HOST; | ||
1171 | } else if (test_bit(B_SESS_VLD, &motg->inputs)) { | ||
1172 | switch (motg->chg_state) { | ||
1173 | case USB_CHG_STATE_UNDEFINED: | ||
1174 | msm_chg_detect_work(&motg->chg_work.work); | ||
1175 | break; | ||
1176 | case USB_CHG_STATE_DETECTED: | ||
1177 | switch (motg->chg_type) { | ||
1178 | case USB_DCP_CHARGER: | ||
1179 | msm_otg_notify_charger(motg, | ||
1180 | IDEV_CHG_MAX); | ||
1181 | break; | ||
1182 | case USB_CDP_CHARGER: | ||
1183 | msm_otg_notify_charger(motg, | ||
1184 | IDEV_CHG_MAX); | ||
1185 | msm_otg_start_peripheral(otg, 1); | ||
1186 | otg->state = OTG_STATE_B_PERIPHERAL; | ||
1187 | break; | ||
1188 | case USB_SDP_CHARGER: | ||
1189 | msm_otg_notify_charger(motg, IUNIT); | ||
1190 | msm_otg_start_peripheral(otg, 1); | ||
1191 | otg->state = OTG_STATE_B_PERIPHERAL; | ||
1192 | break; | ||
1193 | default: | ||
1194 | break; | ||
1195 | } | ||
1196 | break; | ||
1197 | default: | ||
1198 | break; | ||
1199 | } | ||
1200 | } else { | ||
1201 | /* | ||
1202 | * If charger detection work is pending, decrement | ||
1203 | * the pm usage counter to balance with the one that | ||
1204 | * is incremented in charger detection work. | ||
1205 | */ | ||
1206 | if (cancel_delayed_work_sync(&motg->chg_work)) { | ||
1207 | pm_runtime_put_sync(otg->dev); | ||
1208 | msm_otg_reset(otg); | ||
1209 | } | ||
1210 | msm_otg_notify_charger(motg, 0); | ||
1211 | motg->chg_state = USB_CHG_STATE_UNDEFINED; | ||
1212 | motg->chg_type = USB_INVALID_CHARGER; | ||
1213 | } | ||
1214 | pm_runtime_put_sync(otg->dev); | ||
1215 | break; | ||
1216 | case OTG_STATE_B_PERIPHERAL: | ||
1217 | dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n"); | ||
1218 | if (!test_bit(B_SESS_VLD, &motg->inputs) || | ||
1219 | !test_bit(ID, &motg->inputs)) { | ||
1220 | msm_otg_notify_charger(motg, 0); | ||
1221 | msm_otg_start_peripheral(otg, 0); | ||
1222 | motg->chg_state = USB_CHG_STATE_UNDEFINED; | ||
1223 | motg->chg_type = USB_INVALID_CHARGER; | ||
1224 | otg->state = OTG_STATE_B_IDLE; | ||
1225 | msm_otg_reset(otg); | ||
1226 | schedule_work(w); | ||
1227 | } | ||
1228 | break; | ||
1229 | case OTG_STATE_A_HOST: | ||
1230 | dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n"); | ||
1231 | if (test_bit(ID, &motg->inputs)) { | ||
1232 | msm_otg_start_host(otg, 0); | ||
1233 | otg->state = OTG_STATE_B_IDLE; | ||
1234 | msm_otg_reset(otg); | ||
1235 | schedule_work(w); | ||
1236 | } | ||
1237 | break; | ||
1238 | default: | ||
1239 | break; | ||
1240 | } | ||
1241 | } | ||
1242 | |||
1243 | static irqreturn_t msm_otg_irq(int irq, void *data) | ||
1244 | { | ||
1245 | struct msm_otg *motg = data; | ||
1246 | struct otg_transceiver *otg = &motg->otg; | ||
1247 | u32 otgsc = 0; | ||
1248 | |||
1249 | if (atomic_read(&motg->in_lpm)) { | ||
1250 | disable_irq_nosync(irq); | ||
1251 | motg->async_int = 1; | ||
1252 | pm_runtime_get(otg->dev); | ||
1253 | return IRQ_HANDLED; | ||
1254 | } | ||
1255 | |||
1256 | otgsc = readl(USB_OTGSC); | ||
1257 | if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS))) | ||
1258 | return IRQ_NONE; | ||
1259 | |||
1260 | if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) { | ||
1261 | if (otgsc & OTGSC_ID) | ||
1262 | set_bit(ID, &motg->inputs); | ||
1263 | else | ||
1264 | clear_bit(ID, &motg->inputs); | ||
1265 | dev_dbg(otg->dev, "ID set/clear\n"); | ||
1266 | pm_runtime_get_noresume(otg->dev); | ||
1267 | } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) { | ||
1268 | if (otgsc & OTGSC_BSV) | ||
1269 | set_bit(B_SESS_VLD, &motg->inputs); | ||
1270 | else | ||
1271 | clear_bit(B_SESS_VLD, &motg->inputs); | ||
1272 | dev_dbg(otg->dev, "BSV set/clear\n"); | ||
1273 | pm_runtime_get_noresume(otg->dev); | ||
1274 | } | ||
1275 | |||
1276 | writel(otgsc, USB_OTGSC); | ||
1277 | schedule_work(&motg->sm_work); | ||
1278 | return IRQ_HANDLED; | ||
1279 | } | ||
1280 | |||
1281 | static int msm_otg_mode_show(struct seq_file *s, void *unused) | ||
1282 | { | ||
1283 | struct msm_otg *motg = s->private; | ||
1284 | struct otg_transceiver *otg = &motg->otg; | ||
1285 | |||
1286 | switch (otg->state) { | ||
1287 | case OTG_STATE_A_HOST: | ||
1288 | seq_printf(s, "host\n"); | ||
1289 | break; | ||
1290 | case OTG_STATE_B_PERIPHERAL: | ||
1291 | seq_printf(s, "peripheral\n"); | ||
1292 | break; | ||
1293 | default: | ||
1294 | seq_printf(s, "none\n"); | ||
1295 | break; | ||
1296 | } | ||
1297 | |||
1298 | return 0; | ||
1299 | } | ||
1300 | |||
1301 | static int msm_otg_mode_open(struct inode *inode, struct file *file) | ||
1302 | { | ||
1303 | return single_open(file, msm_otg_mode_show, inode->i_private); | ||
1304 | } | ||
1305 | |||
1306 | static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, | ||
1307 | size_t count, loff_t *ppos) | ||
1308 | { | ||
1309 | struct seq_file *s = file->private_data; | ||
1310 | struct msm_otg *motg = s->private; | ||
1311 | char buf[16]; | ||
1312 | struct otg_transceiver *otg = &motg->otg; | ||
1313 | int status = count; | ||
1314 | enum usb_mode_type req_mode; | ||
1315 | |||
1316 | memset(buf, 0x00, sizeof(buf)); | ||
1317 | |||
1318 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) { | ||
1319 | status = -EFAULT; | ||
1320 | goto out; | ||
1321 | } | ||
1322 | |||
1323 | if (!strncmp(buf, "host", 4)) { | ||
1324 | req_mode = USB_HOST; | ||
1325 | } else if (!strncmp(buf, "peripheral", 10)) { | ||
1326 | req_mode = USB_PERIPHERAL; | ||
1327 | } else if (!strncmp(buf, "none", 4)) { | ||
1328 | req_mode = USB_NONE; | ||
1329 | } else { | ||
1330 | status = -EINVAL; | ||
1331 | goto out; | ||
1332 | } | ||
1333 | |||
1334 | switch (req_mode) { | ||
1335 | case USB_NONE: | ||
1336 | switch (otg->state) { | ||
1337 | case OTG_STATE_A_HOST: | ||
1338 | case OTG_STATE_B_PERIPHERAL: | ||
1339 | set_bit(ID, &motg->inputs); | ||
1340 | clear_bit(B_SESS_VLD, &motg->inputs); | ||
1341 | break; | ||
1342 | default: | ||
1343 | goto out; | ||
1344 | } | ||
1345 | break; | ||
1346 | case USB_PERIPHERAL: | ||
1347 | switch (otg->state) { | ||
1348 | case OTG_STATE_B_IDLE: | ||
1349 | case OTG_STATE_A_HOST: | ||
1350 | set_bit(ID, &motg->inputs); | ||
1351 | set_bit(B_SESS_VLD, &motg->inputs); | ||
1352 | break; | ||
1353 | default: | ||
1354 | goto out; | ||
1355 | } | ||
1356 | break; | ||
1357 | case USB_HOST: | ||
1358 | switch (otg->state) { | ||
1359 | case OTG_STATE_B_IDLE: | ||
1360 | case OTG_STATE_B_PERIPHERAL: | ||
1361 | clear_bit(ID, &motg->inputs); | ||
1362 | break; | ||
1363 | default: | ||
1364 | goto out; | ||
1365 | } | ||
1366 | break; | ||
1367 | default: | ||
1368 | goto out; | ||
1369 | } | ||
1370 | |||
1371 | pm_runtime_get_sync(otg->dev); | ||
1372 | schedule_work(&motg->sm_work); | ||
1373 | out: | ||
1374 | return status; | ||
1375 | } | ||
1376 | |||
1377 | const struct file_operations msm_otg_mode_fops = { | ||
1378 | .open = msm_otg_mode_open, | ||
1379 | .read = seq_read, | ||
1380 | .write = msm_otg_mode_write, | ||
1381 | .llseek = seq_lseek, | ||
1382 | .release = single_release, | ||
1383 | }; | ||
1384 | |||
1385 | static struct dentry *msm_otg_dbg_root; | ||
1386 | static struct dentry *msm_otg_dbg_mode; | ||
1387 | |||
1388 | static int msm_otg_debugfs_init(struct msm_otg *motg) | ||
1389 | { | ||
1390 | msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL); | ||
1391 | |||
1392 | if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root)) | ||
1393 | return -ENODEV; | ||
1394 | |||
1395 | msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO | S_IWUSR, | ||
1396 | msm_otg_dbg_root, motg, &msm_otg_mode_fops); | ||
1397 | if (!msm_otg_dbg_mode) { | ||
1398 | debugfs_remove(msm_otg_dbg_root); | ||
1399 | msm_otg_dbg_root = NULL; | ||
1400 | return -ENODEV; | ||
1401 | } | ||
1402 | |||
1403 | return 0; | ||
1404 | } | ||
1405 | |||
1406 | static void msm_otg_debugfs_cleanup(void) | ||
1407 | { | ||
1408 | debugfs_remove(msm_otg_dbg_mode); | ||
1409 | debugfs_remove(msm_otg_dbg_root); | ||
1410 | } | ||
1411 | |||
1412 | static int __init msm_otg_probe(struct platform_device *pdev) | ||
1413 | { | ||
1414 | int ret = 0; | ||
1415 | struct resource *res; | ||
1416 | struct msm_otg *motg; | ||
1417 | struct otg_transceiver *otg; | ||
1418 | |||
1419 | dev_info(&pdev->dev, "msm_otg probe\n"); | ||
1420 | if (!pdev->dev.platform_data) { | ||
1421 | dev_err(&pdev->dev, "No platform data given. Bailing out\n"); | ||
1422 | return -ENODEV; | ||
1423 | } | ||
1424 | |||
1425 | motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL); | ||
1426 | if (!motg) { | ||
1427 | dev_err(&pdev->dev, "unable to allocate msm_otg\n"); | ||
1428 | return -ENOMEM; | ||
1429 | } | ||
1430 | |||
1431 | motg->pdata = pdev->dev.platform_data; | ||
1432 | otg = &motg->otg; | ||
1433 | otg->dev = &pdev->dev; | ||
1434 | |||
1435 | motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk"); | ||
1436 | if (IS_ERR(motg->phy_reset_clk)) { | ||
1437 | dev_err(&pdev->dev, "failed to get usb_phy_clk\n"); | ||
1438 | ret = PTR_ERR(motg->phy_reset_clk); | ||
1439 | goto free_motg; | ||
1440 | } | ||
1441 | |||
1442 | motg->clk = clk_get(&pdev->dev, "usb_hs_clk"); | ||
1443 | if (IS_ERR(motg->clk)) { | ||
1444 | dev_err(&pdev->dev, "failed to get usb_hs_clk\n"); | ||
1445 | ret = PTR_ERR(motg->clk); | ||
1446 | goto put_phy_reset_clk; | ||
1447 | } | ||
1448 | clk_set_rate(motg->clk, 60000000); | ||
1449 | |||
1450 | /* | ||
1451 | * If USB Core is running its protocol engine based on CORE CLK, | ||
1452 | * CORE CLK must be running at >55Mhz for correct HSUSB | ||
1453 | * operation and USB core cannot tolerate frequency changes on | ||
1454 | * CORE CLK. For such USB cores, vote for maximum clk frequency | ||
1455 | * on pclk source | ||
1456 | */ | ||
1457 | if (motg->pdata->pclk_src_name) { | ||
1458 | motg->pclk_src = clk_get(&pdev->dev, | ||
1459 | motg->pdata->pclk_src_name); | ||
1460 | if (IS_ERR(motg->pclk_src)) | ||
1461 | goto put_clk; | ||
1462 | clk_set_rate(motg->pclk_src, INT_MAX); | ||
1463 | clk_enable(motg->pclk_src); | ||
1464 | } else | ||
1465 | motg->pclk_src = ERR_PTR(-ENOENT); | ||
1466 | |||
1467 | |||
1468 | motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk"); | ||
1469 | if (IS_ERR(motg->pclk)) { | ||
1470 | dev_err(&pdev->dev, "failed to get usb_hs_pclk\n"); | ||
1471 | ret = PTR_ERR(motg->pclk); | ||
1472 | goto put_pclk_src; | ||
1473 | } | ||
1474 | |||
1475 | /* | ||
1476 | * USB core clock is not present on all MSM chips. This | ||
1477 | * clock is introduced to remove the dependency on AXI | ||
1478 | * bus frequency. | ||
1479 | */ | ||
1480 | motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk"); | ||
1481 | if (IS_ERR(motg->core_clk)) | ||
1482 | motg->core_clk = NULL; | ||
1483 | |||
1484 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1485 | if (!res) { | ||
1486 | dev_err(&pdev->dev, "failed to get platform resource mem\n"); | ||
1487 | ret = -ENODEV; | ||
1488 | goto put_core_clk; | ||
1489 | } | ||
1490 | |||
1491 | motg->regs = ioremap(res->start, resource_size(res)); | ||
1492 | if (!motg->regs) { | ||
1493 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
1494 | ret = -ENOMEM; | ||
1495 | goto put_core_clk; | ||
1496 | } | ||
1497 | dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs); | ||
1498 | |||
1499 | motg->irq = platform_get_irq(pdev, 0); | ||
1500 | if (!motg->irq) { | ||
1501 | dev_err(&pdev->dev, "platform_get_irq failed\n"); | ||
1502 | ret = -ENODEV; | ||
1503 | goto free_regs; | ||
1504 | } | ||
1505 | |||
1506 | clk_enable(motg->clk); | ||
1507 | clk_enable(motg->pclk); | ||
1508 | |||
1509 | ret = msm_hsusb_init_vddcx(motg, 1); | ||
1510 | if (ret) { | ||
1511 | dev_err(&pdev->dev, "hsusb vddcx configuration failed\n"); | ||
1512 | goto free_regs; | ||
1513 | } | ||
1514 | |||
1515 | ret = msm_hsusb_ldo_init(motg, 1); | ||
1516 | if (ret) { | ||
1517 | dev_err(&pdev->dev, "hsusb vreg configuration failed\n"); | ||
1518 | goto vddcx_exit; | ||
1519 | } | ||
1520 | ret = msm_hsusb_ldo_set_mode(1); | ||
1521 | if (ret) { | ||
1522 | dev_err(&pdev->dev, "hsusb vreg enable failed\n"); | ||
1523 | goto ldo_exit; | ||
1524 | } | ||
1525 | |||
1526 | if (motg->core_clk) | ||
1527 | clk_enable(motg->core_clk); | ||
1528 | |||
1529 | writel(0, USB_USBINTR); | ||
1530 | writel(0, USB_OTGSC); | ||
1531 | |||
1532 | INIT_WORK(&motg->sm_work, msm_otg_sm_work); | ||
1533 | INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work); | ||
1534 | ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED, | ||
1535 | "msm_otg", motg); | ||
1536 | if (ret) { | ||
1537 | dev_err(&pdev->dev, "request irq failed\n"); | ||
1538 | goto disable_clks; | ||
1539 | } | ||
1540 | |||
1541 | otg->init = msm_otg_reset; | ||
1542 | otg->set_host = msm_otg_set_host; | ||
1543 | otg->set_peripheral = msm_otg_set_peripheral; | ||
1544 | otg->set_power = msm_otg_set_power; | ||
1545 | |||
1546 | otg->io_ops = &msm_otg_io_ops; | ||
1547 | |||
1548 | ret = otg_set_transceiver(&motg->otg); | ||
1549 | if (ret) { | ||
1550 | dev_err(&pdev->dev, "otg_set_transceiver failed\n"); | ||
1551 | goto free_irq; | ||
1552 | } | ||
1553 | |||
1554 | platform_set_drvdata(pdev, motg); | ||
1555 | device_init_wakeup(&pdev->dev, 1); | ||
1556 | |||
1557 | if (motg->pdata->mode == USB_OTG && | ||
1558 | motg->pdata->otg_control == OTG_USER_CONTROL) { | ||
1559 | ret = msm_otg_debugfs_init(motg); | ||
1560 | if (ret) | ||
1561 | dev_dbg(&pdev->dev, "mode debugfs file is" | ||
1562 | "not available\n"); | ||
1563 | } | ||
1564 | |||
1565 | pm_runtime_set_active(&pdev->dev); | ||
1566 | pm_runtime_enable(&pdev->dev); | ||
1567 | |||
1568 | return 0; | ||
1569 | free_irq: | ||
1570 | free_irq(motg->irq, motg); | ||
1571 | disable_clks: | ||
1572 | clk_disable(motg->pclk); | ||
1573 | clk_disable(motg->clk); | ||
1574 | ldo_exit: | ||
1575 | msm_hsusb_ldo_init(motg, 0); | ||
1576 | vddcx_exit: | ||
1577 | msm_hsusb_init_vddcx(motg, 0); | ||
1578 | free_regs: | ||
1579 | iounmap(motg->regs); | ||
1580 | put_core_clk: | ||
1581 | if (motg->core_clk) | ||
1582 | clk_put(motg->core_clk); | ||
1583 | clk_put(motg->pclk); | ||
1584 | put_pclk_src: | ||
1585 | if (!IS_ERR(motg->pclk_src)) { | ||
1586 | clk_disable(motg->pclk_src); | ||
1587 | clk_put(motg->pclk_src); | ||
1588 | } | ||
1589 | put_clk: | ||
1590 | clk_put(motg->clk); | ||
1591 | put_phy_reset_clk: | ||
1592 | clk_put(motg->phy_reset_clk); | ||
1593 | free_motg: | ||
1594 | kfree(motg); | ||
1595 | return ret; | ||
1596 | } | ||
1597 | |||
1598 | static int __devexit msm_otg_remove(struct platform_device *pdev) | ||
1599 | { | ||
1600 | struct msm_otg *motg = platform_get_drvdata(pdev); | ||
1601 | struct otg_transceiver *otg = &motg->otg; | ||
1602 | int cnt = 0; | ||
1603 | |||
1604 | if (otg->host || otg->gadget) | ||
1605 | return -EBUSY; | ||
1606 | |||
1607 | msm_otg_debugfs_cleanup(); | ||
1608 | cancel_delayed_work_sync(&motg->chg_work); | ||
1609 | cancel_work_sync(&motg->sm_work); | ||
1610 | |||
1611 | pm_runtime_resume(&pdev->dev); | ||
1612 | |||
1613 | device_init_wakeup(&pdev->dev, 0); | ||
1614 | pm_runtime_disable(&pdev->dev); | ||
1615 | |||
1616 | otg_set_transceiver(NULL); | ||
1617 | free_irq(motg->irq, motg); | ||
1618 | |||
1619 | /* | ||
1620 | * Put PHY in low power mode. | ||
1621 | */ | ||
1622 | ulpi_read(otg, 0x14); | ||
1623 | ulpi_write(otg, 0x08, 0x09); | ||
1624 | |||
1625 | writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); | ||
1626 | while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { | ||
1627 | if (readl(USB_PORTSC) & PORTSC_PHCD) | ||
1628 | break; | ||
1629 | udelay(1); | ||
1630 | cnt++; | ||
1631 | } | ||
1632 | if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) | ||
1633 | dev_err(otg->dev, "Unable to suspend PHY\n"); | ||
1634 | |||
1635 | clk_disable(motg->pclk); | ||
1636 | clk_disable(motg->clk); | ||
1637 | if (motg->core_clk) | ||
1638 | clk_disable(motg->core_clk); | ||
1639 | if (!IS_ERR(motg->pclk_src)) { | ||
1640 | clk_disable(motg->pclk_src); | ||
1641 | clk_put(motg->pclk_src); | ||
1642 | } | ||
1643 | msm_hsusb_ldo_init(motg, 0); | ||
1644 | |||
1645 | iounmap(motg->regs); | ||
1646 | pm_runtime_set_suspended(&pdev->dev); | ||
1647 | |||
1648 | clk_put(motg->phy_reset_clk); | ||
1649 | clk_put(motg->pclk); | ||
1650 | clk_put(motg->clk); | ||
1651 | if (motg->core_clk) | ||
1652 | clk_put(motg->core_clk); | ||
1653 | |||
1654 | kfree(motg); | ||
1655 | |||
1656 | return 0; | ||
1657 | } | ||
1658 | |||
1659 | #ifdef CONFIG_PM_RUNTIME | ||
1660 | static int msm_otg_runtime_idle(struct device *dev) | ||
1661 | { | ||
1662 | struct msm_otg *motg = dev_get_drvdata(dev); | ||
1663 | struct otg_transceiver *otg = &motg->otg; | ||
1664 | |||
1665 | dev_dbg(dev, "OTG runtime idle\n"); | ||
1666 | |||
1667 | /* | ||
1668 | * It is observed some times that a spurious interrupt | ||
1669 | * comes when PHY is put into LPM immediately after PHY reset. | ||
1670 | * This 1 sec delay also prevents entering into LPM immediately | ||
1671 | * after asynchronous interrupt. | ||
1672 | */ | ||
1673 | if (otg->state != OTG_STATE_UNDEFINED) | ||
1674 | pm_schedule_suspend(dev, 1000); | ||
1675 | |||
1676 | return -EAGAIN; | ||
1677 | } | ||
1678 | |||
1679 | static int msm_otg_runtime_suspend(struct device *dev) | ||
1680 | { | ||
1681 | struct msm_otg *motg = dev_get_drvdata(dev); | ||
1682 | |||
1683 | dev_dbg(dev, "OTG runtime suspend\n"); | ||
1684 | return msm_otg_suspend(motg); | ||
1685 | } | ||
1686 | |||
1687 | static int msm_otg_runtime_resume(struct device *dev) | ||
1688 | { | ||
1689 | struct msm_otg *motg = dev_get_drvdata(dev); | ||
1690 | |||
1691 | dev_dbg(dev, "OTG runtime resume\n"); | ||
1692 | return msm_otg_resume(motg); | ||
1693 | } | ||
1694 | #endif | ||
1695 | |||
1696 | #ifdef CONFIG_PM_SLEEP | ||
1697 | static int msm_otg_pm_suspend(struct device *dev) | ||
1698 | { | ||
1699 | struct msm_otg *motg = dev_get_drvdata(dev); | ||
1700 | |||
1701 | dev_dbg(dev, "OTG PM suspend\n"); | ||
1702 | return msm_otg_suspend(motg); | ||
1703 | } | ||
1704 | |||
1705 | static int msm_otg_pm_resume(struct device *dev) | ||
1706 | { | ||
1707 | struct msm_otg *motg = dev_get_drvdata(dev); | ||
1708 | int ret; | ||
1709 | |||
1710 | dev_dbg(dev, "OTG PM resume\n"); | ||
1711 | |||
1712 | ret = msm_otg_resume(motg); | ||
1713 | if (ret) | ||
1714 | return ret; | ||
1715 | |||
1716 | /* | ||
1717 | * Runtime PM Documentation recommends bringing the | ||
1718 | * device to full powered state upon resume. | ||
1719 | */ | ||
1720 | pm_runtime_disable(dev); | ||
1721 | pm_runtime_set_active(dev); | ||
1722 | pm_runtime_enable(dev); | ||
1723 | |||
1724 | return 0; | ||
1725 | } | ||
1726 | #endif | ||
1727 | |||
1728 | #ifdef CONFIG_PM | ||
1729 | static const struct dev_pm_ops msm_otg_dev_pm_ops = { | ||
1730 | SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume) | ||
1731 | SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume, | ||
1732 | msm_otg_runtime_idle) | ||
1733 | }; | ||
1734 | #endif | ||
1735 | |||
1736 | static struct platform_driver msm_otg_driver = { | ||
1737 | .remove = __devexit_p(msm_otg_remove), | ||
1738 | .driver = { | ||
1739 | .name = DRIVER_NAME, | ||
1740 | .owner = THIS_MODULE, | ||
1741 | #ifdef CONFIG_PM | ||
1742 | .pm = &msm_otg_dev_pm_ops, | ||
1743 | #endif | ||
1744 | }, | ||
1745 | }; | ||
1746 | |||
1747 | static int __init msm_otg_init(void) | ||
1748 | { | ||
1749 | return platform_driver_probe(&msm_otg_driver, msm_otg_probe); | ||
1750 | } | ||
1751 | |||
1752 | static void __exit msm_otg_exit(void) | ||
1753 | { | ||
1754 | platform_driver_unregister(&msm_otg_driver); | ||
1755 | } | ||
1756 | |||
1757 | module_init(msm_otg_init); | ||
1758 | module_exit(msm_otg_exit); | ||
1759 | |||
1760 | MODULE_LICENSE("GPL v2"); | ||
1761 | MODULE_DESCRIPTION("MSM USB transceiver driver"); | ||
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index e70014ab0976..c1e360046435 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c | |||
@@ -132,6 +132,8 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) | |||
132 | 132 | ||
133 | platform_set_drvdata(pdev, nop); | 133 | platform_set_drvdata(pdev, nop); |
134 | 134 | ||
135 | ATOMIC_INIT_NOTIFIER_HEAD(&nop->otg.notifier); | ||
136 | |||
135 | return 0; | 137 | return 0; |
136 | exit: | 138 | exit: |
137 | kfree(nop); | 139 | kfree(nop); |
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c index 0a43a7db750f..fb7adeff9ffa 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/otg/otg.c | |||
@@ -64,3 +64,38 @@ int otg_set_transceiver(struct otg_transceiver *x) | |||
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | EXPORT_SYMBOL(otg_set_transceiver); | 66 | EXPORT_SYMBOL(otg_set_transceiver); |
67 | |||
68 | const char *otg_state_string(enum usb_otg_state state) | ||
69 | { | ||
70 | switch (state) { | ||
71 | case OTG_STATE_A_IDLE: | ||
72 | return "a_idle"; | ||
73 | case OTG_STATE_A_WAIT_VRISE: | ||
74 | return "a_wait_vrise"; | ||
75 | case OTG_STATE_A_WAIT_BCON: | ||
76 | return "a_wait_bcon"; | ||
77 | case OTG_STATE_A_HOST: | ||
78 | return "a_host"; | ||
79 | case OTG_STATE_A_SUSPEND: | ||
80 | return "a_suspend"; | ||
81 | case OTG_STATE_A_PERIPHERAL: | ||
82 | return "a_peripheral"; | ||
83 | case OTG_STATE_A_WAIT_VFALL: | ||
84 | return "a_wait_vfall"; | ||
85 | case OTG_STATE_A_VBUS_ERR: | ||
86 | return "a_vbus_err"; | ||
87 | case OTG_STATE_B_IDLE: | ||
88 | return "b_idle"; | ||
89 | case OTG_STATE_B_SRP_INIT: | ||
90 | return "b_srp_init"; | ||
91 | case OTG_STATE_B_PERIPHERAL: | ||
92 | return "b_peripheral"; | ||
93 | case OTG_STATE_B_WAIT_ACON: | ||
94 | return "b_wait_acon"; | ||
95 | case OTG_STATE_B_HOST: | ||
96 | return "b_host"; | ||
97 | default: | ||
98 | return "UNDEFINED"; | ||
99 | } | ||
100 | } | ||
101 | EXPORT_SYMBOL(otg_state_string); | ||
diff --git a/drivers/usb/otg/otg_fsm.c b/drivers/usb/otg/otg_fsm.c new file mode 100644 index 000000000000..b0cc422f2ff9 --- /dev/null +++ b/drivers/usb/otg/otg_fsm.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | * OTG Finite State Machine from OTG spec | ||
3 | * | ||
4 | * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Li Yang <LeoLi@freescale.com> | ||
7 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/usb.h> | ||
29 | #include <linux/usb/gadget.h> | ||
30 | #include <linux/usb/otg.h> | ||
31 | #include <linux/types.h> | ||
32 | |||
33 | #include "otg_fsm.h" | ||
34 | |||
35 | /* Change USB protocol when there is a protocol change */ | ||
36 | static int otg_set_protocol(struct otg_fsm *fsm, int protocol) | ||
37 | { | ||
38 | int ret = 0; | ||
39 | |||
40 | if (fsm->protocol != protocol) { | ||
41 | VDBG("Changing role fsm->protocol= %d; new protocol= %d\n", | ||
42 | fsm->protocol, protocol); | ||
43 | /* stop old protocol */ | ||
44 | if (fsm->protocol == PROTO_HOST) | ||
45 | ret = fsm->ops->start_host(fsm, 0); | ||
46 | else if (fsm->protocol == PROTO_GADGET) | ||
47 | ret = fsm->ops->start_gadget(fsm, 0); | ||
48 | if (ret) | ||
49 | return ret; | ||
50 | |||
51 | /* start new protocol */ | ||
52 | if (protocol == PROTO_HOST) | ||
53 | ret = fsm->ops->start_host(fsm, 1); | ||
54 | else if (protocol == PROTO_GADGET) | ||
55 | ret = fsm->ops->start_gadget(fsm, 1); | ||
56 | if (ret) | ||
57 | return ret; | ||
58 | |||
59 | fsm->protocol = protocol; | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int state_changed; | ||
67 | |||
68 | /* Called when leaving a state. Do state clean up jobs here */ | ||
69 | void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state) | ||
70 | { | ||
71 | switch (old_state) { | ||
72 | case OTG_STATE_B_IDLE: | ||
73 | otg_del_timer(fsm, b_se0_srp_tmr); | ||
74 | fsm->b_se0_srp = 0; | ||
75 | break; | ||
76 | case OTG_STATE_B_SRP_INIT: | ||
77 | fsm->b_srp_done = 0; | ||
78 | break; | ||
79 | case OTG_STATE_B_PERIPHERAL: | ||
80 | break; | ||
81 | case OTG_STATE_B_WAIT_ACON: | ||
82 | otg_del_timer(fsm, b_ase0_brst_tmr); | ||
83 | fsm->b_ase0_brst_tmout = 0; | ||
84 | break; | ||
85 | case OTG_STATE_B_HOST: | ||
86 | break; | ||
87 | case OTG_STATE_A_IDLE: | ||
88 | break; | ||
89 | case OTG_STATE_A_WAIT_VRISE: | ||
90 | otg_del_timer(fsm, a_wait_vrise_tmr); | ||
91 | fsm->a_wait_vrise_tmout = 0; | ||
92 | break; | ||
93 | case OTG_STATE_A_WAIT_BCON: | ||
94 | otg_del_timer(fsm, a_wait_bcon_tmr); | ||
95 | fsm->a_wait_bcon_tmout = 0; | ||
96 | break; | ||
97 | case OTG_STATE_A_HOST: | ||
98 | otg_del_timer(fsm, a_wait_enum_tmr); | ||
99 | break; | ||
100 | case OTG_STATE_A_SUSPEND: | ||
101 | otg_del_timer(fsm, a_aidl_bdis_tmr); | ||
102 | fsm->a_aidl_bdis_tmout = 0; | ||
103 | fsm->a_suspend_req = 0; | ||
104 | break; | ||
105 | case OTG_STATE_A_PERIPHERAL: | ||
106 | break; | ||
107 | case OTG_STATE_A_WAIT_VFALL: | ||
108 | otg_del_timer(fsm, a_wait_vrise_tmr); | ||
109 | break; | ||
110 | case OTG_STATE_A_VBUS_ERR: | ||
111 | break; | ||
112 | default: | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | /* Called when entering a state */ | ||
118 | int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) | ||
119 | { | ||
120 | state_changed = 1; | ||
121 | if (fsm->transceiver->state == new_state) | ||
122 | return 0; | ||
123 | VDBG("Set state: %s\n", otg_state_string(new_state)); | ||
124 | otg_leave_state(fsm, fsm->transceiver->state); | ||
125 | switch (new_state) { | ||
126 | case OTG_STATE_B_IDLE: | ||
127 | otg_drv_vbus(fsm, 0); | ||
128 | otg_chrg_vbus(fsm, 0); | ||
129 | otg_loc_conn(fsm, 0); | ||
130 | otg_loc_sof(fsm, 0); | ||
131 | otg_set_protocol(fsm, PROTO_UNDEF); | ||
132 | otg_add_timer(fsm, b_se0_srp_tmr); | ||
133 | break; | ||
134 | case OTG_STATE_B_SRP_INIT: | ||
135 | otg_start_pulse(fsm); | ||
136 | otg_loc_sof(fsm, 0); | ||
137 | otg_set_protocol(fsm, PROTO_UNDEF); | ||
138 | otg_add_timer(fsm, b_srp_fail_tmr); | ||
139 | break; | ||
140 | case OTG_STATE_B_PERIPHERAL: | ||
141 | otg_chrg_vbus(fsm, 0); | ||
142 | otg_loc_conn(fsm, 1); | ||
143 | otg_loc_sof(fsm, 0); | ||
144 | otg_set_protocol(fsm, PROTO_GADGET); | ||
145 | break; | ||
146 | case OTG_STATE_B_WAIT_ACON: | ||
147 | otg_chrg_vbus(fsm, 0); | ||
148 | otg_loc_conn(fsm, 0); | ||
149 | otg_loc_sof(fsm, 0); | ||
150 | otg_set_protocol(fsm, PROTO_HOST); | ||
151 | otg_add_timer(fsm, b_ase0_brst_tmr); | ||
152 | fsm->a_bus_suspend = 0; | ||
153 | break; | ||
154 | case OTG_STATE_B_HOST: | ||
155 | otg_chrg_vbus(fsm, 0); | ||
156 | otg_loc_conn(fsm, 0); | ||
157 | otg_loc_sof(fsm, 1); | ||
158 | otg_set_protocol(fsm, PROTO_HOST); | ||
159 | usb_bus_start_enum(fsm->transceiver->host, | ||
160 | fsm->transceiver->host->otg_port); | ||
161 | break; | ||
162 | case OTG_STATE_A_IDLE: | ||
163 | otg_drv_vbus(fsm, 0); | ||
164 | otg_chrg_vbus(fsm, 0); | ||
165 | otg_loc_conn(fsm, 0); | ||
166 | otg_loc_sof(fsm, 0); | ||
167 | otg_set_protocol(fsm, PROTO_HOST); | ||
168 | break; | ||
169 | case OTG_STATE_A_WAIT_VRISE: | ||
170 | otg_drv_vbus(fsm, 1); | ||
171 | otg_loc_conn(fsm, 0); | ||
172 | otg_loc_sof(fsm, 0); | ||
173 | otg_set_protocol(fsm, PROTO_HOST); | ||
174 | otg_add_timer(fsm, a_wait_vrise_tmr); | ||
175 | break; | ||
176 | case OTG_STATE_A_WAIT_BCON: | ||
177 | otg_drv_vbus(fsm, 1); | ||
178 | otg_loc_conn(fsm, 0); | ||
179 | otg_loc_sof(fsm, 0); | ||
180 | otg_set_protocol(fsm, PROTO_HOST); | ||
181 | otg_add_timer(fsm, a_wait_bcon_tmr); | ||
182 | break; | ||
183 | case OTG_STATE_A_HOST: | ||
184 | otg_drv_vbus(fsm, 1); | ||
185 | otg_loc_conn(fsm, 0); | ||
186 | otg_loc_sof(fsm, 1); | ||
187 | otg_set_protocol(fsm, PROTO_HOST); | ||
188 | /* | ||
189 | * When HNP is triggered while a_bus_req = 0, a_host will | ||
190 | * suspend too fast to complete a_set_b_hnp_en | ||
191 | */ | ||
192 | if (!fsm->a_bus_req || fsm->a_suspend_req) | ||
193 | otg_add_timer(fsm, a_wait_enum_tmr); | ||
194 | break; | ||
195 | case OTG_STATE_A_SUSPEND: | ||
196 | otg_drv_vbus(fsm, 1); | ||
197 | otg_loc_conn(fsm, 0); | ||
198 | otg_loc_sof(fsm, 0); | ||
199 | otg_set_protocol(fsm, PROTO_HOST); | ||
200 | otg_add_timer(fsm, a_aidl_bdis_tmr); | ||
201 | |||
202 | break; | ||
203 | case OTG_STATE_A_PERIPHERAL: | ||
204 | otg_loc_conn(fsm, 1); | ||
205 | otg_loc_sof(fsm, 0); | ||
206 | otg_set_protocol(fsm, PROTO_GADGET); | ||
207 | otg_drv_vbus(fsm, 1); | ||
208 | break; | ||
209 | case OTG_STATE_A_WAIT_VFALL: | ||
210 | otg_drv_vbus(fsm, 0); | ||
211 | otg_loc_conn(fsm, 0); | ||
212 | otg_loc_sof(fsm, 0); | ||
213 | otg_set_protocol(fsm, PROTO_HOST); | ||
214 | break; | ||
215 | case OTG_STATE_A_VBUS_ERR: | ||
216 | otg_drv_vbus(fsm, 0); | ||
217 | otg_loc_conn(fsm, 0); | ||
218 | otg_loc_sof(fsm, 0); | ||
219 | otg_set_protocol(fsm, PROTO_UNDEF); | ||
220 | break; | ||
221 | default: | ||
222 | break; | ||
223 | } | ||
224 | |||
225 | fsm->transceiver->state = new_state; | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | /* State change judgement */ | ||
230 | int otg_statemachine(struct otg_fsm *fsm) | ||
231 | { | ||
232 | enum usb_otg_state state; | ||
233 | unsigned long flags; | ||
234 | |||
235 | spin_lock_irqsave(&fsm->lock, flags); | ||
236 | |||
237 | state = fsm->transceiver->state; | ||
238 | state_changed = 0; | ||
239 | /* State machine state change judgement */ | ||
240 | |||
241 | switch (state) { | ||
242 | case OTG_STATE_UNDEFINED: | ||
243 | VDBG("fsm->id = %d\n", fsm->id); | ||
244 | if (fsm->id) | ||
245 | otg_set_state(fsm, OTG_STATE_B_IDLE); | ||
246 | else | ||
247 | otg_set_state(fsm, OTG_STATE_A_IDLE); | ||
248 | break; | ||
249 | case OTG_STATE_B_IDLE: | ||
250 | if (!fsm->id) | ||
251 | otg_set_state(fsm, OTG_STATE_A_IDLE); | ||
252 | else if (fsm->b_sess_vld && fsm->transceiver->gadget) | ||
253 | otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); | ||
254 | else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp) | ||
255 | otg_set_state(fsm, OTG_STATE_B_SRP_INIT); | ||
256 | break; | ||
257 | case OTG_STATE_B_SRP_INIT: | ||
258 | if (!fsm->id || fsm->b_srp_done) | ||
259 | otg_set_state(fsm, OTG_STATE_B_IDLE); | ||
260 | break; | ||
261 | case OTG_STATE_B_PERIPHERAL: | ||
262 | if (!fsm->id || !fsm->b_sess_vld) | ||
263 | otg_set_state(fsm, OTG_STATE_B_IDLE); | ||
264 | else if (fsm->b_bus_req && fsm->transceiver-> | ||
265 | gadget->b_hnp_enable && fsm->a_bus_suspend) | ||
266 | otg_set_state(fsm, OTG_STATE_B_WAIT_ACON); | ||
267 | break; | ||
268 | case OTG_STATE_B_WAIT_ACON: | ||
269 | if (fsm->a_conn) | ||
270 | otg_set_state(fsm, OTG_STATE_B_HOST); | ||
271 | else if (!fsm->id || !fsm->b_sess_vld) | ||
272 | otg_set_state(fsm, OTG_STATE_B_IDLE); | ||
273 | else if (fsm->a_bus_resume || fsm->b_ase0_brst_tmout) { | ||
274 | fsm->b_ase0_brst_tmout = 0; | ||
275 | otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); | ||
276 | } | ||
277 | break; | ||
278 | case OTG_STATE_B_HOST: | ||
279 | if (!fsm->id || !fsm->b_sess_vld) | ||
280 | otg_set_state(fsm, OTG_STATE_B_IDLE); | ||
281 | else if (!fsm->b_bus_req || !fsm->a_conn) | ||
282 | otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); | ||
283 | break; | ||
284 | case OTG_STATE_A_IDLE: | ||
285 | if (fsm->id) | ||
286 | otg_set_state(fsm, OTG_STATE_B_IDLE); | ||
287 | else if (!fsm->a_bus_drop && (fsm->a_bus_req || fsm->a_srp_det)) | ||
288 | otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE); | ||
289 | break; | ||
290 | case OTG_STATE_A_WAIT_VRISE: | ||
291 | if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld || | ||
292 | fsm->a_wait_vrise_tmout) { | ||
293 | otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); | ||
294 | } | ||
295 | break; | ||
296 | case OTG_STATE_A_WAIT_BCON: | ||
297 | if (!fsm->a_vbus_vld) | ||
298 | otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); | ||
299 | else if (fsm->b_conn) | ||
300 | otg_set_state(fsm, OTG_STATE_A_HOST); | ||
301 | else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout) | ||
302 | otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); | ||
303 | break; | ||
304 | case OTG_STATE_A_HOST: | ||
305 | if ((!fsm->a_bus_req || fsm->a_suspend_req) && | ||
306 | fsm->transceiver->host->b_hnp_enable) | ||
307 | otg_set_state(fsm, OTG_STATE_A_SUSPEND); | ||
308 | else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop) | ||
309 | otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); | ||
310 | else if (!fsm->a_vbus_vld) | ||
311 | otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); | ||
312 | break; | ||
313 | case OTG_STATE_A_SUSPEND: | ||
314 | if (!fsm->b_conn && fsm->transceiver->host->b_hnp_enable) | ||
315 | otg_set_state(fsm, OTG_STATE_A_PERIPHERAL); | ||
316 | else if (!fsm->b_conn && !fsm->transceiver->host->b_hnp_enable) | ||
317 | otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); | ||
318 | else if (fsm->a_bus_req || fsm->b_bus_resume) | ||
319 | otg_set_state(fsm, OTG_STATE_A_HOST); | ||
320 | else if (fsm->id || fsm->a_bus_drop || fsm->a_aidl_bdis_tmout) | ||
321 | otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); | ||
322 | else if (!fsm->a_vbus_vld) | ||
323 | otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); | ||
324 | break; | ||
325 | case OTG_STATE_A_PERIPHERAL: | ||
326 | if (fsm->id || fsm->a_bus_drop) | ||
327 | otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); | ||
328 | else if (fsm->b_bus_suspend) | ||
329 | otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); | ||
330 | else if (!fsm->a_vbus_vld) | ||
331 | otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); | ||
332 | break; | ||
333 | case OTG_STATE_A_WAIT_VFALL: | ||
334 | if (fsm->id || fsm->a_bus_req || (!fsm->a_sess_vld && | ||
335 | !fsm->b_conn)) | ||
336 | otg_set_state(fsm, OTG_STATE_A_IDLE); | ||
337 | break; | ||
338 | case OTG_STATE_A_VBUS_ERR: | ||
339 | if (fsm->id || fsm->a_bus_drop || fsm->a_clr_err) | ||
340 | otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); | ||
341 | break; | ||
342 | default: | ||
343 | break; | ||
344 | } | ||
345 | spin_unlock_irqrestore(&fsm->lock, flags); | ||
346 | |||
347 | VDBG("quit statemachine, changed = %d\n", state_changed); | ||
348 | return state_changed; | ||
349 | } | ||
diff --git a/drivers/usb/otg/otg_fsm.h b/drivers/usb/otg/otg_fsm.h new file mode 100644 index 000000000000..0cecf1d593a0 --- /dev/null +++ b/drivers/usb/otg/otg_fsm.h | |||
@@ -0,0 +1,154 @@ | |||
1 | /* Copyright (C) 2007,2008 Freescale Semiconductor, Inc. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License as published by the | ||
5 | * Free Software Foundation; either version 2 of the License, or (at your | ||
6 | * option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along | ||
14 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
16 | */ | ||
17 | |||
18 | #undef DEBUG | ||
19 | #undef VERBOSE | ||
20 | |||
21 | #ifdef DEBUG | ||
22 | #define DBG(fmt, args...) printk(KERN_DEBUG "[%s] " fmt , \ | ||
23 | __func__, ## args) | ||
24 | #else | ||
25 | #define DBG(fmt, args...) do {} while (0) | ||
26 | #endif | ||
27 | |||
28 | #ifdef VERBOSE | ||
29 | #define VDBG DBG | ||
30 | #else | ||
31 | #define VDBG(stuff...) do {} while (0) | ||
32 | #endif | ||
33 | |||
34 | #ifdef VERBOSE | ||
35 | #define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__) | ||
36 | #else | ||
37 | #define MPC_LOC do {} while (0) | ||
38 | #endif | ||
39 | |||
40 | #define PROTO_UNDEF (0) | ||
41 | #define PROTO_HOST (1) | ||
42 | #define PROTO_GADGET (2) | ||
43 | |||
44 | /* OTG state machine according to the OTG spec */ | ||
45 | struct otg_fsm { | ||
46 | /* Input */ | ||
47 | int a_bus_resume; | ||
48 | int a_bus_suspend; | ||
49 | int a_conn; | ||
50 | int a_sess_vld; | ||
51 | int a_srp_det; | ||
52 | int a_vbus_vld; | ||
53 | int b_bus_resume; | ||
54 | int b_bus_suspend; | ||
55 | int b_conn; | ||
56 | int b_se0_srp; | ||
57 | int b_sess_end; | ||
58 | int b_sess_vld; | ||
59 | int id; | ||
60 | |||
61 | /* Internal variables */ | ||
62 | int a_set_b_hnp_en; | ||
63 | int b_srp_done; | ||
64 | int b_hnp_enable; | ||
65 | |||
66 | /* Timeout indicator for timers */ | ||
67 | int a_wait_vrise_tmout; | ||
68 | int a_wait_bcon_tmout; | ||
69 | int a_aidl_bdis_tmout; | ||
70 | int b_ase0_brst_tmout; | ||
71 | |||
72 | /* Informative variables */ | ||
73 | int a_bus_drop; | ||
74 | int a_bus_req; | ||
75 | int a_clr_err; | ||
76 | int a_suspend_req; | ||
77 | int b_bus_req; | ||
78 | |||
79 | /* Output */ | ||
80 | int drv_vbus; | ||
81 | int loc_conn; | ||
82 | int loc_sof; | ||
83 | |||
84 | struct otg_fsm_ops *ops; | ||
85 | struct otg_transceiver *transceiver; | ||
86 | |||
87 | /* Current usb protocol used: 0:undefine; 1:host; 2:client */ | ||
88 | int protocol; | ||
89 | spinlock_t lock; | ||
90 | }; | ||
91 | |||
92 | struct otg_fsm_ops { | ||
93 | void (*chrg_vbus)(int on); | ||
94 | void (*drv_vbus)(int on); | ||
95 | void (*loc_conn)(int on); | ||
96 | void (*loc_sof)(int on); | ||
97 | void (*start_pulse)(void); | ||
98 | void (*add_timer)(void *timer); | ||
99 | void (*del_timer)(void *timer); | ||
100 | int (*start_host)(struct otg_fsm *fsm, int on); | ||
101 | int (*start_gadget)(struct otg_fsm *fsm, int on); | ||
102 | }; | ||
103 | |||
104 | |||
105 | static inline void otg_chrg_vbus(struct otg_fsm *fsm, int on) | ||
106 | { | ||
107 | fsm->ops->chrg_vbus(on); | ||
108 | } | ||
109 | |||
110 | static inline void otg_drv_vbus(struct otg_fsm *fsm, int on) | ||
111 | { | ||
112 | if (fsm->drv_vbus != on) { | ||
113 | fsm->drv_vbus = on; | ||
114 | fsm->ops->drv_vbus(on); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static inline void otg_loc_conn(struct otg_fsm *fsm, int on) | ||
119 | { | ||
120 | if (fsm->loc_conn != on) { | ||
121 | fsm->loc_conn = on; | ||
122 | fsm->ops->loc_conn(on); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static inline void otg_loc_sof(struct otg_fsm *fsm, int on) | ||
127 | { | ||
128 | if (fsm->loc_sof != on) { | ||
129 | fsm->loc_sof = on; | ||
130 | fsm->ops->loc_sof(on); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static inline void otg_start_pulse(struct otg_fsm *fsm) | ||
135 | { | ||
136 | fsm->ops->start_pulse(); | ||
137 | } | ||
138 | |||
139 | static inline void otg_add_timer(struct otg_fsm *fsm, void *timer) | ||
140 | { | ||
141 | fsm->ops->add_timer(timer); | ||
142 | } | ||
143 | |||
144 | static inline void otg_del_timer(struct otg_fsm *fsm, void *timer) | ||
145 | { | ||
146 | fsm->ops->del_timer(timer); | ||
147 | } | ||
148 | |||
149 | int otg_statemachine(struct otg_fsm *fsm); | ||
150 | |||
151 | /* Defined by device specific driver, for different timer implementation */ | ||
152 | extern struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, | ||
153 | *a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_fail_tmr, | ||
154 | *a_wait_enum_tmr; | ||
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 0bc97698af15..efeb4d1517ff 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c | |||
@@ -124,7 +124,6 @@ | |||
124 | #define PHY_DPLL_CLK (1 << 0) | 124 | #define PHY_DPLL_CLK (1 << 0) |
125 | 125 | ||
126 | /* In module TWL4030_MODULE_PM_MASTER */ | 126 | /* In module TWL4030_MODULE_PM_MASTER */ |
127 | #define PROTECT_KEY 0x0E | ||
128 | #define STS_HW_CONDITIONS 0x0F | 127 | #define STS_HW_CONDITIONS 0x0F |
129 | 128 | ||
130 | /* In module TWL4030_MODULE_PM_RECEIVER */ | 129 | /* In module TWL4030_MODULE_PM_RECEIVER */ |
@@ -161,6 +160,7 @@ struct twl4030_usb { | |||
161 | 160 | ||
162 | int irq; | 161 | int irq; |
163 | u8 linkstat; | 162 | u8 linkstat; |
163 | bool vbus_supplied; | ||
164 | u8 asleep; | 164 | u8 asleep; |
165 | bool irq_enabled; | 165 | bool irq_enabled; |
166 | }; | 166 | }; |
@@ -251,6 +251,8 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) | |||
251 | int status; | 251 | int status; |
252 | int linkstat = USB_EVENT_NONE; | 252 | int linkstat = USB_EVENT_NONE; |
253 | 253 | ||
254 | twl->vbus_supplied = false; | ||
255 | |||
254 | /* | 256 | /* |
255 | * For ID/VBUS sensing, see manual section 15.4.8 ... | 257 | * For ID/VBUS sensing, see manual section 15.4.8 ... |
256 | * except when using only battery backup power, two | 258 | * except when using only battery backup power, two |
@@ -266,6 +268,9 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) | |||
266 | if (status < 0) | 268 | if (status < 0) |
267 | dev_err(twl->dev, "USB link status err %d\n", status); | 269 | dev_err(twl->dev, "USB link status err %d\n", status); |
268 | else if (status & (BIT(7) | BIT(2))) { | 270 | else if (status & (BIT(7) | BIT(2))) { |
271 | if (status & (BIT(7))) | ||
272 | twl->vbus_supplied = true; | ||
273 | |||
269 | if (status & BIT(2)) | 274 | if (status & BIT(2)) |
270 | linkstat = USB_EVENT_ID; | 275 | linkstat = USB_EVENT_ID; |
271 | else | 276 | else |
@@ -276,6 +281,8 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) | |||
276 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", | 281 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", |
277 | status, status, linkstat); | 282 | status, status, linkstat); |
278 | 283 | ||
284 | twl->otg.last_event = linkstat; | ||
285 | |||
279 | /* REVISIT this assumes host and peripheral controllers | 286 | /* REVISIT this assumes host and peripheral controllers |
280 | * are registered, and that both are active... | 287 | * are registered, and that both are active... |
281 | */ | 288 | */ |
@@ -418,8 +425,13 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) | |||
418 | static int twl4030_usb_ldo_init(struct twl4030_usb *twl) | 425 | static int twl4030_usb_ldo_init(struct twl4030_usb *twl) |
419 | { | 426 | { |
420 | /* Enable writing to power configuration registers */ | 427 | /* Enable writing to power configuration registers */ |
421 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); | 428 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, |
422 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); | 429 | TWL4030_PM_MASTER_KEY_CFG1, |
430 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
431 | |||
432 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, | ||
433 | TWL4030_PM_MASTER_KEY_CFG2, | ||
434 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
423 | 435 | ||
424 | /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/ | 436 | /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/ |
425 | /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/ | 437 | /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/ |
@@ -455,7 +467,8 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl) | |||
455 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); | 467 | twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); |
456 | 468 | ||
457 | /* disable access to power configuration registers */ | 469 | /* disable access to power configuration registers */ |
458 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); | 470 | twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, |
471 | TWL4030_PM_MASTER_PROTECT_KEY); | ||
459 | 472 | ||
460 | return 0; | 473 | return 0; |
461 | 474 | ||
@@ -477,7 +490,7 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev, | |||
477 | 490 | ||
478 | spin_lock_irqsave(&twl->lock, flags); | 491 | spin_lock_irqsave(&twl->lock, flags); |
479 | ret = sprintf(buf, "%s\n", | 492 | ret = sprintf(buf, "%s\n", |
480 | (twl->linkstat == USB_EVENT_VBUS) ? "on" : "off"); | 493 | twl->vbus_supplied ? "on" : "off"); |
481 | spin_unlock_irqrestore(&twl->lock, flags); | 494 | spin_unlock_irqrestore(&twl->lock, flags); |
482 | 495 | ||
483 | return ret; | 496 | return ret; |
@@ -507,7 +520,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
507 | else | 520 | else |
508 | twl4030_phy_resume(twl); | 521 | twl4030_phy_resume(twl); |
509 | 522 | ||
510 | blocking_notifier_call_chain(&twl->otg.notifier, status, | 523 | atomic_notifier_call_chain(&twl->otg.notifier, status, |
511 | twl->otg.gadget); | 524 | twl->otg.gadget); |
512 | } | 525 | } |
513 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); | 526 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); |
@@ -529,7 +542,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl) | |||
529 | twl->asleep = 0; | 542 | twl->asleep = 0; |
530 | } | 543 | } |
531 | 544 | ||
532 | blocking_notifier_call_chain(&twl->otg.notifier, status, | 545 | atomic_notifier_call_chain(&twl->otg.notifier, status, |
533 | twl->otg.gadget); | 546 | twl->otg.gadget); |
534 | } | 547 | } |
535 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); | 548 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); |
@@ -601,6 +614,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) | |||
601 | twl->otg.set_peripheral = twl4030_set_peripheral; | 614 | twl->otg.set_peripheral = twl4030_set_peripheral; |
602 | twl->otg.set_suspend = twl4030_set_suspend; | 615 | twl->otg.set_suspend = twl4030_set_suspend; |
603 | twl->usb_mode = pdata->usb_mode; | 616 | twl->usb_mode = pdata->usb_mode; |
617 | twl->vbus_supplied = false; | ||
604 | twl->asleep = 1; | 618 | twl->asleep = 1; |
605 | 619 | ||
606 | /* init spinlock for workqueue */ | 620 | /* init spinlock for workqueue */ |
@@ -618,7 +632,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) | |||
618 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | 632 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
619 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | 633 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
620 | 634 | ||
621 | BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier); | 635 | ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier); |
622 | 636 | ||
623 | /* Our job is to use irqs and status from the power module | 637 | /* Our job is to use irqs and status from the power module |
624 | * to keep the transceiver disabled when nothing's connected. | 638 | * to keep the transceiver disabled when nothing's connected. |
@@ -673,7 +687,8 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) | |||
673 | /* disable complete OTG block */ | 687 | /* disable complete OTG block */ |
674 | twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); | 688 | twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); |
675 | 689 | ||
676 | twl4030_phy_power(twl, 0); | 690 | if (!twl->asleep) |
691 | twl4030_phy_power(twl, 0); | ||
677 | regulator_put(twl->usb1v5); | 692 | regulator_put(twl->usb1v5); |
678 | regulator_put(twl->usb1v8); | 693 | regulator_put(twl->usb1v8); |
679 | regulator_put(twl->usb3v1); | 694 | 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..cfb5aa72b196 --- /dev/null +++ b/drivers/usb/otg/twl6030-usb.c | |||
@@ -0,0 +1,526 @@ | |||
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 | #include <linux/delay.h> | ||
35 | |||
36 | /* usb register definitions */ | ||
37 | #define USB_VENDOR_ID_LSB 0x00 | ||
38 | #define USB_VENDOR_ID_MSB 0x01 | ||
39 | #define USB_PRODUCT_ID_LSB 0x02 | ||
40 | #define USB_PRODUCT_ID_MSB 0x03 | ||
41 | #define USB_VBUS_CTRL_SET 0x04 | ||
42 | #define USB_VBUS_CTRL_CLR 0x05 | ||
43 | #define USB_ID_CTRL_SET 0x06 | ||
44 | #define USB_ID_CTRL_CLR 0x07 | ||
45 | #define USB_VBUS_INT_SRC 0x08 | ||
46 | #define USB_VBUS_INT_LATCH_SET 0x09 | ||
47 | #define USB_VBUS_INT_LATCH_CLR 0x0A | ||
48 | #define USB_VBUS_INT_EN_LO_SET 0x0B | ||
49 | #define USB_VBUS_INT_EN_LO_CLR 0x0C | ||
50 | #define USB_VBUS_INT_EN_HI_SET 0x0D | ||
51 | #define USB_VBUS_INT_EN_HI_CLR 0x0E | ||
52 | #define USB_ID_INT_SRC 0x0F | ||
53 | #define USB_ID_INT_LATCH_SET 0x10 | ||
54 | #define USB_ID_INT_LATCH_CLR 0x11 | ||
55 | |||
56 | #define USB_ID_INT_EN_LO_SET 0x12 | ||
57 | #define USB_ID_INT_EN_LO_CLR 0x13 | ||
58 | #define USB_ID_INT_EN_HI_SET 0x14 | ||
59 | #define USB_ID_INT_EN_HI_CLR 0x15 | ||
60 | #define USB_OTG_ADP_CTRL 0x16 | ||
61 | #define USB_OTG_ADP_HIGH 0x17 | ||
62 | #define USB_OTG_ADP_LOW 0x18 | ||
63 | #define USB_OTG_ADP_RISE 0x19 | ||
64 | #define USB_OTG_REVISION 0x1A | ||
65 | |||
66 | /* to be moved to LDO */ | ||
67 | #define TWL6030_MISC2 0xE5 | ||
68 | #define TWL6030_CFG_LDO_PD2 0xF5 | ||
69 | #define TWL6030_BACKUP_REG 0xFA | ||
70 | |||
71 | #define STS_HW_CONDITIONS 0x21 | ||
72 | |||
73 | /* In module TWL6030_MODULE_PM_MASTER */ | ||
74 | #define STS_HW_CONDITIONS 0x21 | ||
75 | #define STS_USB_ID BIT(2) | ||
76 | |||
77 | /* In module TWL6030_MODULE_PM_RECEIVER */ | ||
78 | #define VUSB_CFG_TRANS 0x71 | ||
79 | #define VUSB_CFG_STATE 0x72 | ||
80 | #define VUSB_CFG_VOLTAGE 0x73 | ||
81 | |||
82 | /* in module TWL6030_MODULE_MAIN_CHARGE */ | ||
83 | |||
84 | #define CHARGERUSB_CTRL1 0x8 | ||
85 | |||
86 | #define CONTROLLER_STAT1 0x03 | ||
87 | #define VBUS_DET BIT(2) | ||
88 | |||
89 | struct twl6030_usb { | ||
90 | struct otg_transceiver otg; | ||
91 | struct device *dev; | ||
92 | |||
93 | /* for vbus reporting with irqs disabled */ | ||
94 | spinlock_t lock; | ||
95 | |||
96 | struct regulator *usb3v3; | ||
97 | |||
98 | int irq1; | ||
99 | int irq2; | ||
100 | u8 linkstat; | ||
101 | u8 asleep; | ||
102 | bool irq_enabled; | ||
103 | unsigned long features; | ||
104 | }; | ||
105 | |||
106 | #define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg) | ||
107 | |||
108 | /*-------------------------------------------------------------------------*/ | ||
109 | |||
110 | static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module, | ||
111 | u8 data, u8 address) | ||
112 | { | ||
113 | int ret = 0; | ||
114 | |||
115 | ret = twl_i2c_write_u8(module, data, address); | ||
116 | if (ret < 0) | ||
117 | dev_err(twl->dev, | ||
118 | "Write[0x%x] Error %d\n", address, ret); | ||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address) | ||
123 | { | ||
124 | u8 data, ret = 0; | ||
125 | |||
126 | ret = twl_i2c_read_u8(module, &data, address); | ||
127 | if (ret >= 0) | ||
128 | ret = data; | ||
129 | else | ||
130 | dev_err(twl->dev, | ||
131 | "readb[0x%x,0x%x] Error %d\n", | ||
132 | module, address, ret); | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | /*-------------------------------------------------------------------------*/ | ||
137 | static int twl6030_set_phy_clk(struct otg_transceiver *x, int on) | ||
138 | { | ||
139 | struct twl6030_usb *twl; | ||
140 | struct device *dev; | ||
141 | struct twl4030_usb_data *pdata; | ||
142 | |||
143 | twl = xceiv_to_twl(x); | ||
144 | dev = twl->dev; | ||
145 | pdata = dev->platform_data; | ||
146 | |||
147 | pdata->phy_set_clock(twl->dev, on); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int twl6030_phy_init(struct otg_transceiver *x) | ||
153 | { | ||
154 | struct twl6030_usb *twl; | ||
155 | struct device *dev; | ||
156 | struct twl4030_usb_data *pdata; | ||
157 | |||
158 | twl = xceiv_to_twl(x); | ||
159 | dev = twl->dev; | ||
160 | pdata = dev->platform_data; | ||
161 | |||
162 | if (twl->linkstat == USB_EVENT_ID) | ||
163 | pdata->phy_power(twl->dev, 1, 1); | ||
164 | else | ||
165 | pdata->phy_power(twl->dev, 0, 1); | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static void twl6030_phy_shutdown(struct otg_transceiver *x) | ||
171 | { | ||
172 | struct twl6030_usb *twl; | ||
173 | struct device *dev; | ||
174 | struct twl4030_usb_data *pdata; | ||
175 | |||
176 | twl = xceiv_to_twl(x); | ||
177 | dev = twl->dev; | ||
178 | pdata = dev->platform_data; | ||
179 | pdata->phy_power(twl->dev, 0, 0); | ||
180 | } | ||
181 | |||
182 | static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend) | ||
183 | { | ||
184 | struct twl6030_usb *twl = xceiv_to_twl(x); | ||
185 | struct device *dev = twl->dev; | ||
186 | struct twl4030_usb_data *pdata = dev->platform_data; | ||
187 | |||
188 | pdata->phy_suspend(dev, suspend); | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int twl6030_start_srp(struct otg_transceiver *x) | ||
194 | { | ||
195 | struct twl6030_usb *twl = xceiv_to_twl(x); | ||
196 | |||
197 | twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET); | ||
198 | twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET); | ||
199 | |||
200 | mdelay(100); | ||
201 | twl6030_writeb(twl, TWL_MODULE_USB, 0xa0, USB_VBUS_CTRL_CLR); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int twl6030_usb_ldo_init(struct twl6030_usb *twl) | ||
207 | { | ||
208 | char *regulator_name; | ||
209 | |||
210 | if (twl->features & TWL6025_SUBCLASS) | ||
211 | regulator_name = "ldousb"; | ||
212 | else | ||
213 | regulator_name = "vusb"; | ||
214 | |||
215 | /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ | ||
216 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); | ||
217 | |||
218 | /* Program CFG_LDO_PD2 register and set VUSB bit */ | ||
219 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2); | ||
220 | |||
221 | /* Program MISC2 register and set bit VUSB_IN_VBAT */ | ||
222 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); | ||
223 | |||
224 | twl->usb3v3 = regulator_get(twl->dev, regulator_name); | ||
225 | if (IS_ERR(twl->usb3v3)) | ||
226 | return -ENODEV; | ||
227 | |||
228 | /* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */ | ||
229 | twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET); | ||
230 | |||
231 | /* | ||
232 | * Program the USB_ID_CTRL_SET register to enable GND drive | ||
233 | * and the ID comparators | ||
234 | */ | ||
235 | twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static ssize_t twl6030_usb_vbus_show(struct device *dev, | ||
241 | struct device_attribute *attr, char *buf) | ||
242 | { | ||
243 | struct twl6030_usb *twl = dev_get_drvdata(dev); | ||
244 | unsigned long flags; | ||
245 | int ret = -EINVAL; | ||
246 | |||
247 | spin_lock_irqsave(&twl->lock, flags); | ||
248 | |||
249 | switch (twl->linkstat) { | ||
250 | case USB_EVENT_VBUS: | ||
251 | ret = snprintf(buf, PAGE_SIZE, "vbus\n"); | ||
252 | break; | ||
253 | case USB_EVENT_ID: | ||
254 | ret = snprintf(buf, PAGE_SIZE, "id\n"); | ||
255 | break; | ||
256 | case USB_EVENT_NONE: | ||
257 | ret = snprintf(buf, PAGE_SIZE, "none\n"); | ||
258 | break; | ||
259 | default: | ||
260 | ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n"); | ||
261 | } | ||
262 | spin_unlock_irqrestore(&twl->lock, flags); | ||
263 | |||
264 | return ret; | ||
265 | } | ||
266 | static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL); | ||
267 | |||
268 | static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | ||
269 | { | ||
270 | struct twl6030_usb *twl = _twl; | ||
271 | int status; | ||
272 | u8 vbus_state, hw_state; | ||
273 | |||
274 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | ||
275 | |||
276 | vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE, | ||
277 | CONTROLLER_STAT1); | ||
278 | if (!(hw_state & STS_USB_ID)) { | ||
279 | if (vbus_state & VBUS_DET) { | ||
280 | regulator_enable(twl->usb3v3); | ||
281 | twl->asleep = 1; | ||
282 | status = USB_EVENT_VBUS; | ||
283 | twl->otg.default_a = false; | ||
284 | twl->otg.state = OTG_STATE_B_IDLE; | ||
285 | twl->linkstat = status; | ||
286 | twl->otg.last_event = status; | ||
287 | atomic_notifier_call_chain(&twl->otg.notifier, | ||
288 | status, twl->otg.gadget); | ||
289 | } else { | ||
290 | status = USB_EVENT_NONE; | ||
291 | twl->linkstat = status; | ||
292 | twl->otg.last_event = status; | ||
293 | atomic_notifier_call_chain(&twl->otg.notifier, | ||
294 | status, twl->otg.gadget); | ||
295 | if (twl->asleep) { | ||
296 | regulator_disable(twl->usb3v3); | ||
297 | twl->asleep = 0; | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); | ||
302 | |||
303 | return IRQ_HANDLED; | ||
304 | } | ||
305 | |||
306 | static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | ||
307 | { | ||
308 | struct twl6030_usb *twl = _twl; | ||
309 | int status = USB_EVENT_NONE; | ||
310 | u8 hw_state; | ||
311 | |||
312 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | ||
313 | |||
314 | if (hw_state & STS_USB_ID) { | ||
315 | |||
316 | regulator_enable(twl->usb3v3); | ||
317 | twl->asleep = 1; | ||
318 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1); | ||
319 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, | ||
320 | 0x10); | ||
321 | status = USB_EVENT_ID; | ||
322 | twl->otg.default_a = true; | ||
323 | twl->otg.state = OTG_STATE_A_IDLE; | ||
324 | twl->linkstat = status; | ||
325 | twl->otg.last_event = status; | ||
326 | atomic_notifier_call_chain(&twl->otg.notifier, status, | ||
327 | twl->otg.gadget); | ||
328 | } else { | ||
329 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, | ||
330 | 0x10); | ||
331 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, | ||
332 | 0x1); | ||
333 | } | ||
334 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status); | ||
335 | |||
336 | return IRQ_HANDLED; | ||
337 | } | ||
338 | |||
339 | static int twl6030_set_peripheral(struct otg_transceiver *x, | ||
340 | struct usb_gadget *gadget) | ||
341 | { | ||
342 | struct twl6030_usb *twl; | ||
343 | |||
344 | if (!x) | ||
345 | return -ENODEV; | ||
346 | |||
347 | twl = xceiv_to_twl(x); | ||
348 | twl->otg.gadget = gadget; | ||
349 | if (!gadget) | ||
350 | twl->otg.state = OTG_STATE_UNDEFINED; | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int twl6030_enable_irq(struct otg_transceiver *x) | ||
356 | { | ||
357 | struct twl6030_usb *twl = xceiv_to_twl(x); | ||
358 | |||
359 | twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1); | ||
360 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); | ||
361 | twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C); | ||
362 | |||
363 | twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, | ||
364 | REG_INT_MSK_LINE_C); | ||
365 | twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, | ||
366 | REG_INT_MSK_STS_C); | ||
367 | twl6030_usb_irq(twl->irq2, twl); | ||
368 | twl6030_usbotg_irq(twl->irq1, twl); | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) | ||
374 | { | ||
375 | struct twl6030_usb *twl = xceiv_to_twl(x); | ||
376 | |||
377 | /* | ||
378 | * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1 | ||
379 | * register. This enables boost mode. | ||
380 | */ | ||
381 | if (enabled) | ||
382 | twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40, | ||
383 | CHARGERUSB_CTRL1); | ||
384 | else | ||
385 | twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00, | ||
386 | CHARGERUSB_CTRL1); | ||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host) | ||
391 | { | ||
392 | struct twl6030_usb *twl; | ||
393 | |||
394 | if (!x) | ||
395 | return -ENODEV; | ||
396 | |||
397 | twl = xceiv_to_twl(x); | ||
398 | twl->otg.host = host; | ||
399 | if (!host) | ||
400 | twl->otg.state = OTG_STATE_UNDEFINED; | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static int __devinit twl6030_usb_probe(struct platform_device *pdev) | ||
405 | { | ||
406 | struct twl6030_usb *twl; | ||
407 | int status, err; | ||
408 | struct twl4030_usb_data *pdata; | ||
409 | struct device *dev = &pdev->dev; | ||
410 | pdata = dev->platform_data; | ||
411 | |||
412 | twl = kzalloc(sizeof *twl, GFP_KERNEL); | ||
413 | if (!twl) | ||
414 | return -ENOMEM; | ||
415 | |||
416 | twl->dev = &pdev->dev; | ||
417 | twl->irq1 = platform_get_irq(pdev, 0); | ||
418 | twl->irq2 = platform_get_irq(pdev, 1); | ||
419 | twl->features = pdata->features; | ||
420 | twl->otg.dev = twl->dev; | ||
421 | twl->otg.label = "twl6030"; | ||
422 | twl->otg.set_host = twl6030_set_host; | ||
423 | twl->otg.set_peripheral = twl6030_set_peripheral; | ||
424 | twl->otg.set_vbus = twl6030_set_vbus; | ||
425 | twl->otg.init = twl6030_phy_init; | ||
426 | twl->otg.shutdown = twl6030_phy_shutdown; | ||
427 | twl->otg.set_suspend = twl6030_phy_suspend; | ||
428 | twl->otg.start_srp = twl6030_start_srp; | ||
429 | |||
430 | /* init spinlock for workqueue */ | ||
431 | spin_lock_init(&twl->lock); | ||
432 | |||
433 | err = twl6030_usb_ldo_init(twl); | ||
434 | if (err) { | ||
435 | dev_err(&pdev->dev, "ldo init failed\n"); | ||
436 | kfree(twl); | ||
437 | return err; | ||
438 | } | ||
439 | otg_set_transceiver(&twl->otg); | ||
440 | |||
441 | platform_set_drvdata(pdev, twl); | ||
442 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | ||
443 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | ||
444 | |||
445 | ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier); | ||
446 | |||
447 | twl->irq_enabled = true; | ||
448 | status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, | ||
449 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
450 | "twl6030_usb", twl); | ||
451 | if (status < 0) { | ||
452 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
453 | twl->irq1, status); | ||
454 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
455 | kfree(twl); | ||
456 | return status; | ||
457 | } | ||
458 | |||
459 | status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq, | ||
460 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
461 | "twl6030_usb", twl); | ||
462 | if (status < 0) { | ||
463 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
464 | twl->irq2, status); | ||
465 | free_irq(twl->irq1, twl); | ||
466 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
467 | kfree(twl); | ||
468 | return status; | ||
469 | } | ||
470 | |||
471 | twl->asleep = 0; | ||
472 | pdata->phy_init(dev); | ||
473 | twl6030_phy_suspend(&twl->otg, 0); | ||
474 | twl6030_enable_irq(&twl->otg); | ||
475 | dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int __exit twl6030_usb_remove(struct platform_device *pdev) | ||
481 | { | ||
482 | struct twl6030_usb *twl = platform_get_drvdata(pdev); | ||
483 | |||
484 | struct twl4030_usb_data *pdata; | ||
485 | struct device *dev = &pdev->dev; | ||
486 | pdata = dev->platform_data; | ||
487 | |||
488 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, | ||
489 | REG_INT_MSK_LINE_C); | ||
490 | twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, | ||
491 | REG_INT_MSK_STS_C); | ||
492 | free_irq(twl->irq1, twl); | ||
493 | free_irq(twl->irq2, twl); | ||
494 | regulator_put(twl->usb3v3); | ||
495 | pdata->phy_exit(twl->dev); | ||
496 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
497 | kfree(twl); | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static struct platform_driver twl6030_usb_driver = { | ||
503 | .probe = twl6030_usb_probe, | ||
504 | .remove = __exit_p(twl6030_usb_remove), | ||
505 | .driver = { | ||
506 | .name = "twl6030_usb", | ||
507 | .owner = THIS_MODULE, | ||
508 | }, | ||
509 | }; | ||
510 | |||
511 | static int __init twl6030_usb_init(void) | ||
512 | { | ||
513 | return platform_driver_register(&twl6030_usb_driver); | ||
514 | } | ||
515 | subsys_initcall(twl6030_usb_init); | ||
516 | |||
517 | static void __exit twl6030_usb_exit(void) | ||
518 | { | ||
519 | platform_driver_unregister(&twl6030_usb_driver); | ||
520 | } | ||
521 | module_exit(twl6030_usb_exit); | ||
522 | |||
523 | MODULE_ALIAS("platform:twl6030_usb"); | ||
524 | MODULE_AUTHOR("Hema HK <hemahk@ti.com>"); | ||
525 | MODULE_DESCRIPTION("TWL6030 USB transceiver driver"); | ||
526 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index ccc81950822b..770d799d5afb 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c | |||
@@ -29,12 +29,23 @@ | |||
29 | #include <linux/usb/otg.h> | 29 | #include <linux/usb/otg.h> |
30 | #include <linux/usb/ulpi.h> | 30 | #include <linux/usb/ulpi.h> |
31 | 31 | ||
32 | |||
33 | struct ulpi_info { | ||
34 | unsigned int id; | ||
35 | char *name; | ||
36 | }; | ||
37 | |||
32 | #define ULPI_ID(vendor, product) (((vendor) << 16) | (product)) | 38 | #define ULPI_ID(vendor, product) (((vendor) << 16) | (product)) |
39 | #define ULPI_INFO(_id, _name) \ | ||
40 | { \ | ||
41 | .id = (_id), \ | ||
42 | .name = (_name), \ | ||
43 | } | ||
33 | 44 | ||
34 | /* ULPI hardcoded IDs, used for probing */ | 45 | /* ULPI hardcoded IDs, used for probing */ |
35 | static unsigned int ulpi_ids[] = { | 46 | static struct ulpi_info ulpi_ids[] = { |
36 | ULPI_ID(0x04cc, 0x1504), /* NXP ISP1504 */ | 47 | ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"), |
37 | ULPI_ID(0x0424, 0x0006), /* SMSC USB3319 */ | 48 | ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"), |
38 | }; | 49 | }; |
39 | 50 | ||
40 | static int ulpi_set_otg_flags(struct otg_transceiver *otg) | 51 | static int ulpi_set_otg_flags(struct otg_transceiver *otg) |
@@ -137,6 +148,32 @@ static int ulpi_set_flags(struct otg_transceiver *otg) | |||
137 | return ulpi_set_fc_flags(otg); | 148 | return ulpi_set_fc_flags(otg); |
138 | } | 149 | } |
139 | 150 | ||
151 | static int ulpi_check_integrity(struct otg_transceiver *otg) | ||
152 | { | ||
153 | int ret, i; | ||
154 | unsigned int val = 0x55; | ||
155 | |||
156 | for (i = 0; i < 2; i++) { | ||
157 | ret = otg_io_write(otg, val, ULPI_SCRATCH); | ||
158 | if (ret < 0) | ||
159 | return ret; | ||
160 | |||
161 | ret = otg_io_read(otg, ULPI_SCRATCH); | ||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | |||
165 | if (ret != val) { | ||
166 | pr_err("ULPI integrity check: failed!"); | ||
167 | return -ENODEV; | ||
168 | } | ||
169 | val = val << 1; | ||
170 | } | ||
171 | |||
172 | pr_info("ULPI integrity check: passed.\n"); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
140 | static int ulpi_init(struct otg_transceiver *otg) | 177 | static int ulpi_init(struct otg_transceiver *otg) |
141 | { | 178 | { |
142 | int i, vid, pid, ret; | 179 | int i, vid, pid, ret; |
@@ -153,12 +190,19 @@ static int ulpi_init(struct otg_transceiver *otg) | |||
153 | 190 | ||
154 | pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid); | 191 | pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid); |
155 | 192 | ||
156 | for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) | 193 | for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) { |
157 | if (ulpi_ids[i] == ULPI_ID(vid, pid)) | 194 | if (ulpi_ids[i].id == ULPI_ID(vid, pid)) { |
158 | return ulpi_set_flags(otg); | 195 | pr_info("Found %s ULPI transceiver.\n", |
196 | ulpi_ids[i].name); | ||
197 | break; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | ret = ulpi_check_integrity(otg); | ||
202 | if (ret) | ||
203 | return ret; | ||
159 | 204 | ||
160 | pr_err("ULPI ID does not match any known transceiver.\n"); | 205 | return ulpi_set_flags(otg); |
161 | return -ENODEV; | ||
162 | } | 206 | } |
163 | 207 | ||
164 | static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host) | 208 | static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host) |
diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/otg/ulpi_viewport.c new file mode 100644 index 000000000000..e9a37f90994f --- /dev/null +++ b/drivers/usb/otg/ulpi_viewport.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Google, Inc. | ||
3 | * | ||
4 | * This software is licensed under the terms of the GNU General Public | ||
5 | * License version 2, as published by the Free Software Foundation, and | ||
6 | * may be copied, distributed, and modified under those terms. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/usb.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/usb/otg.h> | ||
19 | #include <linux/usb/ulpi.h> | ||
20 | |||
21 | #define ULPI_VIEW_WAKEUP (1 << 31) | ||
22 | #define ULPI_VIEW_RUN (1 << 30) | ||
23 | #define ULPI_VIEW_WRITE (1 << 29) | ||
24 | #define ULPI_VIEW_READ (0 << 29) | ||
25 | #define ULPI_VIEW_ADDR(x) (((x) & 0xff) << 16) | ||
26 | #define ULPI_VIEW_DATA_READ(x) (((x) >> 8) & 0xff) | ||
27 | #define ULPI_VIEW_DATA_WRITE(x) ((x) & 0xff) | ||
28 | |||
29 | static int ulpi_viewport_wait(void __iomem *view, u32 mask) | ||
30 | { | ||
31 | unsigned long usec = 2000; | ||
32 | |||
33 | while (usec--) { | ||
34 | if (!(readl(view) & mask)) | ||
35 | return 0; | ||
36 | |||
37 | udelay(1); | ||
38 | }; | ||
39 | |||
40 | return -ETIMEDOUT; | ||
41 | } | ||
42 | |||
43 | static int ulpi_viewport_read(struct otg_transceiver *otg, u32 reg) | ||
44 | { | ||
45 | int ret; | ||
46 | void __iomem *view = otg->io_priv; | ||
47 | |||
48 | writel(ULPI_VIEW_WAKEUP | ULPI_VIEW_WRITE, view); | ||
49 | ret = ulpi_viewport_wait(view, ULPI_VIEW_WAKEUP); | ||
50 | if (ret) | ||
51 | return ret; | ||
52 | |||
53 | writel(ULPI_VIEW_RUN | ULPI_VIEW_READ | ULPI_VIEW_ADDR(reg), view); | ||
54 | ret = ulpi_viewport_wait(view, ULPI_VIEW_RUN); | ||
55 | if (ret) | ||
56 | return ret; | ||
57 | |||
58 | return ULPI_VIEW_DATA_READ(readl(view)); | ||
59 | } | ||
60 | |||
61 | static int ulpi_viewport_write(struct otg_transceiver *otg, u32 val, u32 reg) | ||
62 | { | ||
63 | int ret; | ||
64 | void __iomem *view = otg->io_priv; | ||
65 | |||
66 | writel(ULPI_VIEW_WAKEUP | ULPI_VIEW_WRITE, view); | ||
67 | ret = ulpi_viewport_wait(view, ULPI_VIEW_WAKEUP); | ||
68 | if (ret) | ||
69 | return ret; | ||
70 | |||
71 | writel(ULPI_VIEW_RUN | ULPI_VIEW_WRITE | ULPI_VIEW_DATA_WRITE(val) | | ||
72 | ULPI_VIEW_ADDR(reg), view); | ||
73 | |||
74 | return ulpi_viewport_wait(view, ULPI_VIEW_RUN); | ||
75 | } | ||
76 | |||
77 | struct otg_io_access_ops ulpi_viewport_access_ops = { | ||
78 | .read = ulpi_viewport_read, | ||
79 | .write = ulpi_viewport_write, | ||
80 | }; | ||