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: USB: asix: Fix AX88772 device PHY selection USB: usblp.c - add Kyocera Mita FS 820 to list of "quirky" printers sisusb_con warning fixes USB: Fixed bug in endpoint release function. USB: small update to Documentation/usb/acm.txt USB storage: fix ipod ejecting issue USB Storage: unusual_devs: add supertop drives USB: omap_udc build fixes (sync with linux-omap) USB: funsoft is borken on sparc USB: fix interaction between different interfaces in an "Option" usb device UHCI: support device_may_wakeup UHCI: make test for ASUS motherboard more specific
This commit is contained in:
commit
f87c8e8054
|
@ -46,6 +46,10 @@ Abstract Control Model (USB CDC ACM) specification.
|
|||
|
||||
3Com USR ISDN Pro TA
|
||||
|
||||
Some cell phones also connect via USB. I know the following phones work:
|
||||
|
||||
SonyEricsson K800i
|
||||
|
||||
Unfortunately many modems and most ISDN TAs use proprietary interfaces and
|
||||
thus won't work with this drivers. Check for ACM compliance before buying.
|
||||
|
||||
|
|
|
@ -217,6 +217,7 @@ static const struct quirk_printer_struct quirk_printers[] = {
|
|||
{ 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
|
||||
{ 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
|
||||
{ 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
|
||||
{ 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -268,6 +268,7 @@ static void ep_device_release(struct device *dev)
|
|||
struct ep_device *ep_dev = to_ep_device(dev);
|
||||
|
||||
dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id);
|
||||
endpoint_free_minor(ep_dev);
|
||||
kfree(ep_dev);
|
||||
}
|
||||
|
||||
|
@ -349,7 +350,6 @@ void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
|
|||
sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
|
||||
sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
|
||||
sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
|
||||
endpoint_free_minor(ep_dev);
|
||||
device_unregister(&ep_dev->dev);
|
||||
endpoint->ep_dev = NULL;
|
||||
destroy_endpoint_class();
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <linux/usb_gadget.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -60,6 +61,11 @@
|
|||
/* bulk DMA seems to be behaving for both IN and OUT */
|
||||
#define USE_DMA
|
||||
|
||||
/* FIXME: OMAP2 currently has some problem in DMA mode */
|
||||
#ifdef CONFIG_ARCH_OMAP2
|
||||
#undef USE_DMA
|
||||
#endif
|
||||
|
||||
/* ISO too */
|
||||
#define USE_ISO
|
||||
|
||||
|
@ -99,7 +105,7 @@ static unsigned fifo_mode = 0;
|
|||
* boot parameter "omap_udc:fifo_mode=42"
|
||||
*/
|
||||
module_param (fifo_mode, uint, 0);
|
||||
MODULE_PARM_DESC (fifo_mode, "endpoint setup (0 == default)");
|
||||
MODULE_PARM_DESC (fifo_mode, "endpoint configuration");
|
||||
|
||||
#ifdef USE_DMA
|
||||
static unsigned use_dma = 1;
|
||||
|
@ -122,7 +128,7 @@ static const char driver_desc [] = DRIVER_DESC;
|
|||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* there's a notion of "current endpoint" for modifying endpoint
|
||||
* state, and PIO access to its FIFO.
|
||||
* state, and PIO access to its FIFO.
|
||||
*/
|
||||
|
||||
static void use_ep(struct omap_ep *ep, u16 select)
|
||||
|
@ -391,7 +397,7 @@ done(struct omap_ep *ep, struct omap_req *req, int status)
|
|||
#define FIFO_EMPTY (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY)
|
||||
#define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY)
|
||||
|
||||
static inline int
|
||||
static inline int
|
||||
write_packet(u8 *buf, struct omap_req *req, unsigned max)
|
||||
{
|
||||
unsigned len;
|
||||
|
@ -456,7 +462,7 @@ static int write_fifo(struct omap_ep *ep, struct omap_req *req)
|
|||
return is_last;
|
||||
}
|
||||
|
||||
static inline int
|
||||
static inline int
|
||||
read_packet(u8 *buf, struct omap_req *req, unsigned avail)
|
||||
{
|
||||
unsigned len;
|
||||
|
@ -542,9 +548,9 @@ static inline dma_addr_t dma_csac(unsigned lch)
|
|||
/* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
|
||||
* read before the DMA controller finished disabling the channel.
|
||||
*/
|
||||
csac = omap_readw(OMAP_DMA_CSAC(lch));
|
||||
csac = OMAP_DMA_CSAC_REG(lch);
|
||||
if (csac == 0)
|
||||
csac = omap_readw(OMAP_DMA_CSAC(lch));
|
||||
csac = OMAP_DMA_CSAC_REG(lch);
|
||||
return csac;
|
||||
}
|
||||
|
||||
|
@ -555,9 +561,9 @@ static inline dma_addr_t dma_cdac(unsigned lch)
|
|||
/* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
|
||||
* read before the DMA controller finished disabling the channel.
|
||||
*/
|
||||
cdac = omap_readw(OMAP_DMA_CDAC(lch));
|
||||
cdac = OMAP_DMA_CDAC_REG(lch);
|
||||
if (cdac == 0)
|
||||
cdac = omap_readw(OMAP_DMA_CDAC(lch));
|
||||
cdac = OMAP_DMA_CDAC_REG(lch);
|
||||
return cdac;
|
||||
}
|
||||
|
||||
|
@ -582,7 +588,7 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
|
|||
}
|
||||
|
||||
#define DMA_DEST_LAST(x) (cpu_is_omap15xx() \
|
||||
? omap_readw(OMAP_DMA_CSAC(x)) /* really: CPC */ \
|
||||
? OMAP_DMA_CSAC_REG(x) /* really: CPC */ \
|
||||
: dma_cdac(x))
|
||||
|
||||
static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
|
||||
|
@ -620,17 +626,19 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
|
|||
|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
|
||||
txdma_ctrl = UDC_TXN_EOT | length;
|
||||
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
|
||||
length, 1, sync_mode);
|
||||
length, 1, sync_mode, 0, 0);
|
||||
} else {
|
||||
length = min(length / ep->maxpacket,
|
||||
(unsigned) UDC_TXN_TSC + 1);
|
||||
txdma_ctrl = length;
|
||||
txdma_ctrl = length;
|
||||
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
|
||||
ep->ep.maxpacket >> 1, length, sync_mode);
|
||||
ep->ep.maxpacket >> 1, length, sync_mode,
|
||||
0, 0);
|
||||
length *= ep->maxpacket;
|
||||
}
|
||||
omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
|
||||
OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
|
||||
OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
|
||||
0, 0);
|
||||
|
||||
omap_start_dma(ep->lch);
|
||||
ep->dma_counter = dma_csac(ep->lch);
|
||||
|
@ -675,9 +683,11 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
|
|||
req->dma_bytes = packets * ep->ep.maxpacket;
|
||||
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
|
||||
ep->ep.maxpacket >> 1, packets,
|
||||
OMAP_DMA_SYNC_ELEMENT);
|
||||
OMAP_DMA_SYNC_ELEMENT,
|
||||
0, 0);
|
||||
omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
|
||||
OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
|
||||
OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
|
||||
0, 0);
|
||||
ep->dma_counter = DMA_DEST_LAST(ep->lch);
|
||||
|
||||
UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
|
||||
|
@ -820,7 +830,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
|
|||
omap_set_dma_dest_params(ep->lch,
|
||||
OMAP_DMA_PORT_TIPB,
|
||||
OMAP_DMA_AMODE_CONSTANT,
|
||||
(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
|
||||
(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
|
||||
0, 0);
|
||||
}
|
||||
} else {
|
||||
status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel,
|
||||
|
@ -831,7 +842,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
|
|||
omap_set_dma_src_params(ep->lch,
|
||||
OMAP_DMA_PORT_TIPB,
|
||||
OMAP_DMA_AMODE_CONSTANT,
|
||||
(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
|
||||
(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
|
||||
0, 0);
|
||||
/* EMIFF */
|
||||
omap_set_dma_dest_burst_mode(ep->lch,
|
||||
OMAP_DMA_DATA_BURST_4);
|
||||
|
@ -846,7 +858,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
|
|||
|
||||
/* channel type P: hw synch (fifo) */
|
||||
if (!cpu_is_omap15xx())
|
||||
omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
|
||||
OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2;
|
||||
}
|
||||
|
||||
just_restart:
|
||||
|
@ -893,7 +905,7 @@ static void dma_channel_release(struct omap_ep *ep)
|
|||
else
|
||||
req = NULL;
|
||||
|
||||
active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0;
|
||||
active = ((1 << 7) & OMAP_DMA_CCR_REG(ep->lch)) != 0;
|
||||
|
||||
DBG("%s release %s %cxdma%d %p\n", ep->ep.name,
|
||||
active ? "active" : "idle",
|
||||
|
@ -1117,7 +1129,7 @@ static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
|
|||
*/
|
||||
dma_channel_release(ep);
|
||||
dma_channel_claim(ep, channel);
|
||||
} else
|
||||
} else
|
||||
done(ep, req, -ECONNRESET);
|
||||
spin_unlock_irqrestore(&ep->udc->lock, flags);
|
||||
return 0;
|
||||
|
@ -1153,7 +1165,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
|
|||
|
||||
/* IN endpoints must already be idle */
|
||||
if ((ep->bEndpointAddress & USB_DIR_IN)
|
||||
&& !list_empty(&ep->queue)) {
|
||||
&& !list_empty(&ep->queue)) {
|
||||
status = -EAGAIN;
|
||||
goto done;
|
||||
}
|
||||
|
@ -1298,6 +1310,23 @@ static void pullup_disable(struct omap_udc *udc)
|
|||
UDC_SYSCON1_REG &= ~UDC_PULLUP_EN;
|
||||
}
|
||||
|
||||
static struct omap_udc *udc;
|
||||
|
||||
static void omap_udc_enable_clock(int enable)
|
||||
{
|
||||
if (udc == NULL || udc->dc_clk == NULL || udc->hhc_clk == NULL)
|
||||
return;
|
||||
|
||||
if (enable) {
|
||||
clk_enable(udc->dc_clk);
|
||||
clk_enable(udc->hhc_clk);
|
||||
udelay(100);
|
||||
} else {
|
||||
clk_disable(udc->hhc_clk);
|
||||
clk_disable(udc->dc_clk);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by whatever detects VBUS sessions: external transceiver
|
||||
* driver, or maybe GPIO0 VBUS IRQ. May request 48 MHz clock.
|
||||
|
@ -1318,10 +1347,22 @@ static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
|
|||
else
|
||||
FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510;
|
||||
}
|
||||
if (udc->dc_clk != NULL && is_active) {
|
||||
if (!udc->clk_requested) {
|
||||
omap_udc_enable_clock(1);
|
||||
udc->clk_requested = 1;
|
||||
}
|
||||
}
|
||||
if (can_pullup(udc))
|
||||
pullup_enable(udc);
|
||||
else
|
||||
pullup_disable(udc);
|
||||
if (udc->dc_clk != NULL && !is_active) {
|
||||
if (udc->clk_requested) {
|
||||
omap_udc_enable_clock(0);
|
||||
udc->clk_requested = 0;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1441,7 +1482,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
|
|||
}
|
||||
}
|
||||
|
||||
/* IN/OUT packets mean we're in the DATA or STATUS stage.
|
||||
/* IN/OUT packets mean we're in the DATA or STATUS stage.
|
||||
* This driver uses only uses protocol stalls (ep0 never halts),
|
||||
* and if we got this far the gadget driver already had a
|
||||
* chance to stall. Tries to be forgiving of host oddities.
|
||||
|
@ -1509,7 +1550,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
|
|||
} else if (stat == 0)
|
||||
UDC_CTRL_REG = UDC_SET_FIFO_EN;
|
||||
UDC_EP_NUM_REG = 0;
|
||||
|
||||
|
||||
/* activate status stage */
|
||||
if (stat == 1) {
|
||||
done(ep0, req, 0);
|
||||
|
@ -1866,7 +1907,7 @@ static void pio_out_timer(unsigned long _ep)
|
|||
|
||||
spin_lock_irqsave(&ep->udc->lock, flags);
|
||||
if (!list_empty(&ep->queue) && ep->ackwait) {
|
||||
use_ep(ep, 0);
|
||||
use_ep(ep, UDC_EP_SEL);
|
||||
stat_flg = UDC_STAT_FLG_REG;
|
||||
|
||||
if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN)
|
||||
|
@ -1876,12 +1917,12 @@ static void pio_out_timer(unsigned long _ep)
|
|||
VDBG("%s: lose, %04x\n", ep->ep.name, stat_flg);
|
||||
req = container_of(ep->queue.next,
|
||||
struct omap_req, queue);
|
||||
UDC_EP_NUM_REG = ep->bEndpointAddress | UDC_EP_SEL;
|
||||
(void) read_fifo(ep, req);
|
||||
UDC_EP_NUM_REG = ep->bEndpointAddress;
|
||||
UDC_CTRL_REG = UDC_SET_FIFO_EN;
|
||||
ep->ackwait = 1 + ep->double_buf;
|
||||
}
|
||||
} else
|
||||
deselect_ep();
|
||||
}
|
||||
mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
|
||||
spin_unlock_irqrestore(&ep->udc->lock, flags);
|
||||
|
@ -2028,7 +2069,17 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct omap_udc *udc;
|
||||
static inline int machine_needs_vbus_session(void)
|
||||
{
|
||||
return (machine_is_omap_innovator()
|
||||
|| machine_is_omap_osk()
|
||||
|| machine_is_omap_apollon()
|
||||
#ifndef CONFIG_MACH_OMAP_H4_OTG
|
||||
|| machine_is_omap_h4()
|
||||
#endif
|
||||
|| machine_is_sx1()
|
||||
);
|
||||
}
|
||||
|
||||
int usb_gadget_register_driver (struct usb_gadget_driver *driver)
|
||||
{
|
||||
|
@ -2070,6 +2121,9 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
|
|||
udc->gadget.dev.driver = &driver->driver;
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
|
||||
if (udc->dc_clk != NULL)
|
||||
omap_udc_enable_clock(1);
|
||||
|
||||
status = driver->bind (&udc->gadget);
|
||||
if (status) {
|
||||
DBG("bind to %s --> %d\n", driver->driver.name, status);
|
||||
|
@ -2103,10 +2157,12 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
|
|||
/* boards that don't have VBUS sensing can't autogate 48MHz;
|
||||
* can't enter deep sleep while a gadget driver is active.
|
||||
*/
|
||||
if (machine_is_omap_innovator() || machine_is_omap_osk())
|
||||
if (machine_needs_vbus_session())
|
||||
omap_vbus_session(&udc->gadget, 1);
|
||||
|
||||
done:
|
||||
if (udc->dc_clk != NULL)
|
||||
omap_udc_enable_clock(0);
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(usb_gadget_register_driver);
|
||||
|
@ -2121,7 +2177,10 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
|
|||
if (!driver || driver != udc->driver || !driver->unbind)
|
||||
return -EINVAL;
|
||||
|
||||
if (machine_is_omap_innovator() || machine_is_omap_osk())
|
||||
if (udc->dc_clk != NULL)
|
||||
omap_udc_enable_clock(1);
|
||||
|
||||
if (machine_needs_vbus_session())
|
||||
omap_vbus_session(&udc->gadget, 0);
|
||||
|
||||
if (udc->transceiver)
|
||||
|
@ -2137,6 +2196,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
|
|||
udc->gadget.dev.driver = NULL;
|
||||
udc->driver = NULL;
|
||||
|
||||
if (udc->dc_clk != NULL)
|
||||
omap_udc_enable_clock(0);
|
||||
DBG("unregistered driver '%s'\n", driver->driver.name);
|
||||
return status;
|
||||
}
|
||||
|
@ -2219,7 +2280,7 @@ static char *trx_mode(unsigned m, int enabled)
|
|||
case 0: return enabled ? "*6wire" : "unused";
|
||||
case 1: return "4wire";
|
||||
case 2: return "3wire";
|
||||
case 3: return "6wire";
|
||||
case 3: return "6wire";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
@ -2228,11 +2289,18 @@ static int proc_otg_show(struct seq_file *s)
|
|||
{
|
||||
u32 tmp;
|
||||
u32 trans;
|
||||
char *ctrl_name;
|
||||
|
||||
tmp = OTG_REV_REG;
|
||||
trans = USB_TRANSCEIVER_CTRL_REG;
|
||||
seq_printf(s, "\nOTG rev %d.%d, transceiver_ctrl %05x\n",
|
||||
tmp >> 4, tmp & 0xf, trans);
|
||||
if (cpu_is_omap24xx()) {
|
||||
ctrl_name = "control_devconf";
|
||||
trans = CONTROL_DEVCONF_REG;
|
||||
} else {
|
||||
ctrl_name = "tranceiver_ctrl";
|
||||
trans = USB_TRANSCEIVER_CTRL_REG;
|
||||
}
|
||||
seq_printf(s, "\nOTG rev %d.%d, %s %05x\n",
|
||||
tmp >> 4, tmp & 0xf, ctrl_name, trans);
|
||||
tmp = OTG_SYSCON_1_REG;
|
||||
seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
|
||||
FOURBITS "\n", tmp,
|
||||
|
@ -2307,7 +2375,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
|
|||
driver_desc,
|
||||
use_dma ? " (dma)" : "");
|
||||
|
||||
tmp = UDC_REV_REG & 0xff;
|
||||
tmp = UDC_REV_REG & 0xff;
|
||||
seq_printf(s,
|
||||
"UDC rev %d.%d, fifo mode %d, gadget %s\n"
|
||||
"hmc %d, transceiver %s\n",
|
||||
|
@ -2315,11 +2383,16 @@ static int proc_udc_show(struct seq_file *s, void *_)
|
|||
fifo_mode,
|
||||
udc->driver ? udc->driver->driver.name : "(none)",
|
||||
HMC,
|
||||
udc->transceiver ? udc->transceiver->label : "(none)");
|
||||
seq_printf(s, "ULPD control %04x req %04x status %04x\n",
|
||||
__REG16(ULPD_CLOCK_CTRL),
|
||||
__REG16(ULPD_SOFT_REQ),
|
||||
__REG16(ULPD_STATUS_REQ));
|
||||
udc->transceiver
|
||||
? udc->transceiver->label
|
||||
: ((cpu_is_omap1710() || cpu_is_omap24xx())
|
||||
? "external" : "(none)"));
|
||||
if (cpu_class_is_omap1()) {
|
||||
seq_printf(s, "ULPD control %04x req %04x status %04x\n",
|
||||
__REG16(ULPD_CLOCK_CTRL),
|
||||
__REG16(ULPD_SOFT_REQ),
|
||||
__REG16(ULPD_STATUS_REQ));
|
||||
}
|
||||
|
||||
/* OTG controller registers */
|
||||
if (!cpu_is_omap15xx())
|
||||
|
@ -2504,9 +2577,10 @@ omap_ep_setup(char *name, u8 addr, u8 type,
|
|||
dbuf = 1;
|
||||
} else {
|
||||
/* double-buffering "not supported" on 15xx,
|
||||
* and ignored for PIO-IN on 16xx
|
||||
* and ignored for PIO-IN on newer chips
|
||||
* (for more reliable behavior)
|
||||
*/
|
||||
if (!use_dma || cpu_is_omap15xx())
|
||||
if (!use_dma || cpu_is_omap15xx() || cpu_is_omap24xx())
|
||||
dbuf = 0;
|
||||
|
||||
switch (maxp) {
|
||||
|
@ -2549,7 +2623,7 @@ omap_ep_setup(char *name, u8 addr, u8 type,
|
|||
ep->bEndpointAddress = addr;
|
||||
ep->bmAttributes = type;
|
||||
ep->double_buf = dbuf;
|
||||
ep->udc = udc;
|
||||
ep->udc = udc;
|
||||
|
||||
ep->ep.name = ep->name;
|
||||
ep->ep.ops = &omap_ep_ops;
|
||||
|
@ -2709,15 +2783,37 @@ static int __init omap_udc_probe(struct platform_device *pdev)
|
|||
struct otg_transceiver *xceiv = NULL;
|
||||
const char *type = NULL;
|
||||
struct omap_usb_config *config = pdev->dev.platform_data;
|
||||
struct clk *dc_clk;
|
||||
struct clk *hhc_clk;
|
||||
|
||||
/* NOTE: "knows" the order of the resources! */
|
||||
if (!request_mem_region(pdev->resource[0].start,
|
||||
if (!request_mem_region(pdev->resource[0].start,
|
||||
pdev->resource[0].end - pdev->resource[0].start + 1,
|
||||
driver_name)) {
|
||||
DBG("request_mem_region failed\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (cpu_is_omap16xx()) {
|
||||
dc_clk = clk_get(&pdev->dev, "usb_dc_ck");
|
||||
hhc_clk = clk_get(&pdev->dev, "usb_hhc_ck");
|
||||
BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
|
||||
/* can't use omap_udc_enable_clock yet */
|
||||
clk_enable(dc_clk);
|
||||
clk_enable(hhc_clk);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (cpu_is_omap24xx()) {
|
||||
dc_clk = clk_get(&pdev->dev, "usb_fck");
|
||||
hhc_clk = clk_get(&pdev->dev, "usb_l4_ick");
|
||||
BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
|
||||
/* can't use omap_udc_enable_clock yet */
|
||||
clk_enable(dc_clk);
|
||||
clk_enable(hhc_clk);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
INFO("OMAP UDC rev %d.%d%s\n",
|
||||
UDC_REV_REG >> 4, UDC_REV_REG & 0xf,
|
||||
config->otg ? ", Mini-AB" : "");
|
||||
|
@ -2727,7 +2823,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
|
|||
hmc = HMC_1510;
|
||||
type = "(unknown)";
|
||||
|
||||
if (machine_is_omap_innovator()) {
|
||||
if (machine_is_omap_innovator() || machine_is_sx1()) {
|
||||
/* just set up software VBUS detect, and then
|
||||
* later rig it so we always report VBUS.
|
||||
* FIXME without really sensing VBUS, we can't
|
||||
|
@ -2756,6 +2852,15 @@ static int __init omap_udc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
hmc = HMC_1610;
|
||||
|
||||
if (cpu_is_omap24xx()) {
|
||||
/* this could be transceiverless in one of the
|
||||
* "we don't need to know" modes.
|
||||
*/
|
||||
type = "external";
|
||||
goto known;
|
||||
}
|
||||
|
||||
switch (hmc) {
|
||||
case 0: /* POWERUP DEFAULT == 0 */
|
||||
case 4:
|
||||
|
@ -2794,6 +2899,7 @@ bad_on_1710:
|
|||
goto cleanup0;
|
||||
}
|
||||
}
|
||||
known:
|
||||
INFO("hmc mode %d, %s transceiver\n", hmc, type);
|
||||
|
||||
/* a "gadget" abstracts/virtualizes the controller */
|
||||
|
@ -2818,8 +2924,8 @@ bad_on_1710:
|
|||
status = request_irq(pdev->resource[1].start, omap_udc_irq,
|
||||
IRQF_SAMPLE_RANDOM, driver_name, udc);
|
||||
if (status != 0) {
|
||||
ERR( "can't get irq %ld, err %d\n",
|
||||
pdev->resource[1].start, status);
|
||||
ERR("can't get irq %d, err %d\n",
|
||||
(int) pdev->resource[1].start, status);
|
||||
goto cleanup1;
|
||||
}
|
||||
|
||||
|
@ -2827,24 +2933,41 @@ bad_on_1710:
|
|||
status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
|
||||
IRQF_SAMPLE_RANDOM, "omap_udc pio", udc);
|
||||
if (status != 0) {
|
||||
ERR( "can't get irq %ld, err %d\n",
|
||||
pdev->resource[2].start, status);
|
||||
ERR("can't get irq %d, err %d\n",
|
||||
(int) pdev->resource[2].start, status);
|
||||
goto cleanup2;
|
||||
}
|
||||
#ifdef USE_ISO
|
||||
status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
|
||||
IRQF_DISABLED, "omap_udc iso", udc);
|
||||
if (status != 0) {
|
||||
ERR("can't get irq %ld, err %d\n",
|
||||
pdev->resource[3].start, status);
|
||||
ERR("can't get irq %d, err %d\n",
|
||||
(int) pdev->resource[3].start, status);
|
||||
goto cleanup3;
|
||||
}
|
||||
#endif
|
||||
if (cpu_is_omap16xx()) {
|
||||
udc->dc_clk = dc_clk;
|
||||
udc->hhc_clk = hhc_clk;
|
||||
clk_disable(hhc_clk);
|
||||
clk_disable(dc_clk);
|
||||
}
|
||||
|
||||
if (cpu_is_omap24xx()) {
|
||||
udc->dc_clk = dc_clk;
|
||||
udc->hhc_clk = hhc_clk;
|
||||
/* FIXME OMAP2 don't release hhc & dc clock */
|
||||
#if 0
|
||||
clk_disable(hhc_clk);
|
||||
clk_disable(dc_clk);
|
||||
#endif
|
||||
}
|
||||
|
||||
create_proc_file();
|
||||
device_add(&udc->gadget.dev);
|
||||
return 0;
|
||||
|
||||
status = device_add(&udc->gadget.dev);
|
||||
if (!status)
|
||||
return status;
|
||||
/* If fail, fall through */
|
||||
#ifdef USE_ISO
|
||||
cleanup3:
|
||||
free_irq(pdev->resource[2].start, udc);
|
||||
|
@ -2860,8 +2983,17 @@ cleanup1:
|
|||
cleanup0:
|
||||
if (xceiv)
|
||||
put_device(xceiv->dev);
|
||||
|
||||
if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
|
||||
clk_disable(hhc_clk);
|
||||
clk_disable(dc_clk);
|
||||
clk_put(hhc_clk);
|
||||
clk_put(dc_clk);
|
||||
}
|
||||
|
||||
release_mem_region(pdev->resource[0].start,
|
||||
pdev->resource[0].end - pdev->resource[0].start + 1);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -2891,6 +3023,13 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
|
|||
free_irq(pdev->resource[2].start, udc);
|
||||
free_irq(pdev->resource[1].start, udc);
|
||||
|
||||
if (udc->dc_clk) {
|
||||
if (udc->clk_requested)
|
||||
omap_udc_enable_clock(0);
|
||||
clk_put(udc->hhc_clk);
|
||||
clk_put(udc->dc_clk);
|
||||
}
|
||||
|
||||
release_mem_region(pdev->resource[0].start,
|
||||
pdev->resource[0].end - pdev->resource[0].start + 1);
|
||||
|
||||
|
|
|
@ -175,6 +175,9 @@ struct omap_udc {
|
|||
unsigned ep0_reset_config:1;
|
||||
unsigned ep0_setup:1;
|
||||
struct completion *done;
|
||||
struct clk *dc_clk;
|
||||
struct clk *hhc_clk;
|
||||
unsigned clk_requested:1;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
|
|
@ -209,24 +209,16 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
|
|||
|
||||
static int remote_wakeup_is_broken(struct uhci_hcd *uhci)
|
||||
{
|
||||
static struct dmi_system_id broken_wakeup_table[] = {
|
||||
{
|
||||
.ident = "Asus A7V8X",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "A7V8X"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "REV 1.xx"),
|
||||
}
|
||||
},
|
||||
{ }
|
||||
};
|
||||
int port;
|
||||
char *sys_info;
|
||||
static char bad_Asus_board[] = "A7V8X";
|
||||
|
||||
/* One of Asus's motherboards has a bug which causes it to
|
||||
* wake up immediately from suspend-to-RAM if any of the ports
|
||||
* are connected. In such cases we will not set EGSM.
|
||||
*/
|
||||
if (dmi_check_system(broken_wakeup_table)) {
|
||||
sys_info = dmi_get_system_info(DMI_BOARD_NAME);
|
||||
if (sys_info && !strcmp(sys_info, bad_Asus_board)) {
|
||||
for (port = 0; port < uhci->rh_numports; ++port) {
|
||||
if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
|
||||
USBPORTSC_CCS)
|
||||
|
@ -265,7 +257,9 @@ __acquires(uhci->lock)
|
|||
int_enable = USBINTR_RESUME;
|
||||
if (remote_wakeup_is_broken(uhci))
|
||||
egsm_enable = 0;
|
||||
if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable)
|
||||
if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
|
||||
!device_may_wakeup(
|
||||
&uhci_to_hcd(uhci)->self.root_hub->dev))
|
||||
uhci->working_RD = int_enable = 0;
|
||||
|
||||
outw(int_enable, uhci->io_addr + USBINTR);
|
||||
|
|
|
@ -403,7 +403,7 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
|
|||
|
||||
|
||||
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
|
||||
(u32)SISUSB_HADDR(x, y), 2, &written);
|
||||
(long)SISUSB_HADDR(x, y), 2, &written);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
}
|
||||
|
@ -438,7 +438,7 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
|
|||
}
|
||||
|
||||
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
|
||||
(u32)SISUSB_HADDR(x, y), count * 2, &written);
|
||||
(long)SISUSB_HADDR(x, y), count * 2, &written);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
}
|
||||
|
@ -492,7 +492,7 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
|
|||
|
||||
|
||||
sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
|
||||
(u32)SISUSB_HADDR(x, y), length, &written);
|
||||
(long)SISUSB_HADDR(x, y), length, &written);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ sisusbcon_bmove(struct vc_data *c, int sy, int sx,
|
|||
|
||||
|
||||
sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
|
||||
(u32)SISUSB_HADDR(dx, dy), length, &written);
|
||||
(long)SISUSB_HADDR(dx, dy), length, &written);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
}
|
||||
|
@ -612,7 +612,7 @@ sisusbcon_switch(struct vc_data *c)
|
|||
length);
|
||||
|
||||
sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
|
||||
(u32)SISUSB_HADDR(0, 0),
|
||||
(long)SISUSB_HADDR(0, 0),
|
||||
length, &written);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
|
@ -939,7 +939,7 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
|
|||
}
|
||||
|
||||
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
|
||||
(u32)SISUSB_HADDR(0, t), length, &written);
|
||||
(long)SISUSB_HADDR(0, t), length, &written);
|
||||
|
||||
mutex_unlock(&sisusb->lock);
|
||||
|
||||
|
|
|
@ -920,7 +920,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
|
|||
goto out2;
|
||||
|
||||
if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
|
||||
0x0000, 0, 0, buf)) < 0) {
|
||||
1, 0, 0, buf)) < 0) {
|
||||
dbg("Select PHY #1 failed: %d", ret);
|
||||
goto out2;
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ config USB_SERIAL_FTDI_SIO
|
|||
|
||||
config USB_SERIAL_FUNSOFT
|
||||
tristate "USB Fundamental Software Dongle Driver"
|
||||
depends on USB_SERIAL
|
||||
depends on USB_SERIAL && !(SPARC || SPARC64)
|
||||
---help---
|
||||
Say Y here if you want to use the Fundamental Software dongle.
|
||||
|
||||
|
|
|
@ -625,6 +625,9 @@ static int option_send_setup(struct usb_serial_port *port)
|
|||
|
||||
dbg("%s", __FUNCTION__);
|
||||
|
||||
if (port->number != 0)
|
||||
return 0;
|
||||
|
||||
portdata = usb_get_serial_port_data(port);
|
||||
|
||||
if (port->tty) {
|
||||
|
|
|
@ -728,7 +728,7 @@ UNUSUAL_DEV( 0x05ac, 0x1204, 0x0000, 0x9999,
|
|||
"Apple",
|
||||
"iPod",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_FIX_CAPACITY ),
|
||||
US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
|
||||
|
||||
UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999,
|
||||
"Apple",
|
||||
|
@ -1358,6 +1358,21 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110,
|
|||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* Reported by Francesco Foresti <frafore@tiscali.it> */
|
||||
UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201,
|
||||
"Super Top",
|
||||
"IDE DEVICE",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* Reported by Robert Schedel <r.schedel@yahoo.de>
|
||||
* Note: this is a 'super top' device like the above 14cd/6600 device */
|
||||
UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
|
||||
"Teac",
|
||||
"HD-35PUK-B",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
|
||||
* and Renato Perini <rperini@email.it>
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue