Commit eff910a9 authored by Linus Torvalds's avatar Linus Torvalds
parents a340ba10 06299db3
...@@ -124,3 +124,14 @@ config USB_SL811_HCD ...@@ -124,3 +124,14 @@ config USB_SL811_HCD
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called sl811-hcd. module will be called sl811-hcd.
config USB_SL811_CS
tristate "CF/PCMCIA support for SL811HS HCD"
depends on USB_SL811_HCD && PCMCIA
default N
help
Wraps a PCMCIA driver around the SL811HS HCD, supporting the RATOC
REX-CFU1U CF card (often used with PDAs). If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called "sl811_cs".
...@@ -7,4 +7,5 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o ...@@ -7,4 +7,5 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* SL811HS HCD (Host Controller Driver) for USB. * SL811HS HCD (Host Controller Driver) for USB.
* *
* Copyright (C) 2004 Psion Teklogix (for NetBook PRO) * Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
* Copyright (C) 2004 David Brownell * Copyright (C) 2004-2005 David Brownell
* *
* Periodic scheduling is based on Roman's OHCI code * Periodic scheduling is based on Roman's OHCI code
* Copyright (C) 1999 Roman Weissgaerber * Copyright (C) 1999 Roman Weissgaerber
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
MODULE_DESCRIPTION("SL811HS USB Host Controller Driver"); MODULE_DESCRIPTION("SL811HS USB Host Controller Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define DRIVER_VERSION "15 Dec 2004" #define DRIVER_VERSION "19 May 2005"
#ifndef DEBUG #ifndef DEBUG
...@@ -121,6 +121,10 @@ static void port_power(struct sl811 *sl811, int is_on) ...@@ -121,6 +121,10 @@ static void port_power(struct sl811 *sl811, int is_on)
/* reset as thoroughly as we can */ /* reset as thoroughly as we can */
if (sl811->board && sl811->board->reset) if (sl811->board && sl811->board->reset)
sl811->board->reset(hcd->self.controller); sl811->board->reset(hcd->self.controller);
else {
sl811_write(sl811, SL11H_CTLREG1, SL11H_CTL1MASK_SE0);
mdelay(20);
}
sl811_write(sl811, SL11H_IRQ_ENABLE, 0); sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
...@@ -443,6 +447,7 @@ static void finish_request( ...@@ -443,6 +447,7 @@ static void finish_request(
spin_lock(&urb->lock); spin_lock(&urb->lock);
if (urb->status == -EINPROGRESS) if (urb->status == -EINPROGRESS)
urb->status = status; urb->status = status;
urb->hcpriv = NULL;
spin_unlock(&urb->lock); spin_unlock(&urb->lock);
spin_unlock(&sl811->lock); spin_unlock(&sl811->lock);
...@@ -661,9 +666,9 @@ static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs) ...@@ -661,9 +666,9 @@ static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs)
#ifdef QUIRK2 #ifdef QUIRK2
/* this may no longer be necessary ... */ /* this may no longer be necessary ... */
if (irqstat == 0 && ret == IRQ_NONE) { if (irqstat == 0) {
irqstat = checkdone(sl811); irqstat = checkdone(sl811);
if (irqstat /* && irq != ~0 */ ) if (irqstat)
sl811->stat_lost++; sl811->stat_lost++;
} }
#endif #endif
...@@ -722,7 +727,8 @@ static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs) ...@@ -722,7 +727,8 @@ static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (sl811->active_a) { if (sl811->active_a) {
sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0); sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0);
finish_request(sl811, sl811->active_a, finish_request(sl811, sl811->active_a,
container_of(sl811->active_a->hep->urb_list.next, container_of(sl811->active_a
->hep->urb_list.next,
struct urb, urb_list), struct urb, urb_list),
NULL, -ESHUTDOWN); NULL, -ESHUTDOWN);
sl811->active_a = NULL; sl811->active_a = NULL;
...@@ -731,7 +737,8 @@ static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs) ...@@ -731,7 +737,8 @@ static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (sl811->active_b) { if (sl811->active_b) {
sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0); sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0);
finish_request(sl811, sl811->active_b, finish_request(sl811, sl811->active_b,
container_of(sl811->active_b->hep->urb_list.next, container_of(sl811->active_b
->hep->urb_list.next,
struct urb, urb_list), struct urb, urb_list),
NULL, -ESHUTDOWN); NULL, -ESHUTDOWN);
sl811->active_b = NULL; sl811->active_b = NULL;
...@@ -890,6 +897,7 @@ static int sl811h_urb_enqueue( ...@@ -890,6 +897,7 @@ static int sl811h_urb_enqueue(
break; break;
} }
ep->hep = hep;
hep->hcpriv = ep; hep->hcpriv = ep;
} }
...@@ -961,15 +969,16 @@ static int sl811h_urb_enqueue( ...@@ -961,15 +969,16 @@ static int sl811h_urb_enqueue(
static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
{ {
struct sl811 *sl811 = hcd_to_sl811(hcd); struct sl811 *sl811 = hcd_to_sl811(hcd);
struct usb_host_endpoint *hep = urb->hcpriv; struct usb_host_endpoint *hep;
unsigned long flags; unsigned long flags;
struct sl811h_ep *ep; struct sl811h_ep *ep;
int retval = 0; int retval = 0;
spin_lock_irqsave(&sl811->lock, flags);
hep = urb->hcpriv;
if (!hep) if (!hep)
return -EINVAL; goto fail;
spin_lock_irqsave(&sl811->lock, flags);
ep = hep->hcpriv; ep = hep->hcpriv;
if (ep) { if (ep) {
/* finish right away if this urb can't be active ... /* finish right away if this urb can't be active ...
...@@ -1017,6 +1026,7 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) ...@@ -1017,6 +1026,7 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
VDBG("dequeue, urb %p active %s; wait4irq\n", urb, VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
(sl811->active_a == ep) ? "A" : "B"); (sl811->active_a == ep) ? "A" : "B");
} else } else
fail:
retval = -EINVAL; retval = -EINVAL;
spin_unlock_irqrestore(&sl811->lock, flags); spin_unlock_irqrestore(&sl811->lock, flags);
return retval; return retval;
...@@ -1576,6 +1586,9 @@ sl811h_start(struct usb_hcd *hcd) ...@@ -1576,6 +1586,9 @@ sl811h_start(struct usb_hcd *hcd)
if (sl811->board && sl811->board->power) if (sl811->board && sl811->board->power)
hub_set_power_budget(udev, sl811->board->power * 2); hub_set_power_budget(udev, sl811->board->power * 2);
/* enable power and interupts */
port_power(sl811, 1);
return 0; return 0;
} }
...@@ -1618,7 +1631,7 @@ static struct hc_driver sl811h_hc_driver = { ...@@ -1618,7 +1631,7 @@ static struct hc_driver sl811h_hc_driver = {
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static int __init_or_module static int __devexit
sl811h_remove(struct device *dev) sl811h_remove(struct device *dev)
{ {
struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_hcd *hcd = dev_get_drvdata(dev);
...@@ -1631,21 +1644,20 @@ sl811h_remove(struct device *dev) ...@@ -1631,21 +1644,20 @@ sl811h_remove(struct device *dev)
remove_debug_file(sl811); remove_debug_file(sl811);
usb_remove_hcd(hcd); usb_remove_hcd(hcd);
iounmap(sl811->data_reg); /* some platforms may use IORESOURCE_IO */
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
release_mem_region(res->start, 1); if (res)
iounmap(sl811->data_reg);
iounmap(sl811->addr_reg);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, 1); if (res)
iounmap(sl811->addr_reg);
usb_put_hcd(hcd); usb_put_hcd(hcd);
return 0; return 0;
} }
#define resource_len(r) (((r)->end - (r)->start) + 1) static int __devinit
static int __init
sl811h_probe(struct device *dev) sl811h_probe(struct device *dev)
{ {
struct usb_hcd *hcd; struct usb_hcd *hcd;
...@@ -1656,7 +1668,7 @@ sl811h_probe(struct device *dev) ...@@ -1656,7 +1668,7 @@ sl811h_probe(struct device *dev)
void __iomem *addr_reg; void __iomem *addr_reg;
void __iomem *data_reg; void __iomem *data_reg;
int retval; int retval;
u8 tmp; u8 tmp, ioaddr = 0;
/* basic sanity checks first. board-specific init logic should /* basic sanity checks first. board-specific init logic should
* have initialized these three resources and probably board * have initialized these three resources and probably board
...@@ -1664,13 +1676,8 @@ sl811h_probe(struct device *dev) ...@@ -1664,13 +1676,8 @@ sl811h_probe(struct device *dev)
* minimal sanity checking. * minimal sanity checking.
*/ */
pdev = container_of(dev, struct platform_device, dev); pdev = container_of(dev, struct platform_device, dev);
if (pdev->num_resources < 3)
return -ENODEV;
addr = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data = platform_get_resource(pdev, IORESOURCE_MEM, 1);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (!addr || !data || irq < 0) if (pdev->num_resources < 3 || irq < 0)
return -ENODEV; return -ENODEV;
/* refuse to confuse usbcore */ /* refuse to confuse usbcore */
...@@ -1679,25 +1686,32 @@ sl811h_probe(struct device *dev) ...@@ -1679,25 +1686,32 @@ sl811h_probe(struct device *dev)
return -EINVAL; return -EINVAL;
} }
if (!request_mem_region(addr->start, 1, hcd_name)) { /* the chip may be wired for either kind of addressing */
addr = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data = platform_get_resource(pdev, IORESOURCE_MEM, 1);
retval = -EBUSY; retval = -EBUSY;
goto err1; if (!addr || !data) {
} addr = platform_get_resource(pdev, IORESOURCE_IO, 0);
addr_reg = ioremap(addr->start, resource_len(addr)); data = platform_get_resource(pdev, IORESOURCE_IO, 1);
if (!addr || !data)
return -ENODEV;
ioaddr = 1;
addr_reg = (void __iomem *) addr->start;
data_reg = (void __iomem *) data->start;
} else {
addr_reg = ioremap(addr->start, 1);
if (addr_reg == NULL) { if (addr_reg == NULL) {
retval = -ENOMEM; retval = -ENOMEM;
goto err2; goto err2;
} }
if (!request_mem_region(data->start, 1, hcd_name)) { data_reg = ioremap(data->start, 1);
retval = -EBUSY;
goto err3;
}
data_reg = ioremap(data->start, resource_len(addr));
if (data_reg == NULL) { if (data_reg == NULL) {
retval = -ENOMEM; retval = -ENOMEM;
goto err4; goto err4;
} }
}
/* allocate and initialize hcd */ /* allocate and initialize hcd */
hcd = usb_create_hcd(&sl811h_hc_driver, dev, dev->bus_id); hcd = usb_create_hcd(&sl811h_hc_driver, dev, dev->bus_id);
...@@ -1737,12 +1751,14 @@ sl811h_probe(struct device *dev) ...@@ -1737,12 +1751,14 @@ sl811h_probe(struct device *dev)
goto err6; goto err6;
} }
/* sl811s would need a different handler for this irq */ /* The chip's IRQ is level triggered, active high. A requirement
#ifdef CONFIG_ARM * for platform device setup is to cope with things like signal
/* Cypress docs say the IRQ is IRQT_HIGH ... */ * inverters (e.g. CF is active low) or working only with edge
set_irq_type(irq, IRQT_RISING); * triggers (e.g. most ARM CPUs). Initial driver stress testing
#endif * was on a system with single edge triggering, so most sorts of
retval = usb_add_hcd(hcd, irq, SA_INTERRUPT); * triggering arrangement should work.
*/
retval = usb_add_hcd(hcd, irq, SA_INTERRUPT | SA_SHIRQ);
if (retval != 0) if (retval != 0)
goto err6; goto err6;
...@@ -1752,14 +1768,12 @@ sl811h_probe(struct device *dev) ...@@ -1752,14 +1768,12 @@ sl811h_probe(struct device *dev)
err6: err6:
usb_put_hcd(hcd); usb_put_hcd(hcd);
err5: err5:
if (!ioaddr)
iounmap(data_reg); iounmap(data_reg);
err4: err4:
release_mem_region(data->start, 1); if (!ioaddr)
err3:
iounmap(addr_reg); iounmap(addr_reg);
err2: err2:
release_mem_region(addr->start, 1);
err1:
DBG("init error, %d\n", retval); DBG("init error, %d\n", retval);
return retval; return retval;
} }
...@@ -1821,16 +1835,18 @@ sl811h_resume(struct device *dev, u32 phase) ...@@ -1821,16 +1835,18 @@ sl811h_resume(struct device *dev, u32 phase)
#endif #endif
static struct device_driver sl811h_driver = { /* this driver is exported so sl811_cs can depend on it */
struct device_driver sl811h_driver = {
.name = (char *) hcd_name, .name = (char *) hcd_name,
.bus = &platform_bus_type, .bus = &platform_bus_type,
.probe = sl811h_probe, .probe = sl811h_probe,
.remove = sl811h_remove, .remove = __devexit_p(sl811h_remove),
.suspend = sl811h_suspend, .suspend = sl811h_suspend,
.resume = sl811h_resume, .resume = sl811h_resume,
}; };
EXPORT_SYMBOL(sl811h_driver);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
This diff is collapsed.
...@@ -364,6 +364,7 @@ static struct usb_device_id id_table_8U232AM [] = { ...@@ -364,6 +364,7 @@ static struct usb_device_id id_table_8U232AM [] = {
{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0, 0x3ff) },
{ USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0, 0x3ff) }, { USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) }, { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) },
...@@ -475,6 +476,7 @@ static struct usb_device_id id_table_FT232BM [] = { ...@@ -475,6 +476,7 @@ static struct usb_device_id id_table_FT232BM [] = {
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
...@@ -618,6 +620,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -618,6 +620,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) },
{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
......
...@@ -144,6 +144,8 @@ ...@@ -144,6 +144,8 @@
/* ELV USB Module UO100 (PID sent by Stefan Frings) */ /* ELV USB Module UO100 (PID sent by Stefan Frings) */
#define FTDI_ELV_UO100_PID 0xFB58 /* Product Id */ #define FTDI_ELV_UO100_PID 0xFB58 /* Product Id */
/* ELV USB Module UM100 (PID sent by Arnim Laeuger) */
#define FTDI_ELV_UM100_PID 0xFB5A /* Product Id */
/* /*
* Definitions for ID TECH (www.idt-net.com) devices * Definitions for ID TECH (www.idt-net.com) devices
......
...@@ -1297,13 +1297,6 @@ static int __init usb_serial_init(void) ...@@ -1297,13 +1297,6 @@ static int __init usb_serial_init(void)
goto exit_bus; goto exit_bus;
} }
/* register the generic driver, if we should */
result = usb_serial_generic_register(debug);
if (result < 0) {
err("%s - registering generic driver failed", __FUNCTION__);
goto exit_generic;
}
usb_serial_tty_driver->owner = THIS_MODULE; usb_serial_tty_driver->owner = THIS_MODULE;
usb_serial_tty_driver->driver_name = "usbserial"; usb_serial_tty_driver->driver_name = "usbserial";
usb_serial_tty_driver->devfs_name = "usb/tts/"; usb_serial_tty_driver->devfs_name = "usb/tts/";
...@@ -1329,17 +1322,24 @@ static int __init usb_serial_init(void) ...@@ -1329,17 +1322,24 @@ static int __init usb_serial_init(void)
goto exit_tty; goto exit_tty;
} }
/* register the generic driver, if we should */
result = usb_serial_generic_register(debug);
if (result < 0) {
err("%s - registering generic driver failed", __FUNCTION__);
goto exit_generic;
}
info(DRIVER_DESC " " DRIVER_VERSION); info(DRIVER_DESC " " DRIVER_VERSION);
return result; return result;
exit_generic:
usb_deregister(&usb_serial_driver);
exit_tty: exit_tty:
tty_unregister_driver(usb_serial_tty_driver); tty_unregister_driver(usb_serial_tty_driver);
exit_reg_driver: exit_reg_driver:
usb_serial_generic_deregister();
exit_generic:
bus_unregister(&usb_serial_bus_type); bus_unregister(&usb_serial_bus_type);
exit_bus: exit_bus:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment