aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/host/sl811-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/sl811-hcd.c')
-rw-r--r--drivers/usb/host/sl811-hcd.c168
1 files changed, 74 insertions, 94 deletions
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 990f06b89ea..a517151867a 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -22,7 +22,7 @@
* and usb-storage.
*
* TODO:
- * - usb suspend/resume triggered by sl811 (with USB_SUSPEND)
+ * - usb suspend/resume triggered by sl811 (with PM_RUNTIME)
* - various issues noted in the code
* - performance work; use both register banks; ...
* - use urb->iso_frame_desc[] with ISO transfers
@@ -39,7 +39,6 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
@@ -47,10 +46,12 @@
#include <linux/usb/sl811.h>
#include <linux/usb/hcd.h>
#include <linux/platform_device.h>
+#include <linux/prefetch.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/system.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
@@ -63,20 +64,9 @@ MODULE_ALIAS("platform:sl811-hcd");
#define DRIVER_VERSION "19 May 2005"
-
-#ifndef DEBUG
-# define STUB_DEBUG_FILE
-#endif
-
/* for now, use only one transfer register bank */
#undef USE_B
-/* this doesn't understand urb->iso_frame_desc[], but if you had a driver
- * that just queued one ISO frame per URB then iso transfers "should" work
- * using the normal urb status fields.
- */
-#define DISABLE_ISO
-
// #define QUIRK2
#define QUIRK3
@@ -106,7 +96,8 @@ static void port_power(struct sl811 *sl811, int is_on)
if (sl811->board && sl811->board->port_power) {
/* switch VBUS, at 500mA unless hub power budget gets set */
- DBG("power %s\n", is_on ? "on" : "off");
+ dev_dbg(hcd->self.controller, "power %s\n",
+ is_on ? "on" : "off");
sl811->board->port_power(hcd->self.controller, is_on);
}
@@ -162,7 +153,7 @@ static void setup_packet(
writeb(SL_SETUP /* | ep->epnum */, data_reg);
writeb(usb_pipedevice(urb->pipe), data_reg);
- /* always OUT/data0 */ ;
+ /* always OUT/data0 */
sl811_write(sl811, bank + SL11H_HOSTCTLREG,
control | SL11H_HCTLMASK_OUT);
ep->length = 0;
@@ -288,7 +279,7 @@ static inline void sofirq_on(struct sl811 *sl811)
{
if (sl811->irq_enable & SL11H_INTMASK_SOFINTR)
return;
- VDBG("sof irq on\n");
+ dev_dbg(sl811_to_hcd(sl811)->self.controller, "sof irq on\n");
sl811->irq_enable |= SL11H_INTMASK_SOFINTR;
}
@@ -296,7 +287,7 @@ static inline void sofirq_off(struct sl811 *sl811)
{
if (!(sl811->irq_enable & SL11H_INTMASK_SOFINTR))
return;
- VDBG("sof irq off\n");
+ dev_dbg(sl811_to_hcd(sl811)->self.controller, "sof irq off\n");
sl811->irq_enable &= ~SL11H_INTMASK_SOFINTR;
}
@@ -344,7 +335,8 @@ static struct sl811h_ep *start(struct sl811 *sl811, u8 bank)
}
if (unlikely(list_empty(&ep->hep->urb_list))) {
- DBG("empty %p queue?\n", ep);
+ dev_dbg(sl811_to_hcd(sl811)->self.controller,
+ "empty %p queue?\n", ep);
return NULL;
}
@@ -397,7 +389,8 @@ static struct sl811h_ep *start(struct sl811 *sl811, u8 bank)
status_packet(sl811, ep, urb, bank, control);
break;
default:
- DBG("bad ep%p pid %02x\n", ep, ep->nextpid);
+ dev_dbg(sl811_to_hcd(sl811)->self.controller,
+ "bad ep%p pid %02x\n", ep, ep->nextpid);
ep = NULL;
}
return ep;
@@ -453,7 +446,8 @@ static void finish_request(
}
/* periodic deschedule */
- DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
+ dev_dbg(sl811_to_hcd(sl811)->self.controller,
+ "deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
struct sl811h_ep *temp;
struct sl811h_ep **prev = &sl811->periodic[i];
@@ -599,7 +593,8 @@ static inline u8 checkdone(struct sl811 *sl811)
ctl = sl811_read(sl811, SL811_EP_A(SL11H_HOSTCTLREG));
if (ctl & SL11H_HCTLMASK_ARM)
sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0);
- DBG("%s DONE_A: ctrl %02x sts %02x\n",
+ dev_dbg(sl811_to_hcd(sl811)->self.controller,
+ "%s DONE_A: ctrl %02x sts %02x\n",
(ctl & SL11H_HCTLMASK_ARM) ? "timeout" : "lost",
ctl,
sl811_read(sl811, SL811_EP_A(SL11H_PKTSTATREG)));
@@ -610,7 +605,8 @@ static inline u8 checkdone(struct sl811 *sl811)
ctl = sl811_read(sl811, SL811_EP_B(SL11H_HOSTCTLREG));
if (ctl & SL11H_HCTLMASK_ARM)
sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0);
- DBG("%s DONE_B: ctrl %02x sts %02x\n",
+ dev_dbg(sl811_to_hcd(sl811)->self.controller,
+ "%s DONE_B: ctrl %02x sts %02x\n",
(ctl & SL11H_HCTLMASK_ARM) ? "timeout" : "lost",
ctl,
sl811_read(sl811, SL811_EP_B(SL11H_PKTSTATREG)));
@@ -671,7 +667,7 @@ retry:
* this one has nothing scheduled.
*/
if (sl811->next_periodic) {
- // ERR("overrun to slot %d\n", index);
+ // dev_err(hcd->self.controller, "overrun to slot %d\n", index);
sl811->stat_overrun++;
}
if (sl811->periodic[index])
@@ -729,7 +725,7 @@ retry:
} else if (irqstat & SL11H_INTMASK_RD) {
if (sl811->port1 & USB_PORT_STAT_SUSPEND) {
- DBG("wakeup\n");
+ dev_dbg(hcd->self.controller, "wakeup\n");
sl811->port1 |= USB_PORT_STAT_C_SUSPEND << 16;
sl811->stat_wake++;
} else
@@ -807,7 +803,7 @@ static int sl811h_urb_enqueue(
int retval;
struct usb_host_endpoint *hep = urb->ep;
-#ifdef DISABLE_ISO
+#ifndef CONFIG_USB_SL811_HCD_ISO
if (type == PIPE_ISOCHRONOUS)
return -ENOSPC;
#endif
@@ -858,9 +854,11 @@ static int sl811h_urb_enqueue(
if (ep->maxpacket > H_MAXPACKET) {
/* iso packets up to 240 bytes could work... */
- DBG("dev %d ep%d maxpacket %d\n",
- udev->devnum, epnum, ep->maxpacket);
+ dev_dbg(hcd->self.controller,
+ "dev %d ep%d maxpacket %d\n", udev->devnum,
+ epnum, ep->maxpacket);
retval = -EINVAL;
+ kfree(ep);
goto fail;
}
@@ -922,7 +920,8 @@ static int sl811h_urb_enqueue(
* to share the faster parts of the tree without needing
* dummy/placeholder nodes
*/
- DBG("schedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
+ dev_dbg(hcd->self.controller, "schedule qh%d/%p branch %d\n",
+ ep->period, ep, ep->branch);
for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
struct sl811h_ep **prev = &sl811->periodic[i];
struct sl811h_ep *here = *prev;
@@ -981,7 +980,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
} else if (sl811->active_a == ep) {
if (time_before_eq(sl811->jiffies_a, jiffies)) {
/* happens a lot with lowspeed?? */
- DBG("giveup on DONE_A: ctrl %02x sts %02x\n",
+ dev_dbg(hcd->self.controller,
+ "giveup on DONE_A: ctrl %02x sts %02x\n",
sl811_read(sl811,
SL811_EP_A(SL11H_HOSTCTLREG)),
sl811_read(sl811,
@@ -995,7 +995,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
} else if (sl811->active_b == ep) {
if (time_before_eq(sl811->jiffies_a, jiffies)) {
/* happens a lot with lowspeed?? */
- DBG("giveup on DONE_B: ctrl %02x sts %02x\n",
+ dev_dbg(hcd->self.controller,
+ "giveup on DONE_B: ctrl %02x sts %02x\n",
sl811_read(sl811,
SL811_EP_B(SL11H_HOSTCTLREG)),
sl811_read(sl811,
@@ -1013,7 +1014,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
if (urb)
finish_request(sl811, ep, urb, 0);
else
- VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
+ dev_dbg(sl811_to_hcd(sl811)->self.controller,
+ "dequeue, urb %p active %s; wait4irq\n", urb,
(sl811->active_a == ep) ? "A" : "B");
} else
retval = -EINVAL;
@@ -1034,7 +1036,7 @@ sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
if (!list_empty(&hep->urb_list))
msleep(3);
if (!list_empty(&hep->urb_list))
- WARNING("ep %p not empty?\n", ep);
+ dev_warn(hcd->self.controller, "ep %p not empty?\n", ep);
kfree(ep);
hep->hcpriv = NULL;
@@ -1110,9 +1112,9 @@ sl811h_hub_descriptor (
desc->wHubCharacteristics = cpu_to_le16(temp);
- /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */
- desc->bitmap[0] = 0 << 1;
- desc->bitmap[1] = ~0;
+ /* ports removable, and legacy PortPwrCtrlMask */
+ desc->u.hs.DeviceRemovable[0] = 0 << 1;
+ desc->u.hs.DeviceRemovable[1] = ~0;
}
static void
@@ -1137,7 +1139,7 @@ sl811h_timer(unsigned long _sl811)
switch (signaling) {
case SL11H_CTL1MASK_SE0:
- DBG("end reset\n");
+ dev_dbg(sl811_to_hcd(sl811)->self.controller, "end reset\n");
sl811->port1 = (USB_PORT_STAT_C_RESET << 16)
| USB_PORT_STAT_POWER;
sl811->ctrl1 = 0;
@@ -1146,11 +1148,12 @@ sl811h_timer(unsigned long _sl811)
irqstat &= ~SL11H_INTMASK_RD;
break;
case SL11H_CTL1MASK_K:
- DBG("end resume\n");
+ dev_dbg(sl811_to_hcd(sl811)->self.controller, "end resume\n");
sl811->port1 &= ~USB_PORT_STAT_SUSPEND;
break;
default:
- DBG("odd timer signaling: %02x\n", signaling);
+ dev_dbg(sl811_to_hcd(sl811)->self.controller,
+ "odd timer signaling: %02x\n", signaling);
break;
}
sl811_write(sl811, SL11H_IRQ_STATUS, irqstat);
@@ -1248,7 +1251,7 @@ sl811h_hub_control(
break;
/* 20 msec of resume/K signaling, other irqs blocked */
- DBG("start resume...\n");
+ dev_dbg(hcd->self.controller, "start resume...\n");
sl811->irq_enable = 0;
sl811_write(sl811, SL11H_IRQ_ENABLE,
sl811->irq_enable);
@@ -1286,7 +1289,8 @@ sl811h_hub_control(
#ifndef VERBOSE
if (*(u16*)(buf+2)) /* only if wPortChange is interesting */
#endif
- DBG("GetPortStatus %08x\n", sl811->port1);
+ dev_dbg(hcd->self.controller, "GetPortStatus %08x\n",
+ sl811->port1);
break;
case SetPortFeature:
if (wIndex != 1 || wLength != 0)
@@ -1298,7 +1302,7 @@ sl811h_hub_control(
if (!(sl811->port1 & USB_PORT_STAT_ENABLE))
goto error;
- DBG("suspend...\n");
+ dev_dbg(hcd->self.controller,"suspend...\n");
sl811->ctrl1 &= ~SL11H_CTL1MASK_SOF_ENA;
sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
break;
@@ -1343,7 +1347,7 @@ static int
sl811h_bus_suspend(struct usb_hcd *hcd)
{
// SOFs off
- DBG("%s\n", __func__);
+ dev_dbg(hcd->self.controller, "%s\n", __func__);
return 0;
}
@@ -1351,7 +1355,7 @@ static int
sl811h_bus_resume(struct usb_hcd *hcd)
{
// SOFs on
- DBG("%s\n", __func__);
+ dev_dbg(hcd->self.controller, "%s\n", __func__);
return 0;
}
@@ -1365,16 +1369,6 @@ sl811h_bus_resume(struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
-#ifdef STUB_DEBUG_FILE
-
-static inline void create_debug_file(struct sl811 *sl811) { }
-static inline void remove_debug_file(struct sl811 *sl811) { }
-
-#else
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
static void dump_irq(struct seq_file *s, char *label, u8 mask)
{
seq_printf(s, "%s %02x%s%s%s%s%s%s\n", label, mask,
@@ -1386,7 +1380,7 @@ static void dump_irq(struct seq_file *s, char *label, u8 mask)
(mask & SL11H_INTMASK_DP) ? " dp" : "");
}
-static int proc_sl811h_show(struct seq_file *s, void *unused)
+static int sl811h_show(struct seq_file *s, void *unused)
{
struct sl811 *sl811 = s->private;
struct sl811h_ep *ep;
@@ -1418,7 +1412,7 @@ static int proc_sl811h_show(struct seq_file *s, void *unused)
case SL11H_CTL1MASK_SE0: s = " se0/reset"; break;
case SL11H_CTL1MASK_K: s = " k/resume"; break;
default: s = "j"; break;
- }; s; }),
+ } s; }),
(t & SL11H_CTL1MASK_LSPD) ? " lowspeed" : "",
(t & SL11H_CTL1MASK_SUSPEND) ? " suspend" : "");
@@ -1451,7 +1445,7 @@ static int proc_sl811h_show(struct seq_file *s, void *unused)
case USB_PID_SETUP: s = "setup"; break;
case USB_PID_ACK: s = "status"; break;
default: s = "?"; break;
- }; s;}),
+ } s;}),
ep->maxpacket,
ep->nak_count, ep->error_count);
list_for_each_entry (urb, &ep->hep->urb_list, urb_list) {
@@ -1497,34 +1491,31 @@ static int proc_sl811h_show(struct seq_file *s, void *unused)
return 0;
}
-static int proc_sl811h_open(struct inode *inode, struct file *file)
+static int sl811h_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_sl811h_show, PDE(inode)->data);
+ return single_open(file, sl811h_show, inode->i_private);
}
-static const struct file_operations proc_ops = {
- .open = proc_sl811h_open,
+static const struct file_operations debug_ops = {
+ .open = sl811h_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
/* expect just one sl811 per system */
-static const char proc_filename[] = "driver/sl811h";
-
static void create_debug_file(struct sl811 *sl811)
{
- sl811->pde = proc_create_data(proc_filename, 0, NULL, &proc_ops, sl811);
+ sl811->debug_file = debugfs_create_file("sl811h", S_IRUGO,
+ usb_debug_root, sl811,
+ &debug_ops);
}
static void remove_debug_file(struct sl811 *sl811)
{
- if (sl811->pde)
- remove_proc_entry(proc_filename, NULL);
+ debugfs_remove(sl811->debug_file);
}
-#endif
-
/*-------------------------------------------------------------------------*/
static void
@@ -1600,7 +1591,7 @@ static struct hc_driver sl811h_hc_driver = {
/*-------------------------------------------------------------------------*/
-static int __devexit
+static int
sl811h_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
@@ -1623,7 +1614,7 @@ sl811h_remove(struct platform_device *dev)
return 0;
}
-static int __devinit
+static int
sl811h_probe(struct platform_device *dev)
{
struct usb_hcd *hcd;
@@ -1636,6 +1627,9 @@ sl811h_probe(struct platform_device *dev)
u8 tmp, ioaddr = 0;
unsigned long irqflags;
+ if (usb_disabled())
+ return -ENODEV;
+
/* basic sanity checks first. board-specific init logic should
* have initialized these three resources and probably board
* specific platform_data. we don't probe for IRQs, and do only
@@ -1650,7 +1644,7 @@ sl811h_probe(struct platform_device *dev)
/* refuse to confuse usbcore */
if (dev->dev.dma_mask) {
- DBG("no we won't dma\n");
+ dev_dbg(&dev->dev, "no we won't dma\n");
return -EINVAL;
}
@@ -1696,7 +1690,7 @@ sl811h_probe(struct platform_device *dev)
spin_lock_init(&sl811->lock);
INIT_LIST_HEAD(&sl811->async);
- sl811->board = dev->dev.platform_data;
+ sl811->board = dev_get_platdata(&dev->dev);
init_timer(&sl811->timer);
sl811->timer.function = sl811h_timer;
sl811->timer.data = (unsigned long) sl811;
@@ -1718,7 +1712,7 @@ sl811h_probe(struct platform_device *dev)
break;
default:
/* reject case 0, SL11S is less functional */
- DBG("chiprev %02x\n", tmp);
+ dev_dbg(&dev->dev, "chiprev %02x\n", tmp);
retval = -ENXIO;
goto err6;
}
@@ -1733,10 +1727,12 @@ sl811h_probe(struct platform_device *dev)
* Use resource IRQ flags if set by platform device setup.
*/
irqflags |= IRQF_SHARED;
- retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | irqflags);
+ retval = usb_add_hcd(hcd, irq, irqflags);
if (retval != 0)
goto err6;
+ device_wakeup_enable(hcd->self.controller);
+
create_debug_file(sl811);
return retval;
@@ -1749,7 +1745,7 @@ sl811h_probe(struct platform_device *dev)
if (!ioaddr)
iounmap(addr_reg);
err2:
- DBG("init error, %d\n", retval);
+ dev_dbg(&dev->dev, "init error, %d\n", retval);
return retval;
}
@@ -1757,7 +1753,7 @@ sl811h_probe(struct platform_device *dev)
/* for this device there's no useful distinction between the controller
* and its root hub, except that the root hub only gets direct PM calls
- * when CONFIG_USB_SUSPEND is enabled.
+ * when CONFIG_PM_RUNTIME is enabled.
*/
static int
@@ -1810,7 +1806,7 @@ sl811h_resume(struct platform_device *dev)
/* this driver is exported so sl811_cs can depend on it */
struct platform_driver sl811h_driver = {
.probe = sl811h_probe,
- .remove = __devexit_p(sl811h_remove),
+ .remove = sl811h_remove,
.suspend = sl811h_suspend,
.resume = sl811h_resume,
@@ -1821,20 +1817,4 @@ struct platform_driver sl811h_driver = {
};
EXPORT_SYMBOL(sl811h_driver);
-/*-------------------------------------------------------------------------*/
-
-static int __init sl811h_init(void)
-{
- if (usb_disabled())
- return -ENODEV;
-
- INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION);
- return platform_driver_register(&sl811h_driver);
-}
-module_init(sl811h_init);
-
-static void __exit sl811h_cleanup(void)
-{
- platform_driver_unregister(&sl811h_driver);
-}
-module_exit(sl811h_cleanup);
+module_platform_driver(sl811h_driver);