2 * Wireless Host Controller (WHC) driver.
4 * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include <linux/kernel.h>
19 #include <linux/init.h>
20 #include <linux/uwb/umc.h>
22 #include "../../wusbcore/wusbhc.h"
27 * One time initialization.
31 static int whc_reset(struct usb_hcd
*usb_hcd
)
37 * Start the wireless host controller.
39 * Start device notification.
41 * Put hc into run state, set DNTS parameters.
43 static int whc_start(struct usb_hcd
*usb_hcd
)
45 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
46 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
50 mutex_lock(&wusbhc
->mutex
);
52 le_writel(WUSBINTR_GEN_CMD_DONE
54 | WUSBINTR_ASYNC_SCHED_SYNCED
58 whc
->base
+ WUSBINTR
);
61 bcid
= wusb_cluster_id_get();
62 ret
= whc_set_cluster_id(whc
, bcid
);
65 wusbhc
->cluster_id
= bcid
;
68 whc_write_wusbcmd(whc
, WUSBCMD_RUN
, WUSBCMD_RUN
);
70 usb_hcd
->uses_new_polling
= 1;
72 usb_hcd
->state
= HC_STATE_RUNNING
;
75 mutex_unlock(&wusbhc
->mutex
);
81 * Stop the wireless host controller.
83 * Stop device notification.
85 * Wait for pending transfer to stop? Put hc into stop state?
87 static void whc_stop(struct usb_hcd
*usb_hcd
)
89 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
90 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
92 mutex_lock(&wusbhc
->mutex
);
95 le_writel(0, whc
->base
+ WUSBINTR
);
96 whc_write_wusbcmd(whc
, WUSBCMD_RUN
, 0);
97 whci_wait_for(&whc
->umc
->dev
, whc
->base
+ WUSBSTS
,
98 WUSBSTS_HCHALTED
, WUSBSTS_HCHALTED
,
101 wusb_cluster_id_put(wusbhc
->cluster_id
);
103 mutex_unlock(&wusbhc
->mutex
);
106 static int whc_get_frame_number(struct usb_hcd
*usb_hcd
)
108 /* Frame numbers are not applicable to WUSB. */
114 * Queue an URB to the ASL or PZL
116 static int whc_urb_enqueue(struct usb_hcd
*usb_hcd
, struct urb
*urb
,
119 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
120 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
123 switch (usb_pipetype(urb
->pipe
)) {
125 ret
= pzl_urb_enqueue(whc
, urb
, mem_flags
);
127 case PIPE_ISOCHRONOUS
:
128 dev_err(&whc
->umc
->dev
, "isochronous transfers unsupported\n");
134 ret
= asl_urb_enqueue(whc
, urb
, mem_flags
);
142 * Remove a queued URB from the ASL or PZL.
144 static int whc_urb_dequeue(struct usb_hcd
*usb_hcd
, struct urb
*urb
, int status
)
146 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
147 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
150 switch (usb_pipetype(urb
->pipe
)) {
152 ret
= pzl_urb_dequeue(whc
, urb
, status
);
154 case PIPE_ISOCHRONOUS
:
160 ret
= asl_urb_dequeue(whc
, urb
, status
);
168 * Wait for all URBs to the endpoint to be completed, then delete the
171 static void whc_endpoint_disable(struct usb_hcd
*usb_hcd
,
172 struct usb_host_endpoint
*ep
)
174 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
175 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
176 struct whc_qset
*qset
;
181 if (usb_endpoint_xfer_bulk(&ep
->desc
)
182 || usb_endpoint_xfer_control(&ep
->desc
))
183 asl_qset_delete(whc
, qset
);
185 pzl_qset_delete(whc
, qset
);
189 static void whc_endpoint_reset(struct usb_hcd
*usb_hcd
,
190 struct usb_host_endpoint
*ep
)
192 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
193 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
194 struct whc_qset
*qset
;
197 spin_lock_irqsave(&whc
->lock
, flags
);
204 if (usb_endpoint_xfer_bulk(&ep
->desc
)
205 || usb_endpoint_xfer_control(&ep
->desc
))
206 queue_work(whc
->workqueue
, &whc
->async_work
);
208 queue_work(whc
->workqueue
, &whc
->periodic_work
);
211 spin_unlock_irqrestore(&whc
->lock
, flags
);
215 static struct hc_driver whc_hc_driver
= {
216 .description
= "whci-hcd",
217 .product_desc
= "Wireless host controller",
218 .hcd_priv_size
= sizeof(struct whc
) - sizeof(struct usb_hcd
),
219 .irq
= whc_int_handler
,
225 .get_frame_number
= whc_get_frame_number
,
226 .urb_enqueue
= whc_urb_enqueue
,
227 .urb_dequeue
= whc_urb_dequeue
,
228 .endpoint_disable
= whc_endpoint_disable
,
229 .endpoint_reset
= whc_endpoint_reset
,
231 .hub_status_data
= wusbhc_rh_status_data
,
232 .hub_control
= wusbhc_rh_control
,
233 .bus_suspend
= wusbhc_rh_suspend
,
234 .bus_resume
= wusbhc_rh_resume
,
235 .start_port_reset
= wusbhc_rh_start_port_reset
,
238 static int whc_probe(struct umc_dev
*umc
)
241 struct usb_hcd
*usb_hcd
;
242 struct wusbhc
*wusbhc
= NULL
;
243 struct whc
*whc
= NULL
;
244 struct device
*dev
= &umc
->dev
;
246 usb_hcd
= usb_create_hcd(&whc_hc_driver
, dev
, "whci");
247 if (usb_hcd
== NULL
) {
248 dev_err(dev
, "unable to create hcd\n");
252 usb_hcd
->wireless
= 1;
254 wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
255 whc
= wusbhc_to_whc(wusbhc
);
263 wusbhc
->uwb_rc
= uwb_rc_get_by_grandpa(umc
->dev
.parent
);
264 if (!wusbhc
->uwb_rc
) {
266 dev_err(dev
, "cannot get radio controller\n");
270 if (whc
->n_devices
> USB_MAXCHILDREN
) {
271 dev_warn(dev
, "USB_MAXCHILDREN too low for WUSB adapter (%u ports)\n",
273 wusbhc
->ports_max
= USB_MAXCHILDREN
;
275 wusbhc
->ports_max
= whc
->n_devices
;
276 wusbhc
->mmcies_max
= whc
->n_mmc_ies
;
277 wusbhc
->start
= whc_wusbhc_start
;
278 wusbhc
->stop
= whc_wusbhc_stop
;
279 wusbhc
->mmcie_add
= whc_mmcie_add
;
280 wusbhc
->mmcie_rm
= whc_mmcie_rm
;
281 wusbhc
->dev_info_set
= whc_dev_info_set
;
282 wusbhc
->bwa_set
= whc_bwa_set
;
283 wusbhc
->set_num_dnts
= whc_set_num_dnts
;
284 wusbhc
->set_ptk
= whc_set_ptk
;
285 wusbhc
->set_gtk
= whc_set_gtk
;
287 ret
= wusbhc_create(wusbhc
);
289 goto error_wusbhc_create
;
291 ret
= usb_add_hcd(usb_hcd
, whc
->umc
->irq
, IRQF_SHARED
);
293 dev_err(dev
, "cannot add HCD: %d\n", ret
);
294 goto error_usb_add_hcd
;
297 ret
= wusbhc_b_create(wusbhc
);
299 dev_err(dev
, "WUSBHC phase B setup failed: %d\n", ret
);
300 goto error_wusbhc_b_create
;
307 error_wusbhc_b_create
:
308 usb_remove_hcd(usb_hcd
);
310 wusbhc_destroy(wusbhc
);
312 uwb_rc_put(wusbhc
->uwb_rc
);
316 usb_put_hcd(usb_hcd
);
321 static void whc_remove(struct umc_dev
*umc
)
323 struct usb_hcd
*usb_hcd
= dev_get_drvdata(&umc
->dev
);
324 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
325 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
328 whc_dbg_clean_up(whc
);
329 wusbhc_b_destroy(wusbhc
);
330 usb_remove_hcd(usb_hcd
);
331 wusbhc_destroy(wusbhc
);
332 uwb_rc_put(wusbhc
->uwb_rc
);
334 usb_put_hcd(usb_hcd
);
338 static struct umc_driver whci_hc_driver
= {
340 .cap_id
= UMC_CAP_ID_WHCI_WUSB_HC
,
342 .remove
= whc_remove
,
345 static int __init
whci_hc_driver_init(void)
347 return umc_driver_register(&whci_hc_driver
);
349 module_init(whci_hc_driver_init
);
351 static void __exit
whci_hc_driver_exit(void)
353 umc_driver_unregister(&whci_hc_driver
);
355 module_exit(whci_hc_driver_exit
);
357 /* PCI device ID's that we handle (so it gets loaded) */
358 static struct pci_device_id whci_hcd_id_table
[] = {
359 { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI
, ~0) },
360 { /* empty last entry */ }
362 MODULE_DEVICE_TABLE(pci
, whci_hcd_id_table
);
364 MODULE_DESCRIPTION("WHCI Wireless USB host controller driver");
365 MODULE_AUTHOR("Cambridge Silicon Radio Ltd.");
366 MODULE_LICENSE("GPL");