Commit 4c077592 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: net2280 fixes: ep halt, sysfs

Small updates:

  - don't try chiprev 0100 erratum 0114 workaround on
    newer chips; and (mostly) revert it when clearing
    endpoint halt feature.  (bugfix)

  - add missing define for the "force crc error" bit;
    I guess those #defines were generated from old chip
    specs!  potentially useful with test software.

  - sysfs register dump includes chiprev and decodes some
    of the more interesting endpoint response bits.

  - makes a sysfs "gadget" node, representing the gadget
    itself.  (decided against the class_device or bus_type
    approaches, until their value outweighs their costs.)
parent 2c970788
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
/* /*
* Copyright (C) 2003 David Brownell * Copyright (C) 2003 David Brownell
* Copyright (C) 2003 NetChip Technologies
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -77,7 +78,7 @@ ...@@ -77,7 +78,7 @@
#define DRIVER_DESC "NetChip 2280 USB Peripheral Controller" #define DRIVER_DESC "NetChip 2280 USB Peripheral Controller"
#define DRIVER_VERSION "May Day 2003" #define DRIVER_VERSION "Bastille Day 2003"
#define DMA_ADDR_INVALID (~(dma_addr_t)0) #define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define EP_DONTUSE 13 /* nonzero */ #define EP_DONTUSE 13 /* nonzero */
...@@ -1345,11 +1346,12 @@ show_registers (struct device *_dev, char *buf) ...@@ -1345,11 +1346,12 @@ show_registers (struct device *_dev, char *buf)
s = "(none)"; s = "(none)";
/* Main Control Registers */ /* Main Control Registers */
t = snprintf (next, size, "%s " DRIVER_VERSION "\n" t = snprintf (next, size, "%s version " DRIVER_VERSION
", chiprev %04x\n"
"devinit %03x fifoctl %08x gadget '%s'\n" "devinit %03x fifoctl %08x gadget '%s'\n"
"pci irqenb0 %02x irqenb1 %08x " "pci irqenb0 %02x irqenb1 %08x "
"irqstat0 %04x irqstat1 %08x\n", "irqstat0 %04x irqstat1 %08x\n",
driver_name, driver_name, dev->chiprev,
readl (&dev->regs->devinit), readl (&dev->regs->devinit),
readl (&dev->regs->fifoctl), readl (&dev->regs->fifoctl),
s, s,
...@@ -1394,16 +1396,33 @@ show_registers (struct device *_dev, char *buf) ...@@ -1394,16 +1396,33 @@ show_registers (struct device *_dev, char *buf)
continue; continue;
t1 = readl (&ep->regs->ep_cfg); t1 = readl (&ep->regs->ep_cfg);
t2 = readl (&ep->regs->ep_rsp) & 0xff;
t = snprintf (next, size, t = snprintf (next, size,
"%s\tcfg %05x rsp %02x enb %02x ", "%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"
ep->ep.name, t1, "irqenb %02x\n",
readl (&ep->regs->ep_rsp) & 0xff, ep->ep.name, t1, t2,
(t2 & (1 << CLEAR_NAK_OUT_PACKETS))
? "NAK " : "",
(t2 & (1 << CLEAR_EP_HIDE_STATUS_PHASE))
? "hide " : "",
(t2 & (1 << CLEAR_EP_FORCE_CRC_ERROR))
? "CRC " : "",
(t2 & (1 << CLEAR_INTERRUPT_MODE))
? "interrupt " : "",
(t2 & (1<<CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE))
? "status " : "",
(t2 & (1 << CLEAR_NAK_OUT_PACKETS_MODE))
? "NAKmode " : "",
(t2 & (1 << CLEAR_ENDPOINT_TOGGLE))
? "DATA1 " : "DATA0 ",
(t2 & (1 << CLEAR_ENDPOINT_HALT))
? "HALT " : "",
readl (&ep->regs->ep_irqenb)); readl (&ep->regs->ep_irqenb));
size -= t; size -= t;
next += t; next += t;
t = snprintf (next, size, t = snprintf (next, size,
"stat %08x avail %04x " "\tstat %08x avail %04x "
"(ep%d%s-%s)%s\n", "(ep%d%s-%s)%s\n",
readl (&ep->regs->ep_stat), readl (&ep->regs->ep_stat),
readl (&ep->regs->ep_avail), readl (&ep->regs->ep_avail),
...@@ -1797,6 +1816,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) ...@@ -1797,6 +1816,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
dev->ep [i].irqs = 0; dev->ep [i].irqs = 0;
/* hook up the driver ... */ /* hook up the driver ... */
driver->driver.bus = 0;
dev->driver = driver; dev->driver = driver;
dev->gadget.dev.driver = &driver->driver; dev->gadget.dev.driver = &driver->driver;
retval = driver->bind (&dev->gadget); retval = driver->bind (&dev->gadget);
...@@ -1808,10 +1828,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) ...@@ -1808,10 +1828,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
return retval; return retval;
} }
// FIXME
// driver_register (&driver->driver);
// device_register (&dev->gadget.dev);
device_create_file (&dev->pdev->dev, &dev_attr_function); device_create_file (&dev->pdev->dev, &dev_attr_function);
device_create_file (&dev->pdev->dev, &dev_attr_queues); device_create_file (&dev->pdev->dev, &dev_attr_queues);
...@@ -1878,10 +1894,6 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) ...@@ -1878,10 +1894,6 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
device_remove_file (&dev->pdev->dev, &dev_attr_function); device_remove_file (&dev->pdev->dev, &dev_attr_function);
device_remove_file (&dev->pdev->dev, &dev_attr_queues); device_remove_file (&dev->pdev->dev, &dev_attr_queues);
// FIXME
// device_unregister()
// driver_unregister (&driver->driver);
DEBUG (dev, "unregistered driver '%s'\n", driver->driver.name); DEBUG (dev, "unregistered driver '%s'\n", driver->driver.name);
return 0; return 0;
} }
...@@ -2050,9 +2062,9 @@ static void handle_ep_small (struct net2280_ep *ep) ...@@ -2050,9 +2062,9 @@ static void handle_ep_small (struct net2280_ep *ep)
/* maybe advance queue to next request */ /* maybe advance queue to next request */
if (ep->num == 0) { if (ep->num == 0) {
/* FIXME need mechanism (request flag?) so control OUT /* NOTE: net2280 could let gadget driver start the
* can decide to stall ep0 after that done() returns, * status stage later. since not all controllers let
* from non-irq context * them control that, the api doesn't (yet) allow it.
*/ */
if (!ep->stopped) if (!ep->stopped)
allow_status (ep); allow_status (ep);
...@@ -2175,6 +2187,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) ...@@ -2175,6 +2187,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
/* watch control traffic at the token level, and force /* watch control traffic at the token level, and force
* synchronization before letting the status stage happen. * synchronization before letting the status stage happen.
* FIXME ignore tokens we'll NAK, until driver responds.
* that'll mean a lot less irqs for some drivers.
*/ */
ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0; ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
if (ep->is_in) if (ep->is_in)
...@@ -2459,6 +2473,13 @@ static irqreturn_t net2280_irq (int irq, void *_dev, struct pt_regs * r) ...@@ -2459,6 +2473,13 @@ static irqreturn_t net2280_irq (int irq, void *_dev, struct pt_regs * r)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void gadget_release (struct device *_dev)
{
struct net2280 *dev = dev_get_drvdata (_dev);
kfree (dev);
}
/* tear down the binding between this driver and the pci device */ /* tear down the binding between this driver and the pci device */
static void net2280_remove (struct pci_dev *pdev) static void net2280_remove (struct pci_dev *pdev)
...@@ -2494,12 +2515,12 @@ static void net2280_remove (struct pci_dev *pdev) ...@@ -2494,12 +2515,12 @@ static void net2280_remove (struct pci_dev *pdev)
pci_resource_len (pdev, 0)); pci_resource_len (pdev, 0));
if (dev->enabled) if (dev->enabled)
pci_disable_device (pdev); pci_disable_device (pdev);
device_unregister (&dev->gadget.dev);
device_remove_file (&pdev->dev, &dev_attr_registers); device_remove_file (&pdev->dev, &dev_attr_registers);
pci_set_drvdata (pdev, 0); pci_set_drvdata (pdev, 0);
INFO (dev, "unbind from pci %s\n", pci_name(pdev)); INFO (dev, "unbind\n");
kfree (dev);
the_controller = 0; the_controller = 0;
} }
...@@ -2519,7 +2540,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2519,7 +2540,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
* usb_gadget_driver_{register,unregister}() must change. * usb_gadget_driver_{register,unregister}() must change.
*/ */
if (the_controller) { if (the_controller) {
WARN (the_controller, "ignoring %s\n", pci_name(pdev)); dev_warn (&pdev->dev, "ignoring\n");
return -EBUSY; return -EBUSY;
} }
...@@ -2535,9 +2556,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2535,9 +2556,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
dev->pdev = pdev; dev->pdev = pdev;
dev->gadget.ops = &net2280_ops; dev->gadget.ops = &net2280_ops;
strcpy (dev->gadget.dev.bus_id, pci_name(pdev)); /* the "gadget" abstracts/virtualizes the controller */
strcpy (dev->gadget.dev.bus_id, "gadget");
dev->gadget.dev.parent = &pdev->dev; dev->gadget.dev.parent = &pdev->dev;
dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
dev->gadget.dev.release = gadget_release;
dev->gadget.name = driver_name; dev->gadget.name = driver_name;
/* now all the pci goodies ... */ /* now all the pci goodies ... */
...@@ -2651,6 +2674,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2651,6 +2674,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
INFO (dev, "version: %s\n", bufp); INFO (dev, "version: %s\n", bufp);
the_controller = dev; the_controller = dev;
device_register (&dev->gadget.dev);
device_create_file (&pdev->dev, &dev_attr_registers); device_create_file (&pdev->dev, &dev_attr_registers);
return 0; return 0;
......
...@@ -389,6 +389,7 @@ struct net2280_ep_regs { /* [11.9] */ ...@@ -389,6 +389,7 @@ struct net2280_ep_regs { /* [11.9] */
u32 ep_rsp; u32 ep_rsp;
#define SET_NAK_OUT_PACKETS 15 #define SET_NAK_OUT_PACKETS 15
#define SET_EP_HIDE_STATUS_PHASE 14 #define SET_EP_HIDE_STATUS_PHASE 14
#define SET_EP_FORCE_CRC_ERROR 13
#define SET_INTERRUPT_MODE 12 #define SET_INTERRUPT_MODE 12
#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11 #define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
#define SET_NAK_OUT_PACKETS_MODE 10 #define SET_NAK_OUT_PACKETS_MODE 10
...@@ -396,6 +397,7 @@ struct net2280_ep_regs { /* [11.9] */ ...@@ -396,6 +397,7 @@ struct net2280_ep_regs { /* [11.9] */
#define SET_ENDPOINT_HALT 8 #define SET_ENDPOINT_HALT 8
#define CLEAR_NAK_OUT_PACKETS 7 #define CLEAR_NAK_OUT_PACKETS 7
#define CLEAR_EP_HIDE_STATUS_PHASE 6 #define CLEAR_EP_HIDE_STATUS_PHASE 6
#define CLEAR_EP_FORCE_CRC_ERROR 5
#define CLEAR_INTERRUPT_MODE 4 #define CLEAR_INTERRUPT_MODE 4
#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3 #define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
#define CLEAR_NAK_OUT_PACKETS_MODE 2 #define CLEAR_NAK_OUT_PACKETS_MODE 2
...@@ -476,6 +478,9 @@ set_idx_reg (struct net2280_regs *regs, u32 index, u32 value) ...@@ -476,6 +478,9 @@ set_idx_reg (struct net2280_regs *regs, u32 index, u32 value)
#define REG_CHIPREV 0x03 /* in bcd */ #define REG_CHIPREV 0x03 /* in bcd */
#define REG_HS_NAK_RATE 0x0a /* NAK per N uframes */ #define REG_HS_NAK_RATE 0x0a /* NAK per N uframes */
#define CHIPREV_1 0x0100
#define CHIPREV_1A 0x0110
#ifdef __KERNEL__ #ifdef __KERNEL__
/* ep a-f highspeed and fullspeed maxpacket, addresses /* ep a-f highspeed and fullspeed maxpacket, addresses
...@@ -529,24 +534,6 @@ static inline void allow_status (struct net2280_ep *ep) ...@@ -529,24 +534,6 @@ static inline void allow_status (struct net2280_ep *ep)
ep->stopped = 1; ep->stopped = 1;
} }
static inline void set_halt (struct net2280_ep *ep)
{
/* ep0 and bulk/intr endpoints */
writel ( (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
/* set NAK_OUT for erratum 0114 */
| (1 << SET_NAK_OUT_PACKETS)
| (1 << SET_ENDPOINT_HALT)
, &ep->regs->ep_rsp);
}
static inline void clear_halt (struct net2280_ep *ep)
{
/* bulk/intr endpoints */
writel ( (1 << CLEAR_ENDPOINT_HALT)
| (1 << CLEAR_ENDPOINT_TOGGLE)
, &ep->regs->ep_rsp);
}
/* count (<= 4) bytes in the next fifo write will be valid */ /* count (<= 4) bytes in the next fifo write will be valid */
static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count) static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count)
{ {
...@@ -589,6 +576,28 @@ struct net2280 { ...@@ -589,6 +576,28 @@ struct net2280 {
// statistics... // statistics...
}; };
static inline void set_halt (struct net2280_ep *ep)
{
/* ep0 and bulk/intr endpoints */
writel ( (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
/* set NAK_OUT for erratum 0114 */
| ((ep->dev->chiprev == CHIPREV_1) << SET_NAK_OUT_PACKETS)
| (1 << SET_ENDPOINT_HALT)
, &ep->regs->ep_rsp);
}
static inline void clear_halt (struct net2280_ep *ep)
{
/* ep0 and bulk/intr endpoints */
writel ( (1 << CLEAR_ENDPOINT_HALT)
| (1 << CLEAR_ENDPOINT_TOGGLE)
/* unless the gadget driver left a short packet in the
* fifo, this reverses the erratum 0114 workaround.
*/
| ((ep->dev->chiprev == CHIPREV_1) << CLEAR_NAK_OUT_PACKETS)
, &ep->regs->ep_rsp);
}
#ifdef USE_RDK_LEDS #ifdef USE_RDK_LEDS
static inline void net2280_led_init (struct net2280 *dev) static inline void net2280_led_init (struct net2280 *dev)
......
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