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 struct hc_driver whc_hc_driver
= {
190 .description
= "whci-hcd",
191 .product_desc
= "Wireless host controller",
192 .hcd_priv_size
= sizeof(struct whc
) - sizeof(struct usb_hcd
),
193 .irq
= whc_int_handler
,
199 .get_frame_number
= whc_get_frame_number
,
200 .urb_enqueue
= whc_urb_enqueue
,
201 .urb_dequeue
= whc_urb_dequeue
,
202 .endpoint_disable
= whc_endpoint_disable
,
204 .hub_status_data
= wusbhc_rh_status_data
,
205 .hub_control
= wusbhc_rh_control
,
206 .bus_suspend
= wusbhc_rh_suspend
,
207 .bus_resume
= wusbhc_rh_resume
,
208 .start_port_reset
= wusbhc_rh_start_port_reset
,
211 static int whc_probe(struct umc_dev
*umc
)
214 struct usb_hcd
*usb_hcd
;
215 struct wusbhc
*wusbhc
= NULL
;
216 struct whc
*whc
= NULL
;
217 struct device
*dev
= &umc
->dev
;
219 usb_hcd
= usb_create_hcd(&whc_hc_driver
, dev
, "whci");
220 if (usb_hcd
== NULL
) {
221 dev_err(dev
, "unable to create hcd\n");
225 usb_hcd
->wireless
= 1;
227 wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
228 whc
= wusbhc_to_whc(wusbhc
);
236 wusbhc
->uwb_rc
= uwb_rc_get_by_grandpa(umc
->dev
.parent
);
237 if (!wusbhc
->uwb_rc
) {
239 dev_err(dev
, "cannot get radio controller\n");
243 if (whc
->n_devices
> USB_MAXCHILDREN
) {
244 dev_warn(dev
, "USB_MAXCHILDREN too low for WUSB adapter (%u ports)\n",
246 wusbhc
->ports_max
= USB_MAXCHILDREN
;
248 wusbhc
->ports_max
= whc
->n_devices
;
249 wusbhc
->mmcies_max
= whc
->n_mmc_ies
;
250 wusbhc
->start
= whc_wusbhc_start
;
251 wusbhc
->stop
= whc_wusbhc_stop
;
252 wusbhc
->mmcie_add
= whc_mmcie_add
;
253 wusbhc
->mmcie_rm
= whc_mmcie_rm
;
254 wusbhc
->dev_info_set
= whc_dev_info_set
;
255 wusbhc
->bwa_set
= whc_bwa_set
;
256 wusbhc
->set_num_dnts
= whc_set_num_dnts
;
257 wusbhc
->set_ptk
= whc_set_ptk
;
258 wusbhc
->set_gtk
= whc_set_gtk
;
260 ret
= wusbhc_create(wusbhc
);
262 goto error_wusbhc_create
;
264 ret
= usb_add_hcd(usb_hcd
, whc
->umc
->irq
, IRQF_SHARED
);
266 dev_err(dev
, "cannot add HCD: %d\n", ret
);
267 goto error_usb_add_hcd
;
270 ret
= wusbhc_b_create(wusbhc
);
272 dev_err(dev
, "WUSBHC phase B setup failed: %d\n", ret
);
273 goto error_wusbhc_b_create
;
278 error_wusbhc_b_create
:
279 usb_remove_hcd(usb_hcd
);
281 wusbhc_destroy(wusbhc
);
283 uwb_rc_put(wusbhc
->uwb_rc
);
287 usb_put_hcd(usb_hcd
);
292 static void whc_remove(struct umc_dev
*umc
)
294 struct usb_hcd
*usb_hcd
= dev_get_drvdata(&umc
->dev
);
295 struct wusbhc
*wusbhc
= usb_hcd_to_wusbhc(usb_hcd
);
296 struct whc
*whc
= wusbhc_to_whc(wusbhc
);
299 wusbhc_b_destroy(wusbhc
);
300 usb_remove_hcd(usb_hcd
);
301 wusbhc_destroy(wusbhc
);
302 uwb_rc_put(wusbhc
->uwb_rc
);
304 usb_put_hcd(usb_hcd
);
308 static struct umc_driver whci_hc_driver
= {
310 .cap_id
= UMC_CAP_ID_WHCI_WUSB_HC
,
312 .remove
= whc_remove
,
315 static int __init
whci_hc_driver_init(void)
317 return umc_driver_register(&whci_hc_driver
);
319 module_init(whci_hc_driver_init
);
321 static void __exit
whci_hc_driver_exit(void)
323 umc_driver_unregister(&whci_hc_driver
);
325 module_exit(whci_hc_driver_exit
);
327 /* PCI device ID's that we handle (so it gets loaded) */
328 static struct pci_device_id whci_hcd_id_table
[] = {
329 { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI
, ~0) },
330 { /* empty last entry */ }
332 MODULE_DEVICE_TABLE(pci
, whci_hcd_id_table
);
334 MODULE_DESCRIPTION("WHCI Wireless USB host controller driver");
335 MODULE_AUTHOR("Cambridge Silicon Radio Ltd.");
336 MODULE_LICENSE("GPL");