Commit 8e22978c57087aac4d88693278db1cc3e94f1253
Committed by
Greg Kroah-Hartman
1 parent
38dcdb3a7d
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
usb: chipidea: drop "13xxx" infix
"ci13xxx" is bad for at least the following reasons: * people often mistype it * it doesn't add any informational value to the names it's used in * it needlessly attracts mail filters This patch replaces it with "ci_hdrc", "ci_udc" or "ci_hw", depending on the situation. Modules with ci13xxx prefix are also renamed accordingly and aliases are added for compatibility. Otherwise, no functional changes. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 19 changed files with 739 additions and 738 deletions Inline Diff
- drivers/usb/chipidea/Makefile
- drivers/usb/chipidea/ci.h
- drivers/usb/chipidea/ci13xxx_imx.c
- drivers/usb/chipidea/ci13xxx_imx.h
- drivers/usb/chipidea/ci13xxx_msm.c
- drivers/usb/chipidea/ci13xxx_pci.c
- drivers/usb/chipidea/ci_hdrc_imx.c
- drivers/usb/chipidea/ci_hdrc_imx.h
- drivers/usb/chipidea/ci_hdrc_msm.c
- drivers/usb/chipidea/ci_hdrc_pci.c
- drivers/usb/chipidea/core.c
- drivers/usb/chipidea/debug.c
- drivers/usb/chipidea/debug.h
- drivers/usb/chipidea/host.c
- drivers/usb/chipidea/host.h
- drivers/usb/chipidea/udc.c
- drivers/usb/chipidea/udc.h
- drivers/usb/chipidea/usbmisc_imx.c
- include/linux/usb/chipidea.h
drivers/usb/chipidea/Makefile
1 | ccflags-$(CONFIG_USB_CHIPIDEA_DEBUG) := -DDEBUG | 1 | ccflags-$(CONFIG_USB_CHIPIDEA_DEBUG) := -DDEBUG |
2 | 2 | ||
3 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o | 3 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o |
4 | 4 | ||
5 | ci_hdrc-y := core.o | 5 | ci_hdrc-y := core.o |
6 | ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o | 6 | ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o |
7 | ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o | 7 | ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o |
8 | ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o | 8 | ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o |
9 | 9 | ||
10 | # Glue/Bridge layers go here | 10 | # Glue/Bridge layers go here |
11 | 11 | ||
12 | obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o | 12 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_msm.o |
13 | 13 | ||
14 | # PCI doesn't provide stubs, need to check | 14 | # PCI doesn't provide stubs, need to check |
15 | ifneq ($(CONFIG_PCI),) | 15 | ifneq ($(CONFIG_PCI),) |
16 | obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o | 16 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_pci.o |
17 | endif | 17 | endif |
18 | 18 | ||
19 | ifneq ($(CONFIG_OF_DEVICE),) | 19 | ifneq ($(CONFIG_OF_DEVICE),) |
20 | obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o usbmisc_imx.o | 20 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_imx.o usbmisc_imx.o |
21 | endif | 21 | endif |
22 | 22 |
drivers/usb/chipidea/ci.h
1 | /* | 1 | /* |
2 | * ci.h - common structures, functions, and macros of the ChipIdea driver | 2 | * ci.h - common structures, functions, and macros of the ChipIdea driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | 4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. |
5 | * | 5 | * |
6 | * Author: David Lopo | 6 | * Author: David Lopo |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #ifndef __DRIVERS_USB_CHIPIDEA_CI_H | 13 | #ifndef __DRIVERS_USB_CHIPIDEA_CI_H |
14 | #define __DRIVERS_USB_CHIPIDEA_CI_H | 14 | #define __DRIVERS_USB_CHIPIDEA_CI_H |
15 | 15 | ||
16 | #include <linux/list.h> | 16 | #include <linux/list.h> |
17 | #include <linux/irqreturn.h> | 17 | #include <linux/irqreturn.h> |
18 | #include <linux/usb.h> | 18 | #include <linux/usb.h> |
19 | #include <linux/usb/gadget.h> | 19 | #include <linux/usb/gadget.h> |
20 | 20 | ||
21 | /****************************************************************************** | 21 | /****************************************************************************** |
22 | * DEFINE | 22 | * DEFINE |
23 | *****************************************************************************/ | 23 | *****************************************************************************/ |
24 | #define TD_PAGE_COUNT 5 | 24 | #define TD_PAGE_COUNT 5 |
25 | #define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */ | 25 | #define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */ |
26 | #define ENDPT_MAX 32 | 26 | #define ENDPT_MAX 32 |
27 | 27 | ||
28 | /****************************************************************************** | 28 | /****************************************************************************** |
29 | * STRUCTURES | 29 | * STRUCTURES |
30 | *****************************************************************************/ | 30 | *****************************************************************************/ |
31 | /** | 31 | /** |
32 | * struct ci13xxx_ep - endpoint representation | 32 | * struct ci_hw_ep - endpoint representation |
33 | * @ep: endpoint structure for gadget drivers | 33 | * @ep: endpoint structure for gadget drivers |
34 | * @dir: endpoint direction (TX/RX) | 34 | * @dir: endpoint direction (TX/RX) |
35 | * @num: endpoint number | 35 | * @num: endpoint number |
36 | * @type: endpoint type | 36 | * @type: endpoint type |
37 | * @name: string description of the endpoint | 37 | * @name: string description of the endpoint |
38 | * @qh: queue head for this endpoint | 38 | * @qh: queue head for this endpoint |
39 | * @wedge: is the endpoint wedged | 39 | * @wedge: is the endpoint wedged |
40 | * @ci: pointer to the controller | 40 | * @ci: pointer to the controller |
41 | * @lock: pointer to controller's spinlock | 41 | * @lock: pointer to controller's spinlock |
42 | * @td_pool: pointer to controller's TD pool | 42 | * @td_pool: pointer to controller's TD pool |
43 | */ | 43 | */ |
44 | struct ci13xxx_ep { | 44 | struct ci_hw_ep { |
45 | struct usb_ep ep; | 45 | struct usb_ep ep; |
46 | u8 dir; | 46 | u8 dir; |
47 | u8 num; | 47 | u8 num; |
48 | u8 type; | 48 | u8 type; |
49 | char name[16]; | 49 | char name[16]; |
50 | struct { | 50 | struct { |
51 | struct list_head queue; | 51 | struct list_head queue; |
52 | struct ci13xxx_qh *ptr; | 52 | struct ci_hw_qh *ptr; |
53 | dma_addr_t dma; | 53 | dma_addr_t dma; |
54 | } qh; | 54 | } qh; |
55 | int wedge; | 55 | int wedge; |
56 | 56 | ||
57 | /* global resources */ | 57 | /* global resources */ |
58 | struct ci13xxx *ci; | 58 | struct ci_hdrc *ci; |
59 | spinlock_t *lock; | 59 | spinlock_t *lock; |
60 | struct dma_pool *td_pool; | 60 | struct dma_pool *td_pool; |
61 | struct td_node *pending_td; | 61 | struct td_node *pending_td; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | enum ci_role { | 64 | enum ci_role { |
65 | CI_ROLE_HOST = 0, | 65 | CI_ROLE_HOST = 0, |
66 | CI_ROLE_GADGET, | 66 | CI_ROLE_GADGET, |
67 | CI_ROLE_END, | 67 | CI_ROLE_END, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * struct ci_role_driver - host/gadget role driver | 71 | * struct ci_role_driver - host/gadget role driver |
72 | * start: start this role | 72 | * start: start this role |
73 | * stop: stop this role | 73 | * stop: stop this role |
74 | * irq: irq handler for this role | 74 | * irq: irq handler for this role |
75 | * name: role name string (host/gadget) | 75 | * name: role name string (host/gadget) |
76 | */ | 76 | */ |
77 | struct ci_role_driver { | 77 | struct ci_role_driver { |
78 | int (*start)(struct ci13xxx *); | 78 | int (*start)(struct ci_hdrc *); |
79 | void (*stop)(struct ci13xxx *); | 79 | void (*stop)(struct ci_hdrc *); |
80 | irqreturn_t (*irq)(struct ci13xxx *); | 80 | irqreturn_t (*irq)(struct ci_hdrc *); |
81 | const char *name; | 81 | const char *name; |
82 | }; | 82 | }; |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * struct hw_bank - hardware register mapping representation | 85 | * struct hw_bank - hardware register mapping representation |
86 | * @lpm: set if the device is LPM capable | 86 | * @lpm: set if the device is LPM capable |
87 | * @phys: physical address of the controller's registers | 87 | * @phys: physical address of the controller's registers |
88 | * @abs: absolute address of the beginning of register window | 88 | * @abs: absolute address of the beginning of register window |
89 | * @cap: capability registers | 89 | * @cap: capability registers |
90 | * @op: operational registers | 90 | * @op: operational registers |
91 | * @size: size of the register window | 91 | * @size: size of the register window |
92 | * @regmap: register lookup table | 92 | * @regmap: register lookup table |
93 | */ | 93 | */ |
94 | struct hw_bank { | 94 | struct hw_bank { |
95 | unsigned lpm; | 95 | unsigned lpm; |
96 | resource_size_t phys; | 96 | resource_size_t phys; |
97 | void __iomem *abs; | 97 | void __iomem *abs; |
98 | void __iomem *cap; | 98 | void __iomem *cap; |
99 | void __iomem *op; | 99 | void __iomem *op; |
100 | size_t size; | 100 | size_t size; |
101 | void __iomem **regmap; | 101 | void __iomem **regmap; |
102 | }; | 102 | }; |
103 | 103 | ||
104 | /** | 104 | /** |
105 | * struct ci13xxx - chipidea device representation | 105 | * struct ci_hdrc - chipidea device representation |
106 | * @dev: pointer to parent device | 106 | * @dev: pointer to parent device |
107 | * @lock: access synchronization | 107 | * @lock: access synchronization |
108 | * @hw_bank: hardware register mapping | 108 | * @hw_bank: hardware register mapping |
109 | * @irq: IRQ number | 109 | * @irq: IRQ number |
110 | * @roles: array of supported roles for this controller | 110 | * @roles: array of supported roles for this controller |
111 | * @role: current role | 111 | * @role: current role |
112 | * @is_otg: if the device is otg-capable | 112 | * @is_otg: if the device is otg-capable |
113 | * @work: work for role changing | 113 | * @work: work for role changing |
114 | * @wq: workqueue thread | 114 | * @wq: workqueue thread |
115 | * @qh_pool: allocation pool for queue heads | 115 | * @qh_pool: allocation pool for queue heads |
116 | * @td_pool: allocation pool for transfer descriptors | 116 | * @td_pool: allocation pool for transfer descriptors |
117 | * @gadget: device side representation for peripheral controller | 117 | * @gadget: device side representation for peripheral controller |
118 | * @driver: gadget driver | 118 | * @driver: gadget driver |
119 | * @hw_ep_max: total number of endpoints supported by hardware | 119 | * @hw_ep_max: total number of endpoints supported by hardware |
120 | * @ci13xxx_ep: array of endpoints | 120 | * @ci_hw_ep: array of endpoints |
121 | * @ep0_dir: ep0 direction | 121 | * @ep0_dir: ep0 direction |
122 | * @ep0out: pointer to ep0 OUT endpoint | 122 | * @ep0out: pointer to ep0 OUT endpoint |
123 | * @ep0in: pointer to ep0 IN endpoint | 123 | * @ep0in: pointer to ep0 IN endpoint |
124 | * @status: ep0 status request | 124 | * @status: ep0 status request |
125 | * @setaddr: if we should set the address on status completion | 125 | * @setaddr: if we should set the address on status completion |
126 | * @address: usb address received from the host | 126 | * @address: usb address received from the host |
127 | * @remote_wakeup: host-enabled remote wakeup | 127 | * @remote_wakeup: host-enabled remote wakeup |
128 | * @suspended: suspended by host | 128 | * @suspended: suspended by host |
129 | * @test_mode: the selected test mode | 129 | * @test_mode: the selected test mode |
130 | * @platdata: platform specific information supplied by parent device | 130 | * @platdata: platform specific information supplied by parent device |
131 | * @vbus_active: is VBUS active | 131 | * @vbus_active: is VBUS active |
132 | * @transceiver: pointer to USB PHY, if any | 132 | * @transceiver: pointer to USB PHY, if any |
133 | * @hcd: pointer to usb_hcd for ehci host driver | 133 | * @hcd: pointer to usb_hcd for ehci host driver |
134 | * @debugfs: root dentry for this controller in debugfs | 134 | * @debugfs: root dentry for this controller in debugfs |
135 | */ | 135 | */ |
136 | struct ci13xxx { | 136 | struct ci_hdrc { |
137 | struct device *dev; | 137 | struct device *dev; |
138 | spinlock_t lock; | 138 | spinlock_t lock; |
139 | struct hw_bank hw_bank; | 139 | struct hw_bank hw_bank; |
140 | int irq; | 140 | int irq; |
141 | struct ci_role_driver *roles[CI_ROLE_END]; | 141 | struct ci_role_driver *roles[CI_ROLE_END]; |
142 | enum ci_role role; | 142 | enum ci_role role; |
143 | bool is_otg; | 143 | bool is_otg; |
144 | struct work_struct work; | 144 | struct work_struct work; |
145 | struct workqueue_struct *wq; | 145 | struct workqueue_struct *wq; |
146 | 146 | ||
147 | struct dma_pool *qh_pool; | 147 | struct dma_pool *qh_pool; |
148 | struct dma_pool *td_pool; | 148 | struct dma_pool *td_pool; |
149 | 149 | ||
150 | struct usb_gadget gadget; | 150 | struct usb_gadget gadget; |
151 | struct usb_gadget_driver *driver; | 151 | struct usb_gadget_driver *driver; |
152 | unsigned hw_ep_max; | 152 | unsigned hw_ep_max; |
153 | struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; | 153 | struct ci_hw_ep ci_hw_ep[ENDPT_MAX]; |
154 | u32 ep0_dir; | 154 | u32 ep0_dir; |
155 | struct ci13xxx_ep *ep0out, *ep0in; | 155 | struct ci_hw_ep *ep0out, *ep0in; |
156 | 156 | ||
157 | struct usb_request *status; | 157 | struct usb_request *status; |
158 | bool setaddr; | 158 | bool setaddr; |
159 | u8 address; | 159 | u8 address; |
160 | u8 remote_wakeup; | 160 | u8 remote_wakeup; |
161 | u8 suspended; | 161 | u8 suspended; |
162 | u8 test_mode; | 162 | u8 test_mode; |
163 | 163 | ||
164 | struct ci13xxx_platform_data *platdata; | 164 | struct ci_hdrc_platform_data *platdata; |
165 | int vbus_active; | 165 | int vbus_active; |
166 | /* FIXME: some day, we'll not use global phy */ | 166 | /* FIXME: some day, we'll not use global phy */ |
167 | bool global_phy; | 167 | bool global_phy; |
168 | struct usb_phy *transceiver; | 168 | struct usb_phy *transceiver; |
169 | struct usb_hcd *hcd; | 169 | struct usb_hcd *hcd; |
170 | struct dentry *debugfs; | 170 | struct dentry *debugfs; |
171 | }; | 171 | }; |
172 | 172 | ||
173 | static inline struct ci_role_driver *ci_role(struct ci13xxx *ci) | 173 | static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci) |
174 | { | 174 | { |
175 | BUG_ON(ci->role >= CI_ROLE_END || !ci->roles[ci->role]); | 175 | BUG_ON(ci->role >= CI_ROLE_END || !ci->roles[ci->role]); |
176 | return ci->roles[ci->role]; | 176 | return ci->roles[ci->role]; |
177 | } | 177 | } |
178 | 178 | ||
179 | static inline int ci_role_start(struct ci13xxx *ci, enum ci_role role) | 179 | static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role) |
180 | { | 180 | { |
181 | int ret; | 181 | int ret; |
182 | 182 | ||
183 | if (role >= CI_ROLE_END) | 183 | if (role >= CI_ROLE_END) |
184 | return -EINVAL; | 184 | return -EINVAL; |
185 | 185 | ||
186 | if (!ci->roles[role]) | 186 | if (!ci->roles[role]) |
187 | return -ENXIO; | 187 | return -ENXIO; |
188 | 188 | ||
189 | ret = ci->roles[role]->start(ci); | 189 | ret = ci->roles[role]->start(ci); |
190 | if (!ret) | 190 | if (!ret) |
191 | ci->role = role; | 191 | ci->role = role; |
192 | return ret; | 192 | return ret; |
193 | } | 193 | } |
194 | 194 | ||
195 | static inline void ci_role_stop(struct ci13xxx *ci) | 195 | static inline void ci_role_stop(struct ci_hdrc *ci) |
196 | { | 196 | { |
197 | enum ci_role role = ci->role; | 197 | enum ci_role role = ci->role; |
198 | 198 | ||
199 | if (role == CI_ROLE_END) | 199 | if (role == CI_ROLE_END) |
200 | return; | 200 | return; |
201 | 201 | ||
202 | ci->role = CI_ROLE_END; | 202 | ci->role = CI_ROLE_END; |
203 | 203 | ||
204 | ci->roles[role]->stop(ci); | 204 | ci->roles[role]->stop(ci); |
205 | } | 205 | } |
206 | 206 | ||
207 | /****************************************************************************** | 207 | /****************************************************************************** |
208 | * REGISTERS | 208 | * REGISTERS |
209 | *****************************************************************************/ | 209 | *****************************************************************************/ |
210 | /* register size */ | 210 | /* register size */ |
211 | #define REG_BITS (32) | 211 | #define REG_BITS (32) |
212 | 212 | ||
213 | /* register indices */ | 213 | /* register indices */ |
214 | enum ci13xxx_regs { | 214 | enum ci_hw_regs { |
215 | CAP_CAPLENGTH, | 215 | CAP_CAPLENGTH, |
216 | CAP_HCCPARAMS, | 216 | CAP_HCCPARAMS, |
217 | CAP_DCCPARAMS, | 217 | CAP_DCCPARAMS, |
218 | CAP_TESTMODE, | 218 | CAP_TESTMODE, |
219 | CAP_LAST = CAP_TESTMODE, | 219 | CAP_LAST = CAP_TESTMODE, |
220 | OP_USBCMD, | 220 | OP_USBCMD, |
221 | OP_USBSTS, | 221 | OP_USBSTS, |
222 | OP_USBINTR, | 222 | OP_USBINTR, |
223 | OP_DEVICEADDR, | 223 | OP_DEVICEADDR, |
224 | OP_ENDPTLISTADDR, | 224 | OP_ENDPTLISTADDR, |
225 | OP_PORTSC, | 225 | OP_PORTSC, |
226 | OP_DEVLC, | 226 | OP_DEVLC, |
227 | OP_OTGSC, | 227 | OP_OTGSC, |
228 | OP_USBMODE, | 228 | OP_USBMODE, |
229 | OP_ENDPTSETUPSTAT, | 229 | OP_ENDPTSETUPSTAT, |
230 | OP_ENDPTPRIME, | 230 | OP_ENDPTPRIME, |
231 | OP_ENDPTFLUSH, | 231 | OP_ENDPTFLUSH, |
232 | OP_ENDPTSTAT, | 232 | OP_ENDPTSTAT, |
233 | OP_ENDPTCOMPLETE, | 233 | OP_ENDPTCOMPLETE, |
234 | OP_ENDPTCTRL, | 234 | OP_ENDPTCTRL, |
235 | /* endptctrl1..15 follow */ | 235 | /* endptctrl1..15 follow */ |
236 | OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2, | 236 | OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2, |
237 | }; | 237 | }; |
238 | 238 | ||
239 | /** | 239 | /** |
240 | * hw_read: reads from a hw register | 240 | * hw_read: reads from a hw register |
241 | * @reg: register index | 241 | * @reg: register index |
242 | * @mask: bitfield mask | 242 | * @mask: bitfield mask |
243 | * | 243 | * |
244 | * This function returns register contents | 244 | * This function returns register contents |
245 | */ | 245 | */ |
246 | static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask) | 246 | static inline u32 hw_read(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask) |
247 | { | 247 | { |
248 | return ioread32(ci->hw_bank.regmap[reg]) & mask; | 248 | return ioread32(ci->hw_bank.regmap[reg]) & mask; |
249 | } | 249 | } |
250 | 250 | ||
251 | /** | 251 | /** |
252 | * hw_write: writes to a hw register | 252 | * hw_write: writes to a hw register |
253 | * @reg: register index | 253 | * @reg: register index |
254 | * @mask: bitfield mask | 254 | * @mask: bitfield mask |
255 | * @data: new value | 255 | * @data: new value |
256 | */ | 256 | */ |
257 | static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg, | 257 | static inline void hw_write(struct ci_hdrc *ci, enum ci_hw_regs reg, |
258 | u32 mask, u32 data) | 258 | u32 mask, u32 data) |
259 | { | 259 | { |
260 | if (~mask) | 260 | if (~mask) |
261 | data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask) | 261 | data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask) |
262 | | (data & mask); | 262 | | (data & mask); |
263 | 263 | ||
264 | iowrite32(data, ci->hw_bank.regmap[reg]); | 264 | iowrite32(data, ci->hw_bank.regmap[reg]); |
265 | } | 265 | } |
266 | 266 | ||
267 | /** | 267 | /** |
268 | * hw_test_and_clear: tests & clears a hw register | 268 | * hw_test_and_clear: tests & clears a hw register |
269 | * @reg: register index | 269 | * @reg: register index |
270 | * @mask: bitfield mask | 270 | * @mask: bitfield mask |
271 | * | 271 | * |
272 | * This function returns register contents | 272 | * This function returns register contents |
273 | */ | 273 | */ |
274 | static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg, | 274 | static inline u32 hw_test_and_clear(struct ci_hdrc *ci, enum ci_hw_regs reg, |
275 | u32 mask) | 275 | u32 mask) |
276 | { | 276 | { |
277 | u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask; | 277 | u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask; |
278 | 278 | ||
279 | iowrite32(val, ci->hw_bank.regmap[reg]); | 279 | iowrite32(val, ci->hw_bank.regmap[reg]); |
280 | return val; | 280 | return val; |
281 | } | 281 | } |
282 | 282 | ||
283 | /** | 283 | /** |
284 | * hw_test_and_write: tests & writes a hw register | 284 | * hw_test_and_write: tests & writes a hw register |
285 | * @reg: register index | 285 | * @reg: register index |
286 | * @mask: bitfield mask | 286 | * @mask: bitfield mask |
287 | * @data: new value | 287 | * @data: new value |
288 | * | 288 | * |
289 | * This function returns register contents | 289 | * This function returns register contents |
290 | */ | 290 | */ |
291 | static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg, | 291 | static inline u32 hw_test_and_write(struct ci_hdrc *ci, enum ci_hw_regs reg, |
292 | u32 mask, u32 data) | 292 | u32 mask, u32 data) |
293 | { | 293 | { |
294 | u32 val = hw_read(ci, reg, ~0); | 294 | u32 val = hw_read(ci, reg, ~0); |
295 | 295 | ||
296 | hw_write(ci, reg, mask, data); | 296 | hw_write(ci, reg, mask, data); |
297 | return (val & mask) >> __ffs(mask); | 297 | return (val & mask) >> __ffs(mask); |
298 | } | 298 | } |
299 | 299 | ||
300 | int hw_device_reset(struct ci13xxx *ci, u32 mode); | 300 | int hw_device_reset(struct ci_hdrc *ci, u32 mode); |
301 | 301 | ||
302 | int hw_port_test_set(struct ci13xxx *ci, u8 mode); | 302 | int hw_port_test_set(struct ci_hdrc *ci, u8 mode); |
303 | 303 | ||
304 | u8 hw_port_test_get(struct ci13xxx *ci); | 304 | u8 hw_port_test_get(struct ci_hdrc *ci); |
305 | 305 | ||
306 | #endif /* __DRIVERS_USB_CHIPIDEA_CI_H */ | 306 | #endif /* __DRIVERS_USB_CHIPIDEA_CI_H */ |
307 | 307 |
drivers/usb/chipidea/ci13xxx_imx.c
1 | /* | File was deleted | |
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * Copyright (C) 2012 Marek Vasut <marex@denx.de> | ||
4 | * on behalf of DENX Software Engineering GmbH | ||
5 | * | ||
6 | * The code contained herein is licensed under the GNU General Public | ||
7 | * License. You may obtain a copy of the GNU General Public License | ||
8 | * Version 2 or later at the following locations: | ||
9 | * | ||
10 | * http://www.opensource.org/licenses/gpl-license.html | ||
11 | * http://www.gnu.org/copyleft/gpl.html | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/of_platform.h> | ||
16 | #include <linux/of_gpio.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/pm_runtime.h> | ||
19 | #include <linux/dma-mapping.h> | ||
20 | #include <linux/usb/chipidea.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/regulator/consumer.h> | ||
23 | |||
24 | #include "ci.h" | ||
25 | #include "ci13xxx_imx.h" | ||
26 | |||
27 | #define pdev_to_phy(pdev) \ | ||
28 | ((struct usb_phy *)platform_get_drvdata(pdev)) | ||
29 | |||
30 | struct ci13xxx_imx_data { | ||
31 | struct usb_phy *phy; | ||
32 | struct platform_device *ci_pdev; | ||
33 | struct clk *clk; | ||
34 | struct regulator *reg_vbus; | ||
35 | }; | ||
36 | |||
37 | static const struct usbmisc_ops *usbmisc_ops; | ||
38 | |||
39 | /* Common functions shared by usbmisc drivers */ | ||
40 | |||
41 | int usbmisc_set_ops(const struct usbmisc_ops *ops) | ||
42 | { | ||
43 | if (usbmisc_ops) | ||
44 | return -EBUSY; | ||
45 | |||
46 | usbmisc_ops = ops; | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | EXPORT_SYMBOL_GPL(usbmisc_set_ops); | ||
51 | |||
52 | void usbmisc_unset_ops(const struct usbmisc_ops *ops) | ||
53 | { | ||
54 | usbmisc_ops = NULL; | ||
55 | } | ||
56 | EXPORT_SYMBOL_GPL(usbmisc_unset_ops); | ||
57 | |||
58 | int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev) | ||
59 | { | ||
60 | struct device_node *np = dev->of_node; | ||
61 | struct of_phandle_args args; | ||
62 | int ret; | ||
63 | |||
64 | usbdev->dev = dev; | ||
65 | |||
66 | ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells", | ||
67 | 0, &args); | ||
68 | if (ret) { | ||
69 | dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n", | ||
70 | ret); | ||
71 | memset(usbdev, 0, sizeof(*usbdev)); | ||
72 | return ret; | ||
73 | } | ||
74 | usbdev->index = args.args[0]; | ||
75 | of_node_put(args.np); | ||
76 | |||
77 | if (of_find_property(np, "disable-over-current", NULL)) | ||
78 | usbdev->disable_oc = 1; | ||
79 | |||
80 | if (of_find_property(np, "external-vbus-divider", NULL)) | ||
81 | usbdev->evdo = 1; | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | EXPORT_SYMBOL_GPL(usbmisc_get_init_data); | ||
86 | |||
87 | /* End of common functions shared by usbmisc drivers*/ | ||
88 | |||
89 | static int ci13xxx_imx_probe(struct platform_device *pdev) | ||
90 | { | ||
91 | struct ci13xxx_imx_data *data; | ||
92 | struct ci13xxx_platform_data pdata = { | ||
93 | .name = "ci13xxx_imx", | ||
94 | .capoffset = DEF_CAPOFFSET, | ||
95 | .flags = CI13XXX_REQUIRE_TRANSCEIVER | | ||
96 | CI13XXX_PULLUP_ON_VBUS | | ||
97 | CI13XXX_DISABLE_STREAMING, | ||
98 | }; | ||
99 | struct resource *res; | ||
100 | int ret; | ||
101 | struct usb_phy *phy; | ||
102 | |||
103 | if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL) | ||
104 | && !usbmisc_ops) | ||
105 | return -EPROBE_DEFER; | ||
106 | |||
107 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
108 | if (!data) { | ||
109 | dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n"); | ||
110 | return -ENOMEM; | ||
111 | } | ||
112 | |||
113 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
114 | if (!res) { | ||
115 | dev_err(&pdev->dev, "Can't get device resources!\n"); | ||
116 | return -ENOENT; | ||
117 | } | ||
118 | |||
119 | data->clk = devm_clk_get(&pdev->dev, NULL); | ||
120 | if (IS_ERR(data->clk)) { | ||
121 | dev_err(&pdev->dev, | ||
122 | "Failed to get clock, err=%ld\n", PTR_ERR(data->clk)); | ||
123 | return PTR_ERR(data->clk); | ||
124 | } | ||
125 | |||
126 | ret = clk_prepare_enable(data->clk); | ||
127 | if (ret) { | ||
128 | dev_err(&pdev->dev, | ||
129 | "Failed to prepare or enable clock, err=%d\n", ret); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); | ||
134 | if (!IS_ERR(phy)) { | ||
135 | ret = usb_phy_init(phy); | ||
136 | if (ret) { | ||
137 | dev_err(&pdev->dev, "unable to init phy: %d\n", ret); | ||
138 | goto err_clk; | ||
139 | } | ||
140 | } else if (PTR_ERR(phy) == -EPROBE_DEFER) { | ||
141 | ret = -EPROBE_DEFER; | ||
142 | goto err_clk; | ||
143 | } | ||
144 | |||
145 | /* we only support host now, so enable vbus here */ | ||
146 | data->reg_vbus = devm_regulator_get(&pdev->dev, "vbus"); | ||
147 | if (!IS_ERR(data->reg_vbus)) { | ||
148 | ret = regulator_enable(data->reg_vbus); | ||
149 | if (ret) { | ||
150 | dev_err(&pdev->dev, | ||
151 | "Failed to enable vbus regulator, err=%d\n", | ||
152 | ret); | ||
153 | goto err_clk; | ||
154 | } | ||
155 | } else { | ||
156 | data->reg_vbus = NULL; | ||
157 | } | ||
158 | |||
159 | pdata.phy = data->phy; | ||
160 | |||
161 | if (!pdev->dev.dma_mask) | ||
162 | pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; | ||
163 | if (!pdev->dev.coherent_dma_mask) | ||
164 | pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
165 | |||
166 | if (usbmisc_ops && usbmisc_ops->init) { | ||
167 | ret = usbmisc_ops->init(&pdev->dev); | ||
168 | if (ret) { | ||
169 | dev_err(&pdev->dev, | ||
170 | "usbmisc init failed, ret=%d\n", ret); | ||
171 | goto err; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | data->ci_pdev = ci13xxx_add_device(&pdev->dev, | ||
176 | pdev->resource, pdev->num_resources, | ||
177 | &pdata); | ||
178 | if (IS_ERR(data->ci_pdev)) { | ||
179 | ret = PTR_ERR(data->ci_pdev); | ||
180 | dev_err(&pdev->dev, | ||
181 | "Can't register ci_hdrc platform device, err=%d\n", | ||
182 | ret); | ||
183 | goto err; | ||
184 | } | ||
185 | |||
186 | if (usbmisc_ops && usbmisc_ops->post) { | ||
187 | ret = usbmisc_ops->post(&pdev->dev); | ||
188 | if (ret) { | ||
189 | dev_err(&pdev->dev, | ||
190 | "usbmisc post failed, ret=%d\n", ret); | ||
191 | goto disable_device; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | platform_set_drvdata(pdev, data); | ||
196 | |||
197 | pm_runtime_no_callbacks(&pdev->dev); | ||
198 | pm_runtime_enable(&pdev->dev); | ||
199 | |||
200 | return 0; | ||
201 | |||
202 | disable_device: | ||
203 | ci13xxx_remove_device(data->ci_pdev); | ||
204 | err: | ||
205 | if (data->reg_vbus) | ||
206 | regulator_disable(data->reg_vbus); | ||
207 | err_clk: | ||
208 | clk_disable_unprepare(data->clk); | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | static int ci13xxx_imx_remove(struct platform_device *pdev) | ||
213 | { | ||
214 | struct ci13xxx_imx_data *data = platform_get_drvdata(pdev); | ||
215 | |||
216 | pm_runtime_disable(&pdev->dev); | ||
217 | ci13xxx_remove_device(data->ci_pdev); | ||
218 | |||
219 | if (data->reg_vbus) | ||
220 | regulator_disable(data->reg_vbus); | ||
221 | |||
222 | if (data->phy) { | ||
223 | usb_phy_shutdown(data->phy); | ||
224 | module_put(data->phy->dev->driver->owner); | ||
225 | } | ||
226 | |||
227 | clk_disable_unprepare(data->clk); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static const struct of_device_id ci13xxx_imx_dt_ids[] = { | ||
233 | { .compatible = "fsl,imx27-usb", }, | ||
234 | { /* sentinel */ } | ||
235 | }; | ||
236 | MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids); | ||
237 | |||
238 | static struct platform_driver ci13xxx_imx_driver = { | ||
239 | .probe = ci13xxx_imx_probe, | ||
240 | .remove = ci13xxx_imx_remove, | ||
241 | .driver = { | ||
242 | .name = "imx_usb", | ||
243 | .owner = THIS_MODULE, | ||
244 | .of_match_table = ci13xxx_imx_dt_ids, | ||
245 | }, | ||
246 | }; | ||
247 | |||
248 | module_platform_driver(ci13xxx_imx_driver); | ||
249 | |||
250 | MODULE_ALIAS("platform:imx-usb"); | ||
251 | MODULE_LICENSE("GPL v2"); | ||
252 | MODULE_DESCRIPTION("CI13xxx i.MX USB binding"); | ||
253 | MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); | ||
254 | MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); | ||
255 | 1 | /* |
drivers/usb/chipidea/ci13xxx_imx.h
1 | /* | File was deleted | |
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | /* Used to set SoC specific callbacks */ | ||
13 | struct usbmisc_ops { | ||
14 | /* It's called once when probe a usb device */ | ||
15 | int (*init)(struct device *dev); | ||
16 | /* It's called once after adding a usb device */ | ||
17 | int (*post)(struct device *dev); | ||
18 | }; | ||
19 | |||
20 | struct usbmisc_usb_device { | ||
21 | struct device *dev; /* usb controller device */ | ||
22 | int index; | ||
23 | |||
24 | unsigned int disable_oc:1; /* over current detect disabled */ | ||
25 | unsigned int evdo:1; /* set external vbus divider option */ | ||
26 | }; | ||
27 | |||
28 | int usbmisc_set_ops(const struct usbmisc_ops *ops); | ||
29 | void usbmisc_unset_ops(const struct usbmisc_ops *ops); | ||
30 | int | ||
31 | usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev); | ||
32 | 1 | /* |
drivers/usb/chipidea/ci13xxx_msm.c
1 | /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. | File was deleted | |
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/platform_device.h> | ||
10 | #include <linux/pm_runtime.h> | ||
11 | #include <linux/usb/msm_hsusb_hw.h> | ||
12 | #include <linux/usb/ulpi.h> | ||
13 | #include <linux/usb/gadget.h> | ||
14 | #include <linux/usb/chipidea.h> | ||
15 | |||
16 | #include "ci.h" | ||
17 | |||
18 | #define MSM_USB_BASE (ci->hw_bank.abs) | ||
19 | |||
20 | static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event) | ||
21 | { | ||
22 | struct device *dev = ci->gadget.dev.parent; | ||
23 | int val; | ||
24 | |||
25 | switch (event) { | ||
26 | case CI13XXX_CONTROLLER_RESET_EVENT: | ||
27 | dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n"); | ||
28 | writel(0, USB_AHBBURST); | ||
29 | writel(0, USB_AHBMODE); | ||
30 | break; | ||
31 | case CI13XXX_CONTROLLER_STOPPED_EVENT: | ||
32 | dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n"); | ||
33 | /* | ||
34 | * Put the transceiver in non-driving mode. Otherwise host | ||
35 | * may not detect soft-disconnection. | ||
36 | */ | ||
37 | val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL); | ||
38 | val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; | ||
39 | val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; | ||
40 | usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL); | ||
41 | break; | ||
42 | default: | ||
43 | dev_dbg(dev, "unknown ci13xxx event\n"); | ||
44 | break; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | static struct ci13xxx_platform_data ci13xxx_msm_platdata = { | ||
49 | .name = "ci13xxx_msm", | ||
50 | .flags = CI13XXX_REGS_SHARED | | ||
51 | CI13XXX_REQUIRE_TRANSCEIVER | | ||
52 | CI13XXX_PULLUP_ON_VBUS | | ||
53 | CI13XXX_DISABLE_STREAMING, | ||
54 | |||
55 | .notify_event = ci13xxx_msm_notify_event, | ||
56 | }; | ||
57 | |||
58 | static int ci13xxx_msm_probe(struct platform_device *pdev) | ||
59 | { | ||
60 | struct platform_device *plat_ci; | ||
61 | |||
62 | dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n"); | ||
63 | |||
64 | plat_ci = ci13xxx_add_device(&pdev->dev, | ||
65 | pdev->resource, pdev->num_resources, | ||
66 | &ci13xxx_msm_platdata); | ||
67 | if (IS_ERR(plat_ci)) { | ||
68 | dev_err(&pdev->dev, "ci13xxx_add_device failed!\n"); | ||
69 | return PTR_ERR(plat_ci); | ||
70 | } | ||
71 | |||
72 | platform_set_drvdata(pdev, plat_ci); | ||
73 | |||
74 | pm_runtime_no_callbacks(&pdev->dev); | ||
75 | pm_runtime_enable(&pdev->dev); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int ci13xxx_msm_remove(struct platform_device *pdev) | ||
81 | { | ||
82 | struct platform_device *plat_ci = platform_get_drvdata(pdev); | ||
83 | |||
84 | pm_runtime_disable(&pdev->dev); | ||
85 | ci13xxx_remove_device(plat_ci); | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static struct platform_driver ci13xxx_msm_driver = { | ||
91 | .probe = ci13xxx_msm_probe, | ||
92 | .remove = ci13xxx_msm_remove, | ||
93 | .driver = { .name = "msm_hsusb", }, | ||
94 | }; | ||
95 | |||
96 | module_platform_driver(ci13xxx_msm_driver); | ||
97 | |||
98 | MODULE_ALIAS("platform:msm_hsusb"); | ||
99 | MODULE_LICENSE("GPL v2"); | ||
100 | 1 | /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. |
drivers/usb/chipidea/ci13xxx_pci.c
1 | /* | File was deleted | |
2 | * ci13xxx_pci.c - MIPS USB IP core family device controller | ||
3 | * | ||
4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | ||
5 | * | ||
6 | * Author: David Lopo | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/usb/gadget.h> | ||
18 | #include <linux/usb/chipidea.h> | ||
19 | |||
20 | /* driver name */ | ||
21 | #define UDC_DRIVER_NAME "ci13xxx_pci" | ||
22 | |||
23 | /****************************************************************************** | ||
24 | * PCI block | ||
25 | *****************************************************************************/ | ||
26 | static struct ci13xxx_platform_data pci_platdata = { | ||
27 | .name = UDC_DRIVER_NAME, | ||
28 | .capoffset = DEF_CAPOFFSET, | ||
29 | }; | ||
30 | |||
31 | static struct ci13xxx_platform_data langwell_pci_platdata = { | ||
32 | .name = UDC_DRIVER_NAME, | ||
33 | .capoffset = 0, | ||
34 | }; | ||
35 | |||
36 | static struct ci13xxx_platform_data penwell_pci_platdata = { | ||
37 | .name = UDC_DRIVER_NAME, | ||
38 | .capoffset = 0, | ||
39 | .power_budget = 200, | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * ci13xxx_pci_probe: PCI probe | ||
44 | * @pdev: USB device controller being probed | ||
45 | * @id: PCI hotplug ID connecting controller to UDC framework | ||
46 | * | ||
47 | * This function returns an error code | ||
48 | * Allocates basic PCI resources for this USB device controller, and then | ||
49 | * invokes the udc_probe() method to start the UDC associated with it | ||
50 | */ | ||
51 | static int ci13xxx_pci_probe(struct pci_dev *pdev, | ||
52 | const struct pci_device_id *id) | ||
53 | { | ||
54 | struct ci13xxx_platform_data *platdata = (void *)id->driver_data; | ||
55 | struct platform_device *plat_ci; | ||
56 | struct resource res[3]; | ||
57 | int retval = 0, nres = 2; | ||
58 | |||
59 | if (!platdata) { | ||
60 | dev_err(&pdev->dev, "device doesn't provide driver data\n"); | ||
61 | return -ENODEV; | ||
62 | } | ||
63 | |||
64 | retval = pcim_enable_device(pdev); | ||
65 | if (retval) | ||
66 | return retval; | ||
67 | |||
68 | if (!pdev->irq) { | ||
69 | dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); | ||
70 | return -ENODEV; | ||
71 | } | ||
72 | |||
73 | pci_set_master(pdev); | ||
74 | pci_try_set_mwi(pdev); | ||
75 | |||
76 | memset(res, 0, sizeof(res)); | ||
77 | res[0].start = pci_resource_start(pdev, 0); | ||
78 | res[0].end = pci_resource_end(pdev, 0); | ||
79 | res[0].flags = IORESOURCE_MEM; | ||
80 | res[1].start = pdev->irq; | ||
81 | res[1].flags = IORESOURCE_IRQ; | ||
82 | |||
83 | plat_ci = ci13xxx_add_device(&pdev->dev, res, nres, platdata); | ||
84 | if (IS_ERR(plat_ci)) { | ||
85 | dev_err(&pdev->dev, "ci13xxx_add_device failed!\n"); | ||
86 | return PTR_ERR(plat_ci); | ||
87 | } | ||
88 | |||
89 | pci_set_drvdata(pdev, plat_ci); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * ci13xxx_pci_remove: PCI remove | ||
96 | * @pdev: USB Device Controller being removed | ||
97 | * | ||
98 | * Reverses the effect of ci13xxx_pci_probe(), | ||
99 | * first invoking the udc_remove() and then releases | ||
100 | * all PCI resources allocated for this USB device controller | ||
101 | */ | ||
102 | static void ci13xxx_pci_remove(struct pci_dev *pdev) | ||
103 | { | ||
104 | struct platform_device *plat_ci = pci_get_drvdata(pdev); | ||
105 | |||
106 | ci13xxx_remove_device(plat_ci); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * PCI device table | ||
111 | * PCI device structure | ||
112 | * | ||
113 | * Check "pci.h" for details | ||
114 | */ | ||
115 | static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { | ||
116 | { | ||
117 | PCI_DEVICE(0x153F, 0x1004), | ||
118 | .driver_data = (kernel_ulong_t)&pci_platdata, | ||
119 | }, | ||
120 | { | ||
121 | PCI_DEVICE(0x153F, 0x1006), | ||
122 | .driver_data = (kernel_ulong_t)&pci_platdata, | ||
123 | }, | ||
124 | { | ||
125 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811), | ||
126 | .driver_data = (kernel_ulong_t)&langwell_pci_platdata, | ||
127 | }, | ||
128 | { | ||
129 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829), | ||
130 | .driver_data = (kernel_ulong_t)&penwell_pci_platdata, | ||
131 | }, | ||
132 | { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } | ||
133 | }; | ||
134 | MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table); | ||
135 | |||
136 | static struct pci_driver ci13xxx_pci_driver = { | ||
137 | .name = UDC_DRIVER_NAME, | ||
138 | .id_table = ci13xxx_pci_id_table, | ||
139 | .probe = ci13xxx_pci_probe, | ||
140 | .remove = ci13xxx_pci_remove, | ||
141 | }; | ||
142 | |||
143 | module_pci_driver(ci13xxx_pci_driver); | ||
144 | |||
145 | MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); | ||
146 | MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); | ||
147 | MODULE_LICENSE("GPL"); | ||
148 | MODULE_VERSION("June 2008"); | ||
149 | 1 | /* |
drivers/usb/chipidea/ci_hdrc_imx.c
File was created | 1 | /* | |
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * Copyright (C) 2012 Marek Vasut <marex@denx.de> | ||
4 | * on behalf of DENX Software Engineering GmbH | ||
5 | * | ||
6 | * The code contained herein is licensed under the GNU General Public | ||
7 | * License. You may obtain a copy of the GNU General Public License | ||
8 | * Version 2 or later at the following locations: | ||
9 | * | ||
10 | * http://www.opensource.org/licenses/gpl-license.html | ||
11 | * http://www.gnu.org/copyleft/gpl.html | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/of_platform.h> | ||
16 | #include <linux/of_gpio.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/pm_runtime.h> | ||
19 | #include <linux/dma-mapping.h> | ||
20 | #include <linux/usb/chipidea.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/regulator/consumer.h> | ||
23 | |||
24 | #include "ci.h" | ||
25 | #include "ci_hdrc_imx.h" | ||
26 | |||
27 | #define pdev_to_phy(pdev) \ | ||
28 | ((struct usb_phy *)platform_get_drvdata(pdev)) | ||
29 | |||
30 | struct ci_hdrc_imx_data { | ||
31 | struct usb_phy *phy; | ||
32 | struct platform_device *ci_pdev; | ||
33 | struct clk *clk; | ||
34 | struct regulator *reg_vbus; | ||
35 | }; | ||
36 | |||
37 | static const struct usbmisc_ops *usbmisc_ops; | ||
38 | |||
39 | /* Common functions shared by usbmisc drivers */ | ||
40 | |||
41 | int usbmisc_set_ops(const struct usbmisc_ops *ops) | ||
42 | { | ||
43 | if (usbmisc_ops) | ||
44 | return -EBUSY; | ||
45 | |||
46 | usbmisc_ops = ops; | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | EXPORT_SYMBOL_GPL(usbmisc_set_ops); | ||
51 | |||
52 | void usbmisc_unset_ops(const struct usbmisc_ops *ops) | ||
53 | { | ||
54 | usbmisc_ops = NULL; | ||
55 | } | ||
56 | EXPORT_SYMBOL_GPL(usbmisc_unset_ops); | ||
57 | |||
58 | int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev) | ||
59 | { | ||
60 | struct device_node *np = dev->of_node; | ||
61 | struct of_phandle_args args; | ||
62 | int ret; | ||
63 | |||
64 | usbdev->dev = dev; | ||
65 | |||
66 | ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells", | ||
67 | 0, &args); | ||
68 | if (ret) { | ||
69 | dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n", | ||
70 | ret); | ||
71 | memset(usbdev, 0, sizeof(*usbdev)); | ||
72 | return ret; | ||
73 | } | ||
74 | usbdev->index = args.args[0]; | ||
75 | of_node_put(args.np); | ||
76 | |||
77 | if (of_find_property(np, "disable-over-current", NULL)) | ||
78 | usbdev->disable_oc = 1; | ||
79 | |||
80 | if (of_find_property(np, "external-vbus-divider", NULL)) | ||
81 | usbdev->evdo = 1; | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | EXPORT_SYMBOL_GPL(usbmisc_get_init_data); | ||
86 | |||
87 | /* End of common functions shared by usbmisc drivers*/ | ||
88 | |||
89 | static int ci_hdrc_imx_probe(struct platform_device *pdev) | ||
90 | { | ||
91 | struct ci_hdrc_imx_data *data; | ||
92 | struct ci_hdrc_platform_data pdata = { | ||
93 | .name = "ci_hdrc_imx", | ||
94 | .capoffset = DEF_CAPOFFSET, | ||
95 | .flags = CI_HDRC_REQUIRE_TRANSCEIVER | | ||
96 | CI_HDRC_PULLUP_ON_VBUS | | ||
97 | CI_HDRC_DISABLE_STREAMING, | ||
98 | }; | ||
99 | struct resource *res; | ||
100 | int ret; | ||
101 | struct usb_phy *phy; | ||
102 | |||
103 | if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL) | ||
104 | && !usbmisc_ops) | ||
105 | return -EPROBE_DEFER; | ||
106 | |||
107 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
108 | if (!data) { | ||
109 | dev_err(&pdev->dev, "Failed to allocate ci_hdrc-imx data!\n"); | ||
110 | return -ENOMEM; | ||
111 | } | ||
112 | |||
113 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
114 | if (!res) { | ||
115 | dev_err(&pdev->dev, "Can't get device resources!\n"); | ||
116 | return -ENOENT; | ||
117 | } | ||
118 | |||
119 | data->clk = devm_clk_get(&pdev->dev, NULL); | ||
120 | if (IS_ERR(data->clk)) { | ||
121 | dev_err(&pdev->dev, | ||
122 | "Failed to get clock, err=%ld\n", PTR_ERR(data->clk)); | ||
123 | return PTR_ERR(data->clk); | ||
124 | } | ||
125 | |||
126 | ret = clk_prepare_enable(data->clk); | ||
127 | if (ret) { | ||
128 | dev_err(&pdev->dev, | ||
129 | "Failed to prepare or enable clock, err=%d\n", ret); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); | ||
134 | if (!IS_ERR(phy)) { | ||
135 | ret = usb_phy_init(phy); | ||
136 | if (ret) { | ||
137 | dev_err(&pdev->dev, "unable to init phy: %d\n", ret); | ||
138 | goto err_clk; | ||
139 | } | ||
140 | } else if (PTR_ERR(phy) == -EPROBE_DEFER) { | ||
141 | ret = -EPROBE_DEFER; | ||
142 | goto err_clk; | ||
143 | } | ||
144 | |||
145 | /* we only support host now, so enable vbus here */ | ||
146 | data->reg_vbus = devm_regulator_get(&pdev->dev, "vbus"); | ||
147 | if (!IS_ERR(data->reg_vbus)) { | ||
148 | ret = regulator_enable(data->reg_vbus); | ||
149 | if (ret) { | ||
150 | dev_err(&pdev->dev, | ||
151 | "Failed to enable vbus regulator, err=%d\n", | ||
152 | ret); | ||
153 | goto err_clk; | ||
154 | } | ||
155 | } else { | ||
156 | data->reg_vbus = NULL; | ||
157 | } | ||
158 | |||
159 | pdata.phy = data->phy; | ||
160 | |||
161 | if (!pdev->dev.dma_mask) | ||
162 | pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; | ||
163 | if (!pdev->dev.coherent_dma_mask) | ||
164 | pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
165 | |||
166 | if (usbmisc_ops && usbmisc_ops->init) { | ||
167 | ret = usbmisc_ops->init(&pdev->dev); | ||
168 | if (ret) { | ||
169 | dev_err(&pdev->dev, | ||
170 | "usbmisc init failed, ret=%d\n", ret); | ||
171 | goto err; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | data->ci_pdev = ci_hdrc_add_device(&pdev->dev, | ||
176 | pdev->resource, pdev->num_resources, | ||
177 | &pdata); | ||
178 | if (IS_ERR(data->ci_pdev)) { | ||
179 | ret = PTR_ERR(data->ci_pdev); | ||
180 | dev_err(&pdev->dev, | ||
181 | "Can't register ci_hdrc platform device, err=%d\n", | ||
182 | ret); | ||
183 | goto err; | ||
184 | } | ||
185 | |||
186 | if (usbmisc_ops && usbmisc_ops->post) { | ||
187 | ret = usbmisc_ops->post(&pdev->dev); | ||
188 | if (ret) { | ||
189 | dev_err(&pdev->dev, | ||
190 | "usbmisc post failed, ret=%d\n", ret); | ||
191 | goto disable_device; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | platform_set_drvdata(pdev, data); | ||
196 | |||
197 | pm_runtime_no_callbacks(&pdev->dev); | ||
198 | pm_runtime_enable(&pdev->dev); | ||
199 | |||
200 | return 0; | ||
201 | |||
202 | disable_device: | ||
203 | ci_hdrc_remove_device(data->ci_pdev); | ||
204 | err: | ||
205 | if (data->reg_vbus) | ||
206 | regulator_disable(data->reg_vbus); | ||
207 | err_clk: | ||
208 | clk_disable_unprepare(data->clk); | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | static int ci_hdrc_imx_remove(struct platform_device *pdev) | ||
213 | { | ||
214 | struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev); | ||
215 | |||
216 | pm_runtime_disable(&pdev->dev); | ||
217 | ci_hdrc_remove_device(data->ci_pdev); | ||
218 | |||
219 | if (data->reg_vbus) | ||
220 | regulator_disable(data->reg_vbus); | ||
221 | |||
222 | if (data->phy) { | ||
223 | usb_phy_shutdown(data->phy); | ||
224 | module_put(data->phy->dev->driver->owner); | ||
225 | } | ||
226 | |||
227 | clk_disable_unprepare(data->clk); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static const struct of_device_id ci_hdrc_imx_dt_ids[] = { | ||
233 | { .compatible = "fsl,imx27-usb", }, | ||
234 | { /* sentinel */ } | ||
235 | }; | ||
236 | MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); | ||
237 | |||
238 | static struct platform_driver ci_hdrc_imx_driver = { | ||
239 | .probe = ci_hdrc_imx_probe, | ||
240 | .remove = ci_hdrc_imx_remove, | ||
241 | .driver = { | ||
242 | .name = "imx_usb", | ||
243 | .owner = THIS_MODULE, | ||
244 | .of_match_table = ci_hdrc_imx_dt_ids, | ||
245 | }, | ||
246 | }; | ||
247 | |||
248 | module_platform_driver(ci_hdrc_imx_driver); | ||
249 | |||
250 | MODULE_ALIAS("platform:imx-usb"); | ||
251 | MODULE_LICENSE("GPL v2"); | ||
252 | MODULE_DESCRIPTION("CI HDRC i.MX USB binding"); | ||
253 | MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); | ||
254 | MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); | ||
255 |
drivers/usb/chipidea/ci_hdrc_imx.h
File was created | 1 | /* | |
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | /* Used to set SoC specific callbacks */ | ||
13 | struct usbmisc_ops { | ||
14 | /* It's called once when probe a usb device */ | ||
15 | int (*init)(struct device *dev); | ||
16 | /* It's called once after adding a usb device */ | ||
17 | int (*post)(struct device *dev); | ||
18 | }; | ||
19 | |||
20 | struct usbmisc_usb_device { | ||
21 | struct device *dev; /* usb controller device */ | ||
22 | int index; | ||
23 | |||
24 | unsigned int disable_oc:1; /* over current detect disabled */ | ||
25 | unsigned int evdo:1; /* set external vbus divider option */ | ||
26 | }; | ||
27 | |||
28 | int usbmisc_set_ops(const struct usbmisc_ops *ops); | ||
29 | void usbmisc_unset_ops(const struct usbmisc_ops *ops); | ||
30 | int | ||
31 | usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev); | ||
32 |
drivers/usb/chipidea/ci_hdrc_msm.c
File was created | 1 | /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. | |
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/platform_device.h> | ||
10 | #include <linux/pm_runtime.h> | ||
11 | #include <linux/usb/msm_hsusb_hw.h> | ||
12 | #include <linux/usb/ulpi.h> | ||
13 | #include <linux/usb/gadget.h> | ||
14 | #include <linux/usb/chipidea.h> | ||
15 | |||
16 | #include "ci.h" | ||
17 | |||
18 | #define MSM_USB_BASE (ci->hw_bank.abs) | ||
19 | |||
20 | static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) | ||
21 | { | ||
22 | struct device *dev = ci->gadget.dev.parent; | ||
23 | int val; | ||
24 | |||
25 | switch (event) { | ||
26 | case CI_HDRC_CONTROLLER_RESET_EVENT: | ||
27 | dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n"); | ||
28 | writel(0, USB_AHBBURST); | ||
29 | writel(0, USB_AHBMODE); | ||
30 | break; | ||
31 | case CI_HDRC_CONTROLLER_STOPPED_EVENT: | ||
32 | dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n"); | ||
33 | /* | ||
34 | * Put the transceiver in non-driving mode. Otherwise host | ||
35 | * may not detect soft-disconnection. | ||
36 | */ | ||
37 | val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL); | ||
38 | val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; | ||
39 | val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; | ||
40 | usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL); | ||
41 | break; | ||
42 | default: | ||
43 | dev_dbg(dev, "unknown ci_hdrc event\n"); | ||
44 | break; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = { | ||
49 | .name = "ci_hdrc_msm", | ||
50 | .flags = CI_HDRC_REGS_SHARED | | ||
51 | CI_HDRC_REQUIRE_TRANSCEIVER | | ||
52 | CI_HDRC_PULLUP_ON_VBUS | | ||
53 | CI_HDRC_DISABLE_STREAMING, | ||
54 | |||
55 | .notify_event = ci_hdrc_msm_notify_event, | ||
56 | }; | ||
57 | |||
58 | static int ci_hdrc_msm_probe(struct platform_device *pdev) | ||
59 | { | ||
60 | struct platform_device *plat_ci; | ||
61 | |||
62 | dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n"); | ||
63 | |||
64 | plat_ci = ci_hdrc_add_device(&pdev->dev, | ||
65 | pdev->resource, pdev->num_resources, | ||
66 | &ci_hdrc_msm_platdata); | ||
67 | if (IS_ERR(plat_ci)) { | ||
68 | dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n"); | ||
69 | return PTR_ERR(plat_ci); | ||
70 | } | ||
71 | |||
72 | platform_set_drvdata(pdev, plat_ci); | ||
73 | |||
74 | pm_runtime_no_callbacks(&pdev->dev); | ||
75 | pm_runtime_enable(&pdev->dev); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int ci_hdrc_msm_remove(struct platform_device *pdev) | ||
81 | { | ||
82 | struct platform_device *plat_ci = platform_get_drvdata(pdev); | ||
83 | |||
84 | pm_runtime_disable(&pdev->dev); | ||
85 | ci_hdrc_remove_device(plat_ci); | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static struct platform_driver ci_hdrc_msm_driver = { | ||
91 | .probe = ci_hdrc_msm_probe, | ||
92 | .remove = ci_hdrc_msm_remove, | ||
93 | .driver = { .name = "msm_hsusb", }, | ||
94 | }; | ||
95 | |||
96 | module_platform_driver(ci_hdrc_msm_driver); | ||
97 | |||
98 | MODULE_ALIAS("platform:msm_hsusb"); | ||
99 | MODULE_ALIAS("platform:ci13xxx_msm"); | ||
100 | MODULE_LICENSE("GPL v2"); | ||
101 |
drivers/usb/chipidea/ci_hdrc_pci.c
File was created | 1 | /* | |
2 | * ci_hdrc_pci.c - MIPS USB IP core family device controller | ||
3 | * | ||
4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | ||
5 | * | ||
6 | * Author: David Lopo | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/usb/gadget.h> | ||
18 | #include <linux/usb/chipidea.h> | ||
19 | |||
20 | /* driver name */ | ||
21 | #define UDC_DRIVER_NAME "ci_hdrc_pci" | ||
22 | |||
23 | /****************************************************************************** | ||
24 | * PCI block | ||
25 | *****************************************************************************/ | ||
26 | static struct ci_hdrc_platform_data pci_platdata = { | ||
27 | .name = UDC_DRIVER_NAME, | ||
28 | .capoffset = DEF_CAPOFFSET, | ||
29 | }; | ||
30 | |||
31 | static struct ci_hdrc_platform_data langwell_pci_platdata = { | ||
32 | .name = UDC_DRIVER_NAME, | ||
33 | .capoffset = 0, | ||
34 | }; | ||
35 | |||
36 | static struct ci_hdrc_platform_data penwell_pci_platdata = { | ||
37 | .name = UDC_DRIVER_NAME, | ||
38 | .capoffset = 0, | ||
39 | .power_budget = 200, | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * ci_hdrc_pci_probe: PCI probe | ||
44 | * @pdev: USB device controller being probed | ||
45 | * @id: PCI hotplug ID connecting controller to UDC framework | ||
46 | * | ||
47 | * This function returns an error code | ||
48 | * Allocates basic PCI resources for this USB device controller, and then | ||
49 | * invokes the udc_probe() method to start the UDC associated with it | ||
50 | */ | ||
51 | static int ci_hdrc_pci_probe(struct pci_dev *pdev, | ||
52 | const struct pci_device_id *id) | ||
53 | { | ||
54 | struct ci_hdrc_platform_data *platdata = (void *)id->driver_data; | ||
55 | struct platform_device *plat_ci; | ||
56 | struct resource res[3]; | ||
57 | int retval = 0, nres = 2; | ||
58 | |||
59 | if (!platdata) { | ||
60 | dev_err(&pdev->dev, "device doesn't provide driver data\n"); | ||
61 | return -ENODEV; | ||
62 | } | ||
63 | |||
64 | retval = pcim_enable_device(pdev); | ||
65 | if (retval) | ||
66 | return retval; | ||
67 | |||
68 | if (!pdev->irq) { | ||
69 | dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); | ||
70 | return -ENODEV; | ||
71 | } | ||
72 | |||
73 | pci_set_master(pdev); | ||
74 | pci_try_set_mwi(pdev); | ||
75 | |||
76 | memset(res, 0, sizeof(res)); | ||
77 | res[0].start = pci_resource_start(pdev, 0); | ||
78 | res[0].end = pci_resource_end(pdev, 0); | ||
79 | res[0].flags = IORESOURCE_MEM; | ||
80 | res[1].start = pdev->irq; | ||
81 | res[1].flags = IORESOURCE_IRQ; | ||
82 | |||
83 | plat_ci = ci_hdrc_add_device(&pdev->dev, res, nres, platdata); | ||
84 | if (IS_ERR(plat_ci)) { | ||
85 | dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n"); | ||
86 | return PTR_ERR(plat_ci); | ||
87 | } | ||
88 | |||
89 | pci_set_drvdata(pdev, plat_ci); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * ci_hdrc_pci_remove: PCI remove | ||
96 | * @pdev: USB Device Controller being removed | ||
97 | * | ||
98 | * Reverses the effect of ci_hdrc_pci_probe(), | ||
99 | * first invoking the udc_remove() and then releases | ||
100 | * all PCI resources allocated for this USB device controller | ||
101 | */ | ||
102 | static void ci_hdrc_pci_remove(struct pci_dev *pdev) | ||
103 | { | ||
104 | struct platform_device *plat_ci = pci_get_drvdata(pdev); | ||
105 | |||
106 | ci_hdrc_remove_device(plat_ci); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * PCI device table | ||
111 | * PCI device structure | ||
112 | * | ||
113 | * Check "pci.h" for details | ||
114 | */ | ||
115 | static DEFINE_PCI_DEVICE_TABLE(ci_hdrc_pci_id_table) = { | ||
116 | { | ||
117 | PCI_DEVICE(0x153F, 0x1004), | ||
118 | .driver_data = (kernel_ulong_t)&pci_platdata, | ||
119 | }, | ||
120 | { | ||
121 | PCI_DEVICE(0x153F, 0x1006), | ||
122 | .driver_data = (kernel_ulong_t)&pci_platdata, | ||
123 | }, | ||
124 | { | ||
125 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811), | ||
126 | .driver_data = (kernel_ulong_t)&langwell_pci_platdata, | ||
127 | }, | ||
128 | { | ||
129 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829), | ||
130 | .driver_data = (kernel_ulong_t)&penwell_pci_platdata, | ||
131 | }, | ||
132 | { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } | ||
133 | }; | ||
134 | MODULE_DEVICE_TABLE(pci, ci_hdrc_pci_id_table); | ||
135 | |||
136 | static struct pci_driver ci_hdrc_pci_driver = { | ||
137 | .name = UDC_DRIVER_NAME, | ||
138 | .id_table = ci_hdrc_pci_id_table, | ||
139 | .probe = ci_hdrc_pci_probe, | ||
140 | .remove = ci_hdrc_pci_remove, | ||
141 | }; | ||
142 | |||
143 | module_pci_driver(ci_hdrc_pci_driver); | ||
144 | |||
145 | MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); | ||
146 | MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); | ||
147 | MODULE_LICENSE("GPL"); | ||
148 | MODULE_VERSION("June 2008"); | ||
149 | MODULE_ALIAS("platform:ci13xxx_pci"); | ||
150 |
drivers/usb/chipidea/core.c
1 | /* | 1 | /* |
2 | * core.c - ChipIdea USB IP core family device controller | 2 | * core.c - ChipIdea USB IP core family device controller |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | 4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. |
5 | * | 5 | * |
6 | * Author: David Lopo | 6 | * Author: David Lopo |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * Description: ChipIdea USB IP core family device controller | 14 | * Description: ChipIdea USB IP core family device controller |
15 | * | 15 | * |
16 | * This driver is composed of several blocks: | 16 | * This driver is composed of several blocks: |
17 | * - HW: hardware interface | 17 | * - HW: hardware interface |
18 | * - DBG: debug facilities (optional) | 18 | * - DBG: debug facilities (optional) |
19 | * - UTIL: utilities | 19 | * - UTIL: utilities |
20 | * - ISR: interrupts handling | 20 | * - ISR: interrupts handling |
21 | * - ENDPT: endpoint operations (Gadget API) | 21 | * - ENDPT: endpoint operations (Gadget API) |
22 | * - GADGET: gadget operations (Gadget API) | 22 | * - GADGET: gadget operations (Gadget API) |
23 | * - BUS: bus glue code, bus abstraction layer | 23 | * - BUS: bus glue code, bus abstraction layer |
24 | * | 24 | * |
25 | * Compile Options | 25 | * Compile Options |
26 | * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities | 26 | * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities |
27 | * - STALL_IN: non-empty bulk-in pipes cannot be halted | 27 | * - STALL_IN: non-empty bulk-in pipes cannot be halted |
28 | * if defined mass storage compliance succeeds but with warnings | 28 | * if defined mass storage compliance succeeds but with warnings |
29 | * => case 4: Hi > Dn | 29 | * => case 4: Hi > Dn |
30 | * => case 5: Hi > Di | 30 | * => case 5: Hi > Di |
31 | * => case 8: Hi <> Do | 31 | * => case 8: Hi <> Do |
32 | * if undefined usbtest 13 fails | 32 | * if undefined usbtest 13 fails |
33 | * - TRACE: enable function tracing (depends on DEBUG) | 33 | * - TRACE: enable function tracing (depends on DEBUG) |
34 | * | 34 | * |
35 | * Main Features | 35 | * Main Features |
36 | * - Chapter 9 & Mass Storage Compliance with Gadget File Storage | 36 | * - Chapter 9 & Mass Storage Compliance with Gadget File Storage |
37 | * - Chapter 9 Compliance with Gadget Zero (STALL_IN undefined) | 37 | * - Chapter 9 Compliance with Gadget Zero (STALL_IN undefined) |
38 | * - Normal & LPM support | 38 | * - Normal & LPM support |
39 | * | 39 | * |
40 | * USBTEST Report | 40 | * USBTEST Report |
41 | * - OK: 0-12, 13 (STALL_IN defined) & 14 | 41 | * - OK: 0-12, 13 (STALL_IN defined) & 14 |
42 | * - Not Supported: 15 & 16 (ISO) | 42 | * - Not Supported: 15 & 16 (ISO) |
43 | * | 43 | * |
44 | * TODO List | 44 | * TODO List |
45 | * - OTG | 45 | * - OTG |
46 | * - Interrupt Traffic | 46 | * - Interrupt Traffic |
47 | * - GET_STATUS(device) - always reports 0 | 47 | * - GET_STATUS(device) - always reports 0 |
48 | * - Gadget API (majority of optional features) | 48 | * - Gadget API (majority of optional features) |
49 | * - Suspend & Remote Wakeup | 49 | * - Suspend & Remote Wakeup |
50 | */ | 50 | */ |
51 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
52 | #include <linux/device.h> | 52 | #include <linux/device.h> |
53 | #include <linux/dma-mapping.h> | 53 | #include <linux/dma-mapping.h> |
54 | #include <linux/platform_device.h> | 54 | #include <linux/platform_device.h> |
55 | #include <linux/module.h> | 55 | #include <linux/module.h> |
56 | #include <linux/idr.h> | 56 | #include <linux/idr.h> |
57 | #include <linux/interrupt.h> | 57 | #include <linux/interrupt.h> |
58 | #include <linux/io.h> | 58 | #include <linux/io.h> |
59 | #include <linux/kernel.h> | 59 | #include <linux/kernel.h> |
60 | #include <linux/slab.h> | 60 | #include <linux/slab.h> |
61 | #include <linux/pm_runtime.h> | 61 | #include <linux/pm_runtime.h> |
62 | #include <linux/usb/ch9.h> | 62 | #include <linux/usb/ch9.h> |
63 | #include <linux/usb/gadget.h> | 63 | #include <linux/usb/gadget.h> |
64 | #include <linux/usb/otg.h> | 64 | #include <linux/usb/otg.h> |
65 | #include <linux/usb/chipidea.h> | 65 | #include <linux/usb/chipidea.h> |
66 | #include <linux/usb/of.h> | 66 | #include <linux/usb/of.h> |
67 | #include <linux/phy.h> | 67 | #include <linux/phy.h> |
68 | 68 | ||
69 | #include "ci.h" | 69 | #include "ci.h" |
70 | #include "udc.h" | 70 | #include "udc.h" |
71 | #include "bits.h" | 71 | #include "bits.h" |
72 | #include "host.h" | 72 | #include "host.h" |
73 | #include "debug.h" | 73 | #include "debug.h" |
74 | 74 | ||
75 | /* Controller register map */ | 75 | /* Controller register map */ |
76 | static uintptr_t ci_regs_nolpm[] = { | 76 | static uintptr_t ci_regs_nolpm[] = { |
77 | [CAP_CAPLENGTH] = 0x000UL, | 77 | [CAP_CAPLENGTH] = 0x000UL, |
78 | [CAP_HCCPARAMS] = 0x008UL, | 78 | [CAP_HCCPARAMS] = 0x008UL, |
79 | [CAP_DCCPARAMS] = 0x024UL, | 79 | [CAP_DCCPARAMS] = 0x024UL, |
80 | [CAP_TESTMODE] = 0x038UL, | 80 | [CAP_TESTMODE] = 0x038UL, |
81 | [OP_USBCMD] = 0x000UL, | 81 | [OP_USBCMD] = 0x000UL, |
82 | [OP_USBSTS] = 0x004UL, | 82 | [OP_USBSTS] = 0x004UL, |
83 | [OP_USBINTR] = 0x008UL, | 83 | [OP_USBINTR] = 0x008UL, |
84 | [OP_DEVICEADDR] = 0x014UL, | 84 | [OP_DEVICEADDR] = 0x014UL, |
85 | [OP_ENDPTLISTADDR] = 0x018UL, | 85 | [OP_ENDPTLISTADDR] = 0x018UL, |
86 | [OP_PORTSC] = 0x044UL, | 86 | [OP_PORTSC] = 0x044UL, |
87 | [OP_DEVLC] = 0x084UL, | 87 | [OP_DEVLC] = 0x084UL, |
88 | [OP_OTGSC] = 0x064UL, | 88 | [OP_OTGSC] = 0x064UL, |
89 | [OP_USBMODE] = 0x068UL, | 89 | [OP_USBMODE] = 0x068UL, |
90 | [OP_ENDPTSETUPSTAT] = 0x06CUL, | 90 | [OP_ENDPTSETUPSTAT] = 0x06CUL, |
91 | [OP_ENDPTPRIME] = 0x070UL, | 91 | [OP_ENDPTPRIME] = 0x070UL, |
92 | [OP_ENDPTFLUSH] = 0x074UL, | 92 | [OP_ENDPTFLUSH] = 0x074UL, |
93 | [OP_ENDPTSTAT] = 0x078UL, | 93 | [OP_ENDPTSTAT] = 0x078UL, |
94 | [OP_ENDPTCOMPLETE] = 0x07CUL, | 94 | [OP_ENDPTCOMPLETE] = 0x07CUL, |
95 | [OP_ENDPTCTRL] = 0x080UL, | 95 | [OP_ENDPTCTRL] = 0x080UL, |
96 | }; | 96 | }; |
97 | 97 | ||
98 | static uintptr_t ci_regs_lpm[] = { | 98 | static uintptr_t ci_regs_lpm[] = { |
99 | [CAP_CAPLENGTH] = 0x000UL, | 99 | [CAP_CAPLENGTH] = 0x000UL, |
100 | [CAP_HCCPARAMS] = 0x008UL, | 100 | [CAP_HCCPARAMS] = 0x008UL, |
101 | [CAP_DCCPARAMS] = 0x024UL, | 101 | [CAP_DCCPARAMS] = 0x024UL, |
102 | [CAP_TESTMODE] = 0x0FCUL, | 102 | [CAP_TESTMODE] = 0x0FCUL, |
103 | [OP_USBCMD] = 0x000UL, | 103 | [OP_USBCMD] = 0x000UL, |
104 | [OP_USBSTS] = 0x004UL, | 104 | [OP_USBSTS] = 0x004UL, |
105 | [OP_USBINTR] = 0x008UL, | 105 | [OP_USBINTR] = 0x008UL, |
106 | [OP_DEVICEADDR] = 0x014UL, | 106 | [OP_DEVICEADDR] = 0x014UL, |
107 | [OP_ENDPTLISTADDR] = 0x018UL, | 107 | [OP_ENDPTLISTADDR] = 0x018UL, |
108 | [OP_PORTSC] = 0x044UL, | 108 | [OP_PORTSC] = 0x044UL, |
109 | [OP_DEVLC] = 0x084UL, | 109 | [OP_DEVLC] = 0x084UL, |
110 | [OP_OTGSC] = 0x0C4UL, | 110 | [OP_OTGSC] = 0x0C4UL, |
111 | [OP_USBMODE] = 0x0C8UL, | 111 | [OP_USBMODE] = 0x0C8UL, |
112 | [OP_ENDPTSETUPSTAT] = 0x0D8UL, | 112 | [OP_ENDPTSETUPSTAT] = 0x0D8UL, |
113 | [OP_ENDPTPRIME] = 0x0DCUL, | 113 | [OP_ENDPTPRIME] = 0x0DCUL, |
114 | [OP_ENDPTFLUSH] = 0x0E0UL, | 114 | [OP_ENDPTFLUSH] = 0x0E0UL, |
115 | [OP_ENDPTSTAT] = 0x0E4UL, | 115 | [OP_ENDPTSTAT] = 0x0E4UL, |
116 | [OP_ENDPTCOMPLETE] = 0x0E8UL, | 116 | [OP_ENDPTCOMPLETE] = 0x0E8UL, |
117 | [OP_ENDPTCTRL] = 0x0ECUL, | 117 | [OP_ENDPTCTRL] = 0x0ECUL, |
118 | }; | 118 | }; |
119 | 119 | ||
120 | static int hw_alloc_regmap(struct ci13xxx *ci, bool is_lpm) | 120 | static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm) |
121 | { | 121 | { |
122 | int i; | 122 | int i; |
123 | 123 | ||
124 | kfree(ci->hw_bank.regmap); | 124 | kfree(ci->hw_bank.regmap); |
125 | 125 | ||
126 | ci->hw_bank.regmap = kzalloc((OP_LAST + 1) * sizeof(void *), | 126 | ci->hw_bank.regmap = kzalloc((OP_LAST + 1) * sizeof(void *), |
127 | GFP_KERNEL); | 127 | GFP_KERNEL); |
128 | if (!ci->hw_bank.regmap) | 128 | if (!ci->hw_bank.regmap) |
129 | return -ENOMEM; | 129 | return -ENOMEM; |
130 | 130 | ||
131 | for (i = 0; i < OP_ENDPTCTRL; i++) | 131 | for (i = 0; i < OP_ENDPTCTRL; i++) |
132 | ci->hw_bank.regmap[i] = | 132 | ci->hw_bank.regmap[i] = |
133 | (i <= CAP_LAST ? ci->hw_bank.cap : ci->hw_bank.op) + | 133 | (i <= CAP_LAST ? ci->hw_bank.cap : ci->hw_bank.op) + |
134 | (is_lpm ? ci_regs_lpm[i] : ci_regs_nolpm[i]); | 134 | (is_lpm ? ci_regs_lpm[i] : ci_regs_nolpm[i]); |
135 | 135 | ||
136 | for (; i <= OP_LAST; i++) | 136 | for (; i <= OP_LAST; i++) |
137 | ci->hw_bank.regmap[i] = ci->hw_bank.op + | 137 | ci->hw_bank.regmap[i] = ci->hw_bank.op + |
138 | 4 * (i - OP_ENDPTCTRL) + | 138 | 4 * (i - OP_ENDPTCTRL) + |
139 | (is_lpm | 139 | (is_lpm |
140 | ? ci_regs_lpm[OP_ENDPTCTRL] | 140 | ? ci_regs_lpm[OP_ENDPTCTRL] |
141 | : ci_regs_nolpm[OP_ENDPTCTRL]); | 141 | : ci_regs_nolpm[OP_ENDPTCTRL]); |
142 | 142 | ||
143 | return 0; | 143 | return 0; |
144 | } | 144 | } |
145 | 145 | ||
146 | /** | 146 | /** |
147 | * hw_port_test_set: writes port test mode (execute without interruption) | 147 | * hw_port_test_set: writes port test mode (execute without interruption) |
148 | * @mode: new value | 148 | * @mode: new value |
149 | * | 149 | * |
150 | * This function returns an error code | 150 | * This function returns an error code |
151 | */ | 151 | */ |
152 | int hw_port_test_set(struct ci13xxx *ci, u8 mode) | 152 | int hw_port_test_set(struct ci_hdrc *ci, u8 mode) |
153 | { | 153 | { |
154 | const u8 TEST_MODE_MAX = 7; | 154 | const u8 TEST_MODE_MAX = 7; |
155 | 155 | ||
156 | if (mode > TEST_MODE_MAX) | 156 | if (mode > TEST_MODE_MAX) |
157 | return -EINVAL; | 157 | return -EINVAL; |
158 | 158 | ||
159 | hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << __ffs(PORTSC_PTC)); | 159 | hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << __ffs(PORTSC_PTC)); |
160 | return 0; | 160 | return 0; |
161 | } | 161 | } |
162 | 162 | ||
163 | /** | 163 | /** |
164 | * hw_port_test_get: reads port test mode value | 164 | * hw_port_test_get: reads port test mode value |
165 | * | 165 | * |
166 | * This function returns port test mode value | 166 | * This function returns port test mode value |
167 | */ | 167 | */ |
168 | u8 hw_port_test_get(struct ci13xxx *ci) | 168 | u8 hw_port_test_get(struct ci_hdrc *ci) |
169 | { | 169 | { |
170 | return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC); | 170 | return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC); |
171 | } | 171 | } |
172 | 172 | ||
173 | static int hw_device_init(struct ci13xxx *ci, void __iomem *base) | 173 | static int hw_device_init(struct ci_hdrc *ci, void __iomem *base) |
174 | { | 174 | { |
175 | u32 reg; | 175 | u32 reg; |
176 | 176 | ||
177 | /* bank is a module variable */ | 177 | /* bank is a module variable */ |
178 | ci->hw_bank.abs = base; | 178 | ci->hw_bank.abs = base; |
179 | 179 | ||
180 | ci->hw_bank.cap = ci->hw_bank.abs; | 180 | ci->hw_bank.cap = ci->hw_bank.abs; |
181 | ci->hw_bank.cap += ci->platdata->capoffset; | 181 | ci->hw_bank.cap += ci->platdata->capoffset; |
182 | ci->hw_bank.op = ci->hw_bank.cap + (ioread32(ci->hw_bank.cap) & 0xff); | 182 | ci->hw_bank.op = ci->hw_bank.cap + (ioread32(ci->hw_bank.cap) & 0xff); |
183 | 183 | ||
184 | hw_alloc_regmap(ci, false); | 184 | hw_alloc_regmap(ci, false); |
185 | reg = hw_read(ci, CAP_HCCPARAMS, HCCPARAMS_LEN) >> | 185 | reg = hw_read(ci, CAP_HCCPARAMS, HCCPARAMS_LEN) >> |
186 | __ffs(HCCPARAMS_LEN); | 186 | __ffs(HCCPARAMS_LEN); |
187 | ci->hw_bank.lpm = reg; | 187 | ci->hw_bank.lpm = reg; |
188 | hw_alloc_regmap(ci, !!reg); | 188 | hw_alloc_regmap(ci, !!reg); |
189 | ci->hw_bank.size = ci->hw_bank.op - ci->hw_bank.abs; | 189 | ci->hw_bank.size = ci->hw_bank.op - ci->hw_bank.abs; |
190 | ci->hw_bank.size += OP_LAST; | 190 | ci->hw_bank.size += OP_LAST; |
191 | ci->hw_bank.size /= sizeof(u32); | 191 | ci->hw_bank.size /= sizeof(u32); |
192 | 192 | ||
193 | reg = hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DEN) >> | 193 | reg = hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DEN) >> |
194 | __ffs(DCCPARAMS_DEN); | 194 | __ffs(DCCPARAMS_DEN); |
195 | ci->hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */ | 195 | ci->hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */ |
196 | 196 | ||
197 | if (ci->hw_ep_max > ENDPT_MAX) | 197 | if (ci->hw_ep_max > ENDPT_MAX) |
198 | return -ENODEV; | 198 | return -ENODEV; |
199 | 199 | ||
200 | dev_dbg(ci->dev, "ChipIdea HDRC found, lpm: %d; cap: %p op: %p\n", | 200 | dev_dbg(ci->dev, "ChipIdea HDRC found, lpm: %d; cap: %p op: %p\n", |
201 | ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op); | 201 | ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op); |
202 | 202 | ||
203 | /* setup lock mode ? */ | 203 | /* setup lock mode ? */ |
204 | 204 | ||
205 | /* ENDPTSETUPSTAT is '0' by default */ | 205 | /* ENDPTSETUPSTAT is '0' by default */ |
206 | 206 | ||
207 | /* HCSPARAMS.bf.ppc SHOULD BE zero for device */ | 207 | /* HCSPARAMS.bf.ppc SHOULD BE zero for device */ |
208 | 208 | ||
209 | return 0; | 209 | return 0; |
210 | } | 210 | } |
211 | 211 | ||
212 | static void hw_phymode_configure(struct ci13xxx *ci) | 212 | static void hw_phymode_configure(struct ci_hdrc *ci) |
213 | { | 213 | { |
214 | u32 portsc, lpm, sts; | 214 | u32 portsc, lpm, sts; |
215 | 215 | ||
216 | switch (ci->platdata->phy_mode) { | 216 | switch (ci->platdata->phy_mode) { |
217 | case USBPHY_INTERFACE_MODE_UTMI: | 217 | case USBPHY_INTERFACE_MODE_UTMI: |
218 | portsc = PORTSC_PTS(PTS_UTMI); | 218 | portsc = PORTSC_PTS(PTS_UTMI); |
219 | lpm = DEVLC_PTS(PTS_UTMI); | 219 | lpm = DEVLC_PTS(PTS_UTMI); |
220 | break; | 220 | break; |
221 | case USBPHY_INTERFACE_MODE_UTMIW: | 221 | case USBPHY_INTERFACE_MODE_UTMIW: |
222 | portsc = PORTSC_PTS(PTS_UTMI) | PORTSC_PTW; | 222 | portsc = PORTSC_PTS(PTS_UTMI) | PORTSC_PTW; |
223 | lpm = DEVLC_PTS(PTS_UTMI) | DEVLC_PTW; | 223 | lpm = DEVLC_PTS(PTS_UTMI) | DEVLC_PTW; |
224 | break; | 224 | break; |
225 | case USBPHY_INTERFACE_MODE_ULPI: | 225 | case USBPHY_INTERFACE_MODE_ULPI: |
226 | portsc = PORTSC_PTS(PTS_ULPI); | 226 | portsc = PORTSC_PTS(PTS_ULPI); |
227 | lpm = DEVLC_PTS(PTS_ULPI); | 227 | lpm = DEVLC_PTS(PTS_ULPI); |
228 | break; | 228 | break; |
229 | case USBPHY_INTERFACE_MODE_SERIAL: | 229 | case USBPHY_INTERFACE_MODE_SERIAL: |
230 | portsc = PORTSC_PTS(PTS_SERIAL); | 230 | portsc = PORTSC_PTS(PTS_SERIAL); |
231 | lpm = DEVLC_PTS(PTS_SERIAL); | 231 | lpm = DEVLC_PTS(PTS_SERIAL); |
232 | sts = 1; | 232 | sts = 1; |
233 | break; | 233 | break; |
234 | case USBPHY_INTERFACE_MODE_HSIC: | 234 | case USBPHY_INTERFACE_MODE_HSIC: |
235 | portsc = PORTSC_PTS(PTS_HSIC); | 235 | portsc = PORTSC_PTS(PTS_HSIC); |
236 | lpm = DEVLC_PTS(PTS_HSIC); | 236 | lpm = DEVLC_PTS(PTS_HSIC); |
237 | break; | 237 | break; |
238 | default: | 238 | default: |
239 | return; | 239 | return; |
240 | } | 240 | } |
241 | 241 | ||
242 | if (ci->hw_bank.lpm) { | 242 | if (ci->hw_bank.lpm) { |
243 | hw_write(ci, OP_DEVLC, DEVLC_PTS(7) | DEVLC_PTW, lpm); | 243 | hw_write(ci, OP_DEVLC, DEVLC_PTS(7) | DEVLC_PTW, lpm); |
244 | hw_write(ci, OP_DEVLC, DEVLC_STS, sts); | 244 | hw_write(ci, OP_DEVLC, DEVLC_STS, sts); |
245 | } else { | 245 | } else { |
246 | hw_write(ci, OP_PORTSC, PORTSC_PTS(7) | PORTSC_PTW, portsc); | 246 | hw_write(ci, OP_PORTSC, PORTSC_PTS(7) | PORTSC_PTW, portsc); |
247 | hw_write(ci, OP_PORTSC, PORTSC_STS, sts); | 247 | hw_write(ci, OP_PORTSC, PORTSC_STS, sts); |
248 | } | 248 | } |
249 | } | 249 | } |
250 | 250 | ||
251 | /** | 251 | /** |
252 | * hw_device_reset: resets chip (execute without interruption) | 252 | * hw_device_reset: resets chip (execute without interruption) |
253 | * @ci: the controller | 253 | * @ci: the controller |
254 | * | 254 | * |
255 | * This function returns an error code | 255 | * This function returns an error code |
256 | */ | 256 | */ |
257 | int hw_device_reset(struct ci13xxx *ci, u32 mode) | 257 | int hw_device_reset(struct ci_hdrc *ci, u32 mode) |
258 | { | 258 | { |
259 | /* should flush & stop before reset */ | 259 | /* should flush & stop before reset */ |
260 | hw_write(ci, OP_ENDPTFLUSH, ~0, ~0); | 260 | hw_write(ci, OP_ENDPTFLUSH, ~0, ~0); |
261 | hw_write(ci, OP_USBCMD, USBCMD_RS, 0); | 261 | hw_write(ci, OP_USBCMD, USBCMD_RS, 0); |
262 | 262 | ||
263 | hw_write(ci, OP_USBCMD, USBCMD_RST, USBCMD_RST); | 263 | hw_write(ci, OP_USBCMD, USBCMD_RST, USBCMD_RST); |
264 | while (hw_read(ci, OP_USBCMD, USBCMD_RST)) | 264 | while (hw_read(ci, OP_USBCMD, USBCMD_RST)) |
265 | udelay(10); /* not RTOS friendly */ | 265 | udelay(10); /* not RTOS friendly */ |
266 | 266 | ||
267 | hw_phymode_configure(ci); | 267 | hw_phymode_configure(ci); |
268 | 268 | ||
269 | if (ci->platdata->notify_event) | 269 | if (ci->platdata->notify_event) |
270 | ci->platdata->notify_event(ci, | 270 | ci->platdata->notify_event(ci, |
271 | CI13XXX_CONTROLLER_RESET_EVENT); | 271 | CI_HDRC_CONTROLLER_RESET_EVENT); |
272 | 272 | ||
273 | if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) | 273 | if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) |
274 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); | 274 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); |
275 | 275 | ||
276 | /* USBMODE should be configured step by step */ | 276 | /* USBMODE should be configured step by step */ |
277 | hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); | 277 | hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); |
278 | hw_write(ci, OP_USBMODE, USBMODE_CM, mode); | 278 | hw_write(ci, OP_USBMODE, USBMODE_CM, mode); |
279 | /* HW >= 2.3 */ | 279 | /* HW >= 2.3 */ |
280 | hw_write(ci, OP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); | 280 | hw_write(ci, OP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); |
281 | 281 | ||
282 | if (hw_read(ci, OP_USBMODE, USBMODE_CM) != mode) { | 282 | if (hw_read(ci, OP_USBMODE, USBMODE_CM) != mode) { |
283 | pr_err("cannot enter in %s mode", ci_role(ci)->name); | 283 | pr_err("cannot enter in %s mode", ci_role(ci)->name); |
284 | pr_err("lpm = %i", ci->hw_bank.lpm); | 284 | pr_err("lpm = %i", ci->hw_bank.lpm); |
285 | return -ENODEV; | 285 | return -ENODEV; |
286 | } | 286 | } |
287 | 287 | ||
288 | return 0; | 288 | return 0; |
289 | } | 289 | } |
290 | 290 | ||
291 | /** | 291 | /** |
292 | * ci_otg_role - pick role based on ID pin state | 292 | * ci_otg_role - pick role based on ID pin state |
293 | * @ci: the controller | 293 | * @ci: the controller |
294 | */ | 294 | */ |
295 | static enum ci_role ci_otg_role(struct ci13xxx *ci) | 295 | static enum ci_role ci_otg_role(struct ci_hdrc *ci) |
296 | { | 296 | { |
297 | u32 sts = hw_read(ci, OP_OTGSC, ~0); | 297 | u32 sts = hw_read(ci, OP_OTGSC, ~0); |
298 | enum ci_role role = sts & OTGSC_ID | 298 | enum ci_role role = sts & OTGSC_ID |
299 | ? CI_ROLE_GADGET | 299 | ? CI_ROLE_GADGET |
300 | : CI_ROLE_HOST; | 300 | : CI_ROLE_HOST; |
301 | 301 | ||
302 | return role; | 302 | return role; |
303 | } | 303 | } |
304 | 304 | ||
305 | /** | 305 | /** |
306 | * ci_role_work - perform role changing based on ID pin | 306 | * ci_role_work - perform role changing based on ID pin |
307 | * @work: work struct | 307 | * @work: work struct |
308 | */ | 308 | */ |
309 | static void ci_role_work(struct work_struct *work) | 309 | static void ci_role_work(struct work_struct *work) |
310 | { | 310 | { |
311 | struct ci13xxx *ci = container_of(work, struct ci13xxx, work); | 311 | struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work); |
312 | enum ci_role role = ci_otg_role(ci); | 312 | enum ci_role role = ci_otg_role(ci); |
313 | 313 | ||
314 | if (role != ci->role) { | 314 | if (role != ci->role) { |
315 | dev_dbg(ci->dev, "switching from %s to %s\n", | 315 | dev_dbg(ci->dev, "switching from %s to %s\n", |
316 | ci_role(ci)->name, ci->roles[role]->name); | 316 | ci_role(ci)->name, ci->roles[role]->name); |
317 | 317 | ||
318 | ci_role_stop(ci); | 318 | ci_role_stop(ci); |
319 | ci_role_start(ci, role); | 319 | ci_role_start(ci, role); |
320 | } | 320 | } |
321 | 321 | ||
322 | enable_irq(ci->irq); | 322 | enable_irq(ci->irq); |
323 | } | 323 | } |
324 | 324 | ||
325 | static irqreturn_t ci_irq(int irq, void *data) | 325 | static irqreturn_t ci_irq(int irq, void *data) |
326 | { | 326 | { |
327 | struct ci13xxx *ci = data; | 327 | struct ci_hdrc *ci = data; |
328 | irqreturn_t ret = IRQ_NONE; | 328 | irqreturn_t ret = IRQ_NONE; |
329 | u32 otgsc = 0; | 329 | u32 otgsc = 0; |
330 | 330 | ||
331 | if (ci->is_otg) | 331 | if (ci->is_otg) |
332 | otgsc = hw_read(ci, OP_OTGSC, ~0); | 332 | otgsc = hw_read(ci, OP_OTGSC, ~0); |
333 | 333 | ||
334 | if (ci->role != CI_ROLE_END) | 334 | if (ci->role != CI_ROLE_END) |
335 | ret = ci_role(ci)->irq(ci); | 335 | ret = ci_role(ci)->irq(ci); |
336 | 336 | ||
337 | if (ci->is_otg && (otgsc & OTGSC_IDIS)) { | 337 | if (ci->is_otg && (otgsc & OTGSC_IDIS)) { |
338 | hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS); | 338 | hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS); |
339 | disable_irq_nosync(ci->irq); | 339 | disable_irq_nosync(ci->irq); |
340 | queue_work(ci->wq, &ci->work); | 340 | queue_work(ci->wq, &ci->work); |
341 | ret = IRQ_HANDLED; | 341 | ret = IRQ_HANDLED; |
342 | } | 342 | } |
343 | 343 | ||
344 | return ret; | 344 | return ret; |
345 | } | 345 | } |
346 | 346 | ||
347 | static DEFINE_IDA(ci_ida); | 347 | static DEFINE_IDA(ci_ida); |
348 | 348 | ||
349 | struct platform_device *ci13xxx_add_device(struct device *dev, | 349 | struct platform_device *ci_hdrc_add_device(struct device *dev, |
350 | struct resource *res, int nres, | 350 | struct resource *res, int nres, |
351 | struct ci13xxx_platform_data *platdata) | 351 | struct ci_hdrc_platform_data *platdata) |
352 | { | 352 | { |
353 | struct platform_device *pdev; | 353 | struct platform_device *pdev; |
354 | int id, ret; | 354 | int id, ret; |
355 | 355 | ||
356 | id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL); | 356 | id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL); |
357 | if (id < 0) | 357 | if (id < 0) |
358 | return ERR_PTR(id); | 358 | return ERR_PTR(id); |
359 | 359 | ||
360 | pdev = platform_device_alloc("ci_hdrc", id); | 360 | pdev = platform_device_alloc("ci_hdrc", id); |
361 | if (!pdev) { | 361 | if (!pdev) { |
362 | ret = -ENOMEM; | 362 | ret = -ENOMEM; |
363 | goto put_id; | 363 | goto put_id; |
364 | } | 364 | } |
365 | 365 | ||
366 | pdev->dev.parent = dev; | 366 | pdev->dev.parent = dev; |
367 | pdev->dev.dma_mask = dev->dma_mask; | 367 | pdev->dev.dma_mask = dev->dma_mask; |
368 | pdev->dev.dma_parms = dev->dma_parms; | 368 | pdev->dev.dma_parms = dev->dma_parms; |
369 | dma_set_coherent_mask(&pdev->dev, dev->coherent_dma_mask); | 369 | dma_set_coherent_mask(&pdev->dev, dev->coherent_dma_mask); |
370 | 370 | ||
371 | ret = platform_device_add_resources(pdev, res, nres); | 371 | ret = platform_device_add_resources(pdev, res, nres); |
372 | if (ret) | 372 | if (ret) |
373 | goto err; | 373 | goto err; |
374 | 374 | ||
375 | ret = platform_device_add_data(pdev, platdata, sizeof(*platdata)); | 375 | ret = platform_device_add_data(pdev, platdata, sizeof(*platdata)); |
376 | if (ret) | 376 | if (ret) |
377 | goto err; | 377 | goto err; |
378 | 378 | ||
379 | ret = platform_device_add(pdev); | 379 | ret = platform_device_add(pdev); |
380 | if (ret) | 380 | if (ret) |
381 | goto err; | 381 | goto err; |
382 | 382 | ||
383 | return pdev; | 383 | return pdev; |
384 | 384 | ||
385 | err: | 385 | err: |
386 | platform_device_put(pdev); | 386 | platform_device_put(pdev); |
387 | put_id: | 387 | put_id: |
388 | ida_simple_remove(&ci_ida, id); | 388 | ida_simple_remove(&ci_ida, id); |
389 | return ERR_PTR(ret); | 389 | return ERR_PTR(ret); |
390 | } | 390 | } |
391 | EXPORT_SYMBOL_GPL(ci13xxx_add_device); | 391 | EXPORT_SYMBOL_GPL(ci_hdrc_add_device); |
392 | 392 | ||
393 | void ci13xxx_remove_device(struct platform_device *pdev) | 393 | void ci_hdrc_remove_device(struct platform_device *pdev) |
394 | { | 394 | { |
395 | int id = pdev->id; | 395 | int id = pdev->id; |
396 | platform_device_unregister(pdev); | 396 | platform_device_unregister(pdev); |
397 | ida_simple_remove(&ci_ida, id); | 397 | ida_simple_remove(&ci_ida, id); |
398 | } | 398 | } |
399 | EXPORT_SYMBOL_GPL(ci13xxx_remove_device); | 399 | EXPORT_SYMBOL_GPL(ci_hdrc_remove_device); |
400 | 400 | ||
401 | static int ci_hdrc_probe(struct platform_device *pdev) | 401 | static int ci_hdrc_probe(struct platform_device *pdev) |
402 | { | 402 | { |
403 | struct device *dev = &pdev->dev; | 403 | struct device *dev = &pdev->dev; |
404 | struct ci13xxx *ci; | 404 | struct ci_hdrc *ci; |
405 | struct resource *res; | 405 | struct resource *res; |
406 | void __iomem *base; | 406 | void __iomem *base; |
407 | int ret; | 407 | int ret; |
408 | enum usb_dr_mode dr_mode; | 408 | enum usb_dr_mode dr_mode; |
409 | 409 | ||
410 | if (!dev->platform_data) { | 410 | if (!dev->platform_data) { |
411 | dev_err(dev, "platform data missing\n"); | 411 | dev_err(dev, "platform data missing\n"); |
412 | return -ENODEV; | 412 | return -ENODEV; |
413 | } | 413 | } |
414 | 414 | ||
415 | if (!dev->of_node && dev->parent) | 415 | if (!dev->of_node && dev->parent) |
416 | dev->of_node = dev->parent->of_node; | 416 | dev->of_node = dev->parent->of_node; |
417 | 417 | ||
418 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 418 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
419 | base = devm_ioremap_resource(dev, res); | 419 | base = devm_ioremap_resource(dev, res); |
420 | if (IS_ERR(base)) | 420 | if (IS_ERR(base)) |
421 | return PTR_ERR(base); | 421 | return PTR_ERR(base); |
422 | 422 | ||
423 | ci = devm_kzalloc(dev, sizeof(*ci), GFP_KERNEL); | 423 | ci = devm_kzalloc(dev, sizeof(*ci), GFP_KERNEL); |
424 | if (!ci) { | 424 | if (!ci) { |
425 | dev_err(dev, "can't allocate device\n"); | 425 | dev_err(dev, "can't allocate device\n"); |
426 | return -ENOMEM; | 426 | return -ENOMEM; |
427 | } | 427 | } |
428 | 428 | ||
429 | ci->dev = dev; | 429 | ci->dev = dev; |
430 | ci->platdata = dev->platform_data; | 430 | ci->platdata = dev->platform_data; |
431 | if (ci->platdata->phy) | 431 | if (ci->platdata->phy) |
432 | ci->transceiver = ci->platdata->phy; | 432 | ci->transceiver = ci->platdata->phy; |
433 | else | 433 | else |
434 | ci->global_phy = true; | 434 | ci->global_phy = true; |
435 | 435 | ||
436 | ret = hw_device_init(ci, base); | 436 | ret = hw_device_init(ci, base); |
437 | if (ret < 0) { | 437 | if (ret < 0) { |
438 | dev_err(dev, "can't initialize hardware\n"); | 438 | dev_err(dev, "can't initialize hardware\n"); |
439 | return -ENODEV; | 439 | return -ENODEV; |
440 | } | 440 | } |
441 | 441 | ||
442 | ci->hw_bank.phys = res->start; | 442 | ci->hw_bank.phys = res->start; |
443 | 443 | ||
444 | ci->irq = platform_get_irq(pdev, 0); | 444 | ci->irq = platform_get_irq(pdev, 0); |
445 | if (ci->irq < 0) { | 445 | if (ci->irq < 0) { |
446 | dev_err(dev, "missing IRQ\n"); | 446 | dev_err(dev, "missing IRQ\n"); |
447 | return -ENODEV; | 447 | return -ENODEV; |
448 | } | 448 | } |
449 | 449 | ||
450 | INIT_WORK(&ci->work, ci_role_work); | 450 | INIT_WORK(&ci->work, ci_role_work); |
451 | ci->wq = create_singlethread_workqueue("ci_otg"); | 451 | ci->wq = create_singlethread_workqueue("ci_otg"); |
452 | if (!ci->wq) { | 452 | if (!ci->wq) { |
453 | dev_err(dev, "can't create workqueue\n"); | 453 | dev_err(dev, "can't create workqueue\n"); |
454 | return -ENODEV; | 454 | return -ENODEV; |
455 | } | 455 | } |
456 | 456 | ||
457 | if (!ci->platdata->phy_mode) | 457 | if (!ci->platdata->phy_mode) |
458 | ci->platdata->phy_mode = of_usb_get_phy_mode(dev->of_node); | 458 | ci->platdata->phy_mode = of_usb_get_phy_mode(dev->of_node); |
459 | 459 | ||
460 | if (!ci->platdata->dr_mode) | 460 | if (!ci->platdata->dr_mode) |
461 | ci->platdata->dr_mode = of_usb_get_dr_mode(dev->of_node); | 461 | ci->platdata->dr_mode = of_usb_get_dr_mode(dev->of_node); |
462 | 462 | ||
463 | if (ci->platdata->dr_mode == USB_DR_MODE_UNKNOWN) | 463 | if (ci->platdata->dr_mode == USB_DR_MODE_UNKNOWN) |
464 | ci->platdata->dr_mode = USB_DR_MODE_OTG; | 464 | ci->platdata->dr_mode = USB_DR_MODE_OTG; |
465 | 465 | ||
466 | dr_mode = ci->platdata->dr_mode; | 466 | dr_mode = ci->platdata->dr_mode; |
467 | /* initialize role(s) before the interrupt is requested */ | 467 | /* initialize role(s) before the interrupt is requested */ |
468 | if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { | 468 | if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { |
469 | ret = ci_hdrc_host_init(ci); | 469 | ret = ci_hdrc_host_init(ci); |
470 | if (ret) | 470 | if (ret) |
471 | dev_info(dev, "doesn't support host\n"); | 471 | dev_info(dev, "doesn't support host\n"); |
472 | } | 472 | } |
473 | 473 | ||
474 | if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) { | 474 | if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) { |
475 | ret = ci_hdrc_gadget_init(ci); | 475 | ret = ci_hdrc_gadget_init(ci); |
476 | if (ret) | 476 | if (ret) |
477 | dev_info(dev, "doesn't support gadget\n"); | 477 | dev_info(dev, "doesn't support gadget\n"); |
478 | } | 478 | } |
479 | 479 | ||
480 | if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { | 480 | if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { |
481 | dev_err(dev, "no supported roles\n"); | 481 | dev_err(dev, "no supported roles\n"); |
482 | ret = -ENODEV; | 482 | ret = -ENODEV; |
483 | goto rm_wq; | 483 | goto rm_wq; |
484 | } | 484 | } |
485 | 485 | ||
486 | if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) { | 486 | if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) { |
487 | ci->is_otg = true; | 487 | ci->is_otg = true; |
488 | /* ID pin needs 1ms debouce time, we delay 2ms for safe */ | 488 | /* ID pin needs 1ms debouce time, we delay 2ms for safe */ |
489 | mdelay(2); | 489 | mdelay(2); |
490 | ci->role = ci_otg_role(ci); | 490 | ci->role = ci_otg_role(ci); |
491 | } else { | 491 | } else { |
492 | ci->role = ci->roles[CI_ROLE_HOST] | 492 | ci->role = ci->roles[CI_ROLE_HOST] |
493 | ? CI_ROLE_HOST | 493 | ? CI_ROLE_HOST |
494 | : CI_ROLE_GADGET; | 494 | : CI_ROLE_GADGET; |
495 | } | 495 | } |
496 | 496 | ||
497 | ret = ci_role_start(ci, ci->role); | 497 | ret = ci_role_start(ci, ci->role); |
498 | if (ret) { | 498 | if (ret) { |
499 | dev_err(dev, "can't start %s role\n", ci_role(ci)->name); | 499 | dev_err(dev, "can't start %s role\n", ci_role(ci)->name); |
500 | ret = -ENODEV; | 500 | ret = -ENODEV; |
501 | goto rm_wq; | 501 | goto rm_wq; |
502 | } | 502 | } |
503 | 503 | ||
504 | platform_set_drvdata(pdev, ci); | 504 | platform_set_drvdata(pdev, ci); |
505 | ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name, | 505 | ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name, |
506 | ci); | 506 | ci); |
507 | if (ret) | 507 | if (ret) |
508 | goto stop; | 508 | goto stop; |
509 | 509 | ||
510 | if (ci->is_otg) | 510 | if (ci->is_otg) |
511 | hw_write(ci, OP_OTGSC, OTGSC_IDIE, OTGSC_IDIE); | 511 | hw_write(ci, OP_OTGSC, OTGSC_IDIE, OTGSC_IDIE); |
512 | 512 | ||
513 | ret = dbg_create_files(ci); | 513 | ret = dbg_create_files(ci); |
514 | if (!ret) | 514 | if (!ret) |
515 | return 0; | 515 | return 0; |
516 | 516 | ||
517 | free_irq(ci->irq, ci); | 517 | free_irq(ci->irq, ci); |
518 | stop: | 518 | stop: |
519 | ci_role_stop(ci); | 519 | ci_role_stop(ci); |
520 | rm_wq: | 520 | rm_wq: |
521 | flush_workqueue(ci->wq); | 521 | flush_workqueue(ci->wq); |
522 | destroy_workqueue(ci->wq); | 522 | destroy_workqueue(ci->wq); |
523 | 523 | ||
524 | return ret; | 524 | return ret; |
525 | } | 525 | } |
526 | 526 | ||
527 | static int ci_hdrc_remove(struct platform_device *pdev) | 527 | static int ci_hdrc_remove(struct platform_device *pdev) |
528 | { | 528 | { |
529 | struct ci13xxx *ci = platform_get_drvdata(pdev); | 529 | struct ci_hdrc *ci = platform_get_drvdata(pdev); |
530 | 530 | ||
531 | dbg_remove_files(ci); | 531 | dbg_remove_files(ci); |
532 | flush_workqueue(ci->wq); | 532 | flush_workqueue(ci->wq); |
533 | destroy_workqueue(ci->wq); | 533 | destroy_workqueue(ci->wq); |
534 | free_irq(ci->irq, ci); | 534 | free_irq(ci->irq, ci); |
535 | ci_role_stop(ci); | 535 | ci_role_stop(ci); |
536 | 536 | ||
537 | return 0; | 537 | return 0; |
538 | } | 538 | } |
539 | 539 | ||
540 | static struct platform_driver ci_hdrc_driver = { | 540 | static struct platform_driver ci_hdrc_driver = { |
541 | .probe = ci_hdrc_probe, | 541 | .probe = ci_hdrc_probe, |
542 | .remove = ci_hdrc_remove, | 542 | .remove = ci_hdrc_remove, |
543 | .driver = { | 543 | .driver = { |
544 | .name = "ci_hdrc", | 544 | .name = "ci_hdrc", |
545 | }, | 545 | }, |
546 | }; | 546 | }; |
547 | 547 | ||
548 | module_platform_driver(ci_hdrc_driver); | 548 | module_platform_driver(ci_hdrc_driver); |
549 | 549 | ||
550 | MODULE_ALIAS("platform:ci_hdrc"); | 550 | MODULE_ALIAS("platform:ci_hdrc"); |
551 | MODULE_ALIAS("platform:ci13xxx"); | 551 | MODULE_ALIAS("platform:ci13xxx"); |
552 | MODULE_LICENSE("GPL v2"); | 552 | MODULE_LICENSE("GPL v2"); |
553 | MODULE_AUTHOR("David Lopo <dlopo@chipidea.mips.com>"); | 553 | MODULE_AUTHOR("David Lopo <dlopo@chipidea.mips.com>"); |
554 | MODULE_DESCRIPTION("ChipIdea HDRC Driver"); | 554 | MODULE_DESCRIPTION("ChipIdea HDRC Driver"); |
555 | 555 |
drivers/usb/chipidea/debug.c
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/device.h> | 2 | #include <linux/device.h> |
3 | #include <linux/types.h> | 3 | #include <linux/types.h> |
4 | #include <linux/spinlock.h> | 4 | #include <linux/spinlock.h> |
5 | #include <linux/debugfs.h> | 5 | #include <linux/debugfs.h> |
6 | #include <linux/seq_file.h> | 6 | #include <linux/seq_file.h> |
7 | #include <linux/uaccess.h> | 7 | #include <linux/uaccess.h> |
8 | #include <linux/usb/ch9.h> | 8 | #include <linux/usb/ch9.h> |
9 | #include <linux/usb/gadget.h> | 9 | #include <linux/usb/gadget.h> |
10 | 10 | ||
11 | #include "ci.h" | 11 | #include "ci.h" |
12 | #include "udc.h" | 12 | #include "udc.h" |
13 | #include "bits.h" | 13 | #include "bits.h" |
14 | #include "debug.h" | 14 | #include "debug.h" |
15 | 15 | ||
16 | /** | 16 | /** |
17 | * ci_device_show: prints information about device capabilities and status | 17 | * ci_device_show: prints information about device capabilities and status |
18 | */ | 18 | */ |
19 | static int ci_device_show(struct seq_file *s, void *data) | 19 | static int ci_device_show(struct seq_file *s, void *data) |
20 | { | 20 | { |
21 | struct ci13xxx *ci = s->private; | 21 | struct ci_hdrc *ci = s->private; |
22 | struct usb_gadget *gadget = &ci->gadget; | 22 | struct usb_gadget *gadget = &ci->gadget; |
23 | 23 | ||
24 | seq_printf(s, "speed = %d\n", gadget->speed); | 24 | seq_printf(s, "speed = %d\n", gadget->speed); |
25 | seq_printf(s, "max_speed = %d\n", gadget->max_speed); | 25 | seq_printf(s, "max_speed = %d\n", gadget->max_speed); |
26 | seq_printf(s, "is_otg = %d\n", gadget->is_otg); | 26 | seq_printf(s, "is_otg = %d\n", gadget->is_otg); |
27 | seq_printf(s, "is_a_peripheral = %d\n", gadget->is_a_peripheral); | 27 | seq_printf(s, "is_a_peripheral = %d\n", gadget->is_a_peripheral); |
28 | seq_printf(s, "b_hnp_enable = %d\n", gadget->b_hnp_enable); | 28 | seq_printf(s, "b_hnp_enable = %d\n", gadget->b_hnp_enable); |
29 | seq_printf(s, "a_hnp_support = %d\n", gadget->a_hnp_support); | 29 | seq_printf(s, "a_hnp_support = %d\n", gadget->a_hnp_support); |
30 | seq_printf(s, "a_alt_hnp_support = %d\n", gadget->a_alt_hnp_support); | 30 | seq_printf(s, "a_alt_hnp_support = %d\n", gadget->a_alt_hnp_support); |
31 | seq_printf(s, "name = %s\n", | 31 | seq_printf(s, "name = %s\n", |
32 | (gadget->name ? gadget->name : "")); | 32 | (gadget->name ? gadget->name : "")); |
33 | 33 | ||
34 | if (!ci->driver) | 34 | if (!ci->driver) |
35 | return 0; | 35 | return 0; |
36 | 36 | ||
37 | seq_printf(s, "gadget function = %s\n", | 37 | seq_printf(s, "gadget function = %s\n", |
38 | (ci->driver->function ? ci->driver->function : "")); | 38 | (ci->driver->function ? ci->driver->function : "")); |
39 | seq_printf(s, "gadget max speed = %d\n", ci->driver->max_speed); | 39 | seq_printf(s, "gadget max speed = %d\n", ci->driver->max_speed); |
40 | 40 | ||
41 | return 0; | 41 | return 0; |
42 | } | 42 | } |
43 | 43 | ||
44 | static int ci_device_open(struct inode *inode, struct file *file) | 44 | static int ci_device_open(struct inode *inode, struct file *file) |
45 | { | 45 | { |
46 | return single_open(file, ci_device_show, inode->i_private); | 46 | return single_open(file, ci_device_show, inode->i_private); |
47 | } | 47 | } |
48 | 48 | ||
49 | static const struct file_operations ci_device_fops = { | 49 | static const struct file_operations ci_device_fops = { |
50 | .open = ci_device_open, | 50 | .open = ci_device_open, |
51 | .read = seq_read, | 51 | .read = seq_read, |
52 | .llseek = seq_lseek, | 52 | .llseek = seq_lseek, |
53 | .release = single_release, | 53 | .release = single_release, |
54 | }; | 54 | }; |
55 | 55 | ||
56 | /** | 56 | /** |
57 | * ci_port_test_show: reads port test mode | 57 | * ci_port_test_show: reads port test mode |
58 | */ | 58 | */ |
59 | static int ci_port_test_show(struct seq_file *s, void *data) | 59 | static int ci_port_test_show(struct seq_file *s, void *data) |
60 | { | 60 | { |
61 | struct ci13xxx *ci = s->private; | 61 | struct ci_hdrc *ci = s->private; |
62 | unsigned long flags; | 62 | unsigned long flags; |
63 | unsigned mode; | 63 | unsigned mode; |
64 | 64 | ||
65 | spin_lock_irqsave(&ci->lock, flags); | 65 | spin_lock_irqsave(&ci->lock, flags); |
66 | mode = hw_port_test_get(ci); | 66 | mode = hw_port_test_get(ci); |
67 | spin_unlock_irqrestore(&ci->lock, flags); | 67 | spin_unlock_irqrestore(&ci->lock, flags); |
68 | 68 | ||
69 | seq_printf(s, "mode = %u\n", mode); | 69 | seq_printf(s, "mode = %u\n", mode); |
70 | 70 | ||
71 | return 0; | 71 | return 0; |
72 | } | 72 | } |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * ci_port_test_write: writes port test mode | 75 | * ci_port_test_write: writes port test mode |
76 | */ | 76 | */ |
77 | static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf, | 77 | static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf, |
78 | size_t count, loff_t *ppos) | 78 | size_t count, loff_t *ppos) |
79 | { | 79 | { |
80 | struct seq_file *s = file->private_data; | 80 | struct seq_file *s = file->private_data; |
81 | struct ci13xxx *ci = s->private; | 81 | struct ci_hdrc *ci = s->private; |
82 | unsigned long flags; | 82 | unsigned long flags; |
83 | unsigned mode; | 83 | unsigned mode; |
84 | char buf[32]; | 84 | char buf[32]; |
85 | int ret; | 85 | int ret; |
86 | 86 | ||
87 | if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | 87 | if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) |
88 | return -EFAULT; | 88 | return -EFAULT; |
89 | 89 | ||
90 | if (sscanf(buf, "%u", &mode) != 1) | 90 | if (sscanf(buf, "%u", &mode) != 1) |
91 | return -EINVAL; | 91 | return -EINVAL; |
92 | 92 | ||
93 | spin_lock_irqsave(&ci->lock, flags); | 93 | spin_lock_irqsave(&ci->lock, flags); |
94 | ret = hw_port_test_set(ci, mode); | 94 | ret = hw_port_test_set(ci, mode); |
95 | spin_unlock_irqrestore(&ci->lock, flags); | 95 | spin_unlock_irqrestore(&ci->lock, flags); |
96 | 96 | ||
97 | return ret ? ret : count; | 97 | return ret ? ret : count; |
98 | } | 98 | } |
99 | 99 | ||
100 | static int ci_port_test_open(struct inode *inode, struct file *file) | 100 | static int ci_port_test_open(struct inode *inode, struct file *file) |
101 | { | 101 | { |
102 | return single_open(file, ci_port_test_show, inode->i_private); | 102 | return single_open(file, ci_port_test_show, inode->i_private); |
103 | } | 103 | } |
104 | 104 | ||
105 | static const struct file_operations ci_port_test_fops = { | 105 | static const struct file_operations ci_port_test_fops = { |
106 | .open = ci_port_test_open, | 106 | .open = ci_port_test_open, |
107 | .write = ci_port_test_write, | 107 | .write = ci_port_test_write, |
108 | .read = seq_read, | 108 | .read = seq_read, |
109 | .llseek = seq_lseek, | 109 | .llseek = seq_lseek, |
110 | .release = single_release, | 110 | .release = single_release, |
111 | }; | 111 | }; |
112 | 112 | ||
113 | /** | 113 | /** |
114 | * ci_qheads_show: DMA contents of all queue heads | 114 | * ci_qheads_show: DMA contents of all queue heads |
115 | */ | 115 | */ |
116 | static int ci_qheads_show(struct seq_file *s, void *data) | 116 | static int ci_qheads_show(struct seq_file *s, void *data) |
117 | { | 117 | { |
118 | struct ci13xxx *ci = s->private; | 118 | struct ci_hdrc *ci = s->private; |
119 | unsigned long flags; | 119 | unsigned long flags; |
120 | unsigned i, j; | 120 | unsigned i, j; |
121 | 121 | ||
122 | if (ci->role != CI_ROLE_GADGET) { | 122 | if (ci->role != CI_ROLE_GADGET) { |
123 | seq_printf(s, "not in gadget mode\n"); | 123 | seq_printf(s, "not in gadget mode\n"); |
124 | return 0; | 124 | return 0; |
125 | } | 125 | } |
126 | 126 | ||
127 | spin_lock_irqsave(&ci->lock, flags); | 127 | spin_lock_irqsave(&ci->lock, flags); |
128 | for (i = 0; i < ci->hw_ep_max/2; i++) { | 128 | for (i = 0; i < ci->hw_ep_max/2; i++) { |
129 | struct ci13xxx_ep *hweprx = &ci->ci13xxx_ep[i]; | 129 | struct ci_hw_ep *hweprx = &ci->ci_hw_ep[i]; |
130 | struct ci13xxx_ep *hweptx = | 130 | struct ci_hw_ep *hweptx = |
131 | &ci->ci13xxx_ep[i + ci->hw_ep_max/2]; | 131 | &ci->ci_hw_ep[i + ci->hw_ep_max/2]; |
132 | seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n", | 132 | seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n", |
133 | i, (u32)hweprx->qh.dma, (u32)hweptx->qh.dma); | 133 | i, (u32)hweprx->qh.dma, (u32)hweptx->qh.dma); |
134 | for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) | 134 | for (j = 0; j < (sizeof(struct ci_hw_qh)/sizeof(u32)); j++) |
135 | seq_printf(s, " %04X: %08X %08X\n", j, | 135 | seq_printf(s, " %04X: %08X %08X\n", j, |
136 | *((u32 *)hweprx->qh.ptr + j), | 136 | *((u32 *)hweprx->qh.ptr + j), |
137 | *((u32 *)hweptx->qh.ptr + j)); | 137 | *((u32 *)hweptx->qh.ptr + j)); |
138 | } | 138 | } |
139 | spin_unlock_irqrestore(&ci->lock, flags); | 139 | spin_unlock_irqrestore(&ci->lock, flags); |
140 | 140 | ||
141 | return 0; | 141 | return 0; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int ci_qheads_open(struct inode *inode, struct file *file) | 144 | static int ci_qheads_open(struct inode *inode, struct file *file) |
145 | { | 145 | { |
146 | return single_open(file, ci_qheads_show, inode->i_private); | 146 | return single_open(file, ci_qheads_show, inode->i_private); |
147 | } | 147 | } |
148 | 148 | ||
149 | static const struct file_operations ci_qheads_fops = { | 149 | static const struct file_operations ci_qheads_fops = { |
150 | .open = ci_qheads_open, | 150 | .open = ci_qheads_open, |
151 | .read = seq_read, | 151 | .read = seq_read, |
152 | .llseek = seq_lseek, | 152 | .llseek = seq_lseek, |
153 | .release = single_release, | 153 | .release = single_release, |
154 | }; | 154 | }; |
155 | 155 | ||
156 | /** | 156 | /** |
157 | * ci_requests_show: DMA contents of all requests currently queued (all endpts) | 157 | * ci_requests_show: DMA contents of all requests currently queued (all endpts) |
158 | */ | 158 | */ |
159 | static int ci_requests_show(struct seq_file *s, void *data) | 159 | static int ci_requests_show(struct seq_file *s, void *data) |
160 | { | 160 | { |
161 | struct ci13xxx *ci = s->private; | 161 | struct ci_hdrc *ci = s->private; |
162 | unsigned long flags; | 162 | unsigned long flags; |
163 | struct list_head *ptr = NULL; | 163 | struct list_head *ptr = NULL; |
164 | struct ci13xxx_req *req = NULL; | 164 | struct ci_hw_req *req = NULL; |
165 | struct td_node *node, *tmpnode; | 165 | struct td_node *node, *tmpnode; |
166 | unsigned i, j, qsize = sizeof(struct ci13xxx_td)/sizeof(u32); | 166 | unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32); |
167 | 167 | ||
168 | if (ci->role != CI_ROLE_GADGET) { | 168 | if (ci->role != CI_ROLE_GADGET) { |
169 | seq_printf(s, "not in gadget mode\n"); | 169 | seq_printf(s, "not in gadget mode\n"); |
170 | return 0; | 170 | return 0; |
171 | } | 171 | } |
172 | 172 | ||
173 | spin_lock_irqsave(&ci->lock, flags); | 173 | spin_lock_irqsave(&ci->lock, flags); |
174 | for (i = 0; i < ci->hw_ep_max; i++) | 174 | for (i = 0; i < ci->hw_ep_max; i++) |
175 | list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) { | 175 | list_for_each(ptr, &ci->ci_hw_ep[i].qh.queue) { |
176 | req = list_entry(ptr, struct ci13xxx_req, queue); | 176 | req = list_entry(ptr, struct ci_hw_req, queue); |
177 | 177 | ||
178 | list_for_each_entry_safe(node, tmpnode, &req->tds, td) { | 178 | list_for_each_entry_safe(node, tmpnode, &req->tds, td) { |
179 | seq_printf(s, "EP=%02i: TD=%08X %s\n", | 179 | seq_printf(s, "EP=%02i: TD=%08X %s\n", |
180 | i % (ci->hw_ep_max / 2), | 180 | i % (ci->hw_ep_max / 2), |
181 | (u32)node->dma, | 181 | (u32)node->dma, |
182 | ((i < ci->hw_ep_max/2) ? | 182 | ((i < ci->hw_ep_max/2) ? |
183 | "RX" : "TX")); | 183 | "RX" : "TX")); |
184 | 184 | ||
185 | for (j = 0; j < qsize; j++) | 185 | for (j = 0; j < qsize; j++) |
186 | seq_printf(s, " %04X: %08X\n", j, | 186 | seq_printf(s, " %04X: %08X\n", j, |
187 | *((u32 *)node->ptr + j)); | 187 | *((u32 *)node->ptr + j)); |
188 | } | 188 | } |
189 | } | 189 | } |
190 | spin_unlock_irqrestore(&ci->lock, flags); | 190 | spin_unlock_irqrestore(&ci->lock, flags); |
191 | 191 | ||
192 | return 0; | 192 | return 0; |
193 | } | 193 | } |
194 | 194 | ||
195 | static int ci_requests_open(struct inode *inode, struct file *file) | 195 | static int ci_requests_open(struct inode *inode, struct file *file) |
196 | { | 196 | { |
197 | return single_open(file, ci_requests_show, inode->i_private); | 197 | return single_open(file, ci_requests_show, inode->i_private); |
198 | } | 198 | } |
199 | 199 | ||
200 | static const struct file_operations ci_requests_fops = { | 200 | static const struct file_operations ci_requests_fops = { |
201 | .open = ci_requests_open, | 201 | .open = ci_requests_open, |
202 | .read = seq_read, | 202 | .read = seq_read, |
203 | .llseek = seq_lseek, | 203 | .llseek = seq_lseek, |
204 | .release = single_release, | 204 | .release = single_release, |
205 | }; | 205 | }; |
206 | 206 | ||
207 | static int ci_role_show(struct seq_file *s, void *data) | 207 | static int ci_role_show(struct seq_file *s, void *data) |
208 | { | 208 | { |
209 | struct ci13xxx *ci = s->private; | 209 | struct ci_hdrc *ci = s->private; |
210 | 210 | ||
211 | seq_printf(s, "%s\n", ci_role(ci)->name); | 211 | seq_printf(s, "%s\n", ci_role(ci)->name); |
212 | 212 | ||
213 | return 0; | 213 | return 0; |
214 | } | 214 | } |
215 | 215 | ||
216 | static ssize_t ci_role_write(struct file *file, const char __user *ubuf, | 216 | static ssize_t ci_role_write(struct file *file, const char __user *ubuf, |
217 | size_t count, loff_t *ppos) | 217 | size_t count, loff_t *ppos) |
218 | { | 218 | { |
219 | struct seq_file *s = file->private_data; | 219 | struct seq_file *s = file->private_data; |
220 | struct ci13xxx *ci = s->private; | 220 | struct ci_hdrc *ci = s->private; |
221 | enum ci_role role; | 221 | enum ci_role role; |
222 | char buf[8]; | 222 | char buf[8]; |
223 | int ret; | 223 | int ret; |
224 | 224 | ||
225 | if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | 225 | if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) |
226 | return -EFAULT; | 226 | return -EFAULT; |
227 | 227 | ||
228 | for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++) | 228 | for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++) |
229 | if (ci->roles[role] && | 229 | if (ci->roles[role] && |
230 | !strncmp(buf, ci->roles[role]->name, | 230 | !strncmp(buf, ci->roles[role]->name, |
231 | strlen(ci->roles[role]->name))) | 231 | strlen(ci->roles[role]->name))) |
232 | break; | 232 | break; |
233 | 233 | ||
234 | if (role == CI_ROLE_END || role == ci->role) | 234 | if (role == CI_ROLE_END || role == ci->role) |
235 | return -EINVAL; | 235 | return -EINVAL; |
236 | 236 | ||
237 | ci_role_stop(ci); | 237 | ci_role_stop(ci); |
238 | ret = ci_role_start(ci, role); | 238 | ret = ci_role_start(ci, role); |
239 | 239 | ||
240 | return ret ? ret : count; | 240 | return ret ? ret : count; |
241 | } | 241 | } |
242 | 242 | ||
243 | static int ci_role_open(struct inode *inode, struct file *file) | 243 | static int ci_role_open(struct inode *inode, struct file *file) |
244 | { | 244 | { |
245 | return single_open(file, ci_role_show, inode->i_private); | 245 | return single_open(file, ci_role_show, inode->i_private); |
246 | } | 246 | } |
247 | 247 | ||
248 | static const struct file_operations ci_role_fops = { | 248 | static const struct file_operations ci_role_fops = { |
249 | .open = ci_role_open, | 249 | .open = ci_role_open, |
250 | .write = ci_role_write, | 250 | .write = ci_role_write, |
251 | .read = seq_read, | 251 | .read = seq_read, |
252 | .llseek = seq_lseek, | 252 | .llseek = seq_lseek, |
253 | .release = single_release, | 253 | .release = single_release, |
254 | }; | 254 | }; |
255 | 255 | ||
256 | /** | 256 | /** |
257 | * dbg_create_files: initializes the attribute interface | 257 | * dbg_create_files: initializes the attribute interface |
258 | * @ci: device | 258 | * @ci: device |
259 | * | 259 | * |
260 | * This function returns an error code | 260 | * This function returns an error code |
261 | */ | 261 | */ |
262 | int dbg_create_files(struct ci13xxx *ci) | 262 | int dbg_create_files(struct ci_hdrc *ci) |
263 | { | 263 | { |
264 | struct dentry *dent; | 264 | struct dentry *dent; |
265 | 265 | ||
266 | ci->debugfs = debugfs_create_dir(dev_name(ci->dev), NULL); | 266 | ci->debugfs = debugfs_create_dir(dev_name(ci->dev), NULL); |
267 | if (!ci->debugfs) | 267 | if (!ci->debugfs) |
268 | return -ENOMEM; | 268 | return -ENOMEM; |
269 | 269 | ||
270 | dent = debugfs_create_file("device", S_IRUGO, ci->debugfs, ci, | 270 | dent = debugfs_create_file("device", S_IRUGO, ci->debugfs, ci, |
271 | &ci_device_fops); | 271 | &ci_device_fops); |
272 | if (!dent) | 272 | if (!dent) |
273 | goto err; | 273 | goto err; |
274 | 274 | ||
275 | dent = debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs, | 275 | dent = debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs, |
276 | ci, &ci_port_test_fops); | 276 | ci, &ci_port_test_fops); |
277 | if (!dent) | 277 | if (!dent) |
278 | goto err; | 278 | goto err; |
279 | 279 | ||
280 | dent = debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci, | 280 | dent = debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci, |
281 | &ci_qheads_fops); | 281 | &ci_qheads_fops); |
282 | if (!dent) | 282 | if (!dent) |
283 | goto err; | 283 | goto err; |
284 | 284 | ||
285 | dent = debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci, | 285 | dent = debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci, |
286 | &ci_requests_fops); | 286 | &ci_requests_fops); |
287 | if (!dent) | 287 | if (!dent) |
288 | goto err; | 288 | goto err; |
289 | 289 | ||
290 | dent = debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci, | 290 | dent = debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci, |
291 | &ci_role_fops); | 291 | &ci_role_fops); |
292 | if (dent) | 292 | if (dent) |
293 | return 0; | 293 | return 0; |
294 | err: | 294 | err: |
295 | debugfs_remove_recursive(ci->debugfs); | 295 | debugfs_remove_recursive(ci->debugfs); |
296 | return -ENOMEM; | 296 | return -ENOMEM; |
297 | } | 297 | } |
298 | 298 | ||
299 | /** | 299 | /** |
300 | * dbg_remove_files: destroys the attribute interface | 300 | * dbg_remove_files: destroys the attribute interface |
301 | * @ci: device | 301 | * @ci: device |
302 | */ | 302 | */ |
303 | void dbg_remove_files(struct ci13xxx *ci) | 303 | void dbg_remove_files(struct ci_hdrc *ci) |
304 | { | 304 | { |
305 | debugfs_remove_recursive(ci->debugfs); | 305 | debugfs_remove_recursive(ci->debugfs); |
306 | } | 306 | } |
307 | 307 |
drivers/usb/chipidea/debug.h
1 | /* | 1 | /* |
2 | * debug.h - ChipIdea USB driver debug interfaces | 2 | * debug.h - ChipIdea USB driver debug interfaces |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | 4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. |
5 | * | 5 | * |
6 | * Author: David Lopo | 6 | * Author: David Lopo |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #ifndef __DRIVERS_USB_CHIPIDEA_DEBUG_H | 13 | #ifndef __DRIVERS_USB_CHIPIDEA_DEBUG_H |
14 | #define __DRIVERS_USB_CHIPIDEA_DEBUG_H | 14 | #define __DRIVERS_USB_CHIPIDEA_DEBUG_H |
15 | 15 | ||
16 | #ifdef CONFIG_USB_CHIPIDEA_DEBUG | 16 | #ifdef CONFIG_USB_CHIPIDEA_DEBUG |
17 | int dbg_create_files(struct ci13xxx *ci); | 17 | int dbg_create_files(struct ci_hdrc *ci); |
18 | void dbg_remove_files(struct ci13xxx *ci); | 18 | void dbg_remove_files(struct ci_hdrc *ci); |
19 | #else | 19 | #else |
20 | static inline int dbg_create_files(struct ci13xxx *ci) | 20 | static inline int dbg_create_files(struct ci_hdrc *ci) |
21 | { | 21 | { |
22 | return 0; | 22 | return 0; |
23 | } | 23 | } |
24 | 24 | ||
25 | static inline void dbg_remove_files(struct ci13xxx *ci) | 25 | static inline void dbg_remove_files(struct ci_hdrc *ci) |
26 | { | 26 | { |
27 | } | 27 | } |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #endif /* __DRIVERS_USB_CHIPIDEA_DEBUG_H */ | 30 | #endif /* __DRIVERS_USB_CHIPIDEA_DEBUG_H */ |
31 | 31 |
drivers/usb/chipidea/host.c
1 | /* | 1 | /* |
2 | * host.c - ChipIdea USB host controller driver | 2 | * host.c - ChipIdea USB host controller driver |
3 | * | 3 | * |
4 | * Copyright (c) 2012 Intel Corporation | 4 | * Copyright (c) 2012 Intel Corporation |
5 | * | 5 | * |
6 | * Author: Alexander Shishkin | 6 | * Author: Alexander Shishkin |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | * | 11 | * |
12 | * This program is distributed in the hope that it will be useful, | 12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | * | 16 | * |
17 | * You should have received a copy of the GNU General Public License | 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 | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/usb.h> | 24 | #include <linux/usb.h> |
25 | #include <linux/usb/hcd.h> | 25 | #include <linux/usb/hcd.h> |
26 | #include <linux/usb/chipidea.h> | 26 | #include <linux/usb/chipidea.h> |
27 | 27 | ||
28 | #include "../host/ehci.h" | 28 | #include "../host/ehci.h" |
29 | 29 | ||
30 | #include "ci.h" | 30 | #include "ci.h" |
31 | #include "bits.h" | 31 | #include "bits.h" |
32 | #include "host.h" | 32 | #include "host.h" |
33 | 33 | ||
34 | static struct hc_driver __read_mostly ci_ehci_hc_driver; | 34 | static struct hc_driver __read_mostly ci_ehci_hc_driver; |
35 | 35 | ||
36 | static irqreturn_t host_irq(struct ci13xxx *ci) | 36 | static irqreturn_t host_irq(struct ci_hdrc *ci) |
37 | { | 37 | { |
38 | return usb_hcd_irq(ci->irq, ci->hcd); | 38 | return usb_hcd_irq(ci->irq, ci->hcd); |
39 | } | 39 | } |
40 | 40 | ||
41 | static int host_start(struct ci13xxx *ci) | 41 | static int host_start(struct ci_hdrc *ci) |
42 | { | 42 | { |
43 | struct usb_hcd *hcd; | 43 | struct usb_hcd *hcd; |
44 | struct ehci_hcd *ehci; | 44 | struct ehci_hcd *ehci; |
45 | int ret; | 45 | int ret; |
46 | 46 | ||
47 | if (usb_disabled()) | 47 | if (usb_disabled()) |
48 | return -ENODEV; | 48 | return -ENODEV; |
49 | 49 | ||
50 | hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev)); | 50 | hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev)); |
51 | if (!hcd) | 51 | if (!hcd) |
52 | return -ENOMEM; | 52 | return -ENOMEM; |
53 | 53 | ||
54 | dev_set_drvdata(ci->dev, ci); | 54 | dev_set_drvdata(ci->dev, ci); |
55 | hcd->rsrc_start = ci->hw_bank.phys; | 55 | hcd->rsrc_start = ci->hw_bank.phys; |
56 | hcd->rsrc_len = ci->hw_bank.size; | 56 | hcd->rsrc_len = ci->hw_bank.size; |
57 | hcd->regs = ci->hw_bank.abs; | 57 | hcd->regs = ci->hw_bank.abs; |
58 | hcd->has_tt = 1; | 58 | hcd->has_tt = 1; |
59 | 59 | ||
60 | hcd->power_budget = ci->platdata->power_budget; | 60 | hcd->power_budget = ci->platdata->power_budget; |
61 | hcd->phy = ci->transceiver; | 61 | hcd->phy = ci->transceiver; |
62 | 62 | ||
63 | ehci = hcd_to_ehci(hcd); | 63 | ehci = hcd_to_ehci(hcd); |
64 | ehci->caps = ci->hw_bank.cap; | 64 | ehci->caps = ci->hw_bank.cap; |
65 | ehci->has_hostpc = ci->hw_bank.lpm; | 65 | ehci->has_hostpc = ci->hw_bank.lpm; |
66 | 66 | ||
67 | ret = usb_add_hcd(hcd, 0, 0); | 67 | ret = usb_add_hcd(hcd, 0, 0); |
68 | if (ret) | 68 | if (ret) |
69 | usb_put_hcd(hcd); | 69 | usb_put_hcd(hcd); |
70 | else | 70 | else |
71 | ci->hcd = hcd; | 71 | ci->hcd = hcd; |
72 | 72 | ||
73 | if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) | 73 | if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) |
74 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); | 74 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); |
75 | 75 | ||
76 | return ret; | 76 | return ret; |
77 | } | 77 | } |
78 | 78 | ||
79 | static void host_stop(struct ci13xxx *ci) | 79 | static void host_stop(struct ci_hdrc *ci) |
80 | { | 80 | { |
81 | struct usb_hcd *hcd = ci->hcd; | 81 | struct usb_hcd *hcd = ci->hcd; |
82 | 82 | ||
83 | usb_remove_hcd(hcd); | 83 | usb_remove_hcd(hcd); |
84 | usb_put_hcd(hcd); | 84 | usb_put_hcd(hcd); |
85 | } | 85 | } |
86 | 86 | ||
87 | int ci_hdrc_host_init(struct ci13xxx *ci) | 87 | int ci_hdrc_host_init(struct ci_hdrc *ci) |
88 | { | 88 | { |
89 | struct ci_role_driver *rdrv; | 89 | struct ci_role_driver *rdrv; |
90 | 90 | ||
91 | if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_HC)) | 91 | if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_HC)) |
92 | return -ENXIO; | 92 | return -ENXIO; |
93 | 93 | ||
94 | rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL); | 94 | rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL); |
95 | if (!rdrv) | 95 | if (!rdrv) |
96 | return -ENOMEM; | 96 | return -ENOMEM; |
97 | 97 | ||
98 | rdrv->start = host_start; | 98 | rdrv->start = host_start; |
99 | rdrv->stop = host_stop; | 99 | rdrv->stop = host_stop; |
100 | rdrv->irq = host_irq; | 100 | rdrv->irq = host_irq; |
101 | rdrv->name = "host"; | 101 | rdrv->name = "host"; |
102 | ci->roles[CI_ROLE_HOST] = rdrv; | 102 | ci->roles[CI_ROLE_HOST] = rdrv; |
103 | 103 | ||
104 | ehci_init_driver(&ci_ehci_hc_driver, NULL); | 104 | ehci_init_driver(&ci_ehci_hc_driver, NULL); |
105 | 105 | ||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 |
drivers/usb/chipidea/host.h
1 | #ifndef __DRIVERS_USB_CHIPIDEA_HOST_H | 1 | #ifndef __DRIVERS_USB_CHIPIDEA_HOST_H |
2 | #define __DRIVERS_USB_CHIPIDEA_HOST_H | 2 | #define __DRIVERS_USB_CHIPIDEA_HOST_H |
3 | 3 | ||
4 | #ifdef CONFIG_USB_CHIPIDEA_HOST | 4 | #ifdef CONFIG_USB_CHIPIDEA_HOST |
5 | 5 | ||
6 | int ci_hdrc_host_init(struct ci13xxx *ci); | 6 | int ci_hdrc_host_init(struct ci_hdrc *ci); |
7 | 7 | ||
8 | #else | 8 | #else |
9 | 9 | ||
10 | static inline int ci_hdrc_host_init(struct ci13xxx *ci) | 10 | static inline int ci_hdrc_host_init(struct ci_hdrc *ci) |
11 | { | 11 | { |
12 | return -ENXIO; | 12 | return -ENXIO; |
13 | } | 13 | } |
14 | 14 | ||
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | #endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */ | 17 | #endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */ |
18 | 18 |
drivers/usb/chipidea/udc.c
1 | /* | 1 | /* |
2 | * udc.c - ChipIdea UDC driver | 2 | * udc.c - ChipIdea UDC driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | 4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. |
5 | * | 5 | * |
6 | * Author: David Lopo | 6 | * Author: David Lopo |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/dmapool.h> | 15 | #include <linux/dmapool.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/irqreturn.h> | 17 | #include <linux/irqreturn.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
21 | #include <linux/usb/ch9.h> | 21 | #include <linux/usb/ch9.h> |
22 | #include <linux/usb/gadget.h> | 22 | #include <linux/usb/gadget.h> |
23 | #include <linux/usb/otg.h> | 23 | #include <linux/usb/otg.h> |
24 | #include <linux/usb/chipidea.h> | 24 | #include <linux/usb/chipidea.h> |
25 | 25 | ||
26 | #include "ci.h" | 26 | #include "ci.h" |
27 | #include "udc.h" | 27 | #include "udc.h" |
28 | #include "bits.h" | 28 | #include "bits.h" |
29 | #include "debug.h" | 29 | #include "debug.h" |
30 | 30 | ||
31 | /* control endpoint description */ | 31 | /* control endpoint description */ |
32 | static const struct usb_endpoint_descriptor | 32 | static const struct usb_endpoint_descriptor |
33 | ctrl_endpt_out_desc = { | 33 | ctrl_endpt_out_desc = { |
34 | .bLength = USB_DT_ENDPOINT_SIZE, | 34 | .bLength = USB_DT_ENDPOINT_SIZE, |
35 | .bDescriptorType = USB_DT_ENDPOINT, | 35 | .bDescriptorType = USB_DT_ENDPOINT, |
36 | 36 | ||
37 | .bEndpointAddress = USB_DIR_OUT, | 37 | .bEndpointAddress = USB_DIR_OUT, |
38 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | 38 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, |
39 | .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), | 39 | .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static const struct usb_endpoint_descriptor | 42 | static const struct usb_endpoint_descriptor |
43 | ctrl_endpt_in_desc = { | 43 | ctrl_endpt_in_desc = { |
44 | .bLength = USB_DT_ENDPOINT_SIZE, | 44 | .bLength = USB_DT_ENDPOINT_SIZE, |
45 | .bDescriptorType = USB_DT_ENDPOINT, | 45 | .bDescriptorType = USB_DT_ENDPOINT, |
46 | 46 | ||
47 | .bEndpointAddress = USB_DIR_IN, | 47 | .bEndpointAddress = USB_DIR_IN, |
48 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | 48 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, |
49 | .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), | 49 | .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), |
50 | }; | 50 | }; |
51 | 51 | ||
52 | /** | 52 | /** |
53 | * hw_ep_bit: calculates the bit number | 53 | * hw_ep_bit: calculates the bit number |
54 | * @num: endpoint number | 54 | * @num: endpoint number |
55 | * @dir: endpoint direction | 55 | * @dir: endpoint direction |
56 | * | 56 | * |
57 | * This function returns bit number | 57 | * This function returns bit number |
58 | */ | 58 | */ |
59 | static inline int hw_ep_bit(int num, int dir) | 59 | static inline int hw_ep_bit(int num, int dir) |
60 | { | 60 | { |
61 | return num + (dir ? 16 : 0); | 61 | return num + (dir ? 16 : 0); |
62 | } | 62 | } |
63 | 63 | ||
64 | static inline int ep_to_bit(struct ci13xxx *ci, int n) | 64 | static inline int ep_to_bit(struct ci_hdrc *ci, int n) |
65 | { | 65 | { |
66 | int fill = 16 - ci->hw_ep_max / 2; | 66 | int fill = 16 - ci->hw_ep_max / 2; |
67 | 67 | ||
68 | if (n >= ci->hw_ep_max / 2) | 68 | if (n >= ci->hw_ep_max / 2) |
69 | n += fill; | 69 | n += fill; |
70 | 70 | ||
71 | return n; | 71 | return n; |
72 | } | 72 | } |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * hw_device_state: enables/disables interrupts (execute without interruption) | 75 | * hw_device_state: enables/disables interrupts (execute without interruption) |
76 | * @dma: 0 => disable, !0 => enable and set dma engine | 76 | * @dma: 0 => disable, !0 => enable and set dma engine |
77 | * | 77 | * |
78 | * This function returns an error code | 78 | * This function returns an error code |
79 | */ | 79 | */ |
80 | static int hw_device_state(struct ci13xxx *ci, u32 dma) | 80 | static int hw_device_state(struct ci_hdrc *ci, u32 dma) |
81 | { | 81 | { |
82 | if (dma) { | 82 | if (dma) { |
83 | hw_write(ci, OP_ENDPTLISTADDR, ~0, dma); | 83 | hw_write(ci, OP_ENDPTLISTADDR, ~0, dma); |
84 | /* interrupt, error, port change, reset, sleep/suspend */ | 84 | /* interrupt, error, port change, reset, sleep/suspend */ |
85 | hw_write(ci, OP_USBINTR, ~0, | 85 | hw_write(ci, OP_USBINTR, ~0, |
86 | USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); | 86 | USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); |
87 | } else { | 87 | } else { |
88 | hw_write(ci, OP_USBINTR, ~0, 0); | 88 | hw_write(ci, OP_USBINTR, ~0, 0); |
89 | } | 89 | } |
90 | return 0; | 90 | return 0; |
91 | } | 91 | } |
92 | 92 | ||
93 | /** | 93 | /** |
94 | * hw_ep_flush: flush endpoint fifo (execute without interruption) | 94 | * hw_ep_flush: flush endpoint fifo (execute without interruption) |
95 | * @num: endpoint number | 95 | * @num: endpoint number |
96 | * @dir: endpoint direction | 96 | * @dir: endpoint direction |
97 | * | 97 | * |
98 | * This function returns an error code | 98 | * This function returns an error code |
99 | */ | 99 | */ |
100 | static int hw_ep_flush(struct ci13xxx *ci, int num, int dir) | 100 | static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir) |
101 | { | 101 | { |
102 | int n = hw_ep_bit(num, dir); | 102 | int n = hw_ep_bit(num, dir); |
103 | 103 | ||
104 | do { | 104 | do { |
105 | /* flush any pending transfer */ | 105 | /* flush any pending transfer */ |
106 | hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n)); | 106 | hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n)); |
107 | while (hw_read(ci, OP_ENDPTFLUSH, BIT(n))) | 107 | while (hw_read(ci, OP_ENDPTFLUSH, BIT(n))) |
108 | cpu_relax(); | 108 | cpu_relax(); |
109 | } while (hw_read(ci, OP_ENDPTSTAT, BIT(n))); | 109 | } while (hw_read(ci, OP_ENDPTSTAT, BIT(n))); |
110 | 110 | ||
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
113 | 113 | ||
114 | /** | 114 | /** |
115 | * hw_ep_disable: disables endpoint (execute without interruption) | 115 | * hw_ep_disable: disables endpoint (execute without interruption) |
116 | * @num: endpoint number | 116 | * @num: endpoint number |
117 | * @dir: endpoint direction | 117 | * @dir: endpoint direction |
118 | * | 118 | * |
119 | * This function returns an error code | 119 | * This function returns an error code |
120 | */ | 120 | */ |
121 | static int hw_ep_disable(struct ci13xxx *ci, int num, int dir) | 121 | static int hw_ep_disable(struct ci_hdrc *ci, int num, int dir) |
122 | { | 122 | { |
123 | hw_ep_flush(ci, num, dir); | 123 | hw_ep_flush(ci, num, dir); |
124 | hw_write(ci, OP_ENDPTCTRL + num, | 124 | hw_write(ci, OP_ENDPTCTRL + num, |
125 | dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0); | 125 | dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0); |
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
129 | /** | 129 | /** |
130 | * hw_ep_enable: enables endpoint (execute without interruption) | 130 | * hw_ep_enable: enables endpoint (execute without interruption) |
131 | * @num: endpoint number | 131 | * @num: endpoint number |
132 | * @dir: endpoint direction | 132 | * @dir: endpoint direction |
133 | * @type: endpoint type | 133 | * @type: endpoint type |
134 | * | 134 | * |
135 | * This function returns an error code | 135 | * This function returns an error code |
136 | */ | 136 | */ |
137 | static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type) | 137 | static int hw_ep_enable(struct ci_hdrc *ci, int num, int dir, int type) |
138 | { | 138 | { |
139 | u32 mask, data; | 139 | u32 mask, data; |
140 | 140 | ||
141 | if (dir) { | 141 | if (dir) { |
142 | mask = ENDPTCTRL_TXT; /* type */ | 142 | mask = ENDPTCTRL_TXT; /* type */ |
143 | data = type << __ffs(mask); | 143 | data = type << __ffs(mask); |
144 | 144 | ||
145 | mask |= ENDPTCTRL_TXS; /* unstall */ | 145 | mask |= ENDPTCTRL_TXS; /* unstall */ |
146 | mask |= ENDPTCTRL_TXR; /* reset data toggle */ | 146 | mask |= ENDPTCTRL_TXR; /* reset data toggle */ |
147 | data |= ENDPTCTRL_TXR; | 147 | data |= ENDPTCTRL_TXR; |
148 | mask |= ENDPTCTRL_TXE; /* enable */ | 148 | mask |= ENDPTCTRL_TXE; /* enable */ |
149 | data |= ENDPTCTRL_TXE; | 149 | data |= ENDPTCTRL_TXE; |
150 | } else { | 150 | } else { |
151 | mask = ENDPTCTRL_RXT; /* type */ | 151 | mask = ENDPTCTRL_RXT; /* type */ |
152 | data = type << __ffs(mask); | 152 | data = type << __ffs(mask); |
153 | 153 | ||
154 | mask |= ENDPTCTRL_RXS; /* unstall */ | 154 | mask |= ENDPTCTRL_RXS; /* unstall */ |
155 | mask |= ENDPTCTRL_RXR; /* reset data toggle */ | 155 | mask |= ENDPTCTRL_RXR; /* reset data toggle */ |
156 | data |= ENDPTCTRL_RXR; | 156 | data |= ENDPTCTRL_RXR; |
157 | mask |= ENDPTCTRL_RXE; /* enable */ | 157 | mask |= ENDPTCTRL_RXE; /* enable */ |
158 | data |= ENDPTCTRL_RXE; | 158 | data |= ENDPTCTRL_RXE; |
159 | } | 159 | } |
160 | hw_write(ci, OP_ENDPTCTRL + num, mask, data); | 160 | hw_write(ci, OP_ENDPTCTRL + num, mask, data); |
161 | return 0; | 161 | return 0; |
162 | } | 162 | } |
163 | 163 | ||
164 | /** | 164 | /** |
165 | * hw_ep_get_halt: return endpoint halt status | 165 | * hw_ep_get_halt: return endpoint halt status |
166 | * @num: endpoint number | 166 | * @num: endpoint number |
167 | * @dir: endpoint direction | 167 | * @dir: endpoint direction |
168 | * | 168 | * |
169 | * This function returns 1 if endpoint halted | 169 | * This function returns 1 if endpoint halted |
170 | */ | 170 | */ |
171 | static int hw_ep_get_halt(struct ci13xxx *ci, int num, int dir) | 171 | static int hw_ep_get_halt(struct ci_hdrc *ci, int num, int dir) |
172 | { | 172 | { |
173 | u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; | 173 | u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; |
174 | 174 | ||
175 | return hw_read(ci, OP_ENDPTCTRL + num, mask) ? 1 : 0; | 175 | return hw_read(ci, OP_ENDPTCTRL + num, mask) ? 1 : 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | /** | 178 | /** |
179 | * hw_test_and_clear_setup_status: test & clear setup status (execute without | 179 | * hw_test_and_clear_setup_status: test & clear setup status (execute without |
180 | * interruption) | 180 | * interruption) |
181 | * @n: endpoint number | 181 | * @n: endpoint number |
182 | * | 182 | * |
183 | * This function returns setup status | 183 | * This function returns setup status |
184 | */ | 184 | */ |
185 | static int hw_test_and_clear_setup_status(struct ci13xxx *ci, int n) | 185 | static int hw_test_and_clear_setup_status(struct ci_hdrc *ci, int n) |
186 | { | 186 | { |
187 | n = ep_to_bit(ci, n); | 187 | n = ep_to_bit(ci, n); |
188 | return hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(n)); | 188 | return hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(n)); |
189 | } | 189 | } |
190 | 190 | ||
191 | /** | 191 | /** |
192 | * hw_ep_prime: primes endpoint (execute without interruption) | 192 | * hw_ep_prime: primes endpoint (execute without interruption) |
193 | * @num: endpoint number | 193 | * @num: endpoint number |
194 | * @dir: endpoint direction | 194 | * @dir: endpoint direction |
195 | * @is_ctrl: true if control endpoint | 195 | * @is_ctrl: true if control endpoint |
196 | * | 196 | * |
197 | * This function returns an error code | 197 | * This function returns an error code |
198 | */ | 198 | */ |
199 | static int hw_ep_prime(struct ci13xxx *ci, int num, int dir, int is_ctrl) | 199 | static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl) |
200 | { | 200 | { |
201 | int n = hw_ep_bit(num, dir); | 201 | int n = hw_ep_bit(num, dir); |
202 | 202 | ||
203 | if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) | 203 | if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) |
204 | return -EAGAIN; | 204 | return -EAGAIN; |
205 | 205 | ||
206 | hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n)); | 206 | hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n)); |
207 | 207 | ||
208 | while (hw_read(ci, OP_ENDPTPRIME, BIT(n))) | 208 | while (hw_read(ci, OP_ENDPTPRIME, BIT(n))) |
209 | cpu_relax(); | 209 | cpu_relax(); |
210 | if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) | 210 | if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) |
211 | return -EAGAIN; | 211 | return -EAGAIN; |
212 | 212 | ||
213 | /* status shoult be tested according with manual but it doesn't work */ | 213 | /* status shoult be tested according with manual but it doesn't work */ |
214 | return 0; | 214 | return 0; |
215 | } | 215 | } |
216 | 216 | ||
217 | /** | 217 | /** |
218 | * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute | 218 | * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute |
219 | * without interruption) | 219 | * without interruption) |
220 | * @num: endpoint number | 220 | * @num: endpoint number |
221 | * @dir: endpoint direction | 221 | * @dir: endpoint direction |
222 | * @value: true => stall, false => unstall | 222 | * @value: true => stall, false => unstall |
223 | * | 223 | * |
224 | * This function returns an error code | 224 | * This function returns an error code |
225 | */ | 225 | */ |
226 | static int hw_ep_set_halt(struct ci13xxx *ci, int num, int dir, int value) | 226 | static int hw_ep_set_halt(struct ci_hdrc *ci, int num, int dir, int value) |
227 | { | 227 | { |
228 | if (value != 0 && value != 1) | 228 | if (value != 0 && value != 1) |
229 | return -EINVAL; | 229 | return -EINVAL; |
230 | 230 | ||
231 | do { | 231 | do { |
232 | enum ci13xxx_regs reg = OP_ENDPTCTRL + num; | 232 | enum ci_hw_regs reg = OP_ENDPTCTRL + num; |
233 | u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; | 233 | u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; |
234 | u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; | 234 | u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; |
235 | 235 | ||
236 | /* data toggle - reserved for EP0 but it's in ESS */ | 236 | /* data toggle - reserved for EP0 but it's in ESS */ |
237 | hw_write(ci, reg, mask_xs|mask_xr, | 237 | hw_write(ci, reg, mask_xs|mask_xr, |
238 | value ? mask_xs : mask_xr); | 238 | value ? mask_xs : mask_xr); |
239 | } while (value != hw_ep_get_halt(ci, num, dir)); | 239 | } while (value != hw_ep_get_halt(ci, num, dir)); |
240 | 240 | ||
241 | return 0; | 241 | return 0; |
242 | } | 242 | } |
243 | 243 | ||
244 | /** | 244 | /** |
245 | * hw_is_port_high_speed: test if port is high speed | 245 | * hw_is_port_high_speed: test if port is high speed |
246 | * | 246 | * |
247 | * This function returns true if high speed port | 247 | * This function returns true if high speed port |
248 | */ | 248 | */ |
249 | static int hw_port_is_high_speed(struct ci13xxx *ci) | 249 | static int hw_port_is_high_speed(struct ci_hdrc *ci) |
250 | { | 250 | { |
251 | return ci->hw_bank.lpm ? hw_read(ci, OP_DEVLC, DEVLC_PSPD) : | 251 | return ci->hw_bank.lpm ? hw_read(ci, OP_DEVLC, DEVLC_PSPD) : |
252 | hw_read(ci, OP_PORTSC, PORTSC_HSP); | 252 | hw_read(ci, OP_PORTSC, PORTSC_HSP); |
253 | } | 253 | } |
254 | 254 | ||
255 | /** | 255 | /** |
256 | * hw_read_intr_enable: returns interrupt enable register | 256 | * hw_read_intr_enable: returns interrupt enable register |
257 | * | 257 | * |
258 | * This function returns register data | 258 | * This function returns register data |
259 | */ | 259 | */ |
260 | static u32 hw_read_intr_enable(struct ci13xxx *ci) | 260 | static u32 hw_read_intr_enable(struct ci_hdrc *ci) |
261 | { | 261 | { |
262 | return hw_read(ci, OP_USBINTR, ~0); | 262 | return hw_read(ci, OP_USBINTR, ~0); |
263 | } | 263 | } |
264 | 264 | ||
265 | /** | 265 | /** |
266 | * hw_read_intr_status: returns interrupt status register | 266 | * hw_read_intr_status: returns interrupt status register |
267 | * | 267 | * |
268 | * This function returns register data | 268 | * This function returns register data |
269 | */ | 269 | */ |
270 | static u32 hw_read_intr_status(struct ci13xxx *ci) | 270 | static u32 hw_read_intr_status(struct ci_hdrc *ci) |
271 | { | 271 | { |
272 | return hw_read(ci, OP_USBSTS, ~0); | 272 | return hw_read(ci, OP_USBSTS, ~0); |
273 | } | 273 | } |
274 | 274 | ||
275 | /** | 275 | /** |
276 | * hw_test_and_clear_complete: test & clear complete status (execute without | 276 | * hw_test_and_clear_complete: test & clear complete status (execute without |
277 | * interruption) | 277 | * interruption) |
278 | * @n: endpoint number | 278 | * @n: endpoint number |
279 | * | 279 | * |
280 | * This function returns complete status | 280 | * This function returns complete status |
281 | */ | 281 | */ |
282 | static int hw_test_and_clear_complete(struct ci13xxx *ci, int n) | 282 | static int hw_test_and_clear_complete(struct ci_hdrc *ci, int n) |
283 | { | 283 | { |
284 | n = ep_to_bit(ci, n); | 284 | n = ep_to_bit(ci, n); |
285 | return hw_test_and_clear(ci, OP_ENDPTCOMPLETE, BIT(n)); | 285 | return hw_test_and_clear(ci, OP_ENDPTCOMPLETE, BIT(n)); |
286 | } | 286 | } |
287 | 287 | ||
288 | /** | 288 | /** |
289 | * hw_test_and_clear_intr_active: test & clear active interrupts (execute | 289 | * hw_test_and_clear_intr_active: test & clear active interrupts (execute |
290 | * without interruption) | 290 | * without interruption) |
291 | * | 291 | * |
292 | * This function returns active interrutps | 292 | * This function returns active interrutps |
293 | */ | 293 | */ |
294 | static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci) | 294 | static u32 hw_test_and_clear_intr_active(struct ci_hdrc *ci) |
295 | { | 295 | { |
296 | u32 reg = hw_read_intr_status(ci) & hw_read_intr_enable(ci); | 296 | u32 reg = hw_read_intr_status(ci) & hw_read_intr_enable(ci); |
297 | 297 | ||
298 | hw_write(ci, OP_USBSTS, ~0, reg); | 298 | hw_write(ci, OP_USBSTS, ~0, reg); |
299 | return reg; | 299 | return reg; |
300 | } | 300 | } |
301 | 301 | ||
302 | /** | 302 | /** |
303 | * hw_test_and_clear_setup_guard: test & clear setup guard (execute without | 303 | * hw_test_and_clear_setup_guard: test & clear setup guard (execute without |
304 | * interruption) | 304 | * interruption) |
305 | * | 305 | * |
306 | * This function returns guard value | 306 | * This function returns guard value |
307 | */ | 307 | */ |
308 | static int hw_test_and_clear_setup_guard(struct ci13xxx *ci) | 308 | static int hw_test_and_clear_setup_guard(struct ci_hdrc *ci) |
309 | { | 309 | { |
310 | return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, 0); | 310 | return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, 0); |
311 | } | 311 | } |
312 | 312 | ||
313 | /** | 313 | /** |
314 | * hw_test_and_set_setup_guard: test & set setup guard (execute without | 314 | * hw_test_and_set_setup_guard: test & set setup guard (execute without |
315 | * interruption) | 315 | * interruption) |
316 | * | 316 | * |
317 | * This function returns guard value | 317 | * This function returns guard value |
318 | */ | 318 | */ |
319 | static int hw_test_and_set_setup_guard(struct ci13xxx *ci) | 319 | static int hw_test_and_set_setup_guard(struct ci_hdrc *ci) |
320 | { | 320 | { |
321 | return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); | 321 | return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); |
322 | } | 322 | } |
323 | 323 | ||
324 | /** | 324 | /** |
325 | * hw_usb_set_address: configures USB address (execute without interruption) | 325 | * hw_usb_set_address: configures USB address (execute without interruption) |
326 | * @value: new USB address | 326 | * @value: new USB address |
327 | * | 327 | * |
328 | * This function explicitly sets the address, without the "USBADRA" (advance) | 328 | * This function explicitly sets the address, without the "USBADRA" (advance) |
329 | * feature, which is not supported by older versions of the controller. | 329 | * feature, which is not supported by older versions of the controller. |
330 | */ | 330 | */ |
331 | static void hw_usb_set_address(struct ci13xxx *ci, u8 value) | 331 | static void hw_usb_set_address(struct ci_hdrc *ci, u8 value) |
332 | { | 332 | { |
333 | hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR, | 333 | hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR, |
334 | value << __ffs(DEVICEADDR_USBADR)); | 334 | value << __ffs(DEVICEADDR_USBADR)); |
335 | } | 335 | } |
336 | 336 | ||
337 | /** | 337 | /** |
338 | * hw_usb_reset: restart device after a bus reset (execute without | 338 | * hw_usb_reset: restart device after a bus reset (execute without |
339 | * interruption) | 339 | * interruption) |
340 | * | 340 | * |
341 | * This function returns an error code | 341 | * This function returns an error code |
342 | */ | 342 | */ |
343 | static int hw_usb_reset(struct ci13xxx *ci) | 343 | static int hw_usb_reset(struct ci_hdrc *ci) |
344 | { | 344 | { |
345 | hw_usb_set_address(ci, 0); | 345 | hw_usb_set_address(ci, 0); |
346 | 346 | ||
347 | /* ESS flushes only at end?!? */ | 347 | /* ESS flushes only at end?!? */ |
348 | hw_write(ci, OP_ENDPTFLUSH, ~0, ~0); | 348 | hw_write(ci, OP_ENDPTFLUSH, ~0, ~0); |
349 | 349 | ||
350 | /* clear setup token semaphores */ | 350 | /* clear setup token semaphores */ |
351 | hw_write(ci, OP_ENDPTSETUPSTAT, 0, 0); | 351 | hw_write(ci, OP_ENDPTSETUPSTAT, 0, 0); |
352 | 352 | ||
353 | /* clear complete status */ | 353 | /* clear complete status */ |
354 | hw_write(ci, OP_ENDPTCOMPLETE, 0, 0); | 354 | hw_write(ci, OP_ENDPTCOMPLETE, 0, 0); |
355 | 355 | ||
356 | /* wait until all bits cleared */ | 356 | /* wait until all bits cleared */ |
357 | while (hw_read(ci, OP_ENDPTPRIME, ~0)) | 357 | while (hw_read(ci, OP_ENDPTPRIME, ~0)) |
358 | udelay(10); /* not RTOS friendly */ | 358 | udelay(10); /* not RTOS friendly */ |
359 | 359 | ||
360 | /* reset all endpoints ? */ | 360 | /* reset all endpoints ? */ |
361 | 361 | ||
362 | /* reset internal status and wait for further instructions | 362 | /* reset internal status and wait for further instructions |
363 | no need to verify the port reset status (ESS does it) */ | 363 | no need to verify the port reset status (ESS does it) */ |
364 | 364 | ||
365 | return 0; | 365 | return 0; |
366 | } | 366 | } |
367 | 367 | ||
368 | /****************************************************************************** | 368 | /****************************************************************************** |
369 | * UTIL block | 369 | * UTIL block |
370 | *****************************************************************************/ | 370 | *****************************************************************************/ |
371 | 371 | ||
372 | static int add_td_to_list(struct ci13xxx_ep *hwep, struct ci13xxx_req *hwreq, | 372 | static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq, |
373 | unsigned length) | 373 | unsigned length) |
374 | { | 374 | { |
375 | int i; | 375 | int i; |
376 | u32 temp; | 376 | u32 temp; |
377 | struct td_node *lastnode, *node = kzalloc(sizeof(struct td_node), | 377 | struct td_node *lastnode, *node = kzalloc(sizeof(struct td_node), |
378 | GFP_ATOMIC); | 378 | GFP_ATOMIC); |
379 | 379 | ||
380 | if (node == NULL) | 380 | if (node == NULL) |
381 | return -ENOMEM; | 381 | return -ENOMEM; |
382 | 382 | ||
383 | node->ptr = dma_pool_alloc(hwep->td_pool, GFP_ATOMIC, | 383 | node->ptr = dma_pool_alloc(hwep->td_pool, GFP_ATOMIC, |
384 | &node->dma); | 384 | &node->dma); |
385 | if (node->ptr == NULL) { | 385 | if (node->ptr == NULL) { |
386 | kfree(node); | 386 | kfree(node); |
387 | return -ENOMEM; | 387 | return -ENOMEM; |
388 | } | 388 | } |
389 | 389 | ||
390 | memset(node->ptr, 0, sizeof(struct ci13xxx_td)); | 390 | memset(node->ptr, 0, sizeof(struct ci_hw_td)); |
391 | node->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES)); | 391 | node->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES)); |
392 | node->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES); | 392 | node->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES); |
393 | node->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE); | 393 | node->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE); |
394 | 394 | ||
395 | temp = (u32) (hwreq->req.dma + hwreq->req.actual); | 395 | temp = (u32) (hwreq->req.dma + hwreq->req.actual); |
396 | if (length) { | 396 | if (length) { |
397 | node->ptr->page[0] = cpu_to_le32(temp); | 397 | node->ptr->page[0] = cpu_to_le32(temp); |
398 | for (i = 1; i < TD_PAGE_COUNT; i++) { | 398 | for (i = 1; i < TD_PAGE_COUNT; i++) { |
399 | u32 page = temp + i * CI13XXX_PAGE_SIZE; | 399 | u32 page = temp + i * CI_HDRC_PAGE_SIZE; |
400 | page &= ~TD_RESERVED_MASK; | 400 | page &= ~TD_RESERVED_MASK; |
401 | node->ptr->page[i] = cpu_to_le32(page); | 401 | node->ptr->page[i] = cpu_to_le32(page); |
402 | } | 402 | } |
403 | } | 403 | } |
404 | 404 | ||
405 | hwreq->req.actual += length; | 405 | hwreq->req.actual += length; |
406 | 406 | ||
407 | if (!list_empty(&hwreq->tds)) { | 407 | if (!list_empty(&hwreq->tds)) { |
408 | /* get the last entry */ | 408 | /* get the last entry */ |
409 | lastnode = list_entry(hwreq->tds.prev, | 409 | lastnode = list_entry(hwreq->tds.prev, |
410 | struct td_node, td); | 410 | struct td_node, td); |
411 | lastnode->ptr->next = cpu_to_le32(node->dma); | 411 | lastnode->ptr->next = cpu_to_le32(node->dma); |
412 | } | 412 | } |
413 | 413 | ||
414 | INIT_LIST_HEAD(&node->td); | 414 | INIT_LIST_HEAD(&node->td); |
415 | list_add_tail(&node->td, &hwreq->tds); | 415 | list_add_tail(&node->td, &hwreq->tds); |
416 | 416 | ||
417 | return 0; | 417 | return 0; |
418 | } | 418 | } |
419 | 419 | ||
420 | /** | 420 | /** |
421 | * _usb_addr: calculates endpoint address from direction & number | 421 | * _usb_addr: calculates endpoint address from direction & number |
422 | * @ep: endpoint | 422 | * @ep: endpoint |
423 | */ | 423 | */ |
424 | static inline u8 _usb_addr(struct ci13xxx_ep *ep) | 424 | static inline u8 _usb_addr(struct ci_hw_ep *ep) |
425 | { | 425 | { |
426 | return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num; | 426 | return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num; |
427 | } | 427 | } |
428 | 428 | ||
429 | /** | 429 | /** |
430 | * _hardware_queue: configures a request at hardware level | 430 | * _hardware_queue: configures a request at hardware level |
431 | * @gadget: gadget | 431 | * @gadget: gadget |
432 | * @hwep: endpoint | 432 | * @hwep: endpoint |
433 | * | 433 | * |
434 | * This function returns an error code | 434 | * This function returns an error code |
435 | */ | 435 | */ |
436 | static int _hardware_enqueue(struct ci13xxx_ep *hwep, struct ci13xxx_req *hwreq) | 436 | static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) |
437 | { | 437 | { |
438 | struct ci13xxx *ci = hwep->ci; | 438 | struct ci_hdrc *ci = hwep->ci; |
439 | int ret = 0; | 439 | int ret = 0; |
440 | unsigned rest = hwreq->req.length; | 440 | unsigned rest = hwreq->req.length; |
441 | int pages = TD_PAGE_COUNT; | 441 | int pages = TD_PAGE_COUNT; |
442 | struct td_node *firstnode, *lastnode; | 442 | struct td_node *firstnode, *lastnode; |
443 | 443 | ||
444 | /* don't queue twice */ | 444 | /* don't queue twice */ |
445 | if (hwreq->req.status == -EALREADY) | 445 | if (hwreq->req.status == -EALREADY) |
446 | return -EALREADY; | 446 | return -EALREADY; |
447 | 447 | ||
448 | hwreq->req.status = -EALREADY; | 448 | hwreq->req.status = -EALREADY; |
449 | 449 | ||
450 | ret = usb_gadget_map_request(&ci->gadget, &hwreq->req, hwep->dir); | 450 | ret = usb_gadget_map_request(&ci->gadget, &hwreq->req, hwep->dir); |
451 | if (ret) | 451 | if (ret) |
452 | return ret; | 452 | return ret; |
453 | 453 | ||
454 | /* | 454 | /* |
455 | * The first buffer could be not page aligned. | 455 | * The first buffer could be not page aligned. |
456 | * In that case we have to span into one extra td. | 456 | * In that case we have to span into one extra td. |
457 | */ | 457 | */ |
458 | if (hwreq->req.dma % PAGE_SIZE) | 458 | if (hwreq->req.dma % PAGE_SIZE) |
459 | pages--; | 459 | pages--; |
460 | 460 | ||
461 | if (rest == 0) | 461 | if (rest == 0) |
462 | add_td_to_list(hwep, hwreq, 0); | 462 | add_td_to_list(hwep, hwreq, 0); |
463 | 463 | ||
464 | while (rest > 0) { | 464 | while (rest > 0) { |
465 | unsigned count = min(hwreq->req.length - hwreq->req.actual, | 465 | unsigned count = min(hwreq->req.length - hwreq->req.actual, |
466 | (unsigned)(pages * CI13XXX_PAGE_SIZE)); | 466 | (unsigned)(pages * CI_HDRC_PAGE_SIZE)); |
467 | add_td_to_list(hwep, hwreq, count); | 467 | add_td_to_list(hwep, hwreq, count); |
468 | rest -= count; | 468 | rest -= count; |
469 | } | 469 | } |
470 | 470 | ||
471 | if (hwreq->req.zero && hwreq->req.length | 471 | if (hwreq->req.zero && hwreq->req.length |
472 | && (hwreq->req.length % hwep->ep.maxpacket == 0)) | 472 | && (hwreq->req.length % hwep->ep.maxpacket == 0)) |
473 | add_td_to_list(hwep, hwreq, 0); | 473 | add_td_to_list(hwep, hwreq, 0); |
474 | 474 | ||
475 | firstnode = list_first_entry(&hwreq->tds, struct td_node, td); | 475 | firstnode = list_first_entry(&hwreq->tds, struct td_node, td); |
476 | 476 | ||
477 | lastnode = list_entry(hwreq->tds.prev, | 477 | lastnode = list_entry(hwreq->tds.prev, |
478 | struct td_node, td); | 478 | struct td_node, td); |
479 | 479 | ||
480 | lastnode->ptr->next = cpu_to_le32(TD_TERMINATE); | 480 | lastnode->ptr->next = cpu_to_le32(TD_TERMINATE); |
481 | if (!hwreq->req.no_interrupt) | 481 | if (!hwreq->req.no_interrupt) |
482 | lastnode->ptr->token |= cpu_to_le32(TD_IOC); | 482 | lastnode->ptr->token |= cpu_to_le32(TD_IOC); |
483 | wmb(); | 483 | wmb(); |
484 | 484 | ||
485 | hwreq->req.actual = 0; | 485 | hwreq->req.actual = 0; |
486 | if (!list_empty(&hwep->qh.queue)) { | 486 | if (!list_empty(&hwep->qh.queue)) { |
487 | struct ci13xxx_req *hwreqprev; | 487 | struct ci_hw_req *hwreqprev; |
488 | int n = hw_ep_bit(hwep->num, hwep->dir); | 488 | int n = hw_ep_bit(hwep->num, hwep->dir); |
489 | int tmp_stat; | 489 | int tmp_stat; |
490 | struct td_node *prevlastnode; | 490 | struct td_node *prevlastnode; |
491 | u32 next = firstnode->dma & TD_ADDR_MASK; | 491 | u32 next = firstnode->dma & TD_ADDR_MASK; |
492 | 492 | ||
493 | hwreqprev = list_entry(hwep->qh.queue.prev, | 493 | hwreqprev = list_entry(hwep->qh.queue.prev, |
494 | struct ci13xxx_req, queue); | 494 | struct ci_hw_req, queue); |
495 | prevlastnode = list_entry(hwreqprev->tds.prev, | 495 | prevlastnode = list_entry(hwreqprev->tds.prev, |
496 | struct td_node, td); | 496 | struct td_node, td); |
497 | 497 | ||
498 | prevlastnode->ptr->next = cpu_to_le32(next); | 498 | prevlastnode->ptr->next = cpu_to_le32(next); |
499 | wmb(); | 499 | wmb(); |
500 | if (hw_read(ci, OP_ENDPTPRIME, BIT(n))) | 500 | if (hw_read(ci, OP_ENDPTPRIME, BIT(n))) |
501 | goto done; | 501 | goto done; |
502 | do { | 502 | do { |
503 | hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW); | 503 | hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW); |
504 | tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n)); | 504 | tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n)); |
505 | } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW)); | 505 | } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW)); |
506 | hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0); | 506 | hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0); |
507 | if (tmp_stat) | 507 | if (tmp_stat) |
508 | goto done; | 508 | goto done; |
509 | } | 509 | } |
510 | 510 | ||
511 | /* QH configuration */ | 511 | /* QH configuration */ |
512 | hwep->qh.ptr->td.next = cpu_to_le32(firstnode->dma); | 512 | hwep->qh.ptr->td.next = cpu_to_le32(firstnode->dma); |
513 | hwep->qh.ptr->td.token &= | 513 | hwep->qh.ptr->td.token &= |
514 | cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE)); | 514 | cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE)); |
515 | 515 | ||
516 | if (hwep->type == USB_ENDPOINT_XFER_ISOC) { | 516 | if (hwep->type == USB_ENDPOINT_XFER_ISOC) { |
517 | u32 mul = hwreq->req.length / hwep->ep.maxpacket; | 517 | u32 mul = hwreq->req.length / hwep->ep.maxpacket; |
518 | 518 | ||
519 | if (hwreq->req.length % hwep->ep.maxpacket) | 519 | if (hwreq->req.length % hwep->ep.maxpacket) |
520 | mul++; | 520 | mul++; |
521 | hwep->qh.ptr->cap |= mul << __ffs(QH_MULT); | 521 | hwep->qh.ptr->cap |= mul << __ffs(QH_MULT); |
522 | } | 522 | } |
523 | 523 | ||
524 | wmb(); /* synchronize before ep prime */ | 524 | wmb(); /* synchronize before ep prime */ |
525 | 525 | ||
526 | ret = hw_ep_prime(ci, hwep->num, hwep->dir, | 526 | ret = hw_ep_prime(ci, hwep->num, hwep->dir, |
527 | hwep->type == USB_ENDPOINT_XFER_CONTROL); | 527 | hwep->type == USB_ENDPOINT_XFER_CONTROL); |
528 | done: | 528 | done: |
529 | return ret; | 529 | return ret; |
530 | } | 530 | } |
531 | 531 | ||
532 | /* | 532 | /* |
533 | * free_pending_td: remove a pending request for the endpoint | 533 | * free_pending_td: remove a pending request for the endpoint |
534 | * @hwep: endpoint | 534 | * @hwep: endpoint |
535 | */ | 535 | */ |
536 | static void free_pending_td(struct ci13xxx_ep *hwep) | 536 | static void free_pending_td(struct ci_hw_ep *hwep) |
537 | { | 537 | { |
538 | struct td_node *pending = hwep->pending_td; | 538 | struct td_node *pending = hwep->pending_td; |
539 | 539 | ||
540 | dma_pool_free(hwep->td_pool, pending->ptr, pending->dma); | 540 | dma_pool_free(hwep->td_pool, pending->ptr, pending->dma); |
541 | hwep->pending_td = NULL; | 541 | hwep->pending_td = NULL; |
542 | kfree(pending); | 542 | kfree(pending); |
543 | } | 543 | } |
544 | 544 | ||
545 | /** | 545 | /** |
546 | * _hardware_dequeue: handles a request at hardware level | 546 | * _hardware_dequeue: handles a request at hardware level |
547 | * @gadget: gadget | 547 | * @gadget: gadget |
548 | * @hwep: endpoint | 548 | * @hwep: endpoint |
549 | * | 549 | * |
550 | * This function returns an error code | 550 | * This function returns an error code |
551 | */ | 551 | */ |
552 | static int _hardware_dequeue(struct ci13xxx_ep *hwep, struct ci13xxx_req *hwreq) | 552 | static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) |
553 | { | 553 | { |
554 | u32 tmptoken; | 554 | u32 tmptoken; |
555 | struct td_node *node, *tmpnode; | 555 | struct td_node *node, *tmpnode; |
556 | unsigned remaining_length; | 556 | unsigned remaining_length; |
557 | unsigned actual = hwreq->req.length; | 557 | unsigned actual = hwreq->req.length; |
558 | 558 | ||
559 | if (hwreq->req.status != -EALREADY) | 559 | if (hwreq->req.status != -EALREADY) |
560 | return -EINVAL; | 560 | return -EINVAL; |
561 | 561 | ||
562 | hwreq->req.status = 0; | 562 | hwreq->req.status = 0; |
563 | 563 | ||
564 | list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { | 564 | list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { |
565 | tmptoken = le32_to_cpu(node->ptr->token); | 565 | tmptoken = le32_to_cpu(node->ptr->token); |
566 | if ((TD_STATUS_ACTIVE & tmptoken) != 0) { | 566 | if ((TD_STATUS_ACTIVE & tmptoken) != 0) { |
567 | hwreq->req.status = -EALREADY; | 567 | hwreq->req.status = -EALREADY; |
568 | return -EBUSY; | 568 | return -EBUSY; |
569 | } | 569 | } |
570 | 570 | ||
571 | remaining_length = (tmptoken & TD_TOTAL_BYTES); | 571 | remaining_length = (tmptoken & TD_TOTAL_BYTES); |
572 | remaining_length >>= __ffs(TD_TOTAL_BYTES); | 572 | remaining_length >>= __ffs(TD_TOTAL_BYTES); |
573 | actual -= remaining_length; | 573 | actual -= remaining_length; |
574 | 574 | ||
575 | hwreq->req.status = tmptoken & TD_STATUS; | 575 | hwreq->req.status = tmptoken & TD_STATUS; |
576 | if ((TD_STATUS_HALTED & hwreq->req.status)) { | 576 | if ((TD_STATUS_HALTED & hwreq->req.status)) { |
577 | hwreq->req.status = -EPIPE; | 577 | hwreq->req.status = -EPIPE; |
578 | break; | 578 | break; |
579 | } else if ((TD_STATUS_DT_ERR & hwreq->req.status)) { | 579 | } else if ((TD_STATUS_DT_ERR & hwreq->req.status)) { |
580 | hwreq->req.status = -EPROTO; | 580 | hwreq->req.status = -EPROTO; |
581 | break; | 581 | break; |
582 | } else if ((TD_STATUS_TR_ERR & hwreq->req.status)) { | 582 | } else if ((TD_STATUS_TR_ERR & hwreq->req.status)) { |
583 | hwreq->req.status = -EILSEQ; | 583 | hwreq->req.status = -EILSEQ; |
584 | break; | 584 | break; |
585 | } | 585 | } |
586 | 586 | ||
587 | if (remaining_length) { | 587 | if (remaining_length) { |
588 | if (hwep->dir) { | 588 | if (hwep->dir) { |
589 | hwreq->req.status = -EPROTO; | 589 | hwreq->req.status = -EPROTO; |
590 | break; | 590 | break; |
591 | } | 591 | } |
592 | } | 592 | } |
593 | /* | 593 | /* |
594 | * As the hardware could still address the freed td | 594 | * As the hardware could still address the freed td |
595 | * which will run the udc unusable, the cleanup of the | 595 | * which will run the udc unusable, the cleanup of the |
596 | * td has to be delayed by one. | 596 | * td has to be delayed by one. |
597 | */ | 597 | */ |
598 | if (hwep->pending_td) | 598 | if (hwep->pending_td) |
599 | free_pending_td(hwep); | 599 | free_pending_td(hwep); |
600 | 600 | ||
601 | hwep->pending_td = node; | 601 | hwep->pending_td = node; |
602 | list_del_init(&node->td); | 602 | list_del_init(&node->td); |
603 | } | 603 | } |
604 | 604 | ||
605 | usb_gadget_unmap_request(&hwep->ci->gadget, &hwreq->req, hwep->dir); | 605 | usb_gadget_unmap_request(&hwep->ci->gadget, &hwreq->req, hwep->dir); |
606 | 606 | ||
607 | hwreq->req.actual += actual; | 607 | hwreq->req.actual += actual; |
608 | 608 | ||
609 | if (hwreq->req.status) | 609 | if (hwreq->req.status) |
610 | return hwreq->req.status; | 610 | return hwreq->req.status; |
611 | 611 | ||
612 | return hwreq->req.actual; | 612 | return hwreq->req.actual; |
613 | } | 613 | } |
614 | 614 | ||
615 | /** | 615 | /** |
616 | * _ep_nuke: dequeues all endpoint requests | 616 | * _ep_nuke: dequeues all endpoint requests |
617 | * @hwep: endpoint | 617 | * @hwep: endpoint |
618 | * | 618 | * |
619 | * This function returns an error code | 619 | * This function returns an error code |
620 | * Caller must hold lock | 620 | * Caller must hold lock |
621 | */ | 621 | */ |
622 | static int _ep_nuke(struct ci13xxx_ep *hwep) | 622 | static int _ep_nuke(struct ci_hw_ep *hwep) |
623 | __releases(hwep->lock) | 623 | __releases(hwep->lock) |
624 | __acquires(hwep->lock) | 624 | __acquires(hwep->lock) |
625 | { | 625 | { |
626 | struct td_node *node, *tmpnode; | 626 | struct td_node *node, *tmpnode; |
627 | if (hwep == NULL) | 627 | if (hwep == NULL) |
628 | return -EINVAL; | 628 | return -EINVAL; |
629 | 629 | ||
630 | hw_ep_flush(hwep->ci, hwep->num, hwep->dir); | 630 | hw_ep_flush(hwep->ci, hwep->num, hwep->dir); |
631 | 631 | ||
632 | while (!list_empty(&hwep->qh.queue)) { | 632 | while (!list_empty(&hwep->qh.queue)) { |
633 | 633 | ||
634 | /* pop oldest request */ | 634 | /* pop oldest request */ |
635 | struct ci13xxx_req *hwreq = list_entry(hwep->qh.queue.next, | 635 | struct ci_hw_req *hwreq = list_entry(hwep->qh.queue.next, |
636 | struct ci13xxx_req, | 636 | struct ci_hw_req, queue); |
637 | queue); | ||
638 | 637 | ||
639 | list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { | 638 | list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { |
640 | dma_pool_free(hwep->td_pool, node->ptr, node->dma); | 639 | dma_pool_free(hwep->td_pool, node->ptr, node->dma); |
641 | list_del_init(&node->td); | 640 | list_del_init(&node->td); |
642 | node->ptr = NULL; | 641 | node->ptr = NULL; |
643 | kfree(node); | 642 | kfree(node); |
644 | } | 643 | } |
645 | 644 | ||
646 | list_del_init(&hwreq->queue); | 645 | list_del_init(&hwreq->queue); |
647 | hwreq->req.status = -ESHUTDOWN; | 646 | hwreq->req.status = -ESHUTDOWN; |
648 | 647 | ||
649 | if (hwreq->req.complete != NULL) { | 648 | if (hwreq->req.complete != NULL) { |
650 | spin_unlock(hwep->lock); | 649 | spin_unlock(hwep->lock); |
651 | hwreq->req.complete(&hwep->ep, &hwreq->req); | 650 | hwreq->req.complete(&hwep->ep, &hwreq->req); |
652 | spin_lock(hwep->lock); | 651 | spin_lock(hwep->lock); |
653 | } | 652 | } |
654 | } | 653 | } |
655 | 654 | ||
656 | if (hwep->pending_td) | 655 | if (hwep->pending_td) |
657 | free_pending_td(hwep); | 656 | free_pending_td(hwep); |
658 | 657 | ||
659 | return 0; | 658 | return 0; |
660 | } | 659 | } |
661 | 660 | ||
662 | /** | 661 | /** |
663 | * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts | 662 | * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts |
664 | * @gadget: gadget | 663 | * @gadget: gadget |
665 | * | 664 | * |
666 | * This function returns an error code | 665 | * This function returns an error code |
667 | */ | 666 | */ |
668 | static int _gadget_stop_activity(struct usb_gadget *gadget) | 667 | static int _gadget_stop_activity(struct usb_gadget *gadget) |
669 | { | 668 | { |
670 | struct usb_ep *ep; | 669 | struct usb_ep *ep; |
671 | struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); | 670 | struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); |
672 | unsigned long flags; | 671 | unsigned long flags; |
673 | 672 | ||
674 | spin_lock_irqsave(&ci->lock, flags); | 673 | spin_lock_irqsave(&ci->lock, flags); |
675 | ci->gadget.speed = USB_SPEED_UNKNOWN; | 674 | ci->gadget.speed = USB_SPEED_UNKNOWN; |
676 | ci->remote_wakeup = 0; | 675 | ci->remote_wakeup = 0; |
677 | ci->suspended = 0; | 676 | ci->suspended = 0; |
678 | spin_unlock_irqrestore(&ci->lock, flags); | 677 | spin_unlock_irqrestore(&ci->lock, flags); |
679 | 678 | ||
680 | /* flush all endpoints */ | 679 | /* flush all endpoints */ |
681 | gadget_for_each_ep(ep, gadget) { | 680 | gadget_for_each_ep(ep, gadget) { |
682 | usb_ep_fifo_flush(ep); | 681 | usb_ep_fifo_flush(ep); |
683 | } | 682 | } |
684 | usb_ep_fifo_flush(&ci->ep0out->ep); | 683 | usb_ep_fifo_flush(&ci->ep0out->ep); |
685 | usb_ep_fifo_flush(&ci->ep0in->ep); | 684 | usb_ep_fifo_flush(&ci->ep0in->ep); |
686 | 685 | ||
687 | if (ci->driver) | 686 | if (ci->driver) |
688 | ci->driver->disconnect(gadget); | 687 | ci->driver->disconnect(gadget); |
689 | 688 | ||
690 | /* make sure to disable all endpoints */ | 689 | /* make sure to disable all endpoints */ |
691 | gadget_for_each_ep(ep, gadget) { | 690 | gadget_for_each_ep(ep, gadget) { |
692 | usb_ep_disable(ep); | 691 | usb_ep_disable(ep); |
693 | } | 692 | } |
694 | 693 | ||
695 | if (ci->status != NULL) { | 694 | if (ci->status != NULL) { |
696 | usb_ep_free_request(&ci->ep0in->ep, ci->status); | 695 | usb_ep_free_request(&ci->ep0in->ep, ci->status); |
697 | ci->status = NULL; | 696 | ci->status = NULL; |
698 | } | 697 | } |
699 | 698 | ||
700 | return 0; | 699 | return 0; |
701 | } | 700 | } |
702 | 701 | ||
703 | /****************************************************************************** | 702 | /****************************************************************************** |
704 | * ISR block | 703 | * ISR block |
705 | *****************************************************************************/ | 704 | *****************************************************************************/ |
706 | /** | 705 | /** |
707 | * isr_reset_handler: USB reset interrupt handler | 706 | * isr_reset_handler: USB reset interrupt handler |
708 | * @ci: UDC device | 707 | * @ci: UDC device |
709 | * | 708 | * |
710 | * This function resets USB engine after a bus reset occurred | 709 | * This function resets USB engine after a bus reset occurred |
711 | */ | 710 | */ |
712 | static void isr_reset_handler(struct ci13xxx *ci) | 711 | static void isr_reset_handler(struct ci_hdrc *ci) |
713 | __releases(ci->lock) | 712 | __releases(ci->lock) |
714 | __acquires(ci->lock) | 713 | __acquires(ci->lock) |
715 | { | 714 | { |
716 | int retval; | 715 | int retval; |
717 | 716 | ||
718 | spin_unlock(&ci->lock); | 717 | spin_unlock(&ci->lock); |
719 | retval = _gadget_stop_activity(&ci->gadget); | 718 | retval = _gadget_stop_activity(&ci->gadget); |
720 | if (retval) | 719 | if (retval) |
721 | goto done; | 720 | goto done; |
722 | 721 | ||
723 | retval = hw_usb_reset(ci); | 722 | retval = hw_usb_reset(ci); |
724 | if (retval) | 723 | if (retval) |
725 | goto done; | 724 | goto done; |
726 | 725 | ||
727 | ci->status = usb_ep_alloc_request(&ci->ep0in->ep, GFP_ATOMIC); | 726 | ci->status = usb_ep_alloc_request(&ci->ep0in->ep, GFP_ATOMIC); |
728 | if (ci->status == NULL) | 727 | if (ci->status == NULL) |
729 | retval = -ENOMEM; | 728 | retval = -ENOMEM; |
730 | 729 | ||
731 | done: | 730 | done: |
732 | spin_lock(&ci->lock); | 731 | spin_lock(&ci->lock); |
733 | 732 | ||
734 | if (retval) | 733 | if (retval) |
735 | dev_err(ci->dev, "error: %i\n", retval); | 734 | dev_err(ci->dev, "error: %i\n", retval); |
736 | } | 735 | } |
737 | 736 | ||
738 | /** | 737 | /** |
739 | * isr_get_status_complete: get_status request complete function | 738 | * isr_get_status_complete: get_status request complete function |
740 | * @ep: endpoint | 739 | * @ep: endpoint |
741 | * @req: request handled | 740 | * @req: request handled |
742 | * | 741 | * |
743 | * Caller must release lock | 742 | * Caller must release lock |
744 | */ | 743 | */ |
745 | static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) | 744 | static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) |
746 | { | 745 | { |
747 | if (ep == NULL || req == NULL) | 746 | if (ep == NULL || req == NULL) |
748 | return; | 747 | return; |
749 | 748 | ||
750 | kfree(req->buf); | 749 | kfree(req->buf); |
751 | usb_ep_free_request(ep, req); | 750 | usb_ep_free_request(ep, req); |
752 | } | 751 | } |
753 | 752 | ||
754 | /** | 753 | /** |
755 | * _ep_queue: queues (submits) an I/O request to an endpoint | 754 | * _ep_queue: queues (submits) an I/O request to an endpoint |
756 | * | 755 | * |
757 | * Caller must hold lock | 756 | * Caller must hold lock |
758 | */ | 757 | */ |
759 | static int _ep_queue(struct usb_ep *ep, struct usb_request *req, | 758 | static int _ep_queue(struct usb_ep *ep, struct usb_request *req, |
760 | gfp_t __maybe_unused gfp_flags) | 759 | gfp_t __maybe_unused gfp_flags) |
761 | { | 760 | { |
762 | struct ci13xxx_ep *hwep = container_of(ep, struct ci13xxx_ep, ep); | 761 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
763 | struct ci13xxx_req *hwreq = container_of(req, struct ci13xxx_req, req); | 762 | struct ci_hw_req *hwreq = container_of(req, struct ci_hw_req, req); |
764 | struct ci13xxx *ci = hwep->ci; | 763 | struct ci_hdrc *ci = hwep->ci; |
765 | int retval = 0; | 764 | int retval = 0; |
766 | 765 | ||
767 | if (ep == NULL || req == NULL || hwep->ep.desc == NULL) | 766 | if (ep == NULL || req == NULL || hwep->ep.desc == NULL) |
768 | return -EINVAL; | 767 | return -EINVAL; |
769 | 768 | ||
770 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) { | 769 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) { |
771 | if (req->length) | 770 | if (req->length) |
772 | hwep = (ci->ep0_dir == RX) ? | 771 | hwep = (ci->ep0_dir == RX) ? |
773 | ci->ep0out : ci->ep0in; | 772 | ci->ep0out : ci->ep0in; |
774 | if (!list_empty(&hwep->qh.queue)) { | 773 | if (!list_empty(&hwep->qh.queue)) { |
775 | _ep_nuke(hwep); | 774 | _ep_nuke(hwep); |
776 | retval = -EOVERFLOW; | 775 | retval = -EOVERFLOW; |
777 | dev_warn(hwep->ci->dev, "endpoint ctrl %X nuked\n", | 776 | dev_warn(hwep->ci->dev, "endpoint ctrl %X nuked\n", |
778 | _usb_addr(hwep)); | 777 | _usb_addr(hwep)); |
779 | } | 778 | } |
780 | } | 779 | } |
781 | 780 | ||
782 | if (usb_endpoint_xfer_isoc(hwep->ep.desc) && | 781 | if (usb_endpoint_xfer_isoc(hwep->ep.desc) && |
783 | hwreq->req.length > (1 + hwep->ep.mult) * hwep->ep.maxpacket) { | 782 | hwreq->req.length > (1 + hwep->ep.mult) * hwep->ep.maxpacket) { |
784 | dev_err(hwep->ci->dev, "request length too big for isochronous\n"); | 783 | dev_err(hwep->ci->dev, "request length too big for isochronous\n"); |
785 | return -EMSGSIZE; | 784 | return -EMSGSIZE; |
786 | } | 785 | } |
787 | 786 | ||
788 | /* first nuke then test link, e.g. previous status has not sent */ | 787 | /* first nuke then test link, e.g. previous status has not sent */ |
789 | if (!list_empty(&hwreq->queue)) { | 788 | if (!list_empty(&hwreq->queue)) { |
790 | dev_err(hwep->ci->dev, "request already in queue\n"); | 789 | dev_err(hwep->ci->dev, "request already in queue\n"); |
791 | return -EBUSY; | 790 | return -EBUSY; |
792 | } | 791 | } |
793 | 792 | ||
794 | /* push request */ | 793 | /* push request */ |
795 | hwreq->req.status = -EINPROGRESS; | 794 | hwreq->req.status = -EINPROGRESS; |
796 | hwreq->req.actual = 0; | 795 | hwreq->req.actual = 0; |
797 | 796 | ||
798 | retval = _hardware_enqueue(hwep, hwreq); | 797 | retval = _hardware_enqueue(hwep, hwreq); |
799 | 798 | ||
800 | if (retval == -EALREADY) | 799 | if (retval == -EALREADY) |
801 | retval = 0; | 800 | retval = 0; |
802 | if (!retval) | 801 | if (!retval) |
803 | list_add_tail(&hwreq->queue, &hwep->qh.queue); | 802 | list_add_tail(&hwreq->queue, &hwep->qh.queue); |
804 | 803 | ||
805 | return retval; | 804 | return retval; |
806 | } | 805 | } |
807 | 806 | ||
808 | /** | 807 | /** |
809 | * isr_get_status_response: get_status request response | 808 | * isr_get_status_response: get_status request response |
810 | * @ci: ci struct | 809 | * @ci: ci struct |
811 | * @setup: setup request packet | 810 | * @setup: setup request packet |
812 | * | 811 | * |
813 | * This function returns an error code | 812 | * This function returns an error code |
814 | */ | 813 | */ |
815 | static int isr_get_status_response(struct ci13xxx *ci, | 814 | static int isr_get_status_response(struct ci_hdrc *ci, |
816 | struct usb_ctrlrequest *setup) | 815 | struct usb_ctrlrequest *setup) |
817 | __releases(hwep->lock) | 816 | __releases(hwep->lock) |
818 | __acquires(hwep->lock) | 817 | __acquires(hwep->lock) |
819 | { | 818 | { |
820 | struct ci13xxx_ep *hwep = ci->ep0in; | 819 | struct ci_hw_ep *hwep = ci->ep0in; |
821 | struct usb_request *req = NULL; | 820 | struct usb_request *req = NULL; |
822 | gfp_t gfp_flags = GFP_ATOMIC; | 821 | gfp_t gfp_flags = GFP_ATOMIC; |
823 | int dir, num, retval; | 822 | int dir, num, retval; |
824 | 823 | ||
825 | if (hwep == NULL || setup == NULL) | 824 | if (hwep == NULL || setup == NULL) |
826 | return -EINVAL; | 825 | return -EINVAL; |
827 | 826 | ||
828 | spin_unlock(hwep->lock); | 827 | spin_unlock(hwep->lock); |
829 | req = usb_ep_alloc_request(&hwep->ep, gfp_flags); | 828 | req = usb_ep_alloc_request(&hwep->ep, gfp_flags); |
830 | spin_lock(hwep->lock); | 829 | spin_lock(hwep->lock); |
831 | if (req == NULL) | 830 | if (req == NULL) |
832 | return -ENOMEM; | 831 | return -ENOMEM; |
833 | 832 | ||
834 | req->complete = isr_get_status_complete; | 833 | req->complete = isr_get_status_complete; |
835 | req->length = 2; | 834 | req->length = 2; |
836 | req->buf = kzalloc(req->length, gfp_flags); | 835 | req->buf = kzalloc(req->length, gfp_flags); |
837 | if (req->buf == NULL) { | 836 | if (req->buf == NULL) { |
838 | retval = -ENOMEM; | 837 | retval = -ENOMEM; |
839 | goto err_free_req; | 838 | goto err_free_req; |
840 | } | 839 | } |
841 | 840 | ||
842 | if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) { | 841 | if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) { |
843 | /* Assume that device is bus powered for now. */ | 842 | /* Assume that device is bus powered for now. */ |
844 | *(u16 *)req->buf = ci->remote_wakeup << 1; | 843 | *(u16 *)req->buf = ci->remote_wakeup << 1; |
845 | retval = 0; | 844 | retval = 0; |
846 | } else if ((setup->bRequestType & USB_RECIP_MASK) \ | 845 | } else if ((setup->bRequestType & USB_RECIP_MASK) \ |
847 | == USB_RECIP_ENDPOINT) { | 846 | == USB_RECIP_ENDPOINT) { |
848 | dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ? | 847 | dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ? |
849 | TX : RX; | 848 | TX : RX; |
850 | num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK; | 849 | num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK; |
851 | *(u16 *)req->buf = hw_ep_get_halt(ci, num, dir); | 850 | *(u16 *)req->buf = hw_ep_get_halt(ci, num, dir); |
852 | } | 851 | } |
853 | /* else do nothing; reserved for future use */ | 852 | /* else do nothing; reserved for future use */ |
854 | 853 | ||
855 | retval = _ep_queue(&hwep->ep, req, gfp_flags); | 854 | retval = _ep_queue(&hwep->ep, req, gfp_flags); |
856 | if (retval) | 855 | if (retval) |
857 | goto err_free_buf; | 856 | goto err_free_buf; |
858 | 857 | ||
859 | return 0; | 858 | return 0; |
860 | 859 | ||
861 | err_free_buf: | 860 | err_free_buf: |
862 | kfree(req->buf); | 861 | kfree(req->buf); |
863 | err_free_req: | 862 | err_free_req: |
864 | spin_unlock(hwep->lock); | 863 | spin_unlock(hwep->lock); |
865 | usb_ep_free_request(&hwep->ep, req); | 864 | usb_ep_free_request(&hwep->ep, req); |
866 | spin_lock(hwep->lock); | 865 | spin_lock(hwep->lock); |
867 | return retval; | 866 | return retval; |
868 | } | 867 | } |
869 | 868 | ||
870 | /** | 869 | /** |
871 | * isr_setup_status_complete: setup_status request complete function | 870 | * isr_setup_status_complete: setup_status request complete function |
872 | * @ep: endpoint | 871 | * @ep: endpoint |
873 | * @req: request handled | 872 | * @req: request handled |
874 | * | 873 | * |
875 | * Caller must release lock. Put the port in test mode if test mode | 874 | * Caller must release lock. Put the port in test mode if test mode |
876 | * feature is selected. | 875 | * feature is selected. |
877 | */ | 876 | */ |
878 | static void | 877 | static void |
879 | isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) | 878 | isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) |
880 | { | 879 | { |
881 | struct ci13xxx *ci = req->context; | 880 | struct ci_hdrc *ci = req->context; |
882 | unsigned long flags; | 881 | unsigned long flags; |
883 | 882 | ||
884 | if (ci->setaddr) { | 883 | if (ci->setaddr) { |
885 | hw_usb_set_address(ci, ci->address); | 884 | hw_usb_set_address(ci, ci->address); |
886 | ci->setaddr = false; | 885 | ci->setaddr = false; |
887 | } | 886 | } |
888 | 887 | ||
889 | spin_lock_irqsave(&ci->lock, flags); | 888 | spin_lock_irqsave(&ci->lock, flags); |
890 | if (ci->test_mode) | 889 | if (ci->test_mode) |
891 | hw_port_test_set(ci, ci->test_mode); | 890 | hw_port_test_set(ci, ci->test_mode); |
892 | spin_unlock_irqrestore(&ci->lock, flags); | 891 | spin_unlock_irqrestore(&ci->lock, flags); |
893 | } | 892 | } |
894 | 893 | ||
895 | /** | 894 | /** |
896 | * isr_setup_status_phase: queues the status phase of a setup transation | 895 | * isr_setup_status_phase: queues the status phase of a setup transation |
897 | * @ci: ci struct | 896 | * @ci: ci struct |
898 | * | 897 | * |
899 | * This function returns an error code | 898 | * This function returns an error code |
900 | */ | 899 | */ |
901 | static int isr_setup_status_phase(struct ci13xxx *ci) | 900 | static int isr_setup_status_phase(struct ci_hdrc *ci) |
902 | { | 901 | { |
903 | int retval; | 902 | int retval; |
904 | struct ci13xxx_ep *hwep; | 903 | struct ci_hw_ep *hwep; |
905 | 904 | ||
906 | hwep = (ci->ep0_dir == TX) ? ci->ep0out : ci->ep0in; | 905 | hwep = (ci->ep0_dir == TX) ? ci->ep0out : ci->ep0in; |
907 | ci->status->context = ci; | 906 | ci->status->context = ci; |
908 | ci->status->complete = isr_setup_status_complete; | 907 | ci->status->complete = isr_setup_status_complete; |
909 | 908 | ||
910 | retval = _ep_queue(&hwep->ep, ci->status, GFP_ATOMIC); | 909 | retval = _ep_queue(&hwep->ep, ci->status, GFP_ATOMIC); |
911 | 910 | ||
912 | return retval; | 911 | return retval; |
913 | } | 912 | } |
914 | 913 | ||
915 | /** | 914 | /** |
916 | * isr_tr_complete_low: transaction complete low level handler | 915 | * isr_tr_complete_low: transaction complete low level handler |
917 | * @hwep: endpoint | 916 | * @hwep: endpoint |
918 | * | 917 | * |
919 | * This function returns an error code | 918 | * This function returns an error code |
920 | * Caller must hold lock | 919 | * Caller must hold lock |
921 | */ | 920 | */ |
922 | static int isr_tr_complete_low(struct ci13xxx_ep *hwep) | 921 | static int isr_tr_complete_low(struct ci_hw_ep *hwep) |
923 | __releases(hwep->lock) | 922 | __releases(hwep->lock) |
924 | __acquires(hwep->lock) | 923 | __acquires(hwep->lock) |
925 | { | 924 | { |
926 | struct ci13xxx_req *hwreq, *hwreqtemp; | 925 | struct ci_hw_req *hwreq, *hwreqtemp; |
927 | struct ci13xxx_ep *hweptemp = hwep; | 926 | struct ci_hw_ep *hweptemp = hwep; |
928 | int retval = 0; | 927 | int retval = 0; |
929 | 928 | ||
930 | list_for_each_entry_safe(hwreq, hwreqtemp, &hwep->qh.queue, | 929 | list_for_each_entry_safe(hwreq, hwreqtemp, &hwep->qh.queue, |
931 | queue) { | 930 | queue) { |
932 | retval = _hardware_dequeue(hwep, hwreq); | 931 | retval = _hardware_dequeue(hwep, hwreq); |
933 | if (retval < 0) | 932 | if (retval < 0) |
934 | break; | 933 | break; |
935 | list_del_init(&hwreq->queue); | 934 | list_del_init(&hwreq->queue); |
936 | if (hwreq->req.complete != NULL) { | 935 | if (hwreq->req.complete != NULL) { |
937 | spin_unlock(hwep->lock); | 936 | spin_unlock(hwep->lock); |
938 | if ((hwep->type == USB_ENDPOINT_XFER_CONTROL) && | 937 | if ((hwep->type == USB_ENDPOINT_XFER_CONTROL) && |
939 | hwreq->req.length) | 938 | hwreq->req.length) |
940 | hweptemp = hwep->ci->ep0in; | 939 | hweptemp = hwep->ci->ep0in; |
941 | hwreq->req.complete(&hweptemp->ep, &hwreq->req); | 940 | hwreq->req.complete(&hweptemp->ep, &hwreq->req); |
942 | spin_lock(hwep->lock); | 941 | spin_lock(hwep->lock); |
943 | } | 942 | } |
944 | } | 943 | } |
945 | 944 | ||
946 | if (retval == -EBUSY) | 945 | if (retval == -EBUSY) |
947 | retval = 0; | 946 | retval = 0; |
948 | 947 | ||
949 | return retval; | 948 | return retval; |
950 | } | 949 | } |
951 | 950 | ||
952 | /** | 951 | /** |
953 | * isr_tr_complete_handler: transaction complete interrupt handler | 952 | * isr_tr_complete_handler: transaction complete interrupt handler |
954 | * @ci: UDC descriptor | 953 | * @ci: UDC descriptor |
955 | * | 954 | * |
956 | * This function handles traffic events | 955 | * This function handles traffic events |
957 | */ | 956 | */ |
958 | static void isr_tr_complete_handler(struct ci13xxx *ci) | 957 | static void isr_tr_complete_handler(struct ci_hdrc *ci) |
959 | __releases(ci->lock) | 958 | __releases(ci->lock) |
960 | __acquires(ci->lock) | 959 | __acquires(ci->lock) |
961 | { | 960 | { |
962 | unsigned i; | 961 | unsigned i; |
963 | u8 tmode = 0; | 962 | u8 tmode = 0; |
964 | 963 | ||
965 | for (i = 0; i < ci->hw_ep_max; i++) { | 964 | for (i = 0; i < ci->hw_ep_max; i++) { |
966 | struct ci13xxx_ep *hwep = &ci->ci13xxx_ep[i]; | 965 | struct ci_hw_ep *hwep = &ci->ci_hw_ep[i]; |
967 | int type, num, dir, err = -EINVAL; | 966 | int type, num, dir, err = -EINVAL; |
968 | struct usb_ctrlrequest req; | 967 | struct usb_ctrlrequest req; |
969 | 968 | ||
970 | if (hwep->ep.desc == NULL) | 969 | if (hwep->ep.desc == NULL) |
971 | continue; /* not configured */ | 970 | continue; /* not configured */ |
972 | 971 | ||
973 | if (hw_test_and_clear_complete(ci, i)) { | 972 | if (hw_test_and_clear_complete(ci, i)) { |
974 | err = isr_tr_complete_low(hwep); | 973 | err = isr_tr_complete_low(hwep); |
975 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) { | 974 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) { |
976 | if (err > 0) /* needs status phase */ | 975 | if (err > 0) /* needs status phase */ |
977 | err = isr_setup_status_phase(ci); | 976 | err = isr_setup_status_phase(ci); |
978 | if (err < 0) { | 977 | if (err < 0) { |
979 | spin_unlock(&ci->lock); | 978 | spin_unlock(&ci->lock); |
980 | if (usb_ep_set_halt(&hwep->ep)) | 979 | if (usb_ep_set_halt(&hwep->ep)) |
981 | dev_err(ci->dev, | 980 | dev_err(ci->dev, |
982 | "error: ep_set_halt\n"); | 981 | "error: ep_set_halt\n"); |
983 | spin_lock(&ci->lock); | 982 | spin_lock(&ci->lock); |
984 | } | 983 | } |
985 | } | 984 | } |
986 | } | 985 | } |
987 | 986 | ||
988 | if (hwep->type != USB_ENDPOINT_XFER_CONTROL || | 987 | if (hwep->type != USB_ENDPOINT_XFER_CONTROL || |
989 | !hw_test_and_clear_setup_status(ci, i)) | 988 | !hw_test_and_clear_setup_status(ci, i)) |
990 | continue; | 989 | continue; |
991 | 990 | ||
992 | if (i != 0) { | 991 | if (i != 0) { |
993 | dev_warn(ci->dev, "ctrl traffic at endpoint %d\n", i); | 992 | dev_warn(ci->dev, "ctrl traffic at endpoint %d\n", i); |
994 | continue; | 993 | continue; |
995 | } | 994 | } |
996 | 995 | ||
997 | /* | 996 | /* |
998 | * Flush data and handshake transactions of previous | 997 | * Flush data and handshake transactions of previous |
999 | * setup packet. | 998 | * setup packet. |
1000 | */ | 999 | */ |
1001 | _ep_nuke(ci->ep0out); | 1000 | _ep_nuke(ci->ep0out); |
1002 | _ep_nuke(ci->ep0in); | 1001 | _ep_nuke(ci->ep0in); |
1003 | 1002 | ||
1004 | /* read_setup_packet */ | 1003 | /* read_setup_packet */ |
1005 | do { | 1004 | do { |
1006 | hw_test_and_set_setup_guard(ci); | 1005 | hw_test_and_set_setup_guard(ci); |
1007 | memcpy(&req, &hwep->qh.ptr->setup, sizeof(req)); | 1006 | memcpy(&req, &hwep->qh.ptr->setup, sizeof(req)); |
1008 | } while (!hw_test_and_clear_setup_guard(ci)); | 1007 | } while (!hw_test_and_clear_setup_guard(ci)); |
1009 | 1008 | ||
1010 | type = req.bRequestType; | 1009 | type = req.bRequestType; |
1011 | 1010 | ||
1012 | ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX; | 1011 | ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX; |
1013 | 1012 | ||
1014 | switch (req.bRequest) { | 1013 | switch (req.bRequest) { |
1015 | case USB_REQ_CLEAR_FEATURE: | 1014 | case USB_REQ_CLEAR_FEATURE: |
1016 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && | 1015 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && |
1017 | le16_to_cpu(req.wValue) == | 1016 | le16_to_cpu(req.wValue) == |
1018 | USB_ENDPOINT_HALT) { | 1017 | USB_ENDPOINT_HALT) { |
1019 | if (req.wLength != 0) | 1018 | if (req.wLength != 0) |
1020 | break; | 1019 | break; |
1021 | num = le16_to_cpu(req.wIndex); | 1020 | num = le16_to_cpu(req.wIndex); |
1022 | dir = num & USB_ENDPOINT_DIR_MASK; | 1021 | dir = num & USB_ENDPOINT_DIR_MASK; |
1023 | num &= USB_ENDPOINT_NUMBER_MASK; | 1022 | num &= USB_ENDPOINT_NUMBER_MASK; |
1024 | if (dir) /* TX */ | 1023 | if (dir) /* TX */ |
1025 | num += ci->hw_ep_max/2; | 1024 | num += ci->hw_ep_max/2; |
1026 | if (!ci->ci13xxx_ep[num].wedge) { | 1025 | if (!ci->ci_hw_ep[num].wedge) { |
1027 | spin_unlock(&ci->lock); | 1026 | spin_unlock(&ci->lock); |
1028 | err = usb_ep_clear_halt( | 1027 | err = usb_ep_clear_halt( |
1029 | &ci->ci13xxx_ep[num].ep); | 1028 | &ci->ci_hw_ep[num].ep); |
1030 | spin_lock(&ci->lock); | 1029 | spin_lock(&ci->lock); |
1031 | if (err) | 1030 | if (err) |
1032 | break; | 1031 | break; |
1033 | } | 1032 | } |
1034 | err = isr_setup_status_phase(ci); | 1033 | err = isr_setup_status_phase(ci); |
1035 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) && | 1034 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) && |
1036 | le16_to_cpu(req.wValue) == | 1035 | le16_to_cpu(req.wValue) == |
1037 | USB_DEVICE_REMOTE_WAKEUP) { | 1036 | USB_DEVICE_REMOTE_WAKEUP) { |
1038 | if (req.wLength != 0) | 1037 | if (req.wLength != 0) |
1039 | break; | 1038 | break; |
1040 | ci->remote_wakeup = 0; | 1039 | ci->remote_wakeup = 0; |
1041 | err = isr_setup_status_phase(ci); | 1040 | err = isr_setup_status_phase(ci); |
1042 | } else { | 1041 | } else { |
1043 | goto delegate; | 1042 | goto delegate; |
1044 | } | 1043 | } |
1045 | break; | 1044 | break; |
1046 | case USB_REQ_GET_STATUS: | 1045 | case USB_REQ_GET_STATUS: |
1047 | if (type != (USB_DIR_IN|USB_RECIP_DEVICE) && | 1046 | if (type != (USB_DIR_IN|USB_RECIP_DEVICE) && |
1048 | type != (USB_DIR_IN|USB_RECIP_ENDPOINT) && | 1047 | type != (USB_DIR_IN|USB_RECIP_ENDPOINT) && |
1049 | type != (USB_DIR_IN|USB_RECIP_INTERFACE)) | 1048 | type != (USB_DIR_IN|USB_RECIP_INTERFACE)) |
1050 | goto delegate; | 1049 | goto delegate; |
1051 | if (le16_to_cpu(req.wLength) != 2 || | 1050 | if (le16_to_cpu(req.wLength) != 2 || |
1052 | le16_to_cpu(req.wValue) != 0) | 1051 | le16_to_cpu(req.wValue) != 0) |
1053 | break; | 1052 | break; |
1054 | err = isr_get_status_response(ci, &req); | 1053 | err = isr_get_status_response(ci, &req); |
1055 | break; | 1054 | break; |
1056 | case USB_REQ_SET_ADDRESS: | 1055 | case USB_REQ_SET_ADDRESS: |
1057 | if (type != (USB_DIR_OUT|USB_RECIP_DEVICE)) | 1056 | if (type != (USB_DIR_OUT|USB_RECIP_DEVICE)) |
1058 | goto delegate; | 1057 | goto delegate; |
1059 | if (le16_to_cpu(req.wLength) != 0 || | 1058 | if (le16_to_cpu(req.wLength) != 0 || |
1060 | le16_to_cpu(req.wIndex) != 0) | 1059 | le16_to_cpu(req.wIndex) != 0) |
1061 | break; | 1060 | break; |
1062 | ci->address = (u8)le16_to_cpu(req.wValue); | 1061 | ci->address = (u8)le16_to_cpu(req.wValue); |
1063 | ci->setaddr = true; | 1062 | ci->setaddr = true; |
1064 | err = isr_setup_status_phase(ci); | 1063 | err = isr_setup_status_phase(ci); |
1065 | break; | 1064 | break; |
1066 | case USB_REQ_SET_FEATURE: | 1065 | case USB_REQ_SET_FEATURE: |
1067 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && | 1066 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && |
1068 | le16_to_cpu(req.wValue) == | 1067 | le16_to_cpu(req.wValue) == |
1069 | USB_ENDPOINT_HALT) { | 1068 | USB_ENDPOINT_HALT) { |
1070 | if (req.wLength != 0) | 1069 | if (req.wLength != 0) |
1071 | break; | 1070 | break; |
1072 | num = le16_to_cpu(req.wIndex); | 1071 | num = le16_to_cpu(req.wIndex); |
1073 | dir = num & USB_ENDPOINT_DIR_MASK; | 1072 | dir = num & USB_ENDPOINT_DIR_MASK; |
1074 | num &= USB_ENDPOINT_NUMBER_MASK; | 1073 | num &= USB_ENDPOINT_NUMBER_MASK; |
1075 | if (dir) /* TX */ | 1074 | if (dir) /* TX */ |
1076 | num += ci->hw_ep_max/2; | 1075 | num += ci->hw_ep_max/2; |
1077 | 1076 | ||
1078 | spin_unlock(&ci->lock); | 1077 | spin_unlock(&ci->lock); |
1079 | err = usb_ep_set_halt(&ci->ci13xxx_ep[num].ep); | 1078 | err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep); |
1080 | spin_lock(&ci->lock); | 1079 | spin_lock(&ci->lock); |
1081 | if (!err) | 1080 | if (!err) |
1082 | isr_setup_status_phase(ci); | 1081 | isr_setup_status_phase(ci); |
1083 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) { | 1082 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) { |
1084 | if (req.wLength != 0) | 1083 | if (req.wLength != 0) |
1085 | break; | 1084 | break; |
1086 | switch (le16_to_cpu(req.wValue)) { | 1085 | switch (le16_to_cpu(req.wValue)) { |
1087 | case USB_DEVICE_REMOTE_WAKEUP: | 1086 | case USB_DEVICE_REMOTE_WAKEUP: |
1088 | ci->remote_wakeup = 1; | 1087 | ci->remote_wakeup = 1; |
1089 | err = isr_setup_status_phase(ci); | 1088 | err = isr_setup_status_phase(ci); |
1090 | break; | 1089 | break; |
1091 | case USB_DEVICE_TEST_MODE: | 1090 | case USB_DEVICE_TEST_MODE: |
1092 | tmode = le16_to_cpu(req.wIndex) >> 8; | 1091 | tmode = le16_to_cpu(req.wIndex) >> 8; |
1093 | switch (tmode) { | 1092 | switch (tmode) { |
1094 | case TEST_J: | 1093 | case TEST_J: |
1095 | case TEST_K: | 1094 | case TEST_K: |
1096 | case TEST_SE0_NAK: | 1095 | case TEST_SE0_NAK: |
1097 | case TEST_PACKET: | 1096 | case TEST_PACKET: |
1098 | case TEST_FORCE_EN: | 1097 | case TEST_FORCE_EN: |
1099 | ci->test_mode = tmode; | 1098 | ci->test_mode = tmode; |
1100 | err = isr_setup_status_phase( | 1099 | err = isr_setup_status_phase( |
1101 | ci); | 1100 | ci); |
1102 | break; | 1101 | break; |
1103 | default: | 1102 | default: |
1104 | break; | 1103 | break; |
1105 | } | 1104 | } |
1106 | default: | 1105 | default: |
1107 | goto delegate; | 1106 | goto delegate; |
1108 | } | 1107 | } |
1109 | } else { | 1108 | } else { |
1110 | goto delegate; | 1109 | goto delegate; |
1111 | } | 1110 | } |
1112 | break; | 1111 | break; |
1113 | default: | 1112 | default: |
1114 | delegate: | 1113 | delegate: |
1115 | if (req.wLength == 0) /* no data phase */ | 1114 | if (req.wLength == 0) /* no data phase */ |
1116 | ci->ep0_dir = TX; | 1115 | ci->ep0_dir = TX; |
1117 | 1116 | ||
1118 | spin_unlock(&ci->lock); | 1117 | spin_unlock(&ci->lock); |
1119 | err = ci->driver->setup(&ci->gadget, &req); | 1118 | err = ci->driver->setup(&ci->gadget, &req); |
1120 | spin_lock(&ci->lock); | 1119 | spin_lock(&ci->lock); |
1121 | break; | 1120 | break; |
1122 | } | 1121 | } |
1123 | 1122 | ||
1124 | if (err < 0) { | 1123 | if (err < 0) { |
1125 | spin_unlock(&ci->lock); | 1124 | spin_unlock(&ci->lock); |
1126 | if (usb_ep_set_halt(&hwep->ep)) | 1125 | if (usb_ep_set_halt(&hwep->ep)) |
1127 | dev_err(ci->dev, "error: ep_set_halt\n"); | 1126 | dev_err(ci->dev, "error: ep_set_halt\n"); |
1128 | spin_lock(&ci->lock); | 1127 | spin_lock(&ci->lock); |
1129 | } | 1128 | } |
1130 | } | 1129 | } |
1131 | } | 1130 | } |
1132 | 1131 | ||
1133 | /****************************************************************************** | 1132 | /****************************************************************************** |
1134 | * ENDPT block | 1133 | * ENDPT block |
1135 | *****************************************************************************/ | 1134 | *****************************************************************************/ |
1136 | /** | 1135 | /** |
1137 | * ep_enable: configure endpoint, making it usable | 1136 | * ep_enable: configure endpoint, making it usable |
1138 | * | 1137 | * |
1139 | * Check usb_ep_enable() at "usb_gadget.h" for details | 1138 | * Check usb_ep_enable() at "usb_gadget.h" for details |
1140 | */ | 1139 | */ |
1141 | static int ep_enable(struct usb_ep *ep, | 1140 | static int ep_enable(struct usb_ep *ep, |
1142 | const struct usb_endpoint_descriptor *desc) | 1141 | const struct usb_endpoint_descriptor *desc) |
1143 | { | 1142 | { |
1144 | struct ci13xxx_ep *hwep = container_of(ep, struct ci13xxx_ep, ep); | 1143 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1145 | int retval = 0; | 1144 | int retval = 0; |
1146 | unsigned long flags; | 1145 | unsigned long flags; |
1147 | u32 cap = 0; | 1146 | u32 cap = 0; |
1148 | 1147 | ||
1149 | if (ep == NULL || desc == NULL) | 1148 | if (ep == NULL || desc == NULL) |
1150 | return -EINVAL; | 1149 | return -EINVAL; |
1151 | 1150 | ||
1152 | spin_lock_irqsave(hwep->lock, flags); | 1151 | spin_lock_irqsave(hwep->lock, flags); |
1153 | 1152 | ||
1154 | /* only internal SW should enable ctrl endpts */ | 1153 | /* only internal SW should enable ctrl endpts */ |
1155 | 1154 | ||
1156 | hwep->ep.desc = desc; | 1155 | hwep->ep.desc = desc; |
1157 | 1156 | ||
1158 | if (!list_empty(&hwep->qh.queue)) | 1157 | if (!list_empty(&hwep->qh.queue)) |
1159 | dev_warn(hwep->ci->dev, "enabling a non-empty endpoint!\n"); | 1158 | dev_warn(hwep->ci->dev, "enabling a non-empty endpoint!\n"); |
1160 | 1159 | ||
1161 | hwep->dir = usb_endpoint_dir_in(desc) ? TX : RX; | 1160 | hwep->dir = usb_endpoint_dir_in(desc) ? TX : RX; |
1162 | hwep->num = usb_endpoint_num(desc); | 1161 | hwep->num = usb_endpoint_num(desc); |
1163 | hwep->type = usb_endpoint_type(desc); | 1162 | hwep->type = usb_endpoint_type(desc); |
1164 | 1163 | ||
1165 | hwep->ep.maxpacket = usb_endpoint_maxp(desc) & 0x07ff; | 1164 | hwep->ep.maxpacket = usb_endpoint_maxp(desc) & 0x07ff; |
1166 | hwep->ep.mult = QH_ISO_MULT(usb_endpoint_maxp(desc)); | 1165 | hwep->ep.mult = QH_ISO_MULT(usb_endpoint_maxp(desc)); |
1167 | 1166 | ||
1168 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) | 1167 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) |
1169 | cap |= QH_IOS; | 1168 | cap |= QH_IOS; |
1170 | if (hwep->num) | 1169 | if (hwep->num) |
1171 | cap |= QH_ZLT; | 1170 | cap |= QH_ZLT; |
1172 | cap |= (hwep->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT; | 1171 | cap |= (hwep->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT; |
1173 | 1172 | ||
1174 | hwep->qh.ptr->cap = cpu_to_le32(cap); | 1173 | hwep->qh.ptr->cap = cpu_to_le32(cap); |
1175 | 1174 | ||
1176 | hwep->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE); /* needed? */ | 1175 | hwep->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE); /* needed? */ |
1177 | 1176 | ||
1178 | /* | 1177 | /* |
1179 | * Enable endpoints in the HW other than ep0 as ep0 | 1178 | * Enable endpoints in the HW other than ep0 as ep0 |
1180 | * is always enabled | 1179 | * is always enabled |
1181 | */ | 1180 | */ |
1182 | if (hwep->num) | 1181 | if (hwep->num) |
1183 | retval |= hw_ep_enable(hwep->ci, hwep->num, hwep->dir, | 1182 | retval |= hw_ep_enable(hwep->ci, hwep->num, hwep->dir, |
1184 | hwep->type); | 1183 | hwep->type); |
1185 | 1184 | ||
1186 | spin_unlock_irqrestore(hwep->lock, flags); | 1185 | spin_unlock_irqrestore(hwep->lock, flags); |
1187 | return retval; | 1186 | return retval; |
1188 | } | 1187 | } |
1189 | 1188 | ||
1190 | /** | 1189 | /** |
1191 | * ep_disable: endpoint is no longer usable | 1190 | * ep_disable: endpoint is no longer usable |
1192 | * | 1191 | * |
1193 | * Check usb_ep_disable() at "usb_gadget.h" for details | 1192 | * Check usb_ep_disable() at "usb_gadget.h" for details |
1194 | */ | 1193 | */ |
1195 | static int ep_disable(struct usb_ep *ep) | 1194 | static int ep_disable(struct usb_ep *ep) |
1196 | { | 1195 | { |
1197 | struct ci13xxx_ep *hwep = container_of(ep, struct ci13xxx_ep, ep); | 1196 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1198 | int direction, retval = 0; | 1197 | int direction, retval = 0; |
1199 | unsigned long flags; | 1198 | unsigned long flags; |
1200 | 1199 | ||
1201 | if (ep == NULL) | 1200 | if (ep == NULL) |
1202 | return -EINVAL; | 1201 | return -EINVAL; |
1203 | else if (hwep->ep.desc == NULL) | 1202 | else if (hwep->ep.desc == NULL) |
1204 | return -EBUSY; | 1203 | return -EBUSY; |
1205 | 1204 | ||
1206 | spin_lock_irqsave(hwep->lock, flags); | 1205 | spin_lock_irqsave(hwep->lock, flags); |
1207 | 1206 | ||
1208 | /* only internal SW should disable ctrl endpts */ | 1207 | /* only internal SW should disable ctrl endpts */ |
1209 | 1208 | ||
1210 | direction = hwep->dir; | 1209 | direction = hwep->dir; |
1211 | do { | 1210 | do { |
1212 | retval |= _ep_nuke(hwep); | 1211 | retval |= _ep_nuke(hwep); |
1213 | retval |= hw_ep_disable(hwep->ci, hwep->num, hwep->dir); | 1212 | retval |= hw_ep_disable(hwep->ci, hwep->num, hwep->dir); |
1214 | 1213 | ||
1215 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) | 1214 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) |
1216 | hwep->dir = (hwep->dir == TX) ? RX : TX; | 1215 | hwep->dir = (hwep->dir == TX) ? RX : TX; |
1217 | 1216 | ||
1218 | } while (hwep->dir != direction); | 1217 | } while (hwep->dir != direction); |
1219 | 1218 | ||
1220 | hwep->ep.desc = NULL; | 1219 | hwep->ep.desc = NULL; |
1221 | 1220 | ||
1222 | spin_unlock_irqrestore(hwep->lock, flags); | 1221 | spin_unlock_irqrestore(hwep->lock, flags); |
1223 | return retval; | 1222 | return retval; |
1224 | } | 1223 | } |
1225 | 1224 | ||
1226 | /** | 1225 | /** |
1227 | * ep_alloc_request: allocate a request object to use with this endpoint | 1226 | * ep_alloc_request: allocate a request object to use with this endpoint |
1228 | * | 1227 | * |
1229 | * Check usb_ep_alloc_request() at "usb_gadget.h" for details | 1228 | * Check usb_ep_alloc_request() at "usb_gadget.h" for details |
1230 | */ | 1229 | */ |
1231 | static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) | 1230 | static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) |
1232 | { | 1231 | { |
1233 | struct ci13xxx_req *hwreq = NULL; | 1232 | struct ci_hw_req *hwreq = NULL; |
1234 | 1233 | ||
1235 | if (ep == NULL) | 1234 | if (ep == NULL) |
1236 | return NULL; | 1235 | return NULL; |
1237 | 1236 | ||
1238 | hwreq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags); | 1237 | hwreq = kzalloc(sizeof(struct ci_hw_req), gfp_flags); |
1239 | if (hwreq != NULL) { | 1238 | if (hwreq != NULL) { |
1240 | INIT_LIST_HEAD(&hwreq->queue); | 1239 | INIT_LIST_HEAD(&hwreq->queue); |
1241 | INIT_LIST_HEAD(&hwreq->tds); | 1240 | INIT_LIST_HEAD(&hwreq->tds); |
1242 | } | 1241 | } |
1243 | 1242 | ||
1244 | return (hwreq == NULL) ? NULL : &hwreq->req; | 1243 | return (hwreq == NULL) ? NULL : &hwreq->req; |
1245 | } | 1244 | } |
1246 | 1245 | ||
1247 | /** | 1246 | /** |
1248 | * ep_free_request: frees a request object | 1247 | * ep_free_request: frees a request object |
1249 | * | 1248 | * |
1250 | * Check usb_ep_free_request() at "usb_gadget.h" for details | 1249 | * Check usb_ep_free_request() at "usb_gadget.h" for details |
1251 | */ | 1250 | */ |
1252 | static void ep_free_request(struct usb_ep *ep, struct usb_request *req) | 1251 | static void ep_free_request(struct usb_ep *ep, struct usb_request *req) |
1253 | { | 1252 | { |
1254 | struct ci13xxx_ep *hwep = container_of(ep, struct ci13xxx_ep, ep); | 1253 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1255 | struct ci13xxx_req *hwreq = container_of(req, struct ci13xxx_req, req); | 1254 | struct ci_hw_req *hwreq = container_of(req, struct ci_hw_req, req); |
1256 | struct td_node *node, *tmpnode; | 1255 | struct td_node *node, *tmpnode; |
1257 | unsigned long flags; | 1256 | unsigned long flags; |
1258 | 1257 | ||
1259 | if (ep == NULL || req == NULL) { | 1258 | if (ep == NULL || req == NULL) { |
1260 | return; | 1259 | return; |
1261 | } else if (!list_empty(&hwreq->queue)) { | 1260 | } else if (!list_empty(&hwreq->queue)) { |
1262 | dev_err(hwep->ci->dev, "freeing queued request\n"); | 1261 | dev_err(hwep->ci->dev, "freeing queued request\n"); |
1263 | return; | 1262 | return; |
1264 | } | 1263 | } |
1265 | 1264 | ||
1266 | spin_lock_irqsave(hwep->lock, flags); | 1265 | spin_lock_irqsave(hwep->lock, flags); |
1267 | 1266 | ||
1268 | list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { | 1267 | list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { |
1269 | dma_pool_free(hwep->td_pool, node->ptr, node->dma); | 1268 | dma_pool_free(hwep->td_pool, node->ptr, node->dma); |
1270 | list_del_init(&node->td); | 1269 | list_del_init(&node->td); |
1271 | node->ptr = NULL; | 1270 | node->ptr = NULL; |
1272 | kfree(node); | 1271 | kfree(node); |
1273 | } | 1272 | } |
1274 | 1273 | ||
1275 | kfree(hwreq); | 1274 | kfree(hwreq); |
1276 | 1275 | ||
1277 | spin_unlock_irqrestore(hwep->lock, flags); | 1276 | spin_unlock_irqrestore(hwep->lock, flags); |
1278 | } | 1277 | } |
1279 | 1278 | ||
1280 | /** | 1279 | /** |
1281 | * ep_queue: queues (submits) an I/O request to an endpoint | 1280 | * ep_queue: queues (submits) an I/O request to an endpoint |
1282 | * | 1281 | * |
1283 | * Check usb_ep_queue()* at usb_gadget.h" for details | 1282 | * Check usb_ep_queue()* at usb_gadget.h" for details |
1284 | */ | 1283 | */ |
1285 | static int ep_queue(struct usb_ep *ep, struct usb_request *req, | 1284 | static int ep_queue(struct usb_ep *ep, struct usb_request *req, |
1286 | gfp_t __maybe_unused gfp_flags) | 1285 | gfp_t __maybe_unused gfp_flags) |
1287 | { | 1286 | { |
1288 | struct ci13xxx_ep *hwep = container_of(ep, struct ci13xxx_ep, ep); | 1287 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1289 | int retval = 0; | 1288 | int retval = 0; |
1290 | unsigned long flags; | 1289 | unsigned long flags; |
1291 | 1290 | ||
1292 | if (ep == NULL || req == NULL || hwep->ep.desc == NULL) | 1291 | if (ep == NULL || req == NULL || hwep->ep.desc == NULL) |
1293 | return -EINVAL; | 1292 | return -EINVAL; |
1294 | 1293 | ||
1295 | spin_lock_irqsave(hwep->lock, flags); | 1294 | spin_lock_irqsave(hwep->lock, flags); |
1296 | retval = _ep_queue(ep, req, gfp_flags); | 1295 | retval = _ep_queue(ep, req, gfp_flags); |
1297 | spin_unlock_irqrestore(hwep->lock, flags); | 1296 | spin_unlock_irqrestore(hwep->lock, flags); |
1298 | return retval; | 1297 | return retval; |
1299 | } | 1298 | } |
1300 | 1299 | ||
1301 | /** | 1300 | /** |
1302 | * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint | 1301 | * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint |
1303 | * | 1302 | * |
1304 | * Check usb_ep_dequeue() at "usb_gadget.h" for details | 1303 | * Check usb_ep_dequeue() at "usb_gadget.h" for details |
1305 | */ | 1304 | */ |
1306 | static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) | 1305 | static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) |
1307 | { | 1306 | { |
1308 | struct ci13xxx_ep *hwep = container_of(ep, struct ci13xxx_ep, ep); | 1307 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1309 | struct ci13xxx_req *hwreq = container_of(req, struct ci13xxx_req, req); | 1308 | struct ci_hw_req *hwreq = container_of(req, struct ci_hw_req, req); |
1310 | unsigned long flags; | 1309 | unsigned long flags; |
1311 | 1310 | ||
1312 | if (ep == NULL || req == NULL || hwreq->req.status != -EALREADY || | 1311 | if (ep == NULL || req == NULL || hwreq->req.status != -EALREADY || |
1313 | hwep->ep.desc == NULL || list_empty(&hwreq->queue) || | 1312 | hwep->ep.desc == NULL || list_empty(&hwreq->queue) || |
1314 | list_empty(&hwep->qh.queue)) | 1313 | list_empty(&hwep->qh.queue)) |
1315 | return -EINVAL; | 1314 | return -EINVAL; |
1316 | 1315 | ||
1317 | spin_lock_irqsave(hwep->lock, flags); | 1316 | spin_lock_irqsave(hwep->lock, flags); |
1318 | 1317 | ||
1319 | hw_ep_flush(hwep->ci, hwep->num, hwep->dir); | 1318 | hw_ep_flush(hwep->ci, hwep->num, hwep->dir); |
1320 | 1319 | ||
1321 | /* pop request */ | 1320 | /* pop request */ |
1322 | list_del_init(&hwreq->queue); | 1321 | list_del_init(&hwreq->queue); |
1323 | 1322 | ||
1324 | usb_gadget_unmap_request(&hwep->ci->gadget, req, hwep->dir); | 1323 | usb_gadget_unmap_request(&hwep->ci->gadget, req, hwep->dir); |
1325 | 1324 | ||
1326 | req->status = -ECONNRESET; | 1325 | req->status = -ECONNRESET; |
1327 | 1326 | ||
1328 | if (hwreq->req.complete != NULL) { | 1327 | if (hwreq->req.complete != NULL) { |
1329 | spin_unlock(hwep->lock); | 1328 | spin_unlock(hwep->lock); |
1330 | hwreq->req.complete(&hwep->ep, &hwreq->req); | 1329 | hwreq->req.complete(&hwep->ep, &hwreq->req); |
1331 | spin_lock(hwep->lock); | 1330 | spin_lock(hwep->lock); |
1332 | } | 1331 | } |
1333 | 1332 | ||
1334 | spin_unlock_irqrestore(hwep->lock, flags); | 1333 | spin_unlock_irqrestore(hwep->lock, flags); |
1335 | return 0; | 1334 | return 0; |
1336 | } | 1335 | } |
1337 | 1336 | ||
1338 | /** | 1337 | /** |
1339 | * ep_set_halt: sets the endpoint halt feature | 1338 | * ep_set_halt: sets the endpoint halt feature |
1340 | * | 1339 | * |
1341 | * Check usb_ep_set_halt() at "usb_gadget.h" for details | 1340 | * Check usb_ep_set_halt() at "usb_gadget.h" for details |
1342 | */ | 1341 | */ |
1343 | static int ep_set_halt(struct usb_ep *ep, int value) | 1342 | static int ep_set_halt(struct usb_ep *ep, int value) |
1344 | { | 1343 | { |
1345 | struct ci13xxx_ep *hwep = container_of(ep, struct ci13xxx_ep, ep); | 1344 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1346 | int direction, retval = 0; | 1345 | int direction, retval = 0; |
1347 | unsigned long flags; | 1346 | unsigned long flags; |
1348 | 1347 | ||
1349 | if (ep == NULL || hwep->ep.desc == NULL) | 1348 | if (ep == NULL || hwep->ep.desc == NULL) |
1350 | return -EINVAL; | 1349 | return -EINVAL; |
1351 | 1350 | ||
1352 | if (usb_endpoint_xfer_isoc(hwep->ep.desc)) | 1351 | if (usb_endpoint_xfer_isoc(hwep->ep.desc)) |
1353 | return -EOPNOTSUPP; | 1352 | return -EOPNOTSUPP; |
1354 | 1353 | ||
1355 | spin_lock_irqsave(hwep->lock, flags); | 1354 | spin_lock_irqsave(hwep->lock, flags); |
1356 | 1355 | ||
1357 | #ifndef STALL_IN | 1356 | #ifndef STALL_IN |
1358 | /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */ | 1357 | /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */ |
1359 | if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX && | 1358 | if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX && |
1360 | !list_empty(&hwep->qh.queue)) { | 1359 | !list_empty(&hwep->qh.queue)) { |
1361 | spin_unlock_irqrestore(hwep->lock, flags); | 1360 | spin_unlock_irqrestore(hwep->lock, flags); |
1362 | return -EAGAIN; | 1361 | return -EAGAIN; |
1363 | } | 1362 | } |
1364 | #endif | 1363 | #endif |
1365 | 1364 | ||
1366 | direction = hwep->dir; | 1365 | direction = hwep->dir; |
1367 | do { | 1366 | do { |
1368 | retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value); | 1367 | retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value); |
1369 | 1368 | ||
1370 | if (!value) | 1369 | if (!value) |
1371 | hwep->wedge = 0; | 1370 | hwep->wedge = 0; |
1372 | 1371 | ||
1373 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) | 1372 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) |
1374 | hwep->dir = (hwep->dir == TX) ? RX : TX; | 1373 | hwep->dir = (hwep->dir == TX) ? RX : TX; |
1375 | 1374 | ||
1376 | } while (hwep->dir != direction); | 1375 | } while (hwep->dir != direction); |
1377 | 1376 | ||
1378 | spin_unlock_irqrestore(hwep->lock, flags); | 1377 | spin_unlock_irqrestore(hwep->lock, flags); |
1379 | return retval; | 1378 | return retval; |
1380 | } | 1379 | } |
1381 | 1380 | ||
1382 | /** | 1381 | /** |
1383 | * ep_set_wedge: sets the halt feature and ignores clear requests | 1382 | * ep_set_wedge: sets the halt feature and ignores clear requests |
1384 | * | 1383 | * |
1385 | * Check usb_ep_set_wedge() at "usb_gadget.h" for details | 1384 | * Check usb_ep_set_wedge() at "usb_gadget.h" for details |
1386 | */ | 1385 | */ |
1387 | static int ep_set_wedge(struct usb_ep *ep) | 1386 | static int ep_set_wedge(struct usb_ep *ep) |
1388 | { | 1387 | { |
1389 | struct ci13xxx_ep *hwep = container_of(ep, struct ci13xxx_ep, ep); | 1388 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1390 | unsigned long flags; | 1389 | unsigned long flags; |
1391 | 1390 | ||
1392 | if (ep == NULL || hwep->ep.desc == NULL) | 1391 | if (ep == NULL || hwep->ep.desc == NULL) |
1393 | return -EINVAL; | 1392 | return -EINVAL; |
1394 | 1393 | ||
1395 | spin_lock_irqsave(hwep->lock, flags); | 1394 | spin_lock_irqsave(hwep->lock, flags); |
1396 | hwep->wedge = 1; | 1395 | hwep->wedge = 1; |
1397 | spin_unlock_irqrestore(hwep->lock, flags); | 1396 | spin_unlock_irqrestore(hwep->lock, flags); |
1398 | 1397 | ||
1399 | return usb_ep_set_halt(ep); | 1398 | return usb_ep_set_halt(ep); |
1400 | } | 1399 | } |
1401 | 1400 | ||
1402 | /** | 1401 | /** |
1403 | * ep_fifo_flush: flushes contents of a fifo | 1402 | * ep_fifo_flush: flushes contents of a fifo |
1404 | * | 1403 | * |
1405 | * Check usb_ep_fifo_flush() at "usb_gadget.h" for details | 1404 | * Check usb_ep_fifo_flush() at "usb_gadget.h" for details |
1406 | */ | 1405 | */ |
1407 | static void ep_fifo_flush(struct usb_ep *ep) | 1406 | static void ep_fifo_flush(struct usb_ep *ep) |
1408 | { | 1407 | { |
1409 | struct ci13xxx_ep *hwep = container_of(ep, struct ci13xxx_ep, ep); | 1408 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1410 | unsigned long flags; | 1409 | unsigned long flags; |
1411 | 1410 | ||
1412 | if (ep == NULL) { | 1411 | if (ep == NULL) { |
1413 | dev_err(hwep->ci->dev, "%02X: -EINVAL\n", _usb_addr(hwep)); | 1412 | dev_err(hwep->ci->dev, "%02X: -EINVAL\n", _usb_addr(hwep)); |
1414 | return; | 1413 | return; |
1415 | } | 1414 | } |
1416 | 1415 | ||
1417 | spin_lock_irqsave(hwep->lock, flags); | 1416 | spin_lock_irqsave(hwep->lock, flags); |
1418 | 1417 | ||
1419 | hw_ep_flush(hwep->ci, hwep->num, hwep->dir); | 1418 | hw_ep_flush(hwep->ci, hwep->num, hwep->dir); |
1420 | 1419 | ||
1421 | spin_unlock_irqrestore(hwep->lock, flags); | 1420 | spin_unlock_irqrestore(hwep->lock, flags); |
1422 | } | 1421 | } |
1423 | 1422 | ||
1424 | /** | 1423 | /** |
1425 | * Endpoint-specific part of the API to the USB controller hardware | 1424 | * Endpoint-specific part of the API to the USB controller hardware |
1426 | * Check "usb_gadget.h" for details | 1425 | * Check "usb_gadget.h" for details |
1427 | */ | 1426 | */ |
1428 | static const struct usb_ep_ops usb_ep_ops = { | 1427 | static const struct usb_ep_ops usb_ep_ops = { |
1429 | .enable = ep_enable, | 1428 | .enable = ep_enable, |
1430 | .disable = ep_disable, | 1429 | .disable = ep_disable, |
1431 | .alloc_request = ep_alloc_request, | 1430 | .alloc_request = ep_alloc_request, |
1432 | .free_request = ep_free_request, | 1431 | .free_request = ep_free_request, |
1433 | .queue = ep_queue, | 1432 | .queue = ep_queue, |
1434 | .dequeue = ep_dequeue, | 1433 | .dequeue = ep_dequeue, |
1435 | .set_halt = ep_set_halt, | 1434 | .set_halt = ep_set_halt, |
1436 | .set_wedge = ep_set_wedge, | 1435 | .set_wedge = ep_set_wedge, |
1437 | .fifo_flush = ep_fifo_flush, | 1436 | .fifo_flush = ep_fifo_flush, |
1438 | }; | 1437 | }; |
1439 | 1438 | ||
1440 | /****************************************************************************** | 1439 | /****************************************************************************** |
1441 | * GADGET block | 1440 | * GADGET block |
1442 | *****************************************************************************/ | 1441 | *****************************************************************************/ |
1443 | static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) | 1442 | static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) |
1444 | { | 1443 | { |
1445 | struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | 1444 | struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); |
1446 | unsigned long flags; | 1445 | unsigned long flags; |
1447 | int gadget_ready = 0; | 1446 | int gadget_ready = 0; |
1448 | 1447 | ||
1449 | if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS)) | 1448 | if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS)) |
1450 | return -EOPNOTSUPP; | 1449 | return -EOPNOTSUPP; |
1451 | 1450 | ||
1452 | spin_lock_irqsave(&ci->lock, flags); | 1451 | spin_lock_irqsave(&ci->lock, flags); |
1453 | ci->vbus_active = is_active; | 1452 | ci->vbus_active = is_active; |
1454 | if (ci->driver) | 1453 | if (ci->driver) |
1455 | gadget_ready = 1; | 1454 | gadget_ready = 1; |
1456 | spin_unlock_irqrestore(&ci->lock, flags); | 1455 | spin_unlock_irqrestore(&ci->lock, flags); |
1457 | 1456 | ||
1458 | if (gadget_ready) { | 1457 | if (gadget_ready) { |
1459 | if (is_active) { | 1458 | if (is_active) { |
1460 | pm_runtime_get_sync(&_gadget->dev); | 1459 | pm_runtime_get_sync(&_gadget->dev); |
1461 | hw_device_reset(ci, USBMODE_CM_DC); | 1460 | hw_device_reset(ci, USBMODE_CM_DC); |
1462 | hw_device_state(ci, ci->ep0out->qh.dma); | 1461 | hw_device_state(ci, ci->ep0out->qh.dma); |
1463 | } else { | 1462 | } else { |
1464 | hw_device_state(ci, 0); | 1463 | hw_device_state(ci, 0); |
1465 | if (ci->platdata->notify_event) | 1464 | if (ci->platdata->notify_event) |
1466 | ci->platdata->notify_event(ci, | 1465 | ci->platdata->notify_event(ci, |
1467 | CI13XXX_CONTROLLER_STOPPED_EVENT); | 1466 | CI_HDRC_CONTROLLER_STOPPED_EVENT); |
1468 | _gadget_stop_activity(&ci->gadget); | 1467 | _gadget_stop_activity(&ci->gadget); |
1469 | pm_runtime_put_sync(&_gadget->dev); | 1468 | pm_runtime_put_sync(&_gadget->dev); |
1470 | } | 1469 | } |
1471 | } | 1470 | } |
1472 | 1471 | ||
1473 | return 0; | 1472 | return 0; |
1474 | } | 1473 | } |
1475 | 1474 | ||
1476 | static int ci13xxx_wakeup(struct usb_gadget *_gadget) | 1475 | static int ci_udc_wakeup(struct usb_gadget *_gadget) |
1477 | { | 1476 | { |
1478 | struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | 1477 | struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); |
1479 | unsigned long flags; | 1478 | unsigned long flags; |
1480 | int ret = 0; | 1479 | int ret = 0; |
1481 | 1480 | ||
1482 | spin_lock_irqsave(&ci->lock, flags); | 1481 | spin_lock_irqsave(&ci->lock, flags); |
1483 | if (!ci->remote_wakeup) { | 1482 | if (!ci->remote_wakeup) { |
1484 | ret = -EOPNOTSUPP; | 1483 | ret = -EOPNOTSUPP; |
1485 | goto out; | 1484 | goto out; |
1486 | } | 1485 | } |
1487 | if (!hw_read(ci, OP_PORTSC, PORTSC_SUSP)) { | 1486 | if (!hw_read(ci, OP_PORTSC, PORTSC_SUSP)) { |
1488 | ret = -EINVAL; | 1487 | ret = -EINVAL; |
1489 | goto out; | 1488 | goto out; |
1490 | } | 1489 | } |
1491 | hw_write(ci, OP_PORTSC, PORTSC_FPR, PORTSC_FPR); | 1490 | hw_write(ci, OP_PORTSC, PORTSC_FPR, PORTSC_FPR); |
1492 | out: | 1491 | out: |
1493 | spin_unlock_irqrestore(&ci->lock, flags); | 1492 | spin_unlock_irqrestore(&ci->lock, flags); |
1494 | return ret; | 1493 | return ret; |
1495 | } | 1494 | } |
1496 | 1495 | ||
1497 | static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned ma) | 1496 | static int ci_udc_vbus_draw(struct usb_gadget *_gadget, unsigned ma) |
1498 | { | 1497 | { |
1499 | struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | 1498 | struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); |
1500 | 1499 | ||
1501 | if (ci->transceiver) | 1500 | if (ci->transceiver) |
1502 | return usb_phy_set_power(ci->transceiver, ma); | 1501 | return usb_phy_set_power(ci->transceiver, ma); |
1503 | return -ENOTSUPP; | 1502 | return -ENOTSUPP; |
1504 | } | 1503 | } |
1505 | 1504 | ||
1506 | /* Change Data+ pullup status | 1505 | /* Change Data+ pullup status |
1507 | * this func is used by usb_gadget_connect/disconnet | 1506 | * this func is used by usb_gadget_connect/disconnet |
1508 | */ | 1507 | */ |
1509 | static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on) | 1508 | static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on) |
1510 | { | 1509 | { |
1511 | struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | 1510 | struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); |
1512 | 1511 | ||
1513 | if (is_on) | 1512 | if (is_on) |
1514 | hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); | 1513 | hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); |
1515 | else | 1514 | else |
1516 | hw_write(ci, OP_USBCMD, USBCMD_RS, 0); | 1515 | hw_write(ci, OP_USBCMD, USBCMD_RS, 0); |
1517 | 1516 | ||
1518 | return 0; | 1517 | return 0; |
1519 | } | 1518 | } |
1520 | 1519 | ||
1521 | static int ci13xxx_start(struct usb_gadget *gadget, | 1520 | static int ci_udc_start(struct usb_gadget *gadget, |
1522 | struct usb_gadget_driver *driver); | 1521 | struct usb_gadget_driver *driver); |
1523 | static int ci13xxx_stop(struct usb_gadget *gadget, | 1522 | static int ci_udc_stop(struct usb_gadget *gadget, |
1524 | struct usb_gadget_driver *driver); | 1523 | struct usb_gadget_driver *driver); |
1525 | /** | 1524 | /** |
1526 | * Device operations part of the API to the USB controller hardware, | 1525 | * Device operations part of the API to the USB controller hardware, |
1527 | * which don't involve endpoints (or i/o) | 1526 | * which don't involve endpoints (or i/o) |
1528 | * Check "usb_gadget.h" for details | 1527 | * Check "usb_gadget.h" for details |
1529 | */ | 1528 | */ |
1530 | static const struct usb_gadget_ops usb_gadget_ops = { | 1529 | static const struct usb_gadget_ops usb_gadget_ops = { |
1531 | .vbus_session = ci13xxx_vbus_session, | 1530 | .vbus_session = ci_udc_vbus_session, |
1532 | .wakeup = ci13xxx_wakeup, | 1531 | .wakeup = ci_udc_wakeup, |
1533 | .pullup = ci13xxx_pullup, | 1532 | .pullup = ci_udc_pullup, |
1534 | .vbus_draw = ci13xxx_vbus_draw, | 1533 | .vbus_draw = ci_udc_vbus_draw, |
1535 | .udc_start = ci13xxx_start, | 1534 | .udc_start = ci_udc_start, |
1536 | .udc_stop = ci13xxx_stop, | 1535 | .udc_stop = ci_udc_stop, |
1537 | }; | 1536 | }; |
1538 | 1537 | ||
1539 | static int init_eps(struct ci13xxx *ci) | 1538 | static int init_eps(struct ci_hdrc *ci) |
1540 | { | 1539 | { |
1541 | int retval = 0, i, j; | 1540 | int retval = 0, i, j; |
1542 | 1541 | ||
1543 | for (i = 0; i < ci->hw_ep_max/2; i++) | 1542 | for (i = 0; i < ci->hw_ep_max/2; i++) |
1544 | for (j = RX; j <= TX; j++) { | 1543 | for (j = RX; j <= TX; j++) { |
1545 | int k = i + j * ci->hw_ep_max/2; | 1544 | int k = i + j * ci->hw_ep_max/2; |
1546 | struct ci13xxx_ep *hwep = &ci->ci13xxx_ep[k]; | 1545 | struct ci_hw_ep *hwep = &ci->ci_hw_ep[k]; |
1547 | 1546 | ||
1548 | scnprintf(hwep->name, sizeof(hwep->name), "ep%i%s", i, | 1547 | scnprintf(hwep->name, sizeof(hwep->name), "ep%i%s", i, |
1549 | (j == TX) ? "in" : "out"); | 1548 | (j == TX) ? "in" : "out"); |
1550 | 1549 | ||
1551 | hwep->ci = ci; | 1550 | hwep->ci = ci; |
1552 | hwep->lock = &ci->lock; | 1551 | hwep->lock = &ci->lock; |
1553 | hwep->td_pool = ci->td_pool; | 1552 | hwep->td_pool = ci->td_pool; |
1554 | 1553 | ||
1555 | hwep->ep.name = hwep->name; | 1554 | hwep->ep.name = hwep->name; |
1556 | hwep->ep.ops = &usb_ep_ops; | 1555 | hwep->ep.ops = &usb_ep_ops; |
1557 | /* | 1556 | /* |
1558 | * for ep0: maxP defined in desc, for other | 1557 | * for ep0: maxP defined in desc, for other |
1559 | * eps, maxP is set by epautoconfig() called | 1558 | * eps, maxP is set by epautoconfig() called |
1560 | * by gadget layer | 1559 | * by gadget layer |
1561 | */ | 1560 | */ |
1562 | hwep->ep.maxpacket = (unsigned short)~0; | 1561 | hwep->ep.maxpacket = (unsigned short)~0; |
1563 | 1562 | ||
1564 | INIT_LIST_HEAD(&hwep->qh.queue); | 1563 | INIT_LIST_HEAD(&hwep->qh.queue); |
1565 | hwep->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, | 1564 | hwep->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, |
1566 | &hwep->qh.dma); | 1565 | &hwep->qh.dma); |
1567 | if (hwep->qh.ptr == NULL) | 1566 | if (hwep->qh.ptr == NULL) |
1568 | retval = -ENOMEM; | 1567 | retval = -ENOMEM; |
1569 | else | 1568 | else |
1570 | memset(hwep->qh.ptr, 0, sizeof(*hwep->qh.ptr)); | 1569 | memset(hwep->qh.ptr, 0, sizeof(*hwep->qh.ptr)); |
1571 | 1570 | ||
1572 | /* | 1571 | /* |
1573 | * set up shorthands for ep0 out and in endpoints, | 1572 | * set up shorthands for ep0 out and in endpoints, |
1574 | * don't add to gadget's ep_list | 1573 | * don't add to gadget's ep_list |
1575 | */ | 1574 | */ |
1576 | if (i == 0) { | 1575 | if (i == 0) { |
1577 | if (j == RX) | 1576 | if (j == RX) |
1578 | ci->ep0out = hwep; | 1577 | ci->ep0out = hwep; |
1579 | else | 1578 | else |
1580 | ci->ep0in = hwep; | 1579 | ci->ep0in = hwep; |
1581 | 1580 | ||
1582 | hwep->ep.maxpacket = CTRL_PAYLOAD_MAX; | 1581 | hwep->ep.maxpacket = CTRL_PAYLOAD_MAX; |
1583 | continue; | 1582 | continue; |
1584 | } | 1583 | } |
1585 | 1584 | ||
1586 | list_add_tail(&hwep->ep.ep_list, &ci->gadget.ep_list); | 1585 | list_add_tail(&hwep->ep.ep_list, &ci->gadget.ep_list); |
1587 | } | 1586 | } |
1588 | 1587 | ||
1589 | return retval; | 1588 | return retval; |
1590 | } | 1589 | } |
1591 | 1590 | ||
1592 | static void destroy_eps(struct ci13xxx *ci) | 1591 | static void destroy_eps(struct ci_hdrc *ci) |
1593 | { | 1592 | { |
1594 | int i; | 1593 | int i; |
1595 | 1594 | ||
1596 | for (i = 0; i < ci->hw_ep_max; i++) { | 1595 | for (i = 0; i < ci->hw_ep_max; i++) { |
1597 | struct ci13xxx_ep *hwep = &ci->ci13xxx_ep[i]; | 1596 | struct ci_hw_ep *hwep = &ci->ci_hw_ep[i]; |
1598 | 1597 | ||
1599 | dma_pool_free(ci->qh_pool, hwep->qh.ptr, hwep->qh.dma); | 1598 | dma_pool_free(ci->qh_pool, hwep->qh.ptr, hwep->qh.dma); |
1600 | } | 1599 | } |
1601 | } | 1600 | } |
1602 | 1601 | ||
1603 | /** | 1602 | /** |
1604 | * ci13xxx_start: register a gadget driver | 1603 | * ci_udc_start: register a gadget driver |
1605 | * @gadget: our gadget | 1604 | * @gadget: our gadget |
1606 | * @driver: the driver being registered | 1605 | * @driver: the driver being registered |
1607 | * | 1606 | * |
1608 | * Interrupts are enabled here. | 1607 | * Interrupts are enabled here. |
1609 | */ | 1608 | */ |
1610 | static int ci13xxx_start(struct usb_gadget *gadget, | 1609 | static int ci_udc_start(struct usb_gadget *gadget, |
1611 | struct usb_gadget_driver *driver) | 1610 | struct usb_gadget_driver *driver) |
1612 | { | 1611 | { |
1613 | struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); | 1612 | struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); |
1614 | unsigned long flags; | 1613 | unsigned long flags; |
1615 | int retval = -ENOMEM; | 1614 | int retval = -ENOMEM; |
1616 | 1615 | ||
1617 | if (driver->disconnect == NULL) | 1616 | if (driver->disconnect == NULL) |
1618 | return -EINVAL; | 1617 | return -EINVAL; |
1619 | 1618 | ||
1620 | 1619 | ||
1621 | ci->ep0out->ep.desc = &ctrl_endpt_out_desc; | 1620 | ci->ep0out->ep.desc = &ctrl_endpt_out_desc; |
1622 | retval = usb_ep_enable(&ci->ep0out->ep); | 1621 | retval = usb_ep_enable(&ci->ep0out->ep); |
1623 | if (retval) | 1622 | if (retval) |
1624 | return retval; | 1623 | return retval; |
1625 | 1624 | ||
1626 | ci->ep0in->ep.desc = &ctrl_endpt_in_desc; | 1625 | ci->ep0in->ep.desc = &ctrl_endpt_in_desc; |
1627 | retval = usb_ep_enable(&ci->ep0in->ep); | 1626 | retval = usb_ep_enable(&ci->ep0in->ep); |
1628 | if (retval) | 1627 | if (retval) |
1629 | return retval; | 1628 | return retval; |
1630 | spin_lock_irqsave(&ci->lock, flags); | 1629 | spin_lock_irqsave(&ci->lock, flags); |
1631 | 1630 | ||
1632 | ci->driver = driver; | 1631 | ci->driver = driver; |
1633 | pm_runtime_get_sync(&ci->gadget.dev); | 1632 | pm_runtime_get_sync(&ci->gadget.dev); |
1634 | if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) { | 1633 | if (ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) { |
1635 | if (ci->vbus_active) { | 1634 | if (ci->vbus_active) { |
1636 | if (ci->platdata->flags & CI13XXX_REGS_SHARED) | 1635 | if (ci->platdata->flags & CI_HDRC_REGS_SHARED) |
1637 | hw_device_reset(ci, USBMODE_CM_DC); | 1636 | hw_device_reset(ci, USBMODE_CM_DC); |
1638 | } else { | 1637 | } else { |
1639 | pm_runtime_put_sync(&ci->gadget.dev); | 1638 | pm_runtime_put_sync(&ci->gadget.dev); |
1640 | goto done; | 1639 | goto done; |
1641 | } | 1640 | } |
1642 | } | 1641 | } |
1643 | 1642 | ||
1644 | retval = hw_device_state(ci, ci->ep0out->qh.dma); | 1643 | retval = hw_device_state(ci, ci->ep0out->qh.dma); |
1645 | if (retval) | 1644 | if (retval) |
1646 | pm_runtime_put_sync(&ci->gadget.dev); | 1645 | pm_runtime_put_sync(&ci->gadget.dev); |
1647 | 1646 | ||
1648 | done: | 1647 | done: |
1649 | spin_unlock_irqrestore(&ci->lock, flags); | 1648 | spin_unlock_irqrestore(&ci->lock, flags); |
1650 | return retval; | 1649 | return retval; |
1651 | } | 1650 | } |
1652 | 1651 | ||
1653 | /** | 1652 | /** |
1654 | * ci13xxx_stop: unregister a gadget driver | 1653 | * ci_udc_stop: unregister a gadget driver |
1655 | */ | 1654 | */ |
1656 | static int ci13xxx_stop(struct usb_gadget *gadget, | 1655 | static int ci_udc_stop(struct usb_gadget *gadget, |
1657 | struct usb_gadget_driver *driver) | 1656 | struct usb_gadget_driver *driver) |
1658 | { | 1657 | { |
1659 | struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); | 1658 | struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); |
1660 | unsigned long flags; | 1659 | unsigned long flags; |
1661 | 1660 | ||
1662 | spin_lock_irqsave(&ci->lock, flags); | 1661 | spin_lock_irqsave(&ci->lock, flags); |
1663 | 1662 | ||
1664 | if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) || | 1663 | if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) || |
1665 | ci->vbus_active) { | 1664 | ci->vbus_active) { |
1666 | hw_device_state(ci, 0); | 1665 | hw_device_state(ci, 0); |
1667 | if (ci->platdata->notify_event) | 1666 | if (ci->platdata->notify_event) |
1668 | ci->platdata->notify_event(ci, | 1667 | ci->platdata->notify_event(ci, |
1669 | CI13XXX_CONTROLLER_STOPPED_EVENT); | 1668 | CI_HDRC_CONTROLLER_STOPPED_EVENT); |
1670 | ci->driver = NULL; | 1669 | ci->driver = NULL; |
1671 | spin_unlock_irqrestore(&ci->lock, flags); | 1670 | spin_unlock_irqrestore(&ci->lock, flags); |
1672 | _gadget_stop_activity(&ci->gadget); | 1671 | _gadget_stop_activity(&ci->gadget); |
1673 | spin_lock_irqsave(&ci->lock, flags); | 1672 | spin_lock_irqsave(&ci->lock, flags); |
1674 | pm_runtime_put(&ci->gadget.dev); | 1673 | pm_runtime_put(&ci->gadget.dev); |
1675 | } | 1674 | } |
1676 | 1675 | ||
1677 | spin_unlock_irqrestore(&ci->lock, flags); | 1676 | spin_unlock_irqrestore(&ci->lock, flags); |
1678 | 1677 | ||
1679 | return 0; | 1678 | return 0; |
1680 | } | 1679 | } |
1681 | 1680 | ||
1682 | /****************************************************************************** | 1681 | /****************************************************************************** |
1683 | * BUS block | 1682 | * BUS block |
1684 | *****************************************************************************/ | 1683 | *****************************************************************************/ |
1685 | /** | 1684 | /** |
1686 | * udc_irq: ci interrupt handler | 1685 | * udc_irq: ci interrupt handler |
1687 | * | 1686 | * |
1688 | * This function returns IRQ_HANDLED if the IRQ has been handled | 1687 | * This function returns IRQ_HANDLED if the IRQ has been handled |
1689 | * It locks access to registers | 1688 | * It locks access to registers |
1690 | */ | 1689 | */ |
1691 | static irqreturn_t udc_irq(struct ci13xxx *ci) | 1690 | static irqreturn_t udc_irq(struct ci_hdrc *ci) |
1692 | { | 1691 | { |
1693 | irqreturn_t retval; | 1692 | irqreturn_t retval; |
1694 | u32 intr; | 1693 | u32 intr; |
1695 | 1694 | ||
1696 | if (ci == NULL) | 1695 | if (ci == NULL) |
1697 | return IRQ_HANDLED; | 1696 | return IRQ_HANDLED; |
1698 | 1697 | ||
1699 | spin_lock(&ci->lock); | 1698 | spin_lock(&ci->lock); |
1700 | 1699 | ||
1701 | if (ci->platdata->flags & CI13XXX_REGS_SHARED) { | 1700 | if (ci->platdata->flags & CI_HDRC_REGS_SHARED) { |
1702 | if (hw_read(ci, OP_USBMODE, USBMODE_CM) != | 1701 | if (hw_read(ci, OP_USBMODE, USBMODE_CM) != |
1703 | USBMODE_CM_DC) { | 1702 | USBMODE_CM_DC) { |
1704 | spin_unlock(&ci->lock); | 1703 | spin_unlock(&ci->lock); |
1705 | return IRQ_NONE; | 1704 | return IRQ_NONE; |
1706 | } | 1705 | } |
1707 | } | 1706 | } |
1708 | intr = hw_test_and_clear_intr_active(ci); | 1707 | intr = hw_test_and_clear_intr_active(ci); |
1709 | 1708 | ||
1710 | if (intr) { | 1709 | if (intr) { |
1711 | /* order defines priority - do NOT change it */ | 1710 | /* order defines priority - do NOT change it */ |
1712 | if (USBi_URI & intr) | 1711 | if (USBi_URI & intr) |
1713 | isr_reset_handler(ci); | 1712 | isr_reset_handler(ci); |
1714 | 1713 | ||
1715 | if (USBi_PCI & intr) { | 1714 | if (USBi_PCI & intr) { |
1716 | ci->gadget.speed = hw_port_is_high_speed(ci) ? | 1715 | ci->gadget.speed = hw_port_is_high_speed(ci) ? |
1717 | USB_SPEED_HIGH : USB_SPEED_FULL; | 1716 | USB_SPEED_HIGH : USB_SPEED_FULL; |
1718 | if (ci->suspended && ci->driver->resume) { | 1717 | if (ci->suspended && ci->driver->resume) { |
1719 | spin_unlock(&ci->lock); | 1718 | spin_unlock(&ci->lock); |
1720 | ci->driver->resume(&ci->gadget); | 1719 | ci->driver->resume(&ci->gadget); |
1721 | spin_lock(&ci->lock); | 1720 | spin_lock(&ci->lock); |
1722 | ci->suspended = 0; | 1721 | ci->suspended = 0; |
1723 | } | 1722 | } |
1724 | } | 1723 | } |
1725 | 1724 | ||
1726 | if (USBi_UI & intr) | 1725 | if (USBi_UI & intr) |
1727 | isr_tr_complete_handler(ci); | 1726 | isr_tr_complete_handler(ci); |
1728 | 1727 | ||
1729 | if (USBi_SLI & intr) { | 1728 | if (USBi_SLI & intr) { |
1730 | if (ci->gadget.speed != USB_SPEED_UNKNOWN && | 1729 | if (ci->gadget.speed != USB_SPEED_UNKNOWN && |
1731 | ci->driver->suspend) { | 1730 | ci->driver->suspend) { |
1732 | ci->suspended = 1; | 1731 | ci->suspended = 1; |
1733 | spin_unlock(&ci->lock); | 1732 | spin_unlock(&ci->lock); |
1734 | ci->driver->suspend(&ci->gadget); | 1733 | ci->driver->suspend(&ci->gadget); |
1735 | spin_lock(&ci->lock); | 1734 | spin_lock(&ci->lock); |
1736 | } | 1735 | } |
1737 | } | 1736 | } |
1738 | retval = IRQ_HANDLED; | 1737 | retval = IRQ_HANDLED; |
1739 | } else { | 1738 | } else { |
1740 | retval = IRQ_NONE; | 1739 | retval = IRQ_NONE; |
1741 | } | 1740 | } |
1742 | spin_unlock(&ci->lock); | 1741 | spin_unlock(&ci->lock); |
1743 | 1742 | ||
1744 | return retval; | 1743 | return retval; |
1745 | } | 1744 | } |
1746 | 1745 | ||
1747 | /** | 1746 | /** |
1748 | * udc_start: initialize gadget role | 1747 | * udc_start: initialize gadget role |
1749 | * @ci: chipidea controller | 1748 | * @ci: chipidea controller |
1750 | */ | 1749 | */ |
1751 | static int udc_start(struct ci13xxx *ci) | 1750 | static int udc_start(struct ci_hdrc *ci) |
1752 | { | 1751 | { |
1753 | struct device *dev = ci->dev; | 1752 | struct device *dev = ci->dev; |
1754 | int retval = 0; | 1753 | int retval = 0; |
1755 | 1754 | ||
1756 | spin_lock_init(&ci->lock); | 1755 | spin_lock_init(&ci->lock); |
1757 | 1756 | ||
1758 | ci->gadget.ops = &usb_gadget_ops; | 1757 | ci->gadget.ops = &usb_gadget_ops; |
1759 | ci->gadget.speed = USB_SPEED_UNKNOWN; | 1758 | ci->gadget.speed = USB_SPEED_UNKNOWN; |
1760 | ci->gadget.max_speed = USB_SPEED_HIGH; | 1759 | ci->gadget.max_speed = USB_SPEED_HIGH; |
1761 | ci->gadget.is_otg = 0; | 1760 | ci->gadget.is_otg = 0; |
1762 | ci->gadget.name = ci->platdata->name; | 1761 | ci->gadget.name = ci->platdata->name; |
1763 | 1762 | ||
1764 | INIT_LIST_HEAD(&ci->gadget.ep_list); | 1763 | INIT_LIST_HEAD(&ci->gadget.ep_list); |
1765 | 1764 | ||
1766 | /* alloc resources */ | 1765 | /* alloc resources */ |
1767 | ci->qh_pool = dma_pool_create("ci13xxx_qh", dev, | 1766 | ci->qh_pool = dma_pool_create("ci_hw_qh", dev, |
1768 | sizeof(struct ci13xxx_qh), | 1767 | sizeof(struct ci_hw_qh), |
1769 | 64, CI13XXX_PAGE_SIZE); | 1768 | 64, CI_HDRC_PAGE_SIZE); |
1770 | if (ci->qh_pool == NULL) | 1769 | if (ci->qh_pool == NULL) |
1771 | return -ENOMEM; | 1770 | return -ENOMEM; |
1772 | 1771 | ||
1773 | ci->td_pool = dma_pool_create("ci13xxx_td", dev, | 1772 | ci->td_pool = dma_pool_create("ci_hw_td", dev, |
1774 | sizeof(struct ci13xxx_td), | 1773 | sizeof(struct ci_hw_td), |
1775 | 64, CI13XXX_PAGE_SIZE); | 1774 | 64, CI_HDRC_PAGE_SIZE); |
1776 | if (ci->td_pool == NULL) { | 1775 | if (ci->td_pool == NULL) { |
1777 | retval = -ENOMEM; | 1776 | retval = -ENOMEM; |
1778 | goto free_qh_pool; | 1777 | goto free_qh_pool; |
1779 | } | 1778 | } |
1780 | 1779 | ||
1781 | retval = init_eps(ci); | 1780 | retval = init_eps(ci); |
1782 | if (retval) | 1781 | if (retval) |
1783 | goto free_pools; | 1782 | goto free_pools; |
1784 | 1783 | ||
1785 | ci->gadget.ep0 = &ci->ep0in->ep; | 1784 | ci->gadget.ep0 = &ci->ep0in->ep; |
1786 | 1785 | ||
1787 | if (ci->global_phy) { | 1786 | if (ci->global_phy) { |
1788 | ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | 1787 | ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); |
1789 | if (IS_ERR(ci->transceiver)) | 1788 | if (IS_ERR(ci->transceiver)) |
1790 | ci->transceiver = NULL; | 1789 | ci->transceiver = NULL; |
1791 | } | 1790 | } |
1792 | 1791 | ||
1793 | if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { | 1792 | if (ci->platdata->flags & CI_HDRC_REQUIRE_TRANSCEIVER) { |
1794 | if (ci->transceiver == NULL) { | 1793 | if (ci->transceiver == NULL) { |
1795 | retval = -ENODEV; | 1794 | retval = -ENODEV; |
1796 | goto destroy_eps; | 1795 | goto destroy_eps; |
1797 | } | 1796 | } |
1798 | } | 1797 | } |
1799 | 1798 | ||
1800 | if (!(ci->platdata->flags & CI13XXX_REGS_SHARED)) { | 1799 | if (!(ci->platdata->flags & CI_HDRC_REGS_SHARED)) { |
1801 | retval = hw_device_reset(ci, USBMODE_CM_DC); | 1800 | retval = hw_device_reset(ci, USBMODE_CM_DC); |
1802 | if (retval) | 1801 | if (retval) |
1803 | goto put_transceiver; | 1802 | goto put_transceiver; |
1804 | } | 1803 | } |
1805 | 1804 | ||
1806 | if (ci->transceiver) { | 1805 | if (ci->transceiver) { |
1807 | retval = otg_set_peripheral(ci->transceiver->otg, | 1806 | retval = otg_set_peripheral(ci->transceiver->otg, |
1808 | &ci->gadget); | 1807 | &ci->gadget); |
1809 | if (retval) | 1808 | if (retval) |
1810 | goto put_transceiver; | 1809 | goto put_transceiver; |
1811 | } | 1810 | } |
1812 | 1811 | ||
1813 | retval = usb_add_gadget_udc(dev, &ci->gadget); | 1812 | retval = usb_add_gadget_udc(dev, &ci->gadget); |
1814 | if (retval) | 1813 | if (retval) |
1815 | goto remove_trans; | 1814 | goto remove_trans; |
1816 | 1815 | ||
1817 | pm_runtime_no_callbacks(&ci->gadget.dev); | 1816 | pm_runtime_no_callbacks(&ci->gadget.dev); |
1818 | pm_runtime_enable(&ci->gadget.dev); | 1817 | pm_runtime_enable(&ci->gadget.dev); |
1819 | 1818 | ||
1820 | return retval; | 1819 | return retval; |
1821 | 1820 | ||
1822 | remove_trans: | 1821 | remove_trans: |
1823 | if (ci->transceiver) { | 1822 | if (ci->transceiver) { |
1824 | otg_set_peripheral(ci->transceiver->otg, NULL); | 1823 | otg_set_peripheral(ci->transceiver->otg, NULL); |
1825 | if (ci->global_phy) | 1824 | if (ci->global_phy) |
1826 | usb_put_phy(ci->transceiver); | 1825 | usb_put_phy(ci->transceiver); |
1827 | } | 1826 | } |
1828 | 1827 | ||
1829 | dev_err(dev, "error = %i\n", retval); | 1828 | dev_err(dev, "error = %i\n", retval); |
1830 | put_transceiver: | 1829 | put_transceiver: |
1831 | if (ci->transceiver && ci->global_phy) | 1830 | if (ci->transceiver && ci->global_phy) |
1832 | usb_put_phy(ci->transceiver); | 1831 | usb_put_phy(ci->transceiver); |
1833 | destroy_eps: | 1832 | destroy_eps: |
1834 | destroy_eps(ci); | 1833 | destroy_eps(ci); |
1835 | free_pools: | 1834 | free_pools: |
1836 | dma_pool_destroy(ci->td_pool); | 1835 | dma_pool_destroy(ci->td_pool); |
1837 | free_qh_pool: | 1836 | free_qh_pool: |
1838 | dma_pool_destroy(ci->qh_pool); | 1837 | dma_pool_destroy(ci->qh_pool); |
1839 | return retval; | 1838 | return retval; |
1840 | } | 1839 | } |
1841 | 1840 | ||
1842 | /** | 1841 | /** |
1843 | * udc_remove: parent remove must call this to remove UDC | 1842 | * udc_remove: parent remove must call this to remove UDC |
1844 | * | 1843 | * |
1845 | * No interrupts active, the IRQ has been released | 1844 | * No interrupts active, the IRQ has been released |
1846 | */ | 1845 | */ |
1847 | static void udc_stop(struct ci13xxx *ci) | 1846 | static void udc_stop(struct ci_hdrc *ci) |
1848 | { | 1847 | { |
1849 | if (ci == NULL) | 1848 | if (ci == NULL) |
1850 | return; | 1849 | return; |
1851 | 1850 | ||
1852 | usb_del_gadget_udc(&ci->gadget); | 1851 | usb_del_gadget_udc(&ci->gadget); |
1853 | 1852 | ||
1854 | destroy_eps(ci); | 1853 | destroy_eps(ci); |
1855 | 1854 | ||
1856 | dma_pool_destroy(ci->td_pool); | 1855 | dma_pool_destroy(ci->td_pool); |
1857 | dma_pool_destroy(ci->qh_pool); | 1856 | dma_pool_destroy(ci->qh_pool); |
1858 | 1857 | ||
1859 | if (ci->transceiver) { | 1858 | if (ci->transceiver) { |
1860 | otg_set_peripheral(ci->transceiver->otg, NULL); | 1859 | otg_set_peripheral(ci->transceiver->otg, NULL); |
1861 | if (ci->global_phy) | 1860 | if (ci->global_phy) |
1862 | usb_put_phy(ci->transceiver); | 1861 | usb_put_phy(ci->transceiver); |
1863 | } | 1862 | } |
1864 | /* my kobject is dynamic, I swear! */ | 1863 | /* my kobject is dynamic, I swear! */ |
1865 | memset(&ci->gadget, 0, sizeof(ci->gadget)); | 1864 | memset(&ci->gadget, 0, sizeof(ci->gadget)); |
1866 | } | 1865 | } |
1867 | 1866 | ||
1868 | /** | 1867 | /** |
1869 | * ci_hdrc_gadget_init - initialize device related bits | 1868 | * ci_hdrc_gadget_init - initialize device related bits |
1870 | * ci: the controller | 1869 | * ci: the controller |
1871 | * | 1870 | * |
1872 | * This function enables the gadget role, if the device is "device capable". | 1871 | * This function enables the gadget role, if the device is "device capable". |
1873 | */ | 1872 | */ |
1874 | int ci_hdrc_gadget_init(struct ci13xxx *ci) | 1873 | int ci_hdrc_gadget_init(struct ci_hdrc *ci) |
1875 | { | 1874 | { |
1876 | struct ci_role_driver *rdrv; | 1875 | struct ci_role_driver *rdrv; |
1877 | 1876 | ||
1878 | if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC)) | 1877 | if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC)) |
1879 | return -ENXIO; | 1878 | return -ENXIO; |
1880 | 1879 | ||
1881 | rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL); | 1880 | rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL); |
1882 | if (!rdrv) | 1881 | if (!rdrv) |
1883 | return -ENOMEM; | 1882 | return -ENOMEM; |
1884 | 1883 | ||
1885 | rdrv->start = udc_start; | 1884 | rdrv->start = udc_start; |
1886 | rdrv->stop = udc_stop; | 1885 | rdrv->stop = udc_stop; |
1887 | rdrv->irq = udc_irq; | 1886 | rdrv->irq = udc_irq; |
1888 | rdrv->name = "gadget"; | 1887 | rdrv->name = "gadget"; |
1889 | ci->roles[CI_ROLE_GADGET] = rdrv; | 1888 | ci->roles[CI_ROLE_GADGET] = rdrv; |
1890 | 1889 | ||
1891 | return 0; | 1890 | return 0; |
1892 | } | 1891 | } |
1893 | 1892 |
drivers/usb/chipidea/udc.h
1 | /* | 1 | /* |
2 | * udc.h - ChipIdea UDC structures | 2 | * udc.h - ChipIdea UDC structures |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | 4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. |
5 | * | 5 | * |
6 | * Author: David Lopo | 6 | * Author: David Lopo |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #ifndef __DRIVERS_USB_CHIPIDEA_UDC_H | 13 | #ifndef __DRIVERS_USB_CHIPIDEA_UDC_H |
14 | #define __DRIVERS_USB_CHIPIDEA_UDC_H | 14 | #define __DRIVERS_USB_CHIPIDEA_UDC_H |
15 | 15 | ||
16 | #include <linux/list.h> | 16 | #include <linux/list.h> |
17 | 17 | ||
18 | #define CTRL_PAYLOAD_MAX 64 | 18 | #define CTRL_PAYLOAD_MAX 64 |
19 | #define RX 0 /* similar to USB_DIR_OUT but can be used as an index */ | 19 | #define RX 0 /* similar to USB_DIR_OUT but can be used as an index */ |
20 | #define TX 1 /* similar to USB_DIR_IN but can be used as an index */ | 20 | #define TX 1 /* similar to USB_DIR_IN but can be used as an index */ |
21 | 21 | ||
22 | /* DMA layout of transfer descriptors */ | 22 | /* DMA layout of transfer descriptors */ |
23 | struct ci13xxx_td { | 23 | struct ci_hw_td { |
24 | /* 0 */ | 24 | /* 0 */ |
25 | u32 next; | 25 | u32 next; |
26 | #define TD_TERMINATE BIT(0) | 26 | #define TD_TERMINATE BIT(0) |
27 | #define TD_ADDR_MASK (0xFFFFFFEUL << 5) | 27 | #define TD_ADDR_MASK (0xFFFFFFEUL << 5) |
28 | /* 1 */ | 28 | /* 1 */ |
29 | u32 token; | 29 | u32 token; |
30 | #define TD_STATUS (0x00FFUL << 0) | 30 | #define TD_STATUS (0x00FFUL << 0) |
31 | #define TD_STATUS_TR_ERR BIT(3) | 31 | #define TD_STATUS_TR_ERR BIT(3) |
32 | #define TD_STATUS_DT_ERR BIT(5) | 32 | #define TD_STATUS_DT_ERR BIT(5) |
33 | #define TD_STATUS_HALTED BIT(6) | 33 | #define TD_STATUS_HALTED BIT(6) |
34 | #define TD_STATUS_ACTIVE BIT(7) | 34 | #define TD_STATUS_ACTIVE BIT(7) |
35 | #define TD_MULTO (0x0003UL << 10) | 35 | #define TD_MULTO (0x0003UL << 10) |
36 | #define TD_IOC BIT(15) | 36 | #define TD_IOC BIT(15) |
37 | #define TD_TOTAL_BYTES (0x7FFFUL << 16) | 37 | #define TD_TOTAL_BYTES (0x7FFFUL << 16) |
38 | /* 2 */ | 38 | /* 2 */ |
39 | u32 page[5]; | 39 | u32 page[5]; |
40 | #define TD_CURR_OFFSET (0x0FFFUL << 0) | 40 | #define TD_CURR_OFFSET (0x0FFFUL << 0) |
41 | #define TD_FRAME_NUM (0x07FFUL << 0) | 41 | #define TD_FRAME_NUM (0x07FFUL << 0) |
42 | #define TD_RESERVED_MASK (0x0FFFUL << 0) | 42 | #define TD_RESERVED_MASK (0x0FFFUL << 0) |
43 | } __attribute__ ((packed, aligned(4))); | 43 | } __attribute__ ((packed, aligned(4))); |
44 | 44 | ||
45 | /* DMA layout of queue heads */ | 45 | /* DMA layout of queue heads */ |
46 | struct ci13xxx_qh { | 46 | struct ci_hw_qh { |
47 | /* 0 */ | 47 | /* 0 */ |
48 | u32 cap; | 48 | u32 cap; |
49 | #define QH_IOS BIT(15) | 49 | #define QH_IOS BIT(15) |
50 | #define QH_MAX_PKT (0x07FFUL << 16) | 50 | #define QH_MAX_PKT (0x07FFUL << 16) |
51 | #define QH_ZLT BIT(29) | 51 | #define QH_ZLT BIT(29) |
52 | #define QH_MULT (0x0003UL << 30) | 52 | #define QH_MULT (0x0003UL << 30) |
53 | #define QH_ISO_MULT(x) ((x >> 11) & 0x03) | 53 | #define QH_ISO_MULT(x) ((x >> 11) & 0x03) |
54 | /* 1 */ | 54 | /* 1 */ |
55 | u32 curr; | 55 | u32 curr; |
56 | /* 2 - 8 */ | 56 | /* 2 - 8 */ |
57 | struct ci13xxx_td td; | 57 | struct ci_hw_td td; |
58 | /* 9 */ | 58 | /* 9 */ |
59 | u32 RESERVED; | 59 | u32 RESERVED; |
60 | struct usb_ctrlrequest setup; | 60 | struct usb_ctrlrequest setup; |
61 | } __attribute__ ((packed, aligned(4))); | 61 | } __attribute__ ((packed, aligned(4))); |
62 | 62 | ||
63 | struct td_node { | 63 | struct td_node { |
64 | struct list_head td; | 64 | struct list_head td; |
65 | dma_addr_t dma; | 65 | dma_addr_t dma; |
66 | struct ci13xxx_td *ptr; | 66 | struct ci_hw_td *ptr; |
67 | }; | 67 | }; |
68 | 68 | ||
69 | /** | 69 | /** |
70 | * struct ci13xxx_req - usb request representation | 70 | * struct ci_hw_req - usb request representation |
71 | * @req: request structure for gadget drivers | 71 | * @req: request structure for gadget drivers |
72 | * @queue: link to QH list | 72 | * @queue: link to QH list |
73 | * @ptr: transfer descriptor for this request | 73 | * @ptr: transfer descriptor for this request |
74 | * @dma: dma address for the transfer descriptor | 74 | * @dma: dma address for the transfer descriptor |
75 | * @zptr: transfer descriptor for the zero packet | 75 | * @zptr: transfer descriptor for the zero packet |
76 | * @zdma: dma address of the zero packet's transfer descriptor | 76 | * @zdma: dma address of the zero packet's transfer descriptor |
77 | */ | 77 | */ |
78 | struct ci13xxx_req { | 78 | struct ci_hw_req { |
79 | struct usb_request req; | 79 | struct usb_request req; |
80 | struct list_head queue; | 80 | struct list_head queue; |
81 | struct list_head tds; | 81 | struct list_head tds; |
82 | }; | 82 | }; |
83 | 83 | ||
84 | #ifdef CONFIG_USB_CHIPIDEA_UDC | 84 | #ifdef CONFIG_USB_CHIPIDEA_UDC |
85 | 85 | ||
86 | int ci_hdrc_gadget_init(struct ci13xxx *ci); | 86 | int ci_hdrc_gadget_init(struct ci_hdrc *ci); |
87 | 87 | ||
88 | #else | 88 | #else |
89 | 89 | ||
90 | static inline int ci_hdrc_gadget_init(struct ci13xxx *ci) | 90 | static inline int ci_hdrc_gadget_init(struct ci_hdrc *ci) |
91 | { | 91 | { |
92 | return -ENXIO; | 92 | return -ENXIO; |
93 | } | 93 | } |
94 | 94 | ||
95 | #endif | 95 | #endif |
96 | 96 | ||
97 | #endif /* __DRIVERS_USB_CHIPIDEA_UDC_H */ | 97 | #endif /* __DRIVERS_USB_CHIPIDEA_UDC_H */ |
98 | 98 |
drivers/usb/chipidea/usbmisc_imx.c
1 | /* | 1 | /* |
2 | * Copyright 2012 Freescale Semiconductor, Inc. | 2 | * Copyright 2012 Freescale Semiconductor, Inc. |
3 | * | 3 | * |
4 | * The code contained herein is licensed under the GNU General Public | 4 | * The code contained herein is licensed under the GNU General Public |
5 | * License. You may obtain a copy of the GNU General Public License | 5 | * License. You may obtain a copy of the GNU General Public License |
6 | * Version 2 or later at the following locations: | 6 | * Version 2 or later at the following locations: |
7 | * | 7 | * |
8 | * http://www.opensource.org/licenses/gpl-license.html | 8 | * http://www.opensource.org/licenses/gpl-license.html |
9 | * http://www.gnu.org/copyleft/gpl.html | 9 | * http://www.gnu.org/copyleft/gpl.html |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/of_platform.h> | 13 | #include <linux/of_platform.h> |
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | 18 | ||
19 | #include "ci13xxx_imx.h" | 19 | #include "ci_hdrc_imx.h" |
20 | 20 | ||
21 | #define USB_DEV_MAX 4 | 21 | #define USB_DEV_MAX 4 |
22 | 22 | ||
23 | #define MX25_USB_PHY_CTRL_OFFSET 0x08 | 23 | #define MX25_USB_PHY_CTRL_OFFSET 0x08 |
24 | #define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23) | 24 | #define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23) |
25 | 25 | ||
26 | #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08 | 26 | #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08 |
27 | #define MX53_USB_UH2_CTRL_OFFSET 0x14 | 27 | #define MX53_USB_UH2_CTRL_OFFSET 0x14 |
28 | #define MX53_USB_UH3_CTRL_OFFSET 0x18 | 28 | #define MX53_USB_UH3_CTRL_OFFSET 0x18 |
29 | #define MX53_BM_OVER_CUR_DIS_H1 BIT(5) | 29 | #define MX53_BM_OVER_CUR_DIS_H1 BIT(5) |
30 | #define MX53_BM_OVER_CUR_DIS_OTG BIT(8) | 30 | #define MX53_BM_OVER_CUR_DIS_OTG BIT(8) |
31 | #define MX53_BM_OVER_CUR_DIS_UHx BIT(30) | 31 | #define MX53_BM_OVER_CUR_DIS_UHx BIT(30) |
32 | 32 | ||
33 | #define MX6_BM_OVER_CUR_DIS BIT(7) | 33 | #define MX6_BM_OVER_CUR_DIS BIT(7) |
34 | 34 | ||
35 | struct imx_usbmisc { | 35 | struct imx_usbmisc { |
36 | void __iomem *base; | 36 | void __iomem *base; |
37 | spinlock_t lock; | 37 | spinlock_t lock; |
38 | struct clk *clk; | 38 | struct clk *clk; |
39 | struct usbmisc_usb_device usbdev[USB_DEV_MAX]; | 39 | struct usbmisc_usb_device usbdev[USB_DEV_MAX]; |
40 | const struct usbmisc_ops *ops; | 40 | const struct usbmisc_ops *ops; |
41 | }; | 41 | }; |
42 | 42 | ||
43 | static struct imx_usbmisc *usbmisc; | 43 | static struct imx_usbmisc *usbmisc; |
44 | 44 | ||
45 | static struct usbmisc_usb_device *get_usbdev(struct device *dev) | 45 | static struct usbmisc_usb_device *get_usbdev(struct device *dev) |
46 | { | 46 | { |
47 | int i, ret; | 47 | int i, ret; |
48 | 48 | ||
49 | for (i = 0; i < USB_DEV_MAX; i++) { | 49 | for (i = 0; i < USB_DEV_MAX; i++) { |
50 | if (usbmisc->usbdev[i].dev == dev) | 50 | if (usbmisc->usbdev[i].dev == dev) |
51 | return &usbmisc->usbdev[i]; | 51 | return &usbmisc->usbdev[i]; |
52 | else if (!usbmisc->usbdev[i].dev) | 52 | else if (!usbmisc->usbdev[i].dev) |
53 | break; | 53 | break; |
54 | } | 54 | } |
55 | 55 | ||
56 | if (i >= USB_DEV_MAX) | 56 | if (i >= USB_DEV_MAX) |
57 | return ERR_PTR(-EBUSY); | 57 | return ERR_PTR(-EBUSY); |
58 | 58 | ||
59 | ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]); | 59 | ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]); |
60 | if (ret) | 60 | if (ret) |
61 | return ERR_PTR(ret); | 61 | return ERR_PTR(ret); |
62 | 62 | ||
63 | return &usbmisc->usbdev[i]; | 63 | return &usbmisc->usbdev[i]; |
64 | } | 64 | } |
65 | 65 | ||
66 | static int usbmisc_imx25_post(struct device *dev) | 66 | static int usbmisc_imx25_post(struct device *dev) |
67 | { | 67 | { |
68 | struct usbmisc_usb_device *usbdev; | 68 | struct usbmisc_usb_device *usbdev; |
69 | void __iomem *reg; | 69 | void __iomem *reg; |
70 | unsigned long flags; | 70 | unsigned long flags; |
71 | u32 val; | 71 | u32 val; |
72 | 72 | ||
73 | usbdev = get_usbdev(dev); | 73 | usbdev = get_usbdev(dev); |
74 | if (IS_ERR(usbdev)) | 74 | if (IS_ERR(usbdev)) |
75 | return PTR_ERR(usbdev); | 75 | return PTR_ERR(usbdev); |
76 | 76 | ||
77 | reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET; | 77 | reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET; |
78 | 78 | ||
79 | if (usbdev->evdo) { | 79 | if (usbdev->evdo) { |
80 | spin_lock_irqsave(&usbmisc->lock, flags); | 80 | spin_lock_irqsave(&usbmisc->lock, flags); |
81 | val = readl(reg); | 81 | val = readl(reg); |
82 | writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg); | 82 | writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg); |
83 | spin_unlock_irqrestore(&usbmisc->lock, flags); | 83 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
84 | usleep_range(5000, 10000); /* needed to stabilize voltage */ | 84 | usleep_range(5000, 10000); /* needed to stabilize voltage */ |
85 | } | 85 | } |
86 | 86 | ||
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | static int usbmisc_imx53_init(struct device *dev) | 90 | static int usbmisc_imx53_init(struct device *dev) |
91 | { | 91 | { |
92 | struct usbmisc_usb_device *usbdev; | 92 | struct usbmisc_usb_device *usbdev; |
93 | void __iomem *reg = NULL; | 93 | void __iomem *reg = NULL; |
94 | unsigned long flags; | 94 | unsigned long flags; |
95 | u32 val = 0; | 95 | u32 val = 0; |
96 | 96 | ||
97 | usbdev = get_usbdev(dev); | 97 | usbdev = get_usbdev(dev); |
98 | if (IS_ERR(usbdev)) | 98 | if (IS_ERR(usbdev)) |
99 | return PTR_ERR(usbdev); | 99 | return PTR_ERR(usbdev); |
100 | 100 | ||
101 | if (usbdev->disable_oc) { | 101 | if (usbdev->disable_oc) { |
102 | spin_lock_irqsave(&usbmisc->lock, flags); | 102 | spin_lock_irqsave(&usbmisc->lock, flags); |
103 | switch (usbdev->index) { | 103 | switch (usbdev->index) { |
104 | case 0: | 104 | case 0: |
105 | reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; | 105 | reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; |
106 | val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG; | 106 | val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG; |
107 | break; | 107 | break; |
108 | case 1: | 108 | case 1: |
109 | reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; | 109 | reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; |
110 | val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1; | 110 | val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1; |
111 | break; | 111 | break; |
112 | case 2: | 112 | case 2: |
113 | reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET; | 113 | reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET; |
114 | val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx; | 114 | val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx; |
115 | break; | 115 | break; |
116 | case 3: | 116 | case 3: |
117 | reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET; | 117 | reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET; |
118 | val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx; | 118 | val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx; |
119 | break; | 119 | break; |
120 | } | 120 | } |
121 | if (reg && val) | 121 | if (reg && val) |
122 | writel(val, reg); | 122 | writel(val, reg); |
123 | spin_unlock_irqrestore(&usbmisc->lock, flags); | 123 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
124 | } | 124 | } |
125 | 125 | ||
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
129 | static int usbmisc_imx6q_init(struct device *dev) | 129 | static int usbmisc_imx6q_init(struct device *dev) |
130 | { | 130 | { |
131 | 131 | ||
132 | struct usbmisc_usb_device *usbdev; | 132 | struct usbmisc_usb_device *usbdev; |
133 | unsigned long flags; | 133 | unsigned long flags; |
134 | u32 reg; | 134 | u32 reg; |
135 | 135 | ||
136 | usbdev = get_usbdev(dev); | 136 | usbdev = get_usbdev(dev); |
137 | if (IS_ERR(usbdev)) | 137 | if (IS_ERR(usbdev)) |
138 | return PTR_ERR(usbdev); | 138 | return PTR_ERR(usbdev); |
139 | 139 | ||
140 | if (usbdev->disable_oc) { | 140 | if (usbdev->disable_oc) { |
141 | spin_lock_irqsave(&usbmisc->lock, flags); | 141 | spin_lock_irqsave(&usbmisc->lock, flags); |
142 | reg = readl(usbmisc->base + usbdev->index * 4); | 142 | reg = readl(usbmisc->base + usbdev->index * 4); |
143 | writel(reg | MX6_BM_OVER_CUR_DIS, | 143 | writel(reg | MX6_BM_OVER_CUR_DIS, |
144 | usbmisc->base + usbdev->index * 4); | 144 | usbmisc->base + usbdev->index * 4); |
145 | spin_unlock_irqrestore(&usbmisc->lock, flags); | 145 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
146 | } | 146 | } |
147 | 147 | ||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | ||
151 | static const struct usbmisc_ops imx25_usbmisc_ops = { | 151 | static const struct usbmisc_ops imx25_usbmisc_ops = { |
152 | .post = usbmisc_imx25_post, | 152 | .post = usbmisc_imx25_post, |
153 | }; | 153 | }; |
154 | 154 | ||
155 | static const struct usbmisc_ops imx53_usbmisc_ops = { | 155 | static const struct usbmisc_ops imx53_usbmisc_ops = { |
156 | .init = usbmisc_imx53_init, | 156 | .init = usbmisc_imx53_init, |
157 | }; | 157 | }; |
158 | 158 | ||
159 | static const struct usbmisc_ops imx6q_usbmisc_ops = { | 159 | static const struct usbmisc_ops imx6q_usbmisc_ops = { |
160 | .init = usbmisc_imx6q_init, | 160 | .init = usbmisc_imx6q_init, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | static const struct of_device_id usbmisc_imx_dt_ids[] = { | 163 | static const struct of_device_id usbmisc_imx_dt_ids[] = { |
164 | { | 164 | { |
165 | .compatible = "fsl,imx25-usbmisc", | 165 | .compatible = "fsl,imx25-usbmisc", |
166 | .data = &imx25_usbmisc_ops, | 166 | .data = &imx25_usbmisc_ops, |
167 | }, | 167 | }, |
168 | { | 168 | { |
169 | .compatible = "fsl,imx53-usbmisc", | 169 | .compatible = "fsl,imx53-usbmisc", |
170 | .data = &imx53_usbmisc_ops, | 170 | .data = &imx53_usbmisc_ops, |
171 | }, | 171 | }, |
172 | { | 172 | { |
173 | .compatible = "fsl,imx6q-usbmisc", | 173 | .compatible = "fsl,imx6q-usbmisc", |
174 | .data = &imx6q_usbmisc_ops, | 174 | .data = &imx6q_usbmisc_ops, |
175 | }, | 175 | }, |
176 | { /* sentinel */ } | 176 | { /* sentinel */ } |
177 | }; | 177 | }; |
178 | MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids); | 178 | MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids); |
179 | 179 | ||
180 | static int usbmisc_imx_probe(struct platform_device *pdev) | 180 | static int usbmisc_imx_probe(struct platform_device *pdev) |
181 | { | 181 | { |
182 | struct resource *res; | 182 | struct resource *res; |
183 | struct imx_usbmisc *data; | 183 | struct imx_usbmisc *data; |
184 | int ret; | 184 | int ret; |
185 | struct of_device_id *tmp_dev; | 185 | struct of_device_id *tmp_dev; |
186 | 186 | ||
187 | if (usbmisc) | 187 | if (usbmisc) |
188 | return -EBUSY; | 188 | return -EBUSY; |
189 | 189 | ||
190 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | 190 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
191 | if (!data) | 191 | if (!data) |
192 | return -ENOMEM; | 192 | return -ENOMEM; |
193 | 193 | ||
194 | spin_lock_init(&data->lock); | 194 | spin_lock_init(&data->lock); |
195 | 195 | ||
196 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 196 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
197 | data->base = devm_ioremap_resource(&pdev->dev, res); | 197 | data->base = devm_ioremap_resource(&pdev->dev, res); |
198 | if (IS_ERR(data->base)) | 198 | if (IS_ERR(data->base)) |
199 | return PTR_ERR(data->base); | 199 | return PTR_ERR(data->base); |
200 | 200 | ||
201 | data->clk = devm_clk_get(&pdev->dev, NULL); | 201 | data->clk = devm_clk_get(&pdev->dev, NULL); |
202 | if (IS_ERR(data->clk)) { | 202 | if (IS_ERR(data->clk)) { |
203 | dev_err(&pdev->dev, | 203 | dev_err(&pdev->dev, |
204 | "failed to get clock, err=%ld\n", PTR_ERR(data->clk)); | 204 | "failed to get clock, err=%ld\n", PTR_ERR(data->clk)); |
205 | return PTR_ERR(data->clk); | 205 | return PTR_ERR(data->clk); |
206 | } | 206 | } |
207 | 207 | ||
208 | ret = clk_prepare_enable(data->clk); | 208 | ret = clk_prepare_enable(data->clk); |
209 | if (ret) { | 209 | if (ret) { |
210 | dev_err(&pdev->dev, | 210 | dev_err(&pdev->dev, |
211 | "clk_prepare_enable failed, err=%d\n", ret); | 211 | "clk_prepare_enable failed, err=%d\n", ret); |
212 | return ret; | 212 | return ret; |
213 | } | 213 | } |
214 | 214 | ||
215 | tmp_dev = (struct of_device_id *) | 215 | tmp_dev = (struct of_device_id *) |
216 | of_match_device(usbmisc_imx_dt_ids, &pdev->dev); | 216 | of_match_device(usbmisc_imx_dt_ids, &pdev->dev); |
217 | data->ops = (const struct usbmisc_ops *)tmp_dev->data; | 217 | data->ops = (const struct usbmisc_ops *)tmp_dev->data; |
218 | usbmisc = data; | 218 | usbmisc = data; |
219 | ret = usbmisc_set_ops(data->ops); | 219 | ret = usbmisc_set_ops(data->ops); |
220 | if (ret) { | 220 | if (ret) { |
221 | usbmisc = NULL; | 221 | usbmisc = NULL; |
222 | clk_disable_unprepare(data->clk); | 222 | clk_disable_unprepare(data->clk); |
223 | return ret; | 223 | return ret; |
224 | } | 224 | } |
225 | 225 | ||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | static int usbmisc_imx_remove(struct platform_device *pdev) | 229 | static int usbmisc_imx_remove(struct platform_device *pdev) |
230 | { | 230 | { |
231 | usbmisc_unset_ops(usbmisc->ops); | 231 | usbmisc_unset_ops(usbmisc->ops); |
232 | clk_disable_unprepare(usbmisc->clk); | 232 | clk_disable_unprepare(usbmisc->clk); |
233 | usbmisc = NULL; | 233 | usbmisc = NULL; |
234 | return 0; | 234 | return 0; |
235 | } | 235 | } |
236 | 236 | ||
237 | static struct platform_driver usbmisc_imx_driver = { | 237 | static struct platform_driver usbmisc_imx_driver = { |
238 | .probe = usbmisc_imx_probe, | 238 | .probe = usbmisc_imx_probe, |
239 | .remove = usbmisc_imx_remove, | 239 | .remove = usbmisc_imx_remove, |
240 | .driver = { | 240 | .driver = { |
241 | .name = "usbmisc_imx", | 241 | .name = "usbmisc_imx", |
242 | .owner = THIS_MODULE, | 242 | .owner = THIS_MODULE, |
243 | .of_match_table = usbmisc_imx_dt_ids, | 243 | .of_match_table = usbmisc_imx_dt_ids, |
244 | }, | 244 | }, |
245 | }; | 245 | }; |
246 | 246 | ||
247 | module_platform_driver(usbmisc_imx_driver); | 247 | module_platform_driver(usbmisc_imx_driver); |
248 | 248 | ||
249 | MODULE_ALIAS("platform:usbmisc-imx"); | 249 | MODULE_ALIAS("platform:usbmisc-imx"); |
250 | MODULE_LICENSE("GPL v2"); | 250 | MODULE_LICENSE("GPL v2"); |
251 | MODULE_DESCRIPTION("driver for imx usb non-core registers"); | 251 | MODULE_DESCRIPTION("driver for imx usb non-core registers"); |
252 | MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); | 252 | MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); |
253 | 253 |
include/linux/usb/chipidea.h
1 | /* | 1 | /* |
2 | * Platform data for the chipidea USB dual role controller | 2 | * Platform data for the chipidea USB dual role controller |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #ifndef __LINUX_USB_CHIPIDEA_H | 5 | #ifndef __LINUX_USB_CHIPIDEA_H |
6 | #define __LINUX_USB_CHIPIDEA_H | 6 | #define __LINUX_USB_CHIPIDEA_H |
7 | 7 | ||
8 | #include <linux/usb/otg.h> | 8 | #include <linux/usb/otg.h> |
9 | 9 | ||
10 | struct ci13xxx; | 10 | struct ci_hdrc; |
11 | struct ci13xxx_platform_data { | 11 | struct ci_hdrc_platform_data { |
12 | const char *name; | 12 | const char *name; |
13 | /* offset of the capability registers */ | 13 | /* offset of the capability registers */ |
14 | uintptr_t capoffset; | 14 | uintptr_t capoffset; |
15 | unsigned power_budget; | 15 | unsigned power_budget; |
16 | struct usb_phy *phy; | 16 | struct usb_phy *phy; |
17 | enum usb_phy_interface phy_mode; | 17 | enum usb_phy_interface phy_mode; |
18 | unsigned long flags; | 18 | unsigned long flags; |
19 | #define CI13XXX_REGS_SHARED BIT(0) | 19 | #define CI_HDRC_REGS_SHARED BIT(0) |
20 | #define CI13XXX_REQUIRE_TRANSCEIVER BIT(1) | 20 | #define CI_HDRC_REQUIRE_TRANSCEIVER BIT(1) |
21 | #define CI13XXX_PULLUP_ON_VBUS BIT(2) | 21 | #define CI_HDRC_PULLUP_ON_VBUS BIT(2) |
22 | #define CI13XXX_DISABLE_STREAMING BIT(3) | 22 | #define CI_HDRC_DISABLE_STREAMING BIT(3) |
23 | enum usb_dr_mode dr_mode; | 23 | enum usb_dr_mode dr_mode; |
24 | #define CI13XXX_CONTROLLER_RESET_EVENT 0 | 24 | #define CI_HDRC_CONTROLLER_RESET_EVENT 0 |
25 | #define CI13XXX_CONTROLLER_STOPPED_EVENT 1 | 25 | #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 |
26 | void (*notify_event) (struct ci13xxx *ci, unsigned event); | 26 | void (*notify_event) (struct ci_hdrc *ci, unsigned event); |
27 | }; | 27 | }; |
28 | 28 | ||
29 | /* Default offset of capability registers */ | 29 | /* Default offset of capability registers */ |
30 | #define DEF_CAPOFFSET 0x100 | 30 | #define DEF_CAPOFFSET 0x100 |
31 | 31 | ||
32 | /* Add ci13xxx device */ | 32 | /* Add ci hdrc device */ |
33 | struct platform_device *ci13xxx_add_device(struct device *dev, | 33 | struct platform_device *ci_hdrc_add_device(struct device *dev, |
34 | struct resource *res, int nres, | 34 | struct resource *res, int nres, |
35 | struct ci13xxx_platform_data *platdata); | 35 | struct ci_hdrc_platform_data *platdata); |
36 | /* Remove ci13xxx device */ | 36 | /* Remove ci hdrc device */ |
37 | void ci13xxx_remove_device(struct platform_device *pdev); | 37 | void ci_hdrc_remove_device(struct platform_device *pdev); |
38 | 38 | ||
39 | #endif | 39 | #endif |
40 | 40 |