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/module.h>
21 #include <linux/uwb/umc.h>
23 #include "../../wusbcore/wusbhc.h"
28 * One time initialization.
32 static int whc_reset(struct usb_hcd
*usb_hcd
)
38 * Start the wireless host controller.
40 * Start device notification.
42 * Put hc into run state, set DNTS parameters.
44 static int whc_start(struct usb_hcd
*usb_hcd
)
46 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
47 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
51 mutex_lock(&wusbhc
->mutex
);
53 le_writel(WUSBINTR_GEN_CMD_DONE
55 | WUSBINTR_ASYNC_SCHED_SYNCED
59 whc
->base
+ WUSBINTR
);
62 bcid
= wusb_cluster_id_get();
63 ret
= whc_set_cluster_id(whc
, bcid
);
66 wusbhc
->cluster_id
= bcid
;
69 whc_write_wusbcmd(whc
, WUSBCMD_RUN
, WUSBCMD_RUN
);
71 usb_hcd
->uses_new_polling
= 1;
72 set_bit(HCD_FLAG_POLL_RH
, &usb_hcd
->flags
);
73 usb_hcd
->state
= HC_STATE_RUNNING
;
76 mutex_unlock(&wusbhc
->mutex
);
82 * Stop the wireless host controller.
84 * Stop device notification.
86 * Wait for pending transfer to stop? Put hc into stop state?
88 static void whc_stop(struct usb_hcd
*usb_hcd
)
90 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
91 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
93 mutex_lock(&wusbhc
->mutex
);
96 le_writel(0, whc
->base
+ WUSBINTR
);
97 whc_write_wusbcmd(whc
, WUSBCMD_RUN
, 0);
98 whci_wait_for(&whc
->umc
->dev
, whc
->base
+ WUSBSTS
,
99 WUSBSTS_HCHALTED
, WUSBSTS_HCHALTED
,
102 wusb_cluster_id_put(wusbhc
->cluster_id
);
104 mutex_unlock(&wusbhc
->mutex
);
107 static int whc_get_frame_number(struct usb_hcd
*usb_hcd
)
109 /* Frame numbers are not applicable to WUSB. */
115 * Queue an URB to the ASL or PZL
117 static int whc_urb_enqueue(struct usb_hcd
*usb_hcd
, struct urb
*urb
,
120 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
121 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
124 switch (usb_pipetype(urb
->pipe
)) {
126 ret
= pzl_urb_enqueue(whc
, urb
, mem_flags
);
128 case PIPE_ISOCHRONOUS
:
129 dev_err(&whc
->umc
->dev
, "isochronous transfers unsupported\n");
135 ret
= asl_urb_enqueue(whc
, urb
, mem_flags
);
143 * Remove a queued URB from the ASL or PZL.
145 static int whc_urb_dequeue(struct usb_hcd
*usb_hcd
, struct urb
*urb
, int status
)
147 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
148 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
151 switch (usb_pipetype(urb
->pipe
)) {
153 ret
= pzl_urb_dequeue(whc
, urb
, status
);
155 case PIPE_ISOCHRONOUS
:
161 ret
= asl_urb_dequeue(whc
, urb
, status
);
169 * Wait for all URBs to the endpoint to be completed, then delete the
172 static void whc_endpoint_disable(struct usb_hcd
*usb_hcd
,
173 struct usb_host_endpoint
*ep
)
175 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
176 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
177 struct whc_qset
*qset
;
182 if (usb_endpoint_xfer_bulk(&ep
->desc
)
183 || usb_endpoint_xfer_control(&ep
->desc
))
184 asl_qset_delete(whc
, qset
);
186 pzl_qset_delete(whc
, qset
);
190 static void whc_endpoint_reset(struct usb_hcd
*usb_hcd
,
191 struct usb_host_endpoint
*ep
)
193 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
194 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
195 struct whc_qset
*qset
;
198 spin_lock_irqsave(&whc
->lock
, flags
);
205 if (usb_endpoint_xfer_bulk(&ep
->desc
)
206 || usb_endpoint_xfer_control(&ep
->desc
))
207 queue_work(whc
->workqueue
, &whc
->async_work
);
209 queue_work(whc
->workqueue
, &whc
->periodic_work
);
212 spin_unlock_irqrestore(&whc
->lock
, flags
);
216 static struct hc_driver whc_hc_driver
= {
217 .description
= "whci-hcd",
218 .product_desc
= "Wireless host controller",
219 .hcd_priv_size
= sizeof(struct whc
) - sizeof(struct usb_hcd
),
220 .irq
= whc_int_handler
,
226 .get_frame_number
= whc_get_frame_number
,
227 .urb_enqueue
= whc_urb_enqueue
,
228 .urb_dequeue
= whc_urb_dequeue
,
229 .endpoint_disable
= whc_endpoint_disable
,
230 .endpoint_reset
= whc_endpoint_reset
,
232 .hub_status_data
= wusbhc_rh_status_data
,
233 .hub_control
= wusbhc_rh_control
,
234 .start_port_reset
= wusbhc_rh_start_port_reset
,
237 static int whc_probe(struct umc_dev
*umc
)
240 struct usb_hcd
*usb_hcd
;
241 struct wusbhc
*wusbhc
;
243 struct device
*dev
= &umc
->dev
;
245 usb_hcd
= usb_create_hcd(&whc_hc_driver
, dev
, "whci");
246 if (usb_hcd
== NULL
) {
247 dev_err(dev
, "unable to create hcd\n");
251 usb_hcd
->wireless
= 1;
252 usb_hcd
->self
.sg_tablesize
= 2048; /* somewhat arbitrary */
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
;
296 device_wakeup_enable(usb_hcd
->self
.controller
);
298 ret
= wusbhc_b_create(wusbhc
);
300 dev_err(dev
, "WUSBHC phase B setup failed: %d\n", ret
);
301 goto error_wusbhc_b_create
;
308 error_wusbhc_b_create
:
309 usb_remove_hcd(usb_hcd
);
311 wusbhc_destroy(wusbhc
);
313 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 __used 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");