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 @@
/*
* Copyright (C) 2003 David Brownell
* Copyright (C) 2003 NetChip Technologies
*
* 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
......@@ -77,7 +78,7 @@
#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 EP_DONTUSE 13 /* nonzero */
......@@ -1345,11 +1346,12 @@ show_registers (struct device *_dev, char *buf)
s = "(none)";
/* 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"
"pci irqenb0 %02x irqenb1 %08x "
"irqstat0 %04x irqstat1 %08x\n",
driver_name,
driver_name, dev->chiprev,
readl (&dev->regs->devinit),
readl (&dev->regs->fifoctl),
s,
......@@ -1394,16 +1396,33 @@ show_registers (struct device *_dev, char *buf)
continue;
t1 = readl (&ep->regs->ep_cfg);
t2 = readl (&ep->regs->ep_rsp) & 0xff;
t = snprintf (next, size,
"%s\tcfg %05x rsp %02x enb %02x ",
ep->ep.name, t1,
readl (&ep->regs->ep_rsp) & 0xff,
"%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"
"irqenb %02x\n",
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));
size -= t;
next += t;
t = snprintf (next, size,
"stat %08x avail %04x "
"\tstat %08x avail %04x "
"(ep%d%s-%s)%s\n",
readl (&ep->regs->ep_stat),
readl (&ep->regs->ep_avail),
......@@ -1797,6 +1816,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
dev->ep [i].irqs = 0;
/* hook up the driver ... */
driver->driver.bus = 0;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
retval = driver->bind (&dev->gadget);
......@@ -1808,10 +1828,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
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_queues);
......@@ -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_queues);
// FIXME
// device_unregister()
// driver_unregister (&driver->driver);
DEBUG (dev, "unregistered driver '%s'\n", driver->driver.name);
return 0;
}
......@@ -2050,9 +2062,9 @@ static void handle_ep_small (struct net2280_ep *ep)
/* maybe advance queue to next request */
if (ep->num == 0) {
/* FIXME need mechanism (request flag?) so control OUT
* can decide to stall ep0 after that done() returns,
* from non-irq context
/* NOTE: net2280 could let gadget driver start the
* status stage later. since not all controllers let
* them control that, the api doesn't (yet) allow it.
*/
if (!ep->stopped)
allow_status (ep);
......@@ -2175,6 +2187,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
/* watch control traffic at the token level, and force
* 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;
if (ep->is_in)
......@@ -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 */
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));
if (dev->enabled)
pci_disable_device (pdev);
device_unregister (&dev->gadget.dev);
device_remove_file (&pdev->dev, &dev_attr_registers);
pci_set_drvdata (pdev, 0);
INFO (dev, "unbind from pci %s\n", pci_name(pdev));
INFO (dev, "unbind\n");
kfree (dev);
the_controller = 0;
}
......@@ -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.
*/
if (the_controller) {
WARN (the_controller, "ignoring %s\n", pci_name(pdev));
dev_warn (&pdev->dev, "ignoring\n");
return -EBUSY;
}
......@@ -2535,9 +2556,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
dev->pdev = pdev;
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.dma_mask = pdev->dev.dma_mask;
dev->gadget.dev.release = gadget_release;
dev->gadget.name = driver_name;
/* now all the pci goodies ... */
......@@ -2651,6 +2674,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
INFO (dev, "version: %s\n", bufp);
the_controller = dev;
device_register (&dev->gadget.dev);
device_create_file (&pdev->dev, &dev_attr_registers);
return 0;
......
......@@ -389,6 +389,7 @@ struct net2280_ep_regs { /* [11.9] */
u32 ep_rsp;
#define SET_NAK_OUT_PACKETS 15
#define SET_EP_HIDE_STATUS_PHASE 14
#define SET_EP_FORCE_CRC_ERROR 13
#define SET_INTERRUPT_MODE 12
#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
#define SET_NAK_OUT_PACKETS_MODE 10
......@@ -396,6 +397,7 @@ struct net2280_ep_regs { /* [11.9] */
#define SET_ENDPOINT_HALT 8
#define CLEAR_NAK_OUT_PACKETS 7
#define CLEAR_EP_HIDE_STATUS_PHASE 6
#define CLEAR_EP_FORCE_CRC_ERROR 5
#define CLEAR_INTERRUPT_MODE 4
#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
#define CLEAR_NAK_OUT_PACKETS_MODE 2
......@@ -476,6 +478,9 @@ set_idx_reg (struct net2280_regs *regs, u32 index, u32 value)
#define REG_CHIPREV 0x03 /* in bcd */
#define REG_HS_NAK_RATE 0x0a /* NAK per N uframes */
#define CHIPREV_1 0x0100
#define CHIPREV_1A 0x0110
#ifdef __KERNEL__
/* ep a-f highspeed and fullspeed maxpacket, addresses
......@@ -529,24 +534,6 @@ static inline void allow_status (struct net2280_ep *ep)
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 */
static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count)
{
......@@ -589,6 +576,28 @@ struct net2280 {
// 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
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