Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (34 commits)
  USB Storage: remove duplicate Nokia entry in unusual_devs.h
  [PATCH] bluetooth: add support for another Kensington dongle
  [PATCH] usb serial: add support for Novatel S720/U720 CDMA/EV-DO modems
  [PATCH] USB: Nokia E70 is an unusual device
  USB: fix to usbfs_snoop logging of user defined control urbs
  USB: at91_udc: Additional checks
  USB: at91_udc: Cleanup variables after failure in usb_gadget_register_driver()
  USB: at91_udc: allow drivers that support high speed
  USB: u132-hcd/ftdi-elan: add support for Option GT 3G Quad card
  USB: at91_udc, misc fixes
  USB: at91 udc, support at91sam926x addresses
  USB: OHCI support for PNX8550
  USB: ohci handles hardware faults during root port resets
  USB: ohci at91 warning fix
  USB: ohci whitespace/comment fixups
  USB: MAINTAINERS update, EHCI and OHCI
  USB: gadget driver unbind() is optional; section fixes; misc
  UHCI: module parameter to ignore overcurrent changes
  USB: Nokia E70 is an unusual device
  USB AUERSWALD: replace kmalloc+memset with kzalloc
  ...
This commit is contained in:
Linus Torvalds 2006-12-21 00:01:06 -08:00
commit fb34d203d0
55 changed files with 1216 additions and 953 deletions

View File

@ -1714,6 +1714,14 @@ and is between 256 and 4096 characters. It is defined in the file
uart6850= [HW,OSS]
Format: <io>,<irq>
uhci-hcd.ignore_oc=
[USB] Ignore overcurrent events (default N).
Some badly-designed motherboards generate lots of
bogus events, for ports that aren't wired to
anything. Set this parameter to avoid log spamming.
Note that genuine overcurrent events won't be
reported either.
usbhid.mousepoll=
[USBHID] The interval which mice are to be polled at.

View File

@ -3130,7 +3130,7 @@ USB EHCI DRIVER
P: David Brownell
M: dbrownell@users.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
S: Odd Fixes
USB ET61X[12]51 DRIVER
P: Luca Risolia
@ -3183,11 +3183,11 @@ S: Maintained
W: http://www.one-eyed-alien.net/~mdharm/linux-usb/
USB OHCI DRIVER
P: Roman Weissgaerber
M: weissg@vienna.at
P: David Brownell
M: dbrownell@users.sourceforge.net
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
S: Odd Fixes
USB OPTION-CARD DRIVER
P: Matthias Urlichs

View File

@ -126,6 +126,7 @@ static struct usb_device_id blacklist_ids[] = {
/* Kensington Bluetooth USB adapter */
{ USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET },
{ USB_DEVICE(0x047d, 0x105e), .driver_info = HCI_WRONG_SCO_MTU },
/* ISSC Bluetooth Adapter v3.1 */
{ USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },

View File

@ -130,7 +130,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
struct usblp {
struct usb_device *dev; /* USB device */
struct semaphore sem; /* locks this struct, especially "dev" */
struct mutex mut; /* locks this struct, especially "dev" */
char *writebuf; /* write transfer_buffer */
char *readbuf; /* read transfer_buffer */
char *statusbuf; /* status transfer_buffer */
@ -465,7 +465,7 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int twoints[2];
int retval = 0;
down (&usblp->sem);
mutex_lock (&usblp->mut);
if (!usblp->present) {
retval = -ENODEV;
goto done;
@ -644,14 +644,14 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
done:
up (&usblp->sem);
mutex_unlock (&usblp->mut);
return retval;
}
static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
int timeout, rv, err = 0, transfer_length = 0;
int timeout, intr, rv, err = 0, transfer_length = 0;
size_t writecount = 0;
while (writecount < count) {
@ -668,14 +668,16 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
if (rv < 0)
return writecount ? writecount : -EINTR;
}
down (&usblp->sem);
intr = mutex_lock_interruptible (&usblp->mut);
if (intr)
return writecount ? writecount : -EINTR;
if (!usblp->present) {
up (&usblp->sem);
mutex_unlock (&usblp->mut);
return -ENODEV;
}
if (usblp->sleeping) {
up (&usblp->sem);
mutex_unlock (&usblp->mut);
return writecount ? writecount : -ENODEV;
}
@ -687,10 +689,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
err = usblp->writeurb->status;
} else
err = usblp_check_status(usblp, err);
up (&usblp->sem);
mutex_unlock (&usblp->mut);
/* if the fault was due to disconnect, let khubd's
* call to usblp_disconnect() grab usblp->sem ...
* call to usblp_disconnect() grab usblp->mut ...
*/
schedule ();
continue;
@ -702,7 +704,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
*/
writecount += transfer_length;
if (writecount == count) {
up(&usblp->sem);
mutex_unlock(&usblp->mut);
break;
}
@ -714,7 +716,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
if (copy_from_user(usblp->writeurb->transfer_buffer,
buffer + writecount, transfer_length)) {
up(&usblp->sem);
mutex_unlock(&usblp->mut);
return writecount ? writecount : -EFAULT;
}
@ -727,10 +729,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
count = -EIO;
else
count = writecount ? writecount : -ENOMEM;
up (&usblp->sem);
mutex_unlock (&usblp->mut);
break;
}
up (&usblp->sem);
mutex_unlock (&usblp->mut);
}
return count;
@ -739,12 +741,14 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
int rv;
int rv, intr;
if (!usblp->bidir)
return -EINVAL;
down (&usblp->sem);
intr = mutex_lock_interruptible (&usblp->mut);
if (intr)
return -EINTR;
if (!usblp->present) {
count = -ENODEV;
goto done;
@ -757,9 +761,9 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
count = -EAGAIN;
goto done;
}
up(&usblp->sem);
mutex_unlock(&usblp->mut);
rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present);
down(&usblp->sem);
mutex_lock(&usblp->mut);
if (rv < 0) {
count = -EINTR;
goto done;
@ -807,7 +811,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
}
done:
up (&usblp->sem);
mutex_unlock (&usblp->mut);
return count;
}
@ -886,7 +890,7 @@ static int usblp_probe(struct usb_interface *intf,
goto abort;
}
usblp->dev = dev;
init_MUTEX (&usblp->sem);
mutex_init (&usblp->mut);
init_waitqueue_head(&usblp->wait);
usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
usblp->intf = intf;
@ -1178,7 +1182,7 @@ static void usblp_disconnect(struct usb_interface *intf)
device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
mutex_lock (&usblp_mutex);
down (&usblp->sem);
mutex_lock (&usblp->mut);
usblp->present = 0;
usb_set_intfdata (intf, NULL);
@ -1187,7 +1191,7 @@ static void usblp_disconnect(struct usb_interface *intf)
usblp->writebuf, usblp->writeurb->transfer_dma);
usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
usblp->readbuf, usblp->readurb->transfer_dma);
up (&usblp->sem);
mutex_unlock (&usblp->mut);
if (!usblp->used)
usblp_cleanup (usblp);
@ -1200,11 +1204,11 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
/* this races against normal access and open */
mutex_lock (&usblp_mutex);
down (&usblp->sem);
mutex_lock (&usblp->mut);
/* we take no more IO */
usblp->sleeping = 1;
usblp_unlink_urbs(usblp);
up (&usblp->sem);
mutex_unlock (&usblp->mut);
mutex_unlock (&usblp_mutex);
return 0;
@ -1216,12 +1220,12 @@ static int usblp_resume (struct usb_interface *intf)
int r;
mutex_lock (&usblp_mutex);
down (&usblp->sem);
mutex_lock (&usblp->mut);
usblp->sleeping = 0;
r = handle_bidir (usblp);
up (&usblp->sem);
mutex_unlock (&usblp->mut);
mutex_unlock (&usblp_mutex);
return r;

View File

@ -962,7 +962,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
kfree(dr);
return -EFAULT;
}
snoop(&ps->dev->dev, "control urb\n");
snoop(&ps->dev->dev, "control urb: bRequest=%02x "
"bRrequestType=%02x wValue=%04x "
"wIndex=%04x wLength=%04x\n",
dr->bRequest, dr->bRequestType, dr->wValue,
dr->wIndex, dr->wLength);
break;
case USBDEVFS_URB_TYPE_BULK:

View File

@ -43,14 +43,16 @@
#include <linux/usb_gadget.h>
#include <asm/byteorder.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach-types.h>
#include <asm/arch/hardware.h>
#include <asm/arch/gpio.h>
#include <asm/arch/board.h>
#include <asm/arch/cpu.h>
#include <asm/arch/at91sam9261_matrix.h>
#include "at91_udc.h"
@ -78,27 +80,11 @@
static const char driver_name [] = "at91_udc";
static const char ep0name[] = "ep0";
/*-------------------------------------------------------------------------*/
/*
* Read from a UDP register.
*/
static inline unsigned long at91_udp_read(unsigned int reg)
{
void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP;
return __raw_readl(udp_base + reg);
}
/*
* Write to a UDP register.
*/
static inline void at91_udp_write(unsigned int reg, unsigned long value)
{
void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP;
__raw_writel(value, udp_base + reg);
}
#define at91_udp_read(dev, reg) \
__raw_readl((dev)->udp_baseaddr + (reg))
#define at91_udp_write(dev, reg, val) \
__raw_writel((val), (dev)->udp_baseaddr + (reg))
/*-------------------------------------------------------------------------*/
@ -210,13 +196,13 @@ static int proc_udc_show(struct seq_file *s, void *unused)
return 0;
}
tmp = at91_udp_read(AT91_UDP_FRM_NUM);
tmp = at91_udp_read(udc, AT91_UDP_FRM_NUM);
seq_printf(s, "frame %05x:%s%s frame=%d\n", tmp,
(tmp & AT91_UDP_FRM_OK) ? " ok" : "",
(tmp & AT91_UDP_FRM_ERR) ? " err" : "",
(tmp & AT91_UDP_NUM));
tmp = at91_udp_read(AT91_UDP_GLB_STAT);
tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
seq_printf(s, "glbstate %02x:%s" FOURBITS "\n", tmp,
(tmp & AT91_UDP_RMWUPE) ? " rmwupe" : "",
(tmp & AT91_UDP_RSMINPR) ? " rsminpr" : "",
@ -224,13 +210,13 @@ static int proc_udc_show(struct seq_file *s, void *unused)
(tmp & AT91_UDP_CONFG) ? " confg" : "",
(tmp & AT91_UDP_FADDEN) ? " fadden" : "");
tmp = at91_udp_read(AT91_UDP_FADDR);
tmp = at91_udp_read(udc, AT91_UDP_FADDR);
seq_printf(s, "faddr %03x:%s fadd=%d\n", tmp,
(tmp & AT91_UDP_FEN) ? " fen" : "",
(tmp & AT91_UDP_FADD));
proc_irq_show(s, "imr ", at91_udp_read(AT91_UDP_IMR));
proc_irq_show(s, "isr ", at91_udp_read(AT91_UDP_ISR));
proc_irq_show(s, "imr ", at91_udp_read(udc, AT91_UDP_IMR));
proc_irq_show(s, "isr ", at91_udp_read(udc, AT91_UDP_ISR));
if (udc->enabled && udc->vbus) {
proc_ep_show(s, &udc->ep[0]);
@ -286,6 +272,7 @@ static inline void remove_debug_file(struct at91_udc *udc) {}
static void done(struct at91_ep *ep, struct at91_request *req, int status)
{
unsigned stopped = ep->stopped;
struct at91_udc *udc = ep->udc;
list_del_init(&req->queue);
if (req->req.status == -EINPROGRESS)
@ -301,7 +288,7 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status)
/* ep0 is always ready; other endpoints need a non-empty queue */
if (list_empty(&ep->queue) && ep->int_mask != (1 << 0))
at91_udp_write(AT91_UDP_IDR, ep->int_mask);
at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask);
}
/*-------------------------------------------------------------------------*/
@ -554,8 +541,8 @@ static int at91_ep_enable(struct usb_ep *_ep,
* reset/init endpoint fifo. NOTE: leaves fifo_bank alone,
* since endpoint resets don't reset hw pingpong state.
*/
at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
at91_udp_write(AT91_UDP_RST_EP, 0);
at91_udp_write(dev, AT91_UDP_RST_EP, ep->int_mask);
at91_udp_write(dev, AT91_UDP_RST_EP, 0);
local_irq_restore(flags);
return 0;
@ -564,6 +551,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
static int at91_ep_disable (struct usb_ep * _ep)
{
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
struct at91_udc *udc = ep->udc;
unsigned long flags;
if (ep == &ep->udc->ep[0])
@ -579,8 +567,8 @@ static int at91_ep_disable (struct usb_ep * _ep)
/* reset fifos and endpoint */
if (ep->udc->clocked) {
at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
at91_udp_write(AT91_UDP_RST_EP, 0);
at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
at91_udp_write(udc, AT91_UDP_RST_EP, 0);
__raw_writel(0, ep->creg);
}
@ -695,10 +683,10 @@ static int at91_ep_queue(struct usb_ep *_ep,
* reconfigures the endpoints.
*/
if (dev->wait_for_config_ack) {
tmp = at91_udp_read(AT91_UDP_GLB_STAT);
tmp = at91_udp_read(dev, AT91_UDP_GLB_STAT);
tmp ^= AT91_UDP_CONFG;
VDBG("toggle config\n");
at91_udp_write(AT91_UDP_GLB_STAT, tmp);
at91_udp_write(dev, AT91_UDP_GLB_STAT, tmp);
}
if (req->req.length == 0) {
ep0_in_status:
@ -727,7 +715,7 @@ static int at91_ep_queue(struct usb_ep *_ep,
if (req && !status) {
list_add_tail (&req->queue, &ep->queue);
at91_udp_write(AT91_UDP_IER, ep->int_mask);
at91_udp_write(dev, AT91_UDP_IER, ep->int_mask);
}
done:
local_irq_restore(flags);
@ -758,6 +746,7 @@ static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
static int at91_ep_set_halt(struct usb_ep *_ep, int value)
{
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
struct at91_udc *udc = ep->udc;
u32 __iomem *creg;
u32 csr;
unsigned long flags;
@ -785,8 +774,8 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value)
csr |= AT91_UDP_FORCESTALL;
VDBG("halt %s\n", ep->ep.name);
} else {
at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
at91_udp_write(AT91_UDP_RST_EP, 0);
at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
at91_udp_write(udc, AT91_UDP_RST_EP, 0);
csr &= ~AT91_UDP_FORCESTALL;
}
__raw_writel(csr, creg);
@ -813,9 +802,11 @@ static struct usb_ep_ops at91_ep_ops = {
static int at91_get_frame(struct usb_gadget *gadget)
{
struct at91_udc *udc = to_udc(gadget);
if (!to_udc(gadget)->clocked)
return -EINVAL;
return at91_udp_read(AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
return at91_udp_read(udc, AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
}
static int at91_wakeup(struct usb_gadget *gadget)
@ -833,11 +824,11 @@ static int at91_wakeup(struct usb_gadget *gadget)
/* NOTE: some "early versions" handle ESR differently ... */
glbstate = at91_udp_read(AT91_UDP_GLB_STAT);
glbstate = at91_udp_read(udc, AT91_UDP_GLB_STAT);
if (!(glbstate & AT91_UDP_ESR))
goto done;
glbstate |= AT91_UDP_ESR;
at91_udp_write(AT91_UDP_GLB_STAT, glbstate);
at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate);
done:
local_irq_restore(flags);
@ -861,6 +852,7 @@ static void udc_reinit(struct at91_udc *udc)
ep->stopped = 0;
ep->fifo_bank = 0;
ep->ep.maxpacket = ep->maxpacket;
ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
// initialiser une queue par endpoint
INIT_LIST_HEAD(&ep->queue);
}
@ -915,14 +907,41 @@ static void pullup(struct at91_udc *udc, int is_on)
if (!udc->enabled || !udc->vbus)
is_on = 0;
DBG("%sactive\n", is_on ? "" : "in");
if (is_on) {
clk_on(udc);
at91_udp_write(AT91_UDP_TXVC, 0);
at91_set_gpio_value(udc->board.pullup_pin, 1);
} else {
at91_udp_write(udc, AT91_UDP_TXVC, 0);
if (cpu_is_at91rm9200())
at91_set_gpio_value(udc->board.pullup_pin, 1);
else if (cpu_is_at91sam9260()) {
u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
txvc |= AT91_UDP_TXVC_PUON;
at91_udp_write(udc, AT91_UDP_TXVC, txvc);
} else if (cpu_is_at91sam9261()) {
u32 usbpucr;
usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
usbpucr |= AT91_MATRIX_USBPUCR_PUON;
at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
}
} else {
stop_activity(udc);
at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
at91_set_gpio_value(udc->board.pullup_pin, 0);
at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
if (cpu_is_at91rm9200())
at91_set_gpio_value(udc->board.pullup_pin, 0);
else if (cpu_is_at91sam9260()) {
u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
txvc &= ~AT91_UDP_TXVC_PUON;
at91_udp_write(udc, AT91_UDP_TXVC, txvc);
} else if (cpu_is_at91sam9261()) {
u32 usbpucr;
usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
}
clk_off(udc);
}
}
@ -936,7 +955,10 @@ static int at91_vbus_session(struct usb_gadget *gadget, int is_active)
// VDBG("vbus %s\n", is_active ? "on" : "off");
local_irq_save(flags);
udc->vbus = (is_active != 0);
pullup(udc, is_active);
if (udc->driver)
pullup(udc, is_active);
else
pullup(udc, 0);
local_irq_restore(flags);
return 0;
}
@ -1086,7 +1108,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_SET_CONFIGURATION:
tmp = at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
if (pkt.r.wValue)
udc->wait_for_config_ack = (tmp == 0);
else
@ -1103,7 +1125,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_GET_STATUS:
tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
if (at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP);
PACKET("get device status\n");
__raw_writeb(tmp, dreg);
@ -1114,17 +1136,17 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
| USB_REQ_SET_FEATURE:
if (w_value != USB_DEVICE_REMOTE_WAKEUP)
goto stall;
tmp = at91_udp_read(AT91_UDP_GLB_STAT);
tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp |= AT91_UDP_ESR;
at91_udp_write(AT91_UDP_GLB_STAT, tmp);
at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
goto succeed;
case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_CLEAR_FEATURE:
if (w_value != USB_DEVICE_REMOTE_WAKEUP)
goto stall;
tmp = at91_udp_read(AT91_UDP_GLB_STAT);
tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp &= ~AT91_UDP_ESR;
at91_udp_write(AT91_UDP_GLB_STAT, tmp);
at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
goto succeed;
/*
@ -1206,8 +1228,8 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
} else if (ep->is_in)
goto stall;
at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
at91_udp_write(AT91_UDP_RST_EP, 0);
at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
at91_udp_write(udc, AT91_UDP_RST_EP, 0);
tmp = __raw_readl(ep->creg);
tmp |= CLR_FX;
tmp &= ~(SET_FX | AT91_UDP_FORCESTALL);
@ -1222,7 +1244,10 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
#undef w_length
/* pass request up to the gadget driver */
status = udc->driver->setup(&udc->gadget, &pkt.r);
if (udc->driver)
status = udc->driver->setup(&udc->gadget, &pkt.r);
else
status = -ENODEV;
if (status < 0) {
stall:
VDBG("req %02x.%02x protocol STALL; stat %d\n",
@ -1300,13 +1325,13 @@ static void handle_ep0(struct at91_udc *udc)
if (udc->wait_for_addr_ack) {
u32 tmp;
at91_udp_write(AT91_UDP_FADDR,
at91_udp_write(udc, AT91_UDP_FADDR,
AT91_UDP_FEN | udc->addr);
tmp = at91_udp_read(AT91_UDP_GLB_STAT);
tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp &= ~AT91_UDP_FADDEN;
if (udc->addr)
tmp |= AT91_UDP_FADDEN;
at91_udp_write(AT91_UDP_GLB_STAT, tmp);
at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
udc->wait_for_addr_ack = 0;
VDBG("address %d\n", udc->addr);
@ -1374,28 +1399,28 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
while (rescans--) {
u32 status;
status = at91_udp_read(AT91_UDP_ISR)
& at91_udp_read(AT91_UDP_IMR);
status = at91_udp_read(udc, AT91_UDP_ISR)
& at91_udp_read(udc, AT91_UDP_IMR);
if (!status)
break;
/* USB reset irq: not maskable */
if (status & AT91_UDP_ENDBUSRES) {
at91_udp_write(AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
at91_udp_write(AT91_UDP_IER, MINIMUS_INTERRUPTUS);
at91_udp_write(udc, AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
at91_udp_write(udc, AT91_UDP_IER, MINIMUS_INTERRUPTUS);
/* Atmel code clears this irq twice */
at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
VDBG("end bus reset\n");
udc->addr = 0;
stop_activity(udc);
/* enable ep0 */
at91_udp_write(AT91_UDP_CSR(0),
at91_udp_write(udc, AT91_UDP_CSR(0),
AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
udc->gadget.speed = USB_SPEED_FULL;
udc->suspended = 0;
at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0));
at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_EP(0));
/*
* NOTE: this driver keeps clocks off unless the
@ -1406,9 +1431,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
/* host initiated suspend (3+ms bus idle) */
} else if (status & AT91_UDP_RXSUSP) {
at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXSUSP);
at91_udp_write(AT91_UDP_IER, AT91_UDP_RXRSM);
at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXSUSP);
at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP);
at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXRSM);
at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP);
// VDBG("bus suspend\n");
if (udc->suspended)
continue;
@ -1425,9 +1450,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
/* host initiated resume */
} else if (status & AT91_UDP_RXRSM) {
at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXRSM);
at91_udp_write(AT91_UDP_IER, AT91_UDP_RXSUSP);
at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXRSM);
at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXSUSP);
at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
// VDBG("bus resume\n");
if (!udc->suspended)
continue;
@ -1485,8 +1510,6 @@ static struct at91_udc controller = {
},
.udc = &controller,
.maxpacket = 8,
.creg = (void __iomem *)(AT91_VA_BASE_UDP
+ AT91_UDP_CSR(0)),
.int_mask = 1 << 0,
},
.ep[1] = {
@ -1497,8 +1520,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 64,
.creg = (void __iomem *)(AT91_VA_BASE_UDP
+ AT91_UDP_CSR(1)),
.int_mask = 1 << 1,
},
.ep[2] = {
@ -1509,8 +1530,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 64,
.creg = (void __iomem *)(AT91_VA_BASE_UDP
+ AT91_UDP_CSR(2)),
.int_mask = 1 << 2,
},
.ep[3] = {
@ -1521,8 +1540,6 @@ static struct at91_udc controller = {
},
.udc = &controller,
.maxpacket = 8,
.creg = (void __iomem *)(AT91_VA_BASE_UDP
+ AT91_UDP_CSR(3)),
.int_mask = 1 << 3,
},
.ep[4] = {
@ -1533,8 +1550,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 256,
.creg = (void __iomem *)(AT91_VA_BASE_UDP
+ AT91_UDP_CSR(4)),
.int_mask = 1 << 4,
},
.ep[5] = {
@ -1545,8 +1560,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 256,
.creg = (void __iomem *)(AT91_VA_BASE_UDP
+ AT91_UDP_CSR(5)),
.int_mask = 1 << 5,
},
/* ep6 and ep7 are also reserved (custom silicon might use them) */
@ -1572,9 +1585,8 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
int retval;
if (!driver
|| driver->speed != USB_SPEED_FULL
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
|| !driver->unbind
|| !driver->setup) {
DBG("bad parameter.\n");
return -EINVAL;
@ -1595,6 +1607,10 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (retval) {
DBG("driver->bind() returned %d\n", retval);
udc->driver = NULL;
udc->gadget.dev.driver = NULL;
udc->gadget.dev.driver_data = NULL;
udc->enabled = 0;
udc->selfpowered = 0;
return retval;
}
@ -1611,12 +1627,12 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
{
struct at91_udc *udc = &controller;
if (!driver || driver != udc->driver)
if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
local_irq_disable();
udc->enabled = 0;
at91_udp_write(AT91_UDP_IDR, ~0);
at91_udp_write(udc, AT91_UDP_IDR, ~0);
pullup(udc, 0);
local_irq_enable();
@ -1641,6 +1657,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct at91_udc *udc;
int retval;
struct resource *res;
if (!dev->platform_data) {
/* small (so we copy it) but critical! */
@ -1658,7 +1675,13 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
return -ENODEV;
}
if (!request_mem_region(AT91RM9200_BASE_UDP, SZ_16K, driver_name)) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENXIO;
if (!request_mem_region(res->start,
res->end - res->start + 1,
driver_name)) {
DBG("someone's using UDC memory\n");
return -EBUSY;
}
@ -1668,15 +1691,23 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
udc->gadget.dev.parent = dev;
udc->board = *(struct at91_udc_data *) dev->platform_data;
udc->pdev = pdev;
udc_reinit(udc);
udc->enabled = 0;
udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
if (!udc->udp_baseaddr) {
release_mem_region(res->start, res->end - res->start + 1);
return -ENOMEM;
}
udc_reinit(udc);
/* get interface and function clocks */
udc->iclk = clk_get(dev, "udc_clk");
udc->fclk = clk_get(dev, "udpck");
if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
DBG("clocks missing\n");
return -ENODEV;
retval = -ENODEV;
goto fail0;
}
retval = device_register(&udc->gadget.dev);
@ -1685,8 +1716,10 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
/* don't do anything until we have both gadget driver and VBUS */
clk_enable(udc->iclk);
at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
at91_udp_write(AT91_UDP_IDR, 0xffffffff);
at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
/* Clear all pending interrupts - UDP may be used by bootloader. */
at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
clk_disable(udc->iclk);
/* request UDC and maybe VBUS irqs */
@ -1698,6 +1731,11 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
goto fail1;
}
if (udc->board.vbus_pin > 0) {
/*
* Get the initial state of VBUS - we cannot expect
* a pending interrupt.
*/
udc->vbus = at91_get_gpio_value(udc->board.vbus_pin);
if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
IRQF_DISABLED, driver_name, udc)) {
DBG("request vbus irq %d failed\n",
@ -1720,7 +1758,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
fail1:
device_unregister(&udc->gadget.dev);
fail0:
release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
release_mem_region(res->start, res->end - res->start + 1);
DBG("%s probe failed, %d\n", driver_name, retval);
return retval;
}
@ -1728,13 +1766,14 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
static int __devexit at91udc_remove(struct platform_device *pdev)
{
struct at91_udc *udc = platform_get_drvdata(pdev);
struct resource *res;
DBG("remove\n");
pullup(udc, 0);
if (udc->driver)
return -EBUSY;
if (udc->driver != 0)
usb_gadget_unregister_driver(udc->driver);
pullup(udc, 0);
device_init_wakeup(&pdev->dev, 0);
remove_debug_file(udc);
@ -1742,7 +1781,10 @@ static int __devexit at91udc_remove(struct platform_device *pdev)
free_irq(udc->board.vbus_pin, udc);
free_irq(udc->udp_irq, udc);
device_unregister(&udc->gadget.dev);
release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
iounmap(udc->udp_baseaddr);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, res->end - res->start + 1);
clk_put(udc->iclk);
clk_put(udc->fclk);

View File

@ -51,10 +51,10 @@
#define AT91_UDP_EP(n) (1 << (n)) /* Endpoint Interrupt Status */
#define AT91_UDP_RXSUSP (1 << 8) /* USB Suspend Interrupt Status */
#define AT91_UDP_RXRSM (1 << 9) /* USB Resume Interrupt Status */
#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status */
#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status [AT91RM9200 only] */
#define AT91_UDP_SOFINT (1 << 11) /* Start of Frame Interrupt Status */
#define AT91_UDP_ENDBUSRES (1 << 12) /* End of Bus Reset Interrpt Status */
#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status */
#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status [AT91RM9200 only] */
#define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */
#define AT91_UDP_RST_EP 0x28 /* Reset Endpoint Register */
@ -84,7 +84,7 @@
#define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */
#define AT91_UDP_TXVC_TXVDIS (1 << 8) /* Transceiver Disable */
#define AT91_UDP_TXVC_PUON (1 << 9) /* PullUp On [AT91SAM9260 only] */
/*-------------------------------------------------------------------------*/
@ -141,6 +141,7 @@ struct at91_udc {
struct clk *iclk, *fclk;
struct platform_device *pdev;
struct proc_dir_entry *pde;
void __iomem *udp_baseaddr;
int udp_irq;
};

View File

@ -779,7 +779,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
return -EINVAL;
if (dum->driver)
return -EBUSY;
if (!driver->bind || !driver->unbind || !driver->setup
if (!driver->bind || !driver->setup
|| driver->speed == USB_SPEED_UNKNOWN)
return -EINVAL;
@ -837,7 +837,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
err_bind_driver:
driver_unregister (&driver->driver);
err_register:
driver->unbind (&dum->gadget);
if (driver->unbind)
driver->unbind (&dum->gadget);
spin_lock_irq (&dum->lock);
dum->pullup = 0;
set_link_state (dum);
@ -857,7 +858,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!dum)
return -ENODEV;
if (!driver || driver != dum->driver)
if (!driver || driver != dum->driver || !driver->unbind)
return -EINVAL;
dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",

View File

@ -4100,7 +4100,7 @@ static struct usb_gadget_driver fsg_driver = {
#endif
.function = (char *) longname,
.bind = fsg_bind,
.unbind = __exit_p(fsg_unbind),
.unbind = fsg_unbind,
.disconnect = fsg_disconnect,
.setup = fsg_setup,
.suspend = fsg_suspend,

View File

@ -123,7 +123,7 @@ struct gmidi_device {
struct usb_request *req; /* for control responses */
u8 config;
struct usb_ep *in_ep, *out_ep;
struct snd_card *card;
struct snd_card *card;
struct snd_rawmidi *rmidi;
struct snd_rawmidi_substream *in_substream;
struct snd_rawmidi_substream *out_substream;
@ -490,7 +490,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
int status = req->status;
switch (status) {
case 0: /* normal completion */
case 0: /* normal completion */
if (ep == dev->out_ep) {
/* we received stuff.
req is queued again, below */
@ -505,7 +505,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
break;
/* this endpoint is normally active while we're configured */
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
@ -656,7 +656,7 @@ gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags)
case USB_SPEED_LOW: speed = "low"; break;
case USB_SPEED_FULL: speed = "full"; break;
case USB_SPEED_HIGH: speed = "high"; break;
default: speed = "?"; break;
default: speed = "?"; break;
}
dev->config = number;
@ -1308,7 +1308,7 @@ static struct usb_gadget_driver gmidi_driver = {
.speed = USB_SPEED_FULL,
.function = (char *)longname,
.bind = gmidi_bind,
.unbind = __exit_p(gmidi_unbind),
.unbind = gmidi_unbind,
.setup = gmidi_setup,
.disconnect = gmidi_disconnect,
@ -1316,7 +1316,7 @@ static struct usb_gadget_driver gmidi_driver = {
.suspend = gmidi_suspend,
.resume = gmidi_resume,
.driver = {
.driver = {
.name = (char *)shortname,
.owner = THIS_MODULE,
},

View File

@ -1432,7 +1432,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver
|| driver->speed != USB_SPEED_FULL
|| !driver->bind
|| !driver->unbind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@ -1495,7 +1494,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
if (!driver || driver != dev->driver)
if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&dev->lock, flags);
@ -1808,13 +1807,8 @@ static void goku_remove(struct pci_dev *pdev)
struct goku_udc *dev = pci_get_drvdata(pdev);
DBG(dev, "%s\n", __FUNCTION__);
/* start with the driver above us */
if (dev->driver) {
/* should have been done already by driver model core */
WARN(dev, "pci remove, driver '%s' is still registered\n",
dev->driver->driver.name);
usb_gadget_unregister_driver(dev->driver);
}
BUG_ON(dev->driver);
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
remove_proc_entry(proc_node_name, NULL);

View File

@ -422,9 +422,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name);
if (!driver
|| driver->speed != USB_SPEED_FULL
|| !driver->bind
|| !driver->unbind || !driver->disconnect || !driver->setup)
|| driver->speed != USB_SPEED_FULL
|| !driver->bind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
if (!dev)
return -ENODEV;
@ -471,7 +472,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
if (!driver || driver != dev->driver)
if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&dev->lock, flags);
@ -2125,9 +2126,11 @@ static int lh7a40x_udc_remove(struct platform_device *pdev)
DEBUG("%s: %p\n", __FUNCTION__, pdev);
if (dev->driver)
return -EBUSY;
udc_disable(dev);
remove_proc_files();
usb_gadget_unregister_driver(dev->driver);
free_irq(IRQ_USBINTR, dev);

View File

@ -2020,7 +2020,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (!driver
|| driver->speed != USB_SPEED_HIGH
|| !driver->bind
|| !driver->unbind
|| !driver->setup)
return -EINVAL;
if (!dev)
@ -2107,7 +2106,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
if (!driver || driver != dev->driver)
if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave (&dev->lock, flags);
@ -2803,13 +2802,7 @@ static void net2280_remove (struct pci_dev *pdev)
{
struct net2280 *dev = pci_get_drvdata (pdev);
/* start with the driver above us */
if (dev->driver) {
/* should have been done already by driver model core */
WARN (dev, "pci remove, driver '%s' is still registered\n",
dev->driver->driver.name);
usb_gadget_unregister_driver (dev->driver);
}
BUG_ON(dev->driver);
/* then clean up the resources we allocated during probe() */
net2280_led_shutdown (dev);

View File

@ -2043,7 +2043,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
// FIXME if otg, check: driver->is_otg
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
|| !driver->unbind
|| !driver->setup)
return -EINVAL;
@ -2087,9 +2086,11 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
status = otg_set_peripheral(udc->transceiver, &udc->gadget);
if (status < 0) {
ERR("can't bind to transceiver\n");
driver->unbind (&udc->gadget);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
if (driver->unbind) {
driver->unbind (&udc->gadget);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
}
goto done;
}
} else {
@ -2117,7 +2118,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!udc)
return -ENODEV;
if (!driver || driver != udc->driver)
if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
if (machine_is_omap_innovator() || machine_is_omap_osk())
@ -2870,6 +2871,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
if (!udc)
return -ENODEV;
if (udc->driver)
return -EBUSY;
udc->done = &done;

View File

@ -1623,7 +1623,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
|| !driver->unbind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@ -1694,7 +1693,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
if (!driver || driver != dev->driver)
if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
local_irq_disable();
@ -2638,9 +2637,11 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
{
struct pxa2xx_udc *dev = platform_get_drvdata(pdev);
if (dev->driver)
return -EBUSY;
udc_disable(dev);
remove_proc_files();
usb_gadget_unregister_driver(dev->driver);
if (dev->got_irq) {
free_irq(IRQ_USB, dev);

View File

@ -296,7 +296,7 @@ static struct usb_gadget_driver gs_gadget_driver = {
#endif /* CONFIG_USB_GADGET_DUALSPEED */
.function = GS_LONG_NAME,
.bind = gs_bind,
.unbind = __exit_p(gs_unbind),
.unbind = gs_unbind,
.setup = gs_setup,
.disconnect = gs_disconnect,
.driver = {

View File

@ -187,7 +187,6 @@ ohci_at91_start (struct usb_hcd *hcd)
{
struct at91_usbh_data *board = hcd->self.controller->platform_data;
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
struct usb_device *root = hcd->self.root_hub;
int ret;
if ((ret = ohci_init(ohci)) < 0)
@ -221,7 +220,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
*/
.start = ohci_at91_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
.shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources

View File

@ -269,7 +269,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
*/
.start = ohci_au1xxx_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
.shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@ -336,7 +336,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev)
static struct platform_driver ohci_hcd_au1xxx_driver = {
.probe = ohci_hcd_au1xxx_drv_probe,
.remove = ohci_hcd_au1xxx_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_au1xxx_drv_suspend, */
/*.resume = ohci_hcd_au1xxx_drv_resume, */
.driver = {

View File

@ -16,7 +16,7 @@
case PIPE_CONTROL: temp = "ctrl"; break; \
case PIPE_BULK: temp = "bulk"; break; \
case PIPE_INTERRUPT: temp = "intr"; break; \
default: temp = "isoc"; break; \
default: temp = "isoc"; break; \
}; temp;})
#define pipestring(pipe) edstring(usb_pipetype(pipe))
@ -205,13 +205,13 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
(temp & RH_PS_PSSC) ? " PSSC" : "", \
(temp & RH_PS_PESC) ? " PESC" : "", \
(temp & RH_PS_CSC) ? " CSC" : "", \
\
\
(temp & RH_PS_LSDA) ? " LSDA" : "", \
(temp & RH_PS_PPS) ? " PPS" : "", \
(temp & RH_PS_PRS) ? " PRS" : "", \
(temp & RH_PS_POCI) ? " POCI" : "", \
(temp & RH_PS_PSS) ? " PSS" : "", \
\
\
(temp & RH_PS_PES) ? " PES" : "", \
(temp & RH_PS_CCS) ? " CCS" : "" \
);
@ -563,7 +563,7 @@ show_periodic (struct class_device *class_dev, char *buf)
(info & ED_SKIP) ? " K" : "",
(ed->hwHeadP &
cpu_to_hc32(ohci, ED_H)) ?
" H" : "");
" H" : "");
size -= temp;
next += temp;

View File

@ -204,7 +204,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
static struct platform_driver ohci_hcd_ep93xx_driver = {
.probe = ohci_hcd_ep93xx_drv_probe,
.remove = ohci_hcd_ep93xx_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_hcd_ep93xx_drv_suspend,
.resume = ohci_hcd_ep93xx_drv_resume,

View File

@ -3,77 +3,21 @@
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
*
*
* [ Initialisation is based on Linus' ]
* [ uhci code and gregs ohci fragments ]
* [ (C) Copyright 1999 Linus Torvalds ]
* [ (C) Copyright 1999 Gregory P. Smith]
*
*
*
*
* OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller
* interfaces (though some non-x86 Intel chips use it). It supports
* smarter hardware than UHCI. A download link for the spec available
* through the http://www.usb.org website.
*
* History:
*
* 2004/03/24 LH7A404 support (Durgesh Pattamatta & Marc Singer)
* 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net)
* 2003/02/24 show registers in sysfs (Kevin Brosius)
*
* 2002/09/03 get rid of ed hashtables, rework periodic scheduling and
* bandwidth accounting; if debugging, show schedules in driverfs
* 2002/07/19 fixes to management of ED and schedule state.
* 2002/06/09 SA-1111 support (Christopher Hoover)
* 2002/06/01 remember frame when HC won't see EDs any more; use that info
* to fix urb unlink races caused by interrupt latency assumptions;
* minor ED field and function naming updates
* 2002/01/18 package as a patch for 2.5.3; this should match the
* 2.4.17 kernel modulo some bugs being fixed.
*
* 2001/10/18 merge pmac cleanup (Benjamin Herrenschmidt) and bugfixes
* from post-2.4.5 patches.
* 2001/09/20 URB_ZERO_PACKET support; hcca_dma portability, OPTi warning
* 2001/09/07 match PCI PM changes, errnos from Linus' tree
* 2001/05/05 fork 2.4.5 version into "hcd" framework, cleanup, simplify;
* pbook pci quirks gone (please fix pbook pci sw!) (db)
*
* 2001/04/08 Identify version on module load (gb)
* 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
pci_map_single (db)
* 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
* 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam)
*
* 2000/09/26 fixed races in removing the private portion of the urb
* 2000/09/07 disable bulk and control lists when unlinking the last
* endpoint descriptor in order to avoid unrecoverable errors on
* the Lucent chips. (rwc@sgi)
* 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some
* urb unlink probs, indentation fixes
* 2000/08/11 various oops fixes mostly affecting iso and cleanup from
* device unplugs.
* 2000/06/28 use PCI hotplug framework, for better power management
* and for Cardbus support (David Brownell)
* 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling
* when the controller loses power; handle UE; cleanup; ...
*
* v5.2 1999/12/07 URB 3rd preview,
* v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi)
* v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume
* i386: HUB, Keyboard, Mouse, Printer
*
* v4.3 1999/10/27 multiple HCs, bulk_request
* v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes
* v4.1 1999/08/27 Randy Dunlap's - ISO API first impl.
* v4.0 1999/08/18
* v3.0 1999/06/25
* v2.1 1999/05/09 code clean up
* v2.0 1999/05/04
* v1.0 1999/04/27 initial release
*
* This file is licenced under the GPL.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
@ -89,7 +33,7 @@
#include <linux/list.h>
#include <linux/usb.h>
#include <linux/usb/otg.h>
#include <linux/dma-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/reboot.h>
@ -183,11 +127,11 @@ static int ohci_urb_enqueue (
int i, size = 0;
unsigned long flags;
int retval = 0;
#ifdef OHCI_VERBOSE_DEBUG
urb_print (urb, "SUB", usb_pipein (pipe));
#endif
/* every endpoint has a ed, locate and maybe (re)initialize it */
if (! (ed = ed_get (ohci, ep, urb->dev, pipe, urb->interval)))
return -ENOMEM;
@ -232,7 +176,7 @@ static int ohci_urb_enqueue (
memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *));
INIT_LIST_HEAD (&urb_priv->pending);
urb_priv->length = size;
urb_priv->ed = ed;
urb_priv->ed = ed;
/* allocate the TDs (deferring hash chain updates) */
for (i = 0; i < size; i++) {
@ -242,7 +186,7 @@ static int ohci_urb_enqueue (
urb_free_priv (ohci, urb_priv);
return -ENOMEM;
}
}
}
spin_lock_irqsave (&ohci->lock, flags);
@ -313,13 +257,13 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
unsigned long flags;
#ifdef OHCI_VERBOSE_DEBUG
urb_print (urb, "UNLINK", 1);
#endif
#endif
spin_lock_irqsave (&ohci->lock, flags);
if (HC_IS_RUNNING(hcd->state)) {
if (HC_IS_RUNNING(hcd->state)) {
urb_priv_t *urb_priv;
/* Unless an IRQ completed the unlink while it was being
@ -512,11 +456,11 @@ static int ohci_init (struct ohci_hcd *ohci)
/* Start an OHCI controller, set the BUS operational
* resets USB and controller
* enable interrupts
* enable interrupts
*/
static int ohci_run (struct ohci_hcd *ohci)
{
u32 mask, temp;
u32 mask, temp;
int first = ohci->fminterval == 0;
struct usb_hcd *hcd = ohci_to_hcd(ohci);
@ -534,7 +478,7 @@ static int ohci_run (struct ohci_hcd *ohci)
/* also: power/overcurrent flags in roothub.a */
}
/* Reset USB nearly "by the book". RemoteWakeupConnected was
/* Reset USB nearly "by the book". RemoteWakeupConnected was
* saved if boot firmware (BIOS/SMM/...) told us it's connected,
* or if bus glue did the same (e.g. for PCI add-in cards with
* PCI PM support).
@ -765,9 +709,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
dl_done_list (ohci);
spin_unlock (&ohci->lock);
if (HC_IS_RUNNING(hcd->state))
ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
}
/* could track INTR_SO to reduce available PCI/... bandwidth */
/* handle any pending URB/ED unlinks, leaving INTR_SF enabled
@ -778,12 +722,12 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
finish_unlinks (ohci, ohci_frame_no(ohci));
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
&& HC_IS_RUNNING(hcd->state))
ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock);
if (HC_IS_RUNNING(hcd->state)) {
ohci_writel (ohci, ints, &regs->intrstatus);
ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
// flush those writes
(void) ohci_readl (ohci, &ohci->regs->control);
}
@ -794,7 +738,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
static void ohci_stop (struct usb_hcd *hcd)
{
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
ohci_dbg (ohci, "stop %s controller (state 0x%02x)\n",
@ -812,8 +756,8 @@ static void ohci_stop (struct usb_hcd *hcd)
remove_debug_files (ohci);
ohci_mem_cleanup (ohci);
if (ohci->hcca) {
dma_free_coherent (hcd->self.controller,
sizeof *ohci->hcca,
dma_free_coherent (hcd->self.controller,
sizeof *ohci->hcca,
ohci->hcca, ohci->hcca_dma);
ohci->hcca = NULL;
ohci->hcca_dma = 0;
@ -836,7 +780,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
* recycle any "live" eds/tds (and urbs) right away.
* later, khubd disconnect processing will recycle the other state,
* (either as disconnect/reconnect, or maybe someday as a reset).
*/
*/
spin_lock_irq(&ohci->lock);
disable (ohci);
usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
@ -875,11 +819,11 @@ static int ohci_restart (struct ohci_hcd *ohci)
/* empty the interrupt branches */
for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0;
for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0;
/* no EDs to remove */
ohci->ed_rm_list = NULL;
/* empty control and bulk lists */
/* empty control and bulk lists */
ohci->ed_controltail = NULL;
ohci->ed_bulktail = NULL;
@ -941,6 +885,10 @@ MODULE_LICENSE ("GPL");
#include "ohci-au1xxx.c"
#endif
#ifdef CONFIG_PNX8550
#include "ohci-pnx8550.c"
#endif
#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
#include "ohci-ppc-soc.c"
#endif

View File

@ -1,9 +1,9 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
*
*
* This file is licenced under GPL
*/
@ -23,13 +23,13 @@
(temp & RH_PS_PSSC) ? " PSSC" : "", \
(temp & RH_PS_PESC) ? " PESC" : "", \
(temp & RH_PS_CSC) ? " CSC" : "", \
\
\
(temp & RH_PS_LSDA) ? " LSDA" : "", \
(temp & RH_PS_PPS) ? " PPS" : "", \
(temp & RH_PS_PRS) ? " PRS" : "", \
(temp & RH_PS_POCI) ? " POCI" : "", \
(temp & RH_PS_PSS) ? " PSS" : "", \
\
\
(temp & RH_PS_PES) ? " PES" : "", \
(temp & RH_PS_CCS) ? " CCS" : "" \
);
@ -484,7 +484,7 @@ ohci_hub_descriptor (
temp = 0;
if (rh & RH_A_NPS) /* no power switching? */
temp |= 0x0002;
if (rh & RH_A_PSM) /* per-port power switching? */
if (rh & RH_A_PSM) /* per-port power switching? */
temp |= 0x0001;
if (rh & RH_A_NOCP) /* no overcurrent reporting? */
temp |= 0x0010;
@ -555,7 +555,7 @@ static void start_hnp(struct ohci_hcd *ohci);
#define tick_before(t1,t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
/* called from some task, normally khubd */
static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
{
__hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
u32 temp;
@ -570,10 +570,13 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
/* spin until any current reset finishes */
for (;;) {
temp = ohci_readl (ohci, portstat);
/* handle e.g. CardBus eject */
if (temp == ~(u32)0)
return -ESHUTDOWN;
if (!(temp & RH_PS_PRS))
break;
udelay (500);
}
}
if (!(temp & RH_PS_CCS))
break;
@ -586,6 +589,8 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
now = ohci_readl(ohci, &ohci->regs->fmnumber);
} while (tick_before(now, reset_done));
/* caller synchronizes using PRSC */
return 0;
}
static int ohci_hub_control (
@ -702,7 +707,7 @@ static int ohci_hub_control (
&ohci->regs->roothub.portstatus [wIndex]);
break;
case USB_PORT_FEAT_RESET:
root_port_reset (ohci, wIndex);
retval = root_port_reset (ohci, wIndex);
break;
default:
goto error;

View File

@ -38,7 +38,7 @@ static void lh7a404_start_hc(struct platform_device *dev)
CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */
udelay(1000);
USBH_CMDSTATUS = OHCI_HCR;
printk(KERN_DEBUG __FILE__
": Clock to USB host has been enabled \n");
}
@ -89,7 +89,7 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
retval = -EBUSY;
goto err1;
}
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) {
pr_debug("ioremap failed");
@ -174,7 +174,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
*/
.start = ohci_lh7a404_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
.shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@ -242,7 +242,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct platform_device *dev)
static struct platform_driver ohci_hcd_lh7a404_driver = {
.probe = ohci_hcd_lh7a404_drv_probe,
.remove = ohci_hcd_lh7a404_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_lh7a404_drv_suspend, */
/*.resume = ohci_hcd_lh7a404_drv_resume, */
.driver = {

View File

@ -1,24 +1,24 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
*
*
* This file is licenced under the GPL.
*/
/*-------------------------------------------------------------------------*/
/*
* There's basically three types of memory:
* OHCI deals with three types of memory:
* - data used only by the HCD ... kmalloc is fine
* - async and periodic schedules, shared by HC and HCD ... these
* need to use dma_pool or dma_alloc_coherent
* - driver buffers, read/written by HC ... the hcd glue or the
* device driver provides us with dma addresses
*
* There's also PCI "register" data, which is memory mapped.
* No memory seen by this driver is pagable.
* There's also "register" data, which is memory mapped.
* No memory seen by this driver (or any HCD) may be paged out.
*/
/*-------------------------------------------------------------------------*/

View File

@ -447,7 +447,7 @@ static const struct hc_driver ohci_omap_hc_driver = {
.reset = ohci_omap_init,
.start = ohci_omap_start,
.stop = ohci_omap_stop,
.shutdown = ohci_shutdown,
.shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@ -533,7 +533,7 @@ static int ohci_omap_resume(struct platform_device *dev)
static struct platform_driver ohci_hcd_omap_driver = {
.probe = ohci_hcd_omap_drv_probe,
.remove = ohci_hcd_omap_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_omap_suspend,
.resume = ohci_omap_resume,

View File

@ -3,17 +3,17 @@
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
*
*
* [ Initialisation is based on Linus' ]
* [ uhci code and gregs ohci fragments ]
* [ (C) Copyright 1999 Linus Torvalds ]
* [ (C) Copyright 1999 Gregory P. Smith]
*
*
* PCI Bus Glue
*
* This file is licenced under the GPL.
*/
#ifndef CONFIG_PCI
#error "This file is PCI bus glue. CONFIG_PCI must be defined."
#endif
@ -83,7 +83,7 @@ ohci_pci_start (struct usb_hcd *hcd)
pci_dev_put(b);
}
/* Check for Compaq's ZFMicro chipset, which needs short
/* Check for Compaq's ZFMicro chipset, which needs short
* delays before control or bulk queues get re-activated
* in finish_unlinks()
*/
@ -238,8 +238,8 @@ static struct pci_driver ohci_pci_driver = {
.shutdown = usb_hcd_pci_shutdown,
};
static int __init ohci_hcd_pci_init (void)
static int __init ohci_hcd_pci_init (void)
{
printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
if (usb_disabled())
@ -253,8 +253,8 @@ module_init (ohci_hcd_pci_init);
/*-------------------------------------------------------------------------*/
static void __exit ohci_hcd_pci_cleanup (void)
{
static void __exit ohci_hcd_pci_cleanup (void)
{
pci_unregister_driver (&ohci_pci_driver);
}
module_exit (ohci_hcd_pci_cleanup);

View File

@ -4,7 +4,7 @@
* driver for Philips PNX4008 USB Host
*
* Authors: Dmitry Chigirev <source@mvista.com>
* Vitaly Wool <vitalywool@gmail.com>
* Vitaly Wool <vitalywool@gmail.com>
*
* register initialization is based on code examples provided by Philips
* Copyright (c) 2005 Koninklijke Philips Electronics N.V.
@ -29,7 +29,7 @@
#include <asm/arch/irqs.h>
#include <asm/arch/gpio.h>
#define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
#define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
/* USB_CTRL bit defines */
#define USB_SLAVE_HCLK_EN (1 << 24)

View File

@ -0,0 +1,258 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Copyright 2002 Hewlett-Packard Company
* (C) Copyright 2005 Embedded Alley Solutions, Inc.
*
* Bus Glue for PNX8550
*
* Written by Christopher Hoover <ch@hpl.hp.com>
* Based on fragments of previous driver by Russell King et al.
*
* Modified for LH7A404 from ohci-sa1111.c
* by Durgesh Pattamatta <pattamattad@sharpsec.com>
*
* Modified for PNX8550 from ohci-sa1111.c and sa-omap.c
* by Vitaly Wool <vitalywool@gmail.com>
*
* This file is licenced under the GPL.
*/
#include <linux/device.h>
#include <linux/platform_device.h>
#include <asm/mach-pnx8550/usb.h>
#include <asm/mach-pnx8550/int.h>
#include <asm/mach-pnx8550/pci.h>
#ifndef CONFIG_PNX8550
#error "This file is PNX8550 bus glue. CONFIG_PNX8550 must be defined."
#endif
extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
static void pnx8550_start_hc(struct platform_device *dev)
{
/*
* Set register CLK48CTL to enable and 48MHz
*/
outl(0x00000003, PCI_BASE | 0x0004770c);
/*
* Set register CLK12CTL to enable and 48MHz
*/
outl(0x00000003, PCI_BASE | 0x00047710);
udelay(100);
}
static void pnx8550_stop_hc(struct platform_device *dev)
{
udelay(10);
}
/*-------------------------------------------------------------------------*/
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
/**
* usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs
* Context: !in_interrupt()
*
* Allocates basic resources for this USB host controller, and
* then invokes the start() method for the HCD associated with it
* through the hotplug entry's driver_data.
*
*/
int usb_hcd_pnx8550_probe (const struct hc_driver *driver,
struct platform_device *dev)
{
int retval;
struct usb_hcd *hcd;
if (dev->resource[0].flags != IORESOURCE_MEM ||
dev->resource[1].flags != IORESOURCE_IRQ) {
dev_err (&dev->dev,"invalid resource type\n");
return -ENOMEM;
}
hcd = usb_create_hcd (driver, &dev->dev, "pnx8550");
if (!hcd)
return -ENOMEM;
hcd->rsrc_start = dev->resource[0].start;
hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] "
"failed\n", hcd->rsrc_start, hcd->rsrc_len);
retval = -EBUSY;
goto err1;
}
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) {
dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n",
hcd->rsrc_start, hcd->rsrc_len);
retval = -ENOMEM;
goto err2;
}
pnx8550_start_hc(dev);
ohci_hcd_init(hcd_to_ohci(hcd));
retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
if (retval == 0)
return retval;
pnx8550_stop_hc(dev);
iounmap(hcd->regs);
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1:
usb_put_hcd(hcd);
return retval;
}
/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
/**
* usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs
* @dev: USB Host Controller being removed
* Context: !in_interrupt()
*
* Reverses the effect of usb_hcd_pnx8550_probe(), first invoking
* the HCD's stop() method. It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*
*/
void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev)
{
usb_remove_hcd(hcd);
pnx8550_stop_hc(dev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
}
/*-------------------------------------------------------------------------*/
static int __devinit
ohci_pnx8550_start (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int ret;
ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci);
if ((ret = ohci_init(ohci)) < 0)
return ret;
if ((ret = ohci_run (ohci)) < 0) {
err ("can't start %s", hcd->self.bus_name);
ohci_stop (hcd);
return ret;
}
return 0;
}
/*-------------------------------------------------------------------------*/
static const struct hc_driver ohci_pnx8550_hc_driver = {
.description = hcd_name,
.product_desc = "PNX8550 OHCI",
.hcd_priv_size = sizeof(struct ohci_hcd),
/*
* generic hardware linkage
*/
.irq = ohci_irq,
.flags = HCD_USB11 | HCD_MEMORY,
/*
* basic lifecycle operations
*/
.start = ohci_pnx8550_start,
.stop = ohci_stop,
/*
* managing i/o requests and associated device resources
*/
.urb_enqueue = ohci_urb_enqueue,
.urb_dequeue = ohci_urb_dequeue,
.endpoint_disable = ohci_endpoint_disable,
/*
* scheduling support
*/
.get_frame_number = ohci_get_frame,
/*
* root hub support
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
#endif
.start_port_reset = ohci_start_port_reset,
};
/*-------------------------------------------------------------------------*/
static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev)
{
int ret;
if (usb_disabled())
return -ENODEV;
ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev);
return ret;
}
static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_hcd_pnx8550_remove(hcd, pdev);
return 0;
}
MODULE_ALIAS("pnx8550-ohci");
static struct platform_driver ohci_hcd_pnx8550_driver = {
.driver = {
.name = "pnx8550-ohci",
},
.probe = ohci_hcd_pnx8550_drv_probe,
.remove = ohci_hcd_pnx8550_drv_remove,
};
static int __init ohci_hcd_pnx8550_init (void)
{
pr_debug (DRIVER_INFO " (pnx8550)");
pr_debug ("block sizes: ed %d td %d\n",
sizeof (struct ed), sizeof (struct td));
return platform_driver_register(&ohci_hcd_pnx8550_driver);
}
static void __exit ohci_hcd_pnx8550_cleanup (void)
{
platform_driver_unregister(&ohci_hcd_pnx8550_driver);
}
module_init (ohci_hcd_pnx8550_init);
module_exit (ohci_hcd_pnx8550_cleanup);

View File

@ -5,7 +5,7 @@
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Copyright 2002 Hewlett-Packard Company
* (C) Copyright 2003-2005 MontaVista Software Inc.
*
*
* Bus Glue for PPC On-Chip OHCI driver
* Tested on Freescale MPC5200 and IBM STB04xxx
*
@ -85,7 +85,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1:
usb_put_hcd(hcd);
usb_put_hcd(hcd);
return retval;
}
@ -148,7 +148,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
*/
.start = ohci_ppc_soc_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
.shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@ -197,7 +197,7 @@ static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
static struct platform_driver ohci_hcd_ppc_soc_driver = {
.probe = ohci_hcd_ppc_soc_drv_probe,
.remove = ohci_hcd_ppc_soc_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
/*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/
/*.resume = ohci_hcd_ppc_soc_drv_resume,*/

View File

@ -47,7 +47,7 @@ static int pxa27x_ohci_select_pmm( int mode )
switch ( mode ) {
case PMM_NPS_MODE:
UHCRHDA |= RH_A_NPS;
break;
break;
case PMM_GLOBAL_MODE:
UHCRHDA &= ~(RH_A_NPS & RH_A_PSM);
break;
@ -60,7 +60,7 @@ static int pxa27x_ohci_select_pmm( int mode )
break;
default:
printk( KERN_ERR
"Invalid mode %d, set to non-power switch mode.\n",
"Invalid mode %d, set to non-power switch mode.\n",
mode );
UHCRHDA |= RH_A_NPS;
@ -270,7 +270,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
*/
.start = ohci_pxa27x_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
.shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@ -359,9 +359,9 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_drv_probe,
.remove = ohci_hcd_pxa27x_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_hcd_pxa27x_drv_suspend,
.suspend = ohci_hcd_pxa27x_drv_suspend,
.resume = ohci_hcd_pxa27x_drv_resume,
#endif
.driver = {

View File

@ -1,9 +1,9 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
*
*
* This file is licenced under the GPL.
*/
@ -89,7 +89,7 @@ __acquires(ohci->lock)
/*-------------------------------------------------------------------------*
* ED handling functions
*-------------------------------------------------------------------------*/
*-------------------------------------------------------------------------*/
/* search for the right schedule branch to use for a periodic ed.
* does some load balancing; returns the branch, or negative errno.
@ -107,7 +107,6 @@ static int balance (struct ohci_hcd *ohci, int interval, int load)
*/
for (i = 0; i < interval ; i++) {
if (branch < 0 || ohci->load [branch] > ohci->load [i]) {
#if 1 /* CONFIG_USB_BANDWIDTH */
int j;
/* usb 1.1 says 90% of one frame */
@ -117,8 +116,7 @@ static int balance (struct ohci_hcd *ohci, int interval, int load)
}
if (j < NUM_INTS)
continue;
#endif
branch = i;
branch = i;
}
}
return branch;
@ -171,7 +169,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
/* link an ed into one of the HC chains */
static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
{
{
int branch;
if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING)
@ -248,7 +246,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
}
ed->branch = branch;
periodic_link (ohci, ed);
}
}
/* the HC may not see the schedule updates yet, but if it does
* then they'll be properly ordered.
@ -277,7 +275,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
*prev = ed->ed_next;
}
ohci->load [i] -= ed->load;
}
}
ohci_to_hcd(ohci)->self.bandwidth_allocated -= ed->load / ed->interval;
ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n",
@ -285,7 +283,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
ed, ed->branch, ed->load, ed->interval);
}
/* unlink an ed from one of the HC chains.
/* unlink an ed from one of the HC chains.
* just the link to the ed is unlinked.
* the link from the ed still points to another operational ed or 0
* so the HC can eventually finish the processing of the unlinked ed
@ -307,7 +305,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
* When finish_unlinks() runs later, after SOF interrupt, it will often
* complete one or more URB unlinks before making that state change.
*/
static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
{
ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP);
wmb ();
@ -397,7 +395,7 @@ static struct ed *ed_get (
unsigned int pipe,
int interval
) {
struct ed *ed;
struct ed *ed;
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
@ -413,9 +411,9 @@ static struct ed *ed_get (
goto done;
}
/* dummy td; end of td list for ed */
/* dummy td; end of td list for ed */
td = td_alloc (ohci, GFP_ATOMIC);
if (!td) {
if (!td) {
/* out of memory */
ed_free (ohci, ed);
ed = NULL;
@ -462,7 +460,7 @@ static struct ed *ed_get (
done:
spin_unlock_irqrestore (&ohci->lock, flags);
return ed;
return ed;
}
/*-------------------------------------------------------------------------*/
@ -474,7 +472,7 @@ static struct ed *ed_get (
* and that ed->state is ED_OPER
*/
static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
{
{
ed->hwINFO |= cpu_to_hc32 (ohci, ED_DEQUEUE);
ed_deschedule (ohci, ed);
@ -541,7 +539,7 @@ td_fill (struct ohci_hcd *ohci, u32 info,
td->ed = urb_priv->ed;
td->next_dl_td = NULL;
td->index = index;
td->urb = urb;
td->urb = urb;
td->data_dma = data;
if (!len)
data = 0;
@ -553,8 +551,8 @@ td_fill (struct ohci_hcd *ohci, u32 info,
(data & 0x0FFF) | 0xE000);
td->ed->last_iso = info & 0xffff;
} else {
td->hwCBP = cpu_to_hc32 (ohci, data);
}
td->hwCBP = cpu_to_hc32 (ohci, data);
}
if (data)
td->hwBE = cpu_to_hc32 (ohci, data + len - 1);
else
@ -597,7 +595,7 @@ static void td_submit_urb (
* use the device toggle bits for resetting, and rely on the fact
* that resetting toggle is meaningless if the endpoint is active.
*/
if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
is_out, 1);
urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C);
@ -721,16 +719,16 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
list_del (&td->td_list);
/* ISO ... drivers see per-TD length/status */
if (tdINFO & TD_ISO) {
u16 tdPSW = ohci_hwPSW (ohci, td, 0);
if (tdINFO & TD_ISO) {
u16 tdPSW = ohci_hwPSW (ohci, td, 0);
int dlen = 0;
/* NOTE: assumes FC in tdINFO == 0, and that
* only the first of 0..MAXPSW psws is used.
*/
cc = (tdPSW >> 12) & 0xF;
if (tdINFO & TD_CC) /* hc didn't touch? */
cc = (tdPSW >> 12) & 0xF;
if (tdINFO & TD_CC) /* hc didn't touch? */
return;
if (usb_pipeout (urb->pipe))
@ -758,7 +756,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
int type = usb_pipetype (urb->pipe);
u32 tdBE = hc32_to_cpup (ohci, &td->hwBE);
cc = TD_CC_GET (tdINFO);
cc = TD_CC_GET (tdINFO);
/* update packet status if needed (short is normally ok) */
if (cc == TD_DATAUNDERRUN
@ -787,7 +785,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
urb, td, 1 + td->index, cc,
urb->actual_length,
urb->transfer_buffer_length);
}
}
}
/*-------------------------------------------------------------------------*/
@ -795,7 +793,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
static inline struct td *
ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
{
struct urb *urb = td->urb;
struct urb *urb = td->urb;
struct ed *ed = td->ed;
struct list_head *tmp = td->td_list.next;
__hc32 toggle = ed->hwHeadP & cpu_to_hc32 (ohci, ED_C);
@ -805,7 +803,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
*/
ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP);
wmb ();
ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H);
ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H);
/* put any later tds from this urb onto the donelist, after 'td',
* order won't matter here: no errors, and nothing was transferred.
@ -833,7 +831,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
info &= ~cpu_to_hc32 (ohci, TD_CC);
next->hwINFO = info;
next->next_dl_td = rev;
next->next_dl_td = rev;
rev = next;
ed->hwHeadP = next->hwNextTD | toggle;
@ -881,8 +879,8 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
/* get TD from hc's singly linked list, and
* prepend to ours. ed->td_list changes later.
*/
while (td_dma) {
int cc;
while (td_dma) {
int cc;
td = dma_to_td (ohci, td_dma);
if (!td) {
@ -901,10 +899,10 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
&& (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H)))
td_rev = ed_halted (ohci, td, cc, td_rev);
td->next_dl_td = td_rev;
td->next_dl_td = td_rev;
td_rev = td;
td_dma = hc32_to_cpup (ohci, &td->hwNextTD);
}
}
return td_rev;
}
@ -1013,9 +1011,9 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
if (modified)
goto rescan_all;
}
}
/* maybe reenable control and bulk lists */
/* maybe reenable control and bulk lists */
if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state)
&& ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING
&& !ohci->ed_rm_list) {
@ -1041,20 +1039,20 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick)
&ohci->regs->ed_bulkcurrent);
}
}
/* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */
if (control) {
ohci->hc_control |= control;
if (ohci->flags & OHCI_QUIRK_ZFMICRO)
mdelay(1);
ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
}
ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
}
if (command) {
if (ohci->flags & OHCI_QUIRK_ZFMICRO)
mdelay(1);
ohci_writel (ohci, command, &ohci->regs->cmdstatus);
}
ohci_writel (ohci, command, &ohci->regs->cmdstatus);
}
}
}
@ -1074,19 +1072,19 @@ dl_done_list (struct ohci_hcd *ohci)
{
struct td *td = dl_reverse_done_list (ohci);
while (td) {
while (td) {
struct td *td_next = td->next_dl_td;
struct urb *urb = td->urb;
urb_priv_t *urb_priv = urb->hcpriv;
struct ed *ed = td->ed;
/* update URB's length and status from TD */
td_done (ohci, urb, td);
urb_priv->td_cnt++;
td_done (ohci, urb, td);
urb_priv->td_cnt++;
/* If all this urb's TDs are done, call complete() */
if (urb_priv->td_cnt == urb_priv->length)
finish_urb (ohci, urb);
if (urb_priv->td_cnt == urb_priv->length)
finish_urb (ohci, urb);
/* clean schedule: unlink EDs that are no longer busy */
if (list_empty (&ed->td_list)) {
@ -1094,25 +1092,26 @@ dl_done_list (struct ohci_hcd *ohci)
start_ed_unlink (ohci, ed);
/* ... reenabling halted EDs only after fault cleanup */
} else if ((ed->hwINFO & cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE))
} else if ((ed->hwINFO & cpu_to_hc32 (ohci,
ED_SKIP | ED_DEQUEUE))
== cpu_to_hc32 (ohci, ED_SKIP)) {
td = list_entry (ed->td_list.next, struct td, td_list);
if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) {
if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) {
ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP);
/* ... hc may need waking-up */
switch (ed->type) {
case PIPE_CONTROL:
ohci_writel (ohci, OHCI_CLF,
&ohci->regs->cmdstatus);
&ohci->regs->cmdstatus);
break;
case PIPE_BULK:
ohci_writel (ohci, OHCI_BLF,
&ohci->regs->cmdstatus);
&ohci->regs->cmdstatus);
break;
}
}
}
td = td_next;
}
td = td_next;
}
}

View File

@ -447,7 +447,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
*/
.start = ohci_s3c2410_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
.shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@ -492,7 +492,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe = ohci_hcd_s3c2410_drv_probe,
.remove = ohci_hcd_s3c2410_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_s3c2410_drv_suspend, */
/*.resume = ohci_hcd_s3c2410_drv_resume, */
.driver = {

View File

@ -4,7 +4,7 @@
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Copyright 2002 Hewlett-Packard Company
*
*
* SA1111 Bus Glue
*
* Written by Christopher Hoover <ch@hpl.hp.com>
@ -12,7 +12,7 @@
*
* This file is licenced under the GPL.
*/
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/arch/assabet.h>
@ -31,7 +31,7 @@ static void sa1111_start_hc(struct sa1111_dev *dev)
{
unsigned int usb_rst = 0;
printk(KERN_DEBUG __FILE__
printk(KERN_DEBUG __FILE__
": starting SA-1111 OHCI USB Controller\n");
#ifdef CONFIG_SA1100_BADGE4
@ -65,7 +65,7 @@ static void sa1111_start_hc(struct sa1111_dev *dev)
static void sa1111_stop_hc(struct sa1111_dev *dev)
{
unsigned int usb_rst;
printk(KERN_DEBUG __FILE__
printk(KERN_DEBUG __FILE__
": stopping SA-1111 OHCI USB Controller\n");
/*

View File

@ -1,9 +1,9 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
*
*
* This file is licenced under the GPL.
*/
@ -14,7 +14,7 @@
*/
typedef __u32 __bitwise __hc32;
typedef __u16 __bitwise __hc16;
/*
* OHCI Endpoint Descriptor (ED) ... holds TD queue
* See OHCI spec, section 4.2
@ -24,7 +24,7 @@ typedef __u16 __bitwise __hc16;
*/
struct ed {
/* first fields are hardware-specified */
__hc32 hwINFO; /* endpoint config bitmap */
__hc32 hwINFO; /* endpoint config bitmap */
/* info bits defined by hcd */
#define ED_DEQUEUE (1 << 27)
/* info bits defined by the hardware */
@ -52,11 +52,11 @@ struct ed {
* usually: OPER --> UNLINK --> (IDLE | OPER) --> ...
*/
u8 state; /* ED_{IDLE,UNLINK,OPER} */
#define ED_IDLE 0x00 /* NOT linked to HC */
#define ED_UNLINK 0x01 /* being unlinked from hc */
#define ED_IDLE 0x00 /* NOT linked to HC */
#define ED_UNLINK 0x01 /* being unlinked from hc */
#define ED_OPER 0x02 /* IS linked to hc */
u8 type; /* PIPE_{BULK,...} */
u8 type; /* PIPE_{BULK,...} */
/* periodic scheduling params (for intr and iso) */
u8 branch;
@ -70,7 +70,7 @@ struct ed {
#define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */
/*
* OHCI Transfer Descriptor (TD) ... one per transfer segment
* See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt)
@ -107,22 +107,22 @@ struct td {
/* (no hwINFO #defines yet for iso tds) */
__hc32 hwCBP; /* Current Buffer Pointer (or 0) */
__hc32 hwNextTD; /* Next TD Pointer */
__hc32 hwBE; /* Memory Buffer End Pointer */
__hc32 hwCBP; /* Current Buffer Pointer (or 0) */
__hc32 hwNextTD; /* Next TD Pointer */
__hc32 hwBE; /* Memory Buffer End Pointer */
/* PSW is only for ISO. Only 1 PSW entry is used, but on
* big-endian PPC hardware that's the second entry.
*/
#define MAXPSW 2
__hc16 hwPSW [MAXPSW];
__hc16 hwPSW [MAXPSW];
/* rest are purely for the driver's use */
__u8 index;
struct ed *ed;
struct td *td_hash; /* dma-->td hashtable */
struct td *next_dl_td;
struct urb *urb;
__u8 index;
struct ed *ed;
struct td *td_hash; /* dma-->td hashtable */
struct td *next_dl_td;
struct urb *urb;
dma_addr_t td_dma; /* addr of this TD */
dma_addr_t data_dma; /* addr of data it points to */
@ -152,8 +152,8 @@ struct td {
#define TD_NOTACCESSED 0x0F
/* map OHCI TD status codes (CC) to errno values */
static const int cc_to_error [16] = {
/* map OHCI TD status codes (CC) to errno values */
static const int cc_to_error [16] = {
/* No Error */ 0,
/* CRC Error */ -EILSEQ,
/* Bit Stuff */ -EPROTO,
@ -169,7 +169,7 @@ static const int cc_to_error [16] = {
/* BufferOver */ -ECOMM,
/* BuffUnder */ -ENOSR,
/* (for HCD) */ -EALREADY,
/* (for HCD) */ -EALREADY
/* (for HCD) */ -EALREADY
};
@ -182,7 +182,7 @@ struct ohci_hcca {
#define NUM_INTS 32
__hc32 int_table [NUM_INTS]; /* periodic schedule */
/*
/*
* OHCI defines u16 frame_no, followed by u16 zero pad.
* Since some processors can't do 16 bit bus accesses,
* portable access must be a 32 bits wide.
@ -262,10 +262,10 @@ struct ohci_regs {
* HcCommandStatus (cmdstatus) register masks
*/
#define OHCI_HCR (1 << 0) /* host controller reset */
#define OHCI_CLF (1 << 1) /* control list filled */
#define OHCI_BLF (1 << 2) /* bulk list filled */
#define OHCI_OCR (1 << 3) /* ownership change request */
#define OHCI_SOC (3 << 16) /* scheduling overrun count */
#define OHCI_CLF (1 << 1) /* control list filled */
#define OHCI_BLF (1 << 2) /* bulk list filled */
#define OHCI_OCR (1 << 3) /* ownership change request */
#define OHCI_SOC (3 << 16) /* scheduling overrun count */
/*
* masks used with interrupt registers:
@ -285,20 +285,20 @@ struct ohci_regs {
/* OHCI ROOT HUB REGISTER MASKS */
/* roothub.portstatus [i] bits */
#define RH_PS_CCS 0x00000001 /* current connect status */
#define RH_PS_PES 0x00000002 /* port enable status*/
#define RH_PS_PSS 0x00000004 /* port suspend status */
#define RH_PS_POCI 0x00000008 /* port over current indicator */
#define RH_PS_PRS 0x00000010 /* port reset status */
#define RH_PS_PPS 0x00000100 /* port power status */
#define RH_PS_LSDA 0x00000200 /* low speed device attached */
#define RH_PS_CSC 0x00010000 /* connect status change */
#define RH_PS_PESC 0x00020000 /* port enable status change */
#define RH_PS_PSSC 0x00040000 /* port suspend status change */
#define RH_PS_OCIC 0x00080000 /* over current indicator change */
#define RH_PS_PRSC 0x00100000 /* port reset status change */
#define RH_PS_CCS 0x00000001 /* current connect status */
#define RH_PS_PES 0x00000002 /* port enable status*/
#define RH_PS_PSS 0x00000004 /* port suspend status */
#define RH_PS_POCI 0x00000008 /* port over current indicator */
#define RH_PS_PRS 0x00000010 /* port reset status */
#define RH_PS_PPS 0x00000100 /* port power status */
#define RH_PS_LSDA 0x00000200 /* low speed device attached */
#define RH_PS_CSC 0x00010000 /* connect status change */
#define RH_PS_PESC 0x00020000 /* port enable status change */
#define RH_PS_PSSC 0x00040000 /* port suspend status change */
#define RH_PS_OCIC 0x00080000 /* over current indicator change */
#define RH_PS_PRSC 0x00100000 /* port reset status change */
/* roothub.status bits */
#define RH_HS_LPS 0x00000001 /* local power status */
@ -333,7 +333,7 @@ typedef struct urb_priv {
} urb_priv_t;
#define TD_HASH_SIZE 64 /* power'o'two */
// sizeof (struct td) ~= 64 == 2^6 ...
// sizeof (struct td) ~= 64 == 2^6 ...
#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE)
@ -364,11 +364,11 @@ struct ohci_hcd {
struct ed *ed_bulktail; /* last in bulk list */
struct ed *ed_controltail; /* last in ctrl list */
struct ed *periodic [NUM_INTS]; /* shadow int_table */
struct ed *periodic [NUM_INTS]; /* shadow int_table */
/*
* OTG controllers and transceivers need software interaction;
* other external transceivers should be software-transparent
* other external transceivers should be software-transparent
*/
struct otg_transceiver *transceiver;
@ -385,7 +385,7 @@ struct ohci_hcd {
*/
int num_ports;
int load [NUM_INTS];
u32 hc_control; /* copy of hc control reg */
u32 hc_control; /* copy of hc control reg */
unsigned long next_statechange; /* suspend/resume */
u32 fminterval; /* saved register */
unsigned autostop:1; /* rh auto stopping/stopped */
@ -598,11 +598,11 @@ static inline void disable (struct ohci_hcd *ohci)
}
#define FI 0x2edf /* 12000 bits per frame (-1) */
#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
#define FIT (1 << 31)
#define LSTHRESH 0x628 /* lowspeed bit threshold */
static void periodic_reinit (struct ohci_hcd *ohci)
static inline void periodic_reinit (struct ohci_hcd *ohci)
{
u32 fi = ohci->fminterval & 0x03fff;
u32 fit = ohci_readl(ohci, &ohci->regs->fminterval) & FIT;
@ -626,11 +626,11 @@ static void periodic_reinit (struct ohci_hcd *ohci)
temp = ohci_readl (hc, &hc->regs->roothub.register); \
temp; })
static u32 roothub_a (struct ohci_hcd *hc)
static inline u32 roothub_a (struct ohci_hcd *hc)
{ return read_roothub (hc, a, 0xfc0fe000); }
static inline u32 roothub_b (struct ohci_hcd *hc)
{ return ohci_readl (hc, &hc->regs->roothub.b); }
static inline u32 roothub_status (struct ohci_hcd *hc)
{ return ohci_readl (hc, &hc->regs->roothub.status); }
static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
static inline u32 roothub_portstatus (struct ohci_hcd *hc, int i)
{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }

View File

@ -40,6 +40,7 @@
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/pci_ids.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
@ -210,15 +211,16 @@ struct u132 {
* these cannot be inlines because we need the structure offset!!
* Does anyone have a better way?????
*/
#define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \
offsetof(struct ohci_regs, member), 0, data);
#define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \
offsetof(struct ohci_regs, member), 0, data);
#define u132_read_pcimem(u132, member, data) \
usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
ohci_regs, member), 0, data);
#define u132_write_pcimem(u132, member, data) \
usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
ohci_regs, member), 0, data);
#define u132_write_pcimem_byte(u132, member, data) \
usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
ohci_regs, member), 0x0e, data);
static inline struct u132 *udev_to_u132(struct u132_udev *udev)
{
u8 udev_number = udev->udev_number;
@ -1574,59 +1576,12 @@ static char *hcfs2string(int state)
return "?";
}
static int u132_usb_reset(struct u132 *u132)
{
int retval;
retval = u132_read_pcimem(u132, control, &u132->hc_control);
if (retval)
return retval;
u132->hc_control &= OHCI_CTRL_RWC;
retval = u132_write_pcimem(u132, control, u132->hc_control);
if (retval)
return retval;
return 0;
}
static int u132_init(struct u132 *u132)
{
int retval;
u32 control;
u132_disable(u132);
u132->next_statechange =
jiffies; /* SMM owns the HC? not for long! */ {
u32 control;
retval = u132_read_pcimem(u132, control, &control);
if (retval)
return retval;
if (control & OHCI_CTRL_IR) {
u32 temp = 50;
retval = u132_write_pcimem(u132, intrenable,
OHCI_INTR_OC);
if (retval)
return retval;
retval = u132_write_pcimem_byte(u132, cmdstatus,
OHCI_OCR);
if (retval)
return retval;
check:{
retval = u132_read_pcimem(u132, control,
&control);
if (retval)
return retval;
}
if (control & OHCI_CTRL_IR) {
msleep(10);
if (--temp == 0) {
dev_err(&u132->platform_dev->dev, "USB "
"HC takeover failed!(BIOS/SMM b"
"ug) control=%08X\n", control);
return -EBUSY;
}
goto check;
}
u132_usb_reset(u132);
}
}
u132->next_statechange = jiffies;
retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
if (retval)
return retval;
@ -1725,7 +1680,7 @@ static int u132_run(struct u132 *u132)
retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
if (retval)
return retval;
retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR);
retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
if (retval)
return retval;
extra:{
@ -1782,7 +1737,7 @@ static int u132_run(struct u132 *u132)
retval = u132_write_pcimem(u132, control, u132->hc_control);
if (retval)
return retval;
retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF);
retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
if (retval)
return retval;
retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
@ -1839,8 +1794,8 @@ static void u132_hcd_stop(struct usb_hcd *hcd)
{
struct u132 *u132 = hcd_to_u132(hcd);
if (u132->going > 1) {
dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
, u132->going);
dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
"een removed %d\n", u132, hcd, u132->going);
} else if (u132->going > 0) {
dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
"ed\n", hcd);
@ -2545,8 +2500,9 @@ static void u132_endpoint_disable(struct usb_hcd *hcd,
{
struct u132 *u132 = hcd_to_u132(hcd);
if (u132->going > 2) {
dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
, u132->going);
dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
") has been removed %d\n", u132, hcd, hep,
u132->going);
} else {
struct u132_endp *endp = hep->hcpriv;
if (endp)
@ -2790,7 +2746,6 @@ static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
} else if (u132->going > 0) {
dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
"ed\n", hcd);
dump_stack();
return -ESHUTDOWN;
} else {
int i, changed = 0, length = 1;
@ -3034,12 +2989,15 @@ static int __devexit u132_remove(struct platform_device *pdev)
struct usb_hcd *hcd = platform_get_drvdata(pdev);
if (hcd) {
struct u132 *u132 = hcd_to_u132(hcd);
dump_stack();
if (u132->going++ > 1) {
dev_err(&u132->platform_dev->dev, "already being remove"
"d\n");
return -ENODEV;
} else {
int rings = MAX_U132_RINGS;
int endps = MAX_U132_ENDPS;
dev_err(&u132->platform_dev->dev, "removing device u132"
".%d\n", u132->sequence_num);
msleep(100);
down(&u132->sw_lock);
u132_monitor_cancel_work(u132);
@ -3121,10 +3079,24 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
static int __devinit u132_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
int retval;
u32 control;
u32 rh_a = -1;
u32 num_ports;
msleep(100);
if (u132_exiting > 0) {
return -ENODEV;
} /* refuse to confuse usbcore */
}
retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
if (retval)
return retval;
retval = ftdi_read_pcimem(pdev, control, &control);
if (retval)
return retval;
retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
if (retval)
return retval;
num_ports = rh_a & RH_A_NDP; /* refuse to confuse usbcore */
if (pdev->dev.dma_mask) {
return -EINVAL;
}

View File

@ -60,6 +60,11 @@ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
Alan Stern"
#define DRIVER_DESC "USB Universal Host Controller Interface driver"
/* for flakey hardware, ignore overcurrent indicators */
static int ignore_oc;
module_param(ignore_oc, bool, S_IRUGO);
MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications");
/*
* debug = 0, no debugging messages
* debug = 1, dump failed URBs except for stalls
@ -169,6 +174,11 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
{
int port;
/* If we have to ignore overcurrent events then almost by definition
* we can't depend on resume-detect interrupts. */
if (ignore_oc)
return 1;
switch (to_pci_dev(uhci_dev(uhci))->vendor) {
default:
break;
@ -921,7 +931,8 @@ static int __init uhci_hcd_init(void)
{
int retval = -ENOMEM;
printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n");
printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n",
ignore_oc ? ", overcurrent ignored" : "");
if (usb_disabled())
return -ENODEV;

View File

@ -52,10 +52,20 @@ static int any_ports_active(struct uhci_hcd *uhci)
static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
{
int port;
int mask = RWC_BITS;
/* Some boards (both VIA and Intel apparently) report bogus
* overcurrent indications, causing massive log spam unless
* we completely ignore them. This doesn't seem to be a problem
* with the chipset so much as with the way it is connected on
* the motherboard; if the overcurrent input is left to float
* then it may constantly register false positives. */
if (ignore_oc)
mask &= ~USBPORTSC_OCC;
*buf = 0;
for (port = 0; port < uhci->rh_numports; ++port) {
if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & mask) ||
test_bit(port, &uhci->port_c_suspend))
*buf |= (1 << (port + 1));
}
@ -263,7 +273,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
wPortChange |= USB_PORT_STAT_C_CONNECTION;
if (status & USBPORTSC_PEC)
wPortChange |= USB_PORT_STAT_C_ENABLE;
if (status & USBPORTSC_OCC)
if ((status & USBPORTSC_OCC) && !ignore_oc)
wPortChange |= USB_PORT_STAT_C_OVERCURRENT;
if (test_bit(port, &uhci->port_c_suspend)) {

View File

@ -159,13 +159,13 @@ void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3);
input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
}
void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
}
void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)

View File

@ -209,13 +209,15 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
}
}
if (data[1] & 0x10)
wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
}
else
wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
wacom_report_key(wcombo, wacom->tool[0], data[1] & 0x10);
if (data[1] & 0x10) /* only report prox-in when in area */
wacom_report_key(wcombo, wacom->tool[0], 1);
if (!(data[1] & 0x90)) /* report prox-out when physically out */
wacom_report_key(wcombo, wacom->tool[0], 0);
wacom_input_sync(wcombo);
/* send pad data */
@ -405,7 +407,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
return 0;
if (wacom->features->type >= INTUOS3) {
if (wacom->features->type >= INTUOS3S) {
wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
@ -423,7 +425,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
if (data[1] & 0x02) {
/* Rotation packet */
if (wacom->features->type >= INTUOS3) {
if (wacom->features->type >= INTUOS3S) {
/* I3 marker pen rotation reported as wheel
* due to valuator limitation
*/
@ -547,11 +549,11 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 63, GRAPHIRE },
{ "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 63, WACOM_G4 },
{ "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 },
{ "Wacom Volito", 8, 5104, 3712, 511, 0, GRAPHIRE },
{ "Wacom PenStation2", 8, 3250, 2320, 255, 0, GRAPHIRE },
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 0, GRAPHIRE },
{ "Wacom Volito2 2x3", 8, 3248, 2320, 511, 0, GRAPHIRE },
{ "Wacom PenPartner2", 8, 3250, 2320, 255, 0, GRAPHIRE },
{ "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE },
{ "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE },
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE },
{ "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE },
{ "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE },
{ "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 63, INTUOS },
{ "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 63, INTUOS },
{ "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 63, INTUOS },
@ -580,7 +582,7 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L },
{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L },
{ "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 },
{ "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 15, INTUOS3S },
{ "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S },
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, INTUOS },
{ }

View File

@ -1376,7 +1376,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
}
/* we have access to the device. Now lets allocate memory */
ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL);
ccp = kzalloc(sizeof(auerchar_t), GFP_KERNEL);
if (ccp == NULL) {
err ("out of memory");
ret = -ENOMEM;
@ -1384,7 +1384,6 @@ static int auerchar_open (struct inode *inode, struct file *file)
}
/* Initialize device descriptor */
memset( ccp, 0, sizeof(auerchar_t));
init_MUTEX( &ccp->mutex);
init_MUTEX( &ccp->readmutex);
auerbuf_init (&ccp->bufctl);
@ -1912,14 +1911,13 @@ static int auerswald_probe (struct usb_interface *intf,
return -ENODEV;
/* allocate memory for our device and initialize it */
cp = kmalloc (sizeof(auerswald_t), GFP_KERNEL);
cp = kzalloc (sizeof(auerswald_t), GFP_KERNEL);
if (cp == NULL) {
err ("out of memory");
goto pfail;
}
/* Initialize device descriptor */
memset (cp, 0, sizeof(auerswald_t));
init_MUTEX (&cp->mutex);
cp->usbdev = usbdev;
auerchain_init (&cp->controlchain);

View File

@ -40,6 +40,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/ioctl.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kref.h>
@ -51,6 +52,10 @@ MODULE_AUTHOR("Tony Olech");
MODULE_DESCRIPTION("FTDI ELAN driver");
MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
static int distrust_firmware = 1;
module_param(distrust_firmware, bool, 0);
MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
"t setup");
extern struct platform_driver u132_platform_driver;
static struct workqueue_struct *status_queue;
static struct workqueue_struct *command_queue;
@ -66,7 +71,9 @@ static struct list_head ftdi_static_list;
* end of the global variables protected by ftdi_module_lock
*/
#include "usb_u132.h"
#define TD_DEVNOTRESP 5
#include <asm/io.h>
#include "../core/hcd.h"
#include "../host/ohci.h"
/* Define these values to match your devices*/
#define USB_FTDI_ELAN_VENDOR_ID 0x0403
#define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea
@ -551,7 +558,7 @@ static void ftdi_elan_status_work(struct work_struct *work)
} else {
dev_err(&ftdi->udev->dev, "initialized failed - trying "
"again in 10 seconds\n");
work_delay_in_msec = 10 *1000;
work_delay_in_msec = 1 *1000;
}
} else if (ftdi->registered == 0) {
work_delay_in_msec = 10;
@ -2288,82 +2295,229 @@ static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi)
}
}
static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
#define ftdi_read_pcimem(ftdi, member, data) ftdi_elan_read_pcimem(ftdi, \
offsetof(struct ohci_regs, member), 0, data);
#define ftdi_write_pcimem(ftdi, member, data) ftdi_elan_write_pcimem(ftdi, \
offsetof(struct ohci_regs, member), 0, data);
#define OHCI_QUIRK_AMD756 0x01
#define OHCI_QUIRK_SUPERIO 0x02
#define OHCI_QUIRK_INITRESET 0x04
#define OHCI_BIG_ENDIAN 0x08
#define OHCI_QUIRK_ZFMICRO 0x10
#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
OHCI_INTR_WDH)
static int ftdi_elan_check_controller(struct usb_ftdi *ftdi, int quirk)
{
int devices = 0;
int retval;
u32 hc_control;
int num_ports;
u32 control;
u32 rh_a = -1;
u32 status;
u32 fminterval;
u32 hc_fminterval;
u32 periodicstart;
u32 cmdstatus;
u32 roothub_a;
int mask = OHCI_INTR_INIT;
int sleep_time = 0;
int reset_timeout = 30; /* ... allow extra time */
int temp;
retval = ftdi_write_pcimem(ftdi, intrdisable, OHCI_INTR_MIE);
if (retval)
return retval;
retval = ftdi_read_pcimem(ftdi, control, &control);
if (retval)
return retval;
retval = ftdi_read_pcimem(ftdi, roothub.a, &rh_a);
if (retval)
return retval;
num_ports = rh_a & RH_A_NDP;
retval = ftdi_read_pcimem(ftdi, fminterval, &hc_fminterval);
if (retval)
return retval;
hc_fminterval &= 0x3fff;
if (hc_fminterval != FI) {
}
hc_fminterval |= FSMP(hc_fminterval) << 16;
retval = ftdi_read_pcimem(ftdi, control, &hc_control);
if (retval)
return retval;
switch (hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_OPER:
sleep_time = 0;
break;
case OHCI_USB_SUSPEND:
case OHCI_USB_RESUME:
hc_control &= OHCI_CTRL_RWC;
hc_control |= OHCI_USB_RESUME;
sleep_time = 10;
break;
default:
hc_control &= OHCI_CTRL_RWC;
hc_control |= OHCI_USB_RESET;
sleep_time = 50;
break;
}
retval = ftdi_write_pcimem(ftdi, control, hc_control);
if (retval)
return retval;
retval = ftdi_read_pcimem(ftdi, control, &control);
if (retval)
return retval;
msleep(sleep_time);
retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a);
if (retval)
return retval;
if (!(roothub_a & RH_A_NPS)) { /* power down each port */
for (temp = 0; temp < num_ports; temp++) {
retval = ftdi_write_pcimem(ftdi,
roothub.portstatus[temp], RH_PS_LSDA);
if (retval)
return retval;
}
}
retval = ftdi_read_pcimem(ftdi, control, &control);
if (retval)
return retval;
retry:retval = ftdi_read_pcimem(ftdi, cmdstatus, &status);
if (retval)
return retval;
retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_HCR);
if (retval)
return retval;
extra:{
retval = ftdi_read_pcimem(ftdi, cmdstatus, &status);
if (retval)
return retval;
if (0 != (status & OHCI_HCR)) {
if (--reset_timeout == 0) {
dev_err(&ftdi->udev->dev, "USB HC reset timed o"
"ut!\n");
return -ENODEV;
} else {
msleep(5);
goto extra;
}
}
}
if (quirk & OHCI_QUIRK_INITRESET) {
retval = ftdi_write_pcimem(ftdi, control, hc_control);
if (retval)
return retval;
retval = ftdi_read_pcimem(ftdi, control, &control);
if (retval)
return retval;
}
retval = ftdi_write_pcimem(ftdi, ed_controlhead, 0x00000000);
if (retval)
return retval;
retval = ftdi_write_pcimem(ftdi, ed_bulkhead, 0x11000000);
if (retval)
return retval;
retval = ftdi_write_pcimem(ftdi, hcca, 0x00000000);
if (retval)
return retval;
retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval);
if (retval)
return retval;
retval = ftdi_write_pcimem(ftdi, fminterval,
((fminterval & FIT) ^ FIT) | hc_fminterval);
if (retval)
return retval;
retval = ftdi_write_pcimem(ftdi, periodicstart,
((9 *hc_fminterval) / 10) & 0x3fff);
if (retval)
return retval;
retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval);
if (retval)
return retval;
retval = ftdi_read_pcimem(ftdi, periodicstart, &periodicstart);
if (retval)
return retval;
if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
if (!(quirk & OHCI_QUIRK_INITRESET)) {
quirk |= OHCI_QUIRK_INITRESET;
goto retry;
} else
dev_err(&ftdi->udev->dev, "init err(%08x %04x)\n",
fminterval, periodicstart);
} /* start controller operations */
hc_control &= OHCI_CTRL_RWC;
hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
retval = ftdi_write_pcimem(ftdi, control, hc_control);
if (retval)
return retval;
retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_BLF);
if (retval)
return retval;
retval = ftdi_read_pcimem(ftdi, cmdstatus, &cmdstatus);
if (retval)
return retval;
retval = ftdi_read_pcimem(ftdi, control, &control);
if (retval)
return retval;
retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_DRWE);
if (retval)
return retval;
retval = ftdi_write_pcimem(ftdi, intrstatus, mask);
if (retval)
return retval;
retval = ftdi_write_pcimem(ftdi, intrdisable,
OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
OHCI_INTR_SO);
if (retval)
return retval; /* handle root hub init quirks ... */
retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a);
if (retval)
return retval;
roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
if (quirk & OHCI_QUIRK_SUPERIO) {
roothub_a |= RH_A_NOCP;
roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a);
if (retval)
return retval;
} else if ((quirk & OHCI_QUIRK_AMD756) || distrust_firmware) {
roothub_a |= RH_A_NPS;
retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a);
if (retval)
return retval;
}
retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_LPSC);
if (retval)
return retval;
retval = ftdi_write_pcimem(ftdi, roothub.b,
(roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
if (retval)
return retval;
retval = ftdi_read_pcimem(ftdi, control, &control);
if (retval)
return retval;
mdelay((roothub_a >> 23) & 0x1fe);
for (temp = 0; temp < num_ports; temp++) {
u32 portstatus;
retval = ftdi_read_pcimem(ftdi, roothub.portstatus[temp],
&portstatus);
if (retval)
return retval;
if (1 & portstatus)
devices += 1;
}
return devices;
}
static int ftdi_elan_setup_controller(struct usb_ftdi *ftdi, int fn)
{
u32 latence_timer;
u32 controlreg;
int UxxxStatus;
u32 pcidata;
int reg = 0;
int foundOHCI = 0;
u8 fn;
int activePCIfn = 0;
u32 pciVID = 0;
u32 pciPID = 0;
UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
if (UxxxStatus)
return UxxxStatus;
msleep(750);
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
if (UxxxStatus)
return UxxxStatus;
msleep(250);
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
if (UxxxStatus)
return UxxxStatus;
msleep(1000);
for (fn = 0; (fn < 4) && (!foundOHCI); fn++) {
activePCIfn = fn << 8;
ftdi->function = fn + 1;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
&pcidata);
if (UxxxStatus)
return UxxxStatus;
pciVID = pcidata & 0xFFFF;
pciPID = (pcidata >> 16) & 0xFFFF;
if ((pciVID == 0x1045) && (pciPID == 0xc861)) {
foundOHCI = 1;
} else if ((pciVID == 0x1033) && (pciPID == 0x0035)) {
foundOHCI = 1;
} else if ((pciVID == 0x10b9) && (pciPID == 0x5237)) {
foundOHCI = 1;
} else if ((pciVID == 0x11c1) && (pciPID == 0x5802)) {
foundOHCI = 1;
} else if ((pciVID == 0x11AB) && (pciPID == 0x1FA6)) {
}
}
if (foundOHCI == 0) {
return -ENXIO;
}
ftdi->platform_data.vendor = pciVID;
ftdi->platform_data.device = pciPID;
int activePCIfn = fn << 8;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
if (UxxxStatus)
return UxxxStatus;
@ -2408,162 +2562,201 @@ static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
&pcidata);
if (UxxxStatus)
return UxxxStatus;
for (reg = 0; reg <= 0x54; reg += 4) {
UxxxStatus = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (UxxxStatus)
return UxxxStatus;
}
return 0;
}
static int ftdi_elan_close_controller(struct usb_ftdi *ftdi, int fn)
{
u32 latence_timer;
int UxxxStatus;
u32 pcidata;
int reg = 0;
int activePCIfn = fn << 8;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
if (UxxxStatus)
return UxxxStatus;
reg = 16;
UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
0xFFFFFFFF);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
&pcidata);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
0x00000000);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
&pcidata);
if (UxxxStatus)
return UxxxStatus;
reg = 12;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
&latence_timer);
if (UxxxStatus)
return UxxxStatus;
latence_timer &= 0xFFFF00FF;
latence_timer |= 0x00001600;
UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
latence_timer);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
&pcidata);
if (UxxxStatus)
return UxxxStatus;
reg = 4;
UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
0x00);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
&pcidata);
if (UxxxStatus)
return UxxxStatus;
return 0;
}
static int ftdi_elan_found_controller(struct usb_ftdi *ftdi, int fn, int quirk)
{
int result;
int UxxxStatus;
UxxxStatus = ftdi_elan_setup_controller(ftdi, fn);
if (UxxxStatus)
return UxxxStatus;
result = ftdi_elan_check_controller(ftdi, quirk);
UxxxStatus = ftdi_elan_close_controller(ftdi, fn);
if (UxxxStatus)
return UxxxStatus;
return result;
}
static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
{
u32 controlreg;
u8 sensebits;
int UxxxStatus;
UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
if (UxxxStatus)
return UxxxStatus;
msleep(750);
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
if (UxxxStatus)
return UxxxStatus;
msleep(250);
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
if (UxxxStatus)
return UxxxStatus;
msleep(1000);
sensebits = (controlreg >> 16) & 0x000F;
if (0x0D == sensebits)
return 0;
else
return - ENXIO;
}
static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi)
{
int UxxxStatus;
u32 pcidata;
int U132Status;
int reg;
int reset_repeat = 0;
do_reset:reg = 8;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x01);
if (U132Status)
return U132Status;
reset_check:{
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
if (pcidata & 1) {
msleep(500);
if (reset_repeat++ > 100) {
reset_repeat = 0;
goto do_reset;
} else
goto reset_check;
int reg = 0;
u8 fn;
int activePCIfn = 0;
int max_devices = 0;
int controllers = 0;
int unrecognized = 0;
ftdi->function = 0;
for (fn = 0; (fn < 4); fn++) {
u32 pciVID = 0;
u32 pciPID = 0;
int devices = 0;
activePCIfn = fn << 8;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
&pcidata);
if (UxxxStatus)
return UxxxStatus;
pciVID = pcidata & 0xFFFF;
pciPID = (pcidata >> 16) & 0xFFFF;
if ((pciVID == PCI_VENDOR_ID_OPTI) && (pciPID == 0xc861)) {
devices = ftdi_elan_found_controller(ftdi, fn, 0);
controllers += 1;
} else if ((pciVID == PCI_VENDOR_ID_NEC) && (pciPID == 0x0035))
{
devices = ftdi_elan_found_controller(ftdi, fn, 0);
controllers += 1;
} else if ((pciVID == PCI_VENDOR_ID_AL) && (pciPID == 0x5237)) {
devices = ftdi_elan_found_controller(ftdi, fn, 0);
controllers += 1;
} else if ((pciVID == PCI_VENDOR_ID_ATT) && (pciPID == 0x5802))
{
devices = ftdi_elan_found_controller(ftdi, fn, 0);
controllers += 1;
} else if (pciVID == PCI_VENDOR_ID_AMD && pciPID == 0x740c) {
devices = ftdi_elan_found_controller(ftdi, fn,
OHCI_QUIRK_AMD756);
controllers += 1;
} else if (pciVID == PCI_VENDOR_ID_COMPAQ && pciPID == 0xa0f8) {
devices = ftdi_elan_found_controller(ftdi, fn,
OHCI_QUIRK_ZFMICRO);
controllers += 1;
} else if (0 == pcidata) {
} else
unrecognized += 1;
if (devices > max_devices) {
max_devices = devices;
ftdi->function = fn + 1;
ftdi->platform_data.vendor = pciVID;
ftdi->platform_data.device = pciPID;
}
}
goto dump_regs;
msleep(500);
reg = 0x28;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x11000000);
if (U132Status)
return U132Status;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x40;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf);
if (U132Status)
return U132Status;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x34;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf2edf);
if (U132Status)
return U132Status;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 4;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0xA0);
if (U132Status)
return U132Status;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
msleep(250);
reg = 8;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x04);
if (U132Status)
return U132Status;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x28;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 8;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x48;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x00001200);
if (U132Status)
return U132Status;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x54;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x58;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x34;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x28002edf);
if (U132Status)
return U132Status;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
msleep(100);
reg = 0x50;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10000);
if (U132Status)
return U132Status;
reg = 0x54;
power_check:U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
if (!(pcidata & 1)) {
msleep(500);
goto power_check;
if (ftdi->function > 0) {
UxxxStatus = ftdi_elan_setup_controller(ftdi,
ftdi->function - 1);
if (UxxxStatus)
return UxxxStatus;
return 0;
} else if (controllers > 0) {
return -ENXIO;
} else if (unrecognized > 0) {
return -ENXIO;
} else {
ftdi->enumerated = 0;
return -ENXIO;
}
msleep(3000);
reg = 0x54;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x58;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x54;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
if (U132Status)
return U132Status;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x54;
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10);
if (U132Status)
return U132Status;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
msleep(750);
reg = 0x54;
if (0) {
U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
if (U132Status)
return U132Status;
}
if (0) {
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
}
reg = 0x54;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
reg = 0x58;
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
dump_regs:for (reg = 0; reg <= 0x54; reg += 4) {
U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (U132Status)
return U132Status;
}
return 0;
}
@ -2688,6 +2881,7 @@ static void ftdi_elan_disconnect(struct usb_interface *interface)
platform_device_unregister(&ftdi->platform_dev);
ftdi->synchronized = 0;
ftdi->enumerated = 0;
ftdi->initialized = 0;
ftdi->registered = 0;
}
flush_workqueue(status_queue);

View File

@ -282,6 +282,7 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
dev->dev = NULL;
goto out;
}
dev_set_drvdata(dev->dev, dev);
servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;

View File

@ -120,8 +120,8 @@ static void tv_disconnect(struct usb_interface *interface)
struct trancevibrator *dev;
dev = usb_get_intfdata (interface);
usb_set_intfdata(interface, NULL);
device_remove_file(&interface->dev, &dev_attr_speed);
usb_set_intfdata(interface, NULL);
usb_put_dev(dev->udev);
kfree(dev);
}

View File

@ -79,160 +79,6 @@ struct gl_header {
struct gl_packet packets;
};
#ifdef GENELINK_ACK
// FIXME: this code is incomplete, not debugged; it doesn't
// handle interrupts correctly; it should use the generic
// status IRQ code (which didn't exist back in 2001).
struct gl_priv {
struct urb *irq_urb;
char irq_buf [INTERRUPT_BUFSIZE];
};
static inline int gl_control_write(struct usbnet *dev, u8 request, u16 value)
{
int retval;
retval = usb_control_msg(dev->udev,
usb_sndctrlpipe(dev->udev, 0),
request,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
value,
0, // index
0, // data buffer
0, // size
USB_CTRL_SET_TIMEOUT);
return retval;
}
static void gl_interrupt_complete(struct urb *urb)
{
int status = urb->status;
switch (status) {
case 0:
/* success */
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
__FUNCTION__, status);
return;
default:
dbg("%s - nonzero urb status received: %d",
__FUNCTION__, urb->status);
}
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status)
err("%s - usb_submit_urb failed with result %d",
__FUNCTION__, status);
}
static int gl_interrupt_read(struct usbnet *dev)
{
struct gl_priv *priv = dev->priv_data;
int retval;
// issue usb interrupt read
if (priv && priv->irq_urb) {
// submit urb
if ((retval = usb_submit_urb(priv->irq_urb, GFP_KERNEL)) != 0)
dbg("gl_interrupt_read: submit fail - %X...", retval);
else
dbg("gl_interrupt_read: submit success...");
}
return 0;
}
// check whether another side is connected
static int genelink_check_connect(struct usbnet *dev)
{
int retval;
dbg("genelink_check_connect...");
// detect whether another side is connected
if ((retval = gl_control_write(dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
dbg("%s: genelink_check_connect write fail - %X",
dev->net->name, retval);
return retval;
}
// usb interrupt read to ack another side
if ((retval = gl_interrupt_read(dev)) != 0) {
dbg("%s: genelink_check_connect read fail - %X",
dev->net->name, retval);
return retval;
}
dbg("%s: genelink_check_connect read success", dev->net->name);
return 0;
}
// allocate and initialize the private data for genelink
static int genelink_init(struct usbnet *dev)
{
struct gl_priv *priv;
// allocate the private data structure
if ((priv = kmalloc(sizeof *priv, GFP_KERNEL)) == 0) {
dbg("%s: cannot allocate private data per device",
dev->net->name);
return -ENOMEM;
}
// allocate irq urb
if ((priv->irq_urb = usb_alloc_urb(0, GFP_KERNEL)) == 0) {
dbg("%s: cannot allocate private irq urb per device",
dev->net->name);
kfree(priv);
return -ENOMEM;
}
// fill irq urb
usb_fill_int_urb(priv->irq_urb, dev->udev,
usb_rcvintpipe(dev->udev, GENELINK_INTERRUPT_PIPE),
priv->irq_buf, INTERRUPT_BUFSIZE,
gl_interrupt_complete, 0,
GENELINK_INTERRUPT_INTERVAL);
// set private data pointer
dev->priv_data = priv;
return 0;
}
// release the private data
static int genelink_free(struct usbnet *dev)
{
struct gl_priv *priv = dev->priv_data;
if (!priv)
return 0;
// FIXME: can't cancel here; it's synchronous, and
// should have happened earlier in any case (interrupt
// handling needs to be generic)
// cancel irq urb first
usb_kill_urb(priv->irq_urb);
// free irq urb
usb_free_urb(priv->irq_urb);
// free the private data structure
kfree(priv);
return 0;
}
#endif
static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
struct gl_header *header;

View File

@ -124,10 +124,11 @@
#define RX_URB_FAIL 3
/* Define these values to match your device */
#define VENDOR_ID_REALTEK 0x0bda
#define VENDOR_ID_REALTEK 0x0bda
#define VENDOR_ID_MELCO 0x0411
#define VENDOR_ID_MICRONET 0x3980
#define VENDOR_ID_MICRONET 0x3980
#define VENDOR_ID_LONGSHINE 0x07b8
#define VENDOR_ID_OQO 0x1557
#define VENDOR_ID_ZYXEL 0x0586
#define PRODUCT_ID_RTL8150 0x8150
@ -144,6 +145,7 @@ static struct usb_device_id rtl8150_table[] = {
{USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)},
{USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)},
{USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)},
{USB_DEVICE(VENDOR_ID_OQO, PRODUCT_ID_RTL8150)},
{USB_DEVICE(VENDOR_ID_ZYXEL, PRODUCT_ID_PRESTIGE)},
{}
};

View File

@ -19,8 +19,11 @@
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
{ USB_DEVICE(0x1410, 0x1130) }, /* Novatel Wireless S720 CDMA/EV-DO */
{ USB_DEVICE(0x1410, 0x2110) }, /* Novatel Wireless U720 CDMA/EV-DO */
{ USB_DEVICE(0x1410, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
{ USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */
{ USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);

View File

@ -69,6 +69,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ } /* Terminating Entry */
};

View File

@ -962,21 +962,6 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
cypress_set_termios(port, &priv->tmp_termios);
return (0);
break;
/* these are called when setting baud rate from gpsd */
case TCGETS:
if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {
return -EFAULT;
}
return (0);
break;
case TCSETS:
if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {
return -EFAULT;
}
/* here we need to call cypress_set_termios to invoke the new settings */
cypress_set_termios(port, &priv->tmp_termios);
return (0);
break;
/* This code comes from drivers/char/serial.c and ftdi_sio.c */
case TIOCMIWAIT:
while (priv != NULL) {

View File

@ -452,6 +452,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) },
{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },

View File

@ -312,8 +312,9 @@
/* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */
/* unit for PIC16's/PIC18's */
#define FTDI_CCSICDU20_0_PID 0xF9D0
#define FTDI_CCSICDU40_1_PID 0xF9D1
#define FTDI_CCSICDU20_0_PID 0xF9D0
#define FTDI_CCSICDU40_1_PID 0xF9D1
#define FTDI_CCSMACHX_2_PID 0xF9D2
/* Inside Accesso contactless reader (http://www.insidefr.com) */
#define INSIDE_ACCESSO 0xFAD0

View File

@ -14,6 +14,9 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <asm/uaccess.h>
static int debug;
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x1404, 0xcddc) },
@ -21,6 +24,26 @@ static struct usb_device_id id_table [] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
static int funsoft_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct termios t;
dbg("%s - port %d, cmd 0x%04x", __FUNCTION__, port->number, cmd);
if (cmd == TCSETSF) {
if (user_termios_to_kernel_termios(&t, (void __user *)arg))
return -EFAULT;
dbg("%s - iflag:%x oflag:%x cflag:%x lflag:%x", __FUNCTION__,
t.c_iflag, t.c_oflag, t.c_cflag, t.c_lflag);
if (!(t.c_lflag & ICANON))
return -EINVAL;
}
return -ENOIOCTLCMD;
}
static struct usb_driver funsoft_driver = {
.name = "funsoft",
.probe = usb_serial_probe,
@ -39,6 +62,7 @@ static struct usb_serial_driver funsoft_device = {
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 1,
.ioctl = funsoft_ioctl,
};
static int __init funsoft_init(void)
@ -63,3 +87,6 @@ static void __exit funsoft_exit(void)
module_init(funsoft_init);
module_exit(funsoft_exit);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");

View File

@ -87,10 +87,6 @@ static int klsi_105_write_room (struct usb_serial_port *port);
static void klsi_105_read_bulk_callback (struct urb *urb);
static void klsi_105_set_termios (struct usb_serial_port *port,
struct ktermios *old);
static int klsi_105_ioctl (struct usb_serial_port *port,
struct file * file,
unsigned int cmd,
unsigned long arg);
static void klsi_105_throttle (struct usb_serial_port *port);
static void klsi_105_unthrottle (struct usb_serial_port *port);
/*
@ -140,7 +136,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
.chars_in_buffer = klsi_105_chars_in_buffer,
.write_room = klsi_105_write_room,
.read_bulk_callback =klsi_105_read_bulk_callback,
.ioctl = klsi_105_ioctl,
.set_termios = klsi_105_set_termios,
/*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget,
@ -899,69 +894,6 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
*/
return retval;
}
static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
void __user *user_arg = (void __user *)arg;
dbg("%scmd=0x%x", __FUNCTION__, cmd);
/* Based on code from acm.c and others */
switch (cmd) {
case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */
dbg("%s - TIOCMIWAIT not handled", __FUNCTION__);
return -ENOIOCTLCMD;
case TIOCGICOUNT:
/* return count of modemline transitions */
/* TODO */
dbg("%s - TIOCGICOUNT not handled", __FUNCTION__);
return -ENOIOCTLCMD;
case TCGETS:
/* return current info to caller */
dbg("%s - TCGETS data faked/incomplete", __FUNCTION__);
if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios)))
return -EFAULT;
if (kernel_termios_to_user_termios((struct termios __user *)arg,
&priv->termios))
return -EFAULT;
return 0;
case TCSETS:
/* set port termios to the one given by the user */
dbg("%s - TCSETS not handled", __FUNCTION__);
if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios)))
return -EFAULT;
if (user_termios_to_kernel_termios(&priv->termios,
(struct termios __user *)arg))
return -EFAULT;
klsi_105_set_termios(port, &priv->termios);
return 0;
case TCSETSW: {
/* set port termios and try to wait for completion of last
* write operation */
/* We guess here. If there are not too many write urbs
* outstanding, we lie. */
/* what is the right way to wait here? schedule() ? */
/*
while (klsi_105_chars_in_buffer(port) > (NUM_URBS / 4 ) * URB_TRANSFER_BUFFER_SIZE)
schedule();
*/
return -ENOIOCTLCMD;
}
default:
dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
return(-ENOIOCTLCMD);
break;
}
return 0;
} /* klsi_105_ioctl */
static void klsi_105_throttle (struct usb_serial_port *port)
{

View File

@ -2460,12 +2460,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
tty_ldisc_deref(ld);
return 0;
case TCGETS:
if (kernel_termios_to_user_termios
((struct termios __user *)argp, tty->termios))
return -EFAULT;
return 0;
case TIOCSERGETLSR:
dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
return mos7840_get_lsr_info(mos7840_port, argp);

View File

@ -79,6 +79,7 @@ static int option_send_setup(struct usb_serial_port *port);
#define OPTION_PRODUCT_COBRA 0x6500
#define OPTION_PRODUCT_COBRA2 0x6600
#define HUAWEI_PRODUCT_E600 0x1001
#define HUAWEI_PRODUCT_E220 0x1003
#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
#define NOVATELWIRELESS_PRODUCT_U740 0x1400
#define ANYDATA_PRODUCT_ID 0x6501
@ -90,6 +91,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
@ -103,6 +105,7 @@ static struct usb_device_id option_ids1[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },

View File

@ -153,6 +153,13 @@ UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
/* Reported by <honkkis@gmail.com> */
UNUSUAL_DEV( 0x0421, 0x0433, 0x0100, 0x0100,
"Nokia",
"E70",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
/* Reported by Jon Hart <Jon.Hart@web.de> */
UNUSUAL_DEV( 0x0421, 0x0434, 0x0100, 0x0100,
"Nokia",
@ -1328,6 +1335,15 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
/* This prevents the kernel from detecting the virtual cd-drive with the
* Windows drivers. <johann.wilhelm@student.tugraz.at>
*/
UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0xffff,
"HUAWEI",
"E220 USB-UMTS Install",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_DEVICE),
/* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
UNUSUAL_DEV( 0x132b, 0x000b, 0x0001, 0x0001,
"Minolta",