Sfoglia il codice sorgente

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
Linus Torvalds 19 anni fa
parent
commit
f87c8e8054

+ 4 - 0
Documentation/usb/acm.txt

@@ -46,6 +46,10 @@ Abstract Control Model (USB CDC ACM) specification.
 
 
 	3Com USR ISDN Pro TA
 	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
   Unfortunately many modems and most ISDN TAs use proprietary interfaces and
 thus won't work with this drivers. Check for ACM compliance before buying.
 thus won't work with this drivers. Check for ACM compliance before buying.
 
 

+ 1 - 0
drivers/usb/class/usblp.c

@@ -217,6 +217,7 @@ static const struct quirk_printer_struct quirk_printers[] = {
 	{ 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
 	{ 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
 	{ 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
 	{ 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
 	{ 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (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 }
 	{ 0, 0 }
 };
 };
 
 

+ 1 - 1
drivers/usb/core/endpoint.c

@@ -268,6 +268,7 @@ static void ep_device_release(struct device *dev)
 	struct ep_device *ep_dev = to_ep_device(dev);
 	struct ep_device *ep_dev = to_ep_device(dev);
 
 
 	dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id);
 	dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id);
+	endpoint_free_minor(ep_dev);
 	kfree(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);
 		sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
 		sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
 		sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
 		sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
 		sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
-		endpoint_free_minor(ep_dev);
 		device_unregister(&ep_dev->dev);
 		device_unregister(&ep_dev->dev);
 		endpoint->ep_dev = NULL;
 		endpoint->ep_dev = NULL;
 		destroy_endpoint_class();
 		destroy_endpoint_class();

+ 192 - 53
drivers/usb/gadget/omap_udc.c

@@ -42,6 +42,7 @@
 #include <linux/usb_gadget.h>
 #include <linux/usb_gadget.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/otg.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
+#include <linux/clk.h>
 
 
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/io.h>
@@ -60,6 +61,11 @@
 /* bulk DMA seems to be behaving for both IN and OUT */
 /* bulk DMA seems to be behaving for both IN and OUT */
 #define	USE_DMA
 #define	USE_DMA
 
 
+/* FIXME: OMAP2 currently has some problem in DMA mode */
+#ifdef CONFIG_ARCH_OMAP2
+#undef USE_DMA
+#endif
+
 /* ISO too */
 /* ISO too */
 #define	USE_ISO
 #define	USE_ISO
 
 
@@ -99,7 +105,7 @@ static unsigned fifo_mode = 0;
  * boot parameter "omap_udc:fifo_mode=42"
  * boot parameter "omap_udc:fifo_mode=42"
  */
  */
 module_param (fifo_mode, uint, 0);
 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
 #ifdef	USE_DMA
 static unsigned use_dma = 1;
 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
 /* 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)
 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_EMPTY	(UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY)
 #define FIFO_UNREADABLE (UDC_EP_HALTED | 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)
 write_packet(u8 *buf, struct omap_req *req, unsigned max)
 {
 {
 	unsigned	len;
 	unsigned	len;
@@ -456,7 +462,7 @@ static int write_fifo(struct omap_ep *ep, struct omap_req *req)
 	return is_last;
 	return is_last;
 }
 }
 
 
-static inline int 
+static inline int
 read_packet(u8 *buf, struct omap_req *req, unsigned avail)
 read_packet(u8 *buf, struct omap_req *req, unsigned avail)
 {
 {
 	unsigned	len;
 	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
 	/* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
 	 * read before the DMA controller finished disabling the channel.
 	 * 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)
 	if (csac == 0)
-		csac = omap_readw(OMAP_DMA_CSAC(lch));
+		csac = OMAP_DMA_CSAC_REG(lch);
 	return csac;
 	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
 	/* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
 	 * read before the DMA controller finished disabling the channel.
 	 * 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)
 	if (cdac == 0)
-		cdac = omap_readw(OMAP_DMA_CDAC(lch));
+		cdac = OMAP_DMA_CDAC_REG(lch);
 	return cdac;
 	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() \
 #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))
 		: dma_cdac(x))
 
 
 static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
 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)) {
 			|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
 		txdma_ctrl = UDC_TXN_EOT | length;
 		txdma_ctrl = UDC_TXN_EOT | length;
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-				length, 1, sync_mode);
+				length, 1, sync_mode, 0, 0);
 	} else {
 	} else {
 		length = min(length / ep->maxpacket,
 		length = min(length / ep->maxpacket,
 				(unsigned) UDC_TXN_TSC + 1);
 				(unsigned) UDC_TXN_TSC + 1);
- 		txdma_ctrl = length;
+		txdma_ctrl = length;
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
 		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;
 		length *= ep->maxpacket;
 	}
 	}
 	omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
 	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);
 	omap_start_dma(ep->lch);
 	ep->dma_counter = dma_csac(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;
 	req->dma_bytes = packets * ep->ep.maxpacket;
 	omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
 	omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
 			ep->ep.maxpacket >> 1, packets,
 			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_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);
 	ep->dma_counter = DMA_DEST_LAST(ep->lch);
 
 
 	UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
 	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_set_dma_dest_params(ep->lch,
 				OMAP_DMA_PORT_TIPB,
 				OMAP_DMA_PORT_TIPB,
 				OMAP_DMA_AMODE_CONSTANT,
 				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 {
 	} else {
 		status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel,
 		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_set_dma_src_params(ep->lch,
 				OMAP_DMA_PORT_TIPB,
 				OMAP_DMA_PORT_TIPB,
 				OMAP_DMA_AMODE_CONSTANT,
 				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 */
 			/* EMIFF */
 			omap_set_dma_dest_burst_mode(ep->lch,
 			omap_set_dma_dest_burst_mode(ep->lch,
 						OMAP_DMA_DATA_BURST_4);
 						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) */
 		/* channel type P: hw synch (fifo) */
 		if (!cpu_is_omap15xx())
 		if (!cpu_is_omap15xx())
-			omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
+			OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2;
 	}
 	}
 
 
 just_restart:
 just_restart:
@@ -893,7 +905,7 @@ static void dma_channel_release(struct omap_ep *ep)
 	else
 	else
 		req = NULL;
 		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,
 	DBG("%s release %s %cxdma%d %p\n", ep->ep.name,
 			active ? "active" : "idle",
 			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_release(ep);
 		dma_channel_claim(ep, channel);
 		dma_channel_claim(ep, channel);
-	} else 
+	} else
 		done(ep, req, -ECONNRESET);
 		done(ep, req, -ECONNRESET);
 	spin_unlock_irqrestore(&ep->udc->lock, flags);
 	spin_unlock_irqrestore(&ep->udc->lock, flags);
 	return 0;
 	return 0;
@@ -1153,7 +1165,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
 
 
 		/* IN endpoints must already be idle */
 		/* IN endpoints must already be idle */
 		if ((ep->bEndpointAddress & USB_DIR_IN)
 		if ((ep->bEndpointAddress & USB_DIR_IN)
-				&& !list_empty(&ep->queue)) { 
+				&& !list_empty(&ep->queue)) {
 			status = -EAGAIN;
 			status = -EAGAIN;
 			goto done;
 			goto done;
 		}
 		}
@@ -1298,6 +1310,23 @@ static void pullup_disable(struct omap_udc *udc)
 	UDC_SYSCON1_REG &= ~UDC_PULLUP_EN;
 	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
  * Called by whatever detects VBUS sessions:  external transceiver
  * driver, or maybe GPIO0 VBUS IRQ.  May request 48 MHz clock.
  * 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
 		else
 			FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510;
 			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))
 	if (can_pullup(udc))
 		pullup_enable(udc);
 		pullup_enable(udc);
 	else
 	else
 		pullup_disable(udc);
 		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);
 	spin_unlock_irqrestore(&udc->lock, flags);
 	return 0;
 	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),
 	 * This driver uses only uses protocol stalls (ep0 never halts),
 	 * and if we got this far the gadget driver already had a
 	 * and if we got this far the gadget driver already had a
 	 * chance to stall.  Tries to be forgiving of host oddities.
 	 * 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)
 				} else if (stat == 0)
 					UDC_CTRL_REG = UDC_SET_FIFO_EN;
 					UDC_CTRL_REG = UDC_SET_FIFO_EN;
 				UDC_EP_NUM_REG = 0;
 				UDC_EP_NUM_REG = 0;
-				
+
 				/* activate status stage */
 				/* activate status stage */
 				if (stat == 1) {
 				if (stat == 1) {
 					done(ep0, req, 0);
 					done(ep0, req, 0);
@@ -1866,7 +1907,7 @@ static void pio_out_timer(unsigned long _ep)
 
 
 	spin_lock_irqsave(&ep->udc->lock, flags);
 	spin_lock_irqsave(&ep->udc->lock, flags);
 	if (!list_empty(&ep->queue) && ep->ackwait) {
 	if (!list_empty(&ep->queue) && ep->ackwait) {
-		use_ep(ep, 0);
+		use_ep(ep, UDC_EP_SEL);
 		stat_flg = UDC_STAT_FLG_REG;
 		stat_flg = UDC_STAT_FLG_REG;
 
 
 		if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN)
 		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);
 			VDBG("%s: lose, %04x\n", ep->ep.name, stat_flg);
 			req = container_of(ep->queue.next,
 			req = container_of(ep->queue.next,
 					struct omap_req, queue);
 					struct omap_req, queue);
-			UDC_EP_NUM_REG = ep->bEndpointAddress | UDC_EP_SEL;
 			(void) read_fifo(ep, req);
 			(void) read_fifo(ep, req);
 			UDC_EP_NUM_REG = ep->bEndpointAddress;
 			UDC_EP_NUM_REG = ep->bEndpointAddress;
 			UDC_CTRL_REG = UDC_SET_FIFO_EN;
 			UDC_CTRL_REG = UDC_SET_FIFO_EN;
 			ep->ackwait = 1 + ep->double_buf;
 			ep->ackwait = 1 + ep->double_buf;
-		}
+		} else
+			deselect_ep();
 	}
 	}
 	mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
 	mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
 	spin_unlock_irqrestore(&ep->udc->lock, flags);
 	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)
 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;
 	udc->gadget.dev.driver = &driver->driver;
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 
+	if (udc->dc_clk != NULL)
+		omap_udc_enable_clock(1);
+
 	status = driver->bind (&udc->gadget);
 	status = driver->bind (&udc->gadget);
 	if (status) {
 	if (status) {
 		DBG("bind to %s --> %d\n", driver->driver.name, 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;
 	/* boards that don't have VBUS sensing can't autogate 48MHz;
 	 * can't enter deep sleep while a gadget driver is active.
 	 * 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);
 		omap_vbus_session(&udc->gadget, 1);
 
 
 done:
 done:
+	if (udc->dc_clk != NULL)
+		omap_udc_enable_clock(0);
 	return status;
 	return status;
 }
 }
 EXPORT_SYMBOL(usb_gadget_register_driver);
 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)
 	if (!driver || driver != udc->driver || !driver->unbind)
 		return -EINVAL;
 		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);
 		omap_vbus_session(&udc->gadget, 0);
 
 
 	if (udc->transceiver)
 	if (udc->transceiver)
@@ -2137,6 +2196,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 	udc->gadget.dev.driver = NULL;
 	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
+	if (udc->dc_clk != NULL)
+		omap_udc_enable_clock(0);
 	DBG("unregistered driver '%s'\n", driver->driver.name);
 	DBG("unregistered driver '%s'\n", driver->driver.name);
 	return status;
 	return status;
 }
 }
@@ -2219,7 +2280,7 @@ static char *trx_mode(unsigned m, int enabled)
 	case 0:		return enabled ? "*6wire" : "unused";
 	case 0:		return enabled ? "*6wire" : "unused";
 	case 1:		return "4wire";
 	case 1:		return "4wire";
 	case 2:		return "3wire";
 	case 2:		return "3wire";
-	case 3: 	return "6wire";
+	case 3:		return "6wire";
 	default:	return "unknown";
 	default:	return "unknown";
 	}
 	}
 }
 }
@@ -2228,11 +2289,18 @@ static int proc_otg_show(struct seq_file *s)
 {
 {
 	u32		tmp;
 	u32		tmp;
 	u32		trans;
 	u32		trans;
+	char		*ctrl_name;
 
 
 	tmp = OTG_REV_REG;
 	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;
 	tmp = OTG_SYSCON_1_REG;
 	seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
 	seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
 			FOURBITS "\n", tmp,
 			FOURBITS "\n", tmp,
@@ -2307,7 +2375,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
 		driver_desc,
 		driver_desc,
 		use_dma ?  " (dma)" : "");
 		use_dma ?  " (dma)" : "");
 
 
-	tmp = UDC_REV_REG & 0xff; 
+	tmp = UDC_REV_REG & 0xff;
 	seq_printf(s,
 	seq_printf(s,
 		"UDC rev %d.%d, fifo mode %d, gadget %s\n"
 		"UDC rev %d.%d, fifo mode %d, gadget %s\n"
 		"hmc %d, transceiver %s\n",
 		"hmc %d, transceiver %s\n",
@@ -2315,11 +2383,16 @@ static int proc_udc_show(struct seq_file *s, void *_)
 		fifo_mode,
 		fifo_mode,
 		udc->driver ? udc->driver->driver.name : "(none)",
 		udc->driver ? udc->driver->driver.name : "(none)",
 		HMC,
 		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 */
 	/* OTG controller registers */
 	if (!cpu_is_omap15xx())
 	if (!cpu_is_omap15xx())
@@ -2504,9 +2577,10 @@ omap_ep_setup(char *name, u8 addr, u8 type,
 		dbuf = 1;
 		dbuf = 1;
 	} else {
 	} else {
 		/* double-buffering "not supported" on 15xx,
 		/* 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;
 			dbuf = 0;
 
 
 		switch (maxp) {
 		switch (maxp) {
@@ -2549,7 +2623,7 @@ omap_ep_setup(char *name, u8 addr, u8 type,
 	ep->bEndpointAddress = addr;
 	ep->bEndpointAddress = addr;
 	ep->bmAttributes = type;
 	ep->bmAttributes = type;
 	ep->double_buf = dbuf;
 	ep->double_buf = dbuf;
-	ep->udc = udc; 
+	ep->udc = udc;
 
 
 	ep->ep.name = ep->name;
 	ep->ep.name = ep->name;
 	ep->ep.ops = &omap_ep_ops;
 	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;
 	struct otg_transceiver	*xceiv = NULL;
 	const char		*type = NULL;
 	const char		*type = NULL;
 	struct omap_usb_config	*config = pdev->dev.platform_data;
 	struct omap_usb_config	*config = pdev->dev.platform_data;
+	struct clk		*dc_clk;
+	struct clk		*hhc_clk;
 
 
 	/* NOTE:  "knows" the order of the resources! */
 	/* 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,
 			pdev->resource[0].end - pdev->resource[0].start + 1,
 			driver_name)) {
 			driver_name)) {
 		DBG("request_mem_region failed\n");
 		DBG("request_mem_region failed\n");
 		return -EBUSY;
 		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",
 	INFO("OMAP UDC rev %d.%d%s\n",
 		UDC_REV_REG >> 4, UDC_REV_REG & 0xf,
 		UDC_REV_REG >> 4, UDC_REV_REG & 0xf,
 		config->otg ? ", Mini-AB" : "");
 		config->otg ? ", Mini-AB" : "");
@@ -2727,7 +2823,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 		hmc = HMC_1510;
 		hmc = HMC_1510;
 		type = "(unknown)";
 		type = "(unknown)";
 
 
-		if (machine_is_omap_innovator()) {
+		if (machine_is_omap_innovator() || machine_is_sx1()) {
 			/* just set up software VBUS detect, and then
 			/* just set up software VBUS detect, and then
 			 * later rig it so we always report VBUS.
 			 * later rig it so we always report VBUS.
 			 * FIXME without really sensing VBUS, we can't
 			 * 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;
 		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) {
 		switch (hmc) {
 		case 0:			/* POWERUP DEFAULT == 0 */
 		case 0:			/* POWERUP DEFAULT == 0 */
 		case 4:
 		case 4:
@@ -2794,6 +2899,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 			goto cleanup0;
 			goto cleanup0;
 		}
 		}
 	}
 	}
+known:
 	INFO("hmc mode %d, %s transceiver\n", hmc, type);
 	INFO("hmc mode %d, %s transceiver\n", hmc, type);
 
 
 	/* a "gadget" abstracts/virtualizes the controller */
 	/* a "gadget" abstracts/virtualizes the controller */
@@ -2818,8 +2924,8 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 	status = request_irq(pdev->resource[1].start, omap_udc_irq,
 	status = request_irq(pdev->resource[1].start, omap_udc_irq,
 			IRQF_SAMPLE_RANDOM, driver_name, udc);
 			IRQF_SAMPLE_RANDOM, driver_name, udc);
 	if (status != 0) {
 	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;
 		goto cleanup1;
 	}
 	}
 
 
@@ -2827,24 +2933,41 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 	status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
 	status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
 			IRQF_SAMPLE_RANDOM, "omap_udc pio", udc);
 			IRQF_SAMPLE_RANDOM, "omap_udc pio", udc);
 	if (status != 0) {
 	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;
 		goto cleanup2;
 	}
 	}
 #ifdef	USE_ISO
 #ifdef	USE_ISO
 	status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
 	status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
 			IRQF_DISABLED, "omap_udc iso", udc);
 			IRQF_DISABLED, "omap_udc iso", udc);
 	if (status != 0) {
 	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;
 		goto cleanup3;
 	}
 	}
 #endif
 #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();
 	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
 #ifdef	USE_ISO
 cleanup3:
 cleanup3:
 	free_irq(pdev->resource[2].start, udc);
 	free_irq(pdev->resource[2].start, udc);
@@ -2860,8 +2983,17 @@ static int __init omap_udc_probe(struct platform_device *pdev)
 cleanup0:
 cleanup0:
 	if (xceiv)
 	if (xceiv)
 		put_device(xceiv->dev);
 		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,
 	release_mem_region(pdev->resource[0].start,
 			pdev->resource[0].end - pdev->resource[0].start + 1);
 			pdev->resource[0].end - pdev->resource[0].start + 1);
+
 	return status;
 	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[2].start, udc);
 	free_irq(pdev->resource[1].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,
 	release_mem_region(pdev->resource[0].start,
 			pdev->resource[0].end - pdev->resource[0].start + 1);
 			pdev->resource[0].end - pdev->resource[0].start + 1);
 
 

+ 3 - 0
drivers/usb/gadget/omap_udc.h

@@ -175,6 +175,9 @@ struct omap_udc {
 	unsigned			ep0_reset_config:1;
 	unsigned			ep0_reset_config:1;
 	unsigned			ep0_setup:1;
 	unsigned			ep0_setup:1;
 	struct completion		*done;
 	struct completion		*done;
+	struct clk			*dc_clk;
+	struct clk			*hhc_clk;
+	unsigned			clk_requested:1;
 };
 };
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/

+ 7 - 13
drivers/usb/host/uhci-hcd.c

@@ -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 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;
 	int port;
+	char *sys_info;
+	static char bad_Asus_board[] = "A7V8X";
 
 
 	/* One of Asus's motherboards has a bug which causes it to
 	/* One of Asus's motherboards has a bug which causes it to
 	 * wake up immediately from suspend-to-RAM if any of the ports
 	 * wake up immediately from suspend-to-RAM if any of the ports
 	 * are connected.  In such cases we will not set EGSM.
 	 * 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) {
 		for (port = 0; port < uhci->rh_numports; ++port) {
 			if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
 			if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
 					USBPORTSC_CCS)
 					USBPORTSC_CCS)
@@ -265,7 +257,9 @@ __acquires(uhci->lock)
 	int_enable = USBINTR_RESUME;
 	int_enable = USBINTR_RESUME;
 	if (remote_wakeup_is_broken(uhci))
 	if (remote_wakeup_is_broken(uhci))
 		egsm_enable = 0;
 		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;
 		uhci->working_RD = int_enable = 0;
 
 
 	outw(int_enable, uhci->io_addr + USBINTR);
 	outw(int_enable, uhci->io_addr + USBINTR);

+ 6 - 6
drivers/usb/misc/sisusbvga/sisusb_con.c

@@ -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),
 	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);
 	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),
 	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);
 	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),
 	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);
 	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),
 	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);
 	mutex_unlock(&sisusb->lock);
 }
 }
@@ -612,7 +612,7 @@ sisusbcon_switch(struct vc_data *c)
 								length);
 								length);
 
 
 	sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
 	sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
-				(u32)SISUSB_HADDR(0, 0),
+				(long)SISUSB_HADDR(0, 0),
 				length, &written);
 				length, &written);
 
 
 	mutex_unlock(&sisusb->lock);
 	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),
 	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);
 	mutex_unlock(&sisusb->lock);
 
 

+ 1 - 1
drivers/usb/net/asix.c

@@ -920,7 +920,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 		goto out2;
 		goto out2;
 
 
 	if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
 	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);
 		dbg("Select PHY #1 failed: %d", ret);
 		goto out2;
 		goto out2;
 	}
 	}

+ 1 - 1
drivers/usb/serial/Kconfig

@@ -170,7 +170,7 @@ config USB_SERIAL_FTDI_SIO
 
 
 config USB_SERIAL_FUNSOFT
 config USB_SERIAL_FUNSOFT
 	tristate "USB Fundamental Software Dongle Driver"
 	tristate "USB Fundamental Software Dongle Driver"
-	depends on USB_SERIAL
+	depends on USB_SERIAL && !(SPARC || SPARC64)
 	---help---
 	---help---
 	  Say Y here if you want to use the Fundamental Software dongle.
 	  Say Y here if you want to use the Fundamental Software dongle.
 
 

+ 3 - 0
drivers/usb/serial/option.c

@@ -625,6 +625,9 @@ static int option_send_setup(struct usb_serial_port *port)
 
 
 	dbg("%s", __FUNCTION__);
 	dbg("%s", __FUNCTION__);
 
 
+	if (port->number != 0)
+		return 0;
+
 	portdata = usb_get_serial_port_data(port);
 	portdata = usb_get_serial_port_data(port);
 
 
 	if (port->tty) {
 	if (port->tty) {

+ 16 - 1
drivers/usb/storage/unusual_devs.h

@@ -728,7 +728,7 @@ UNUSUAL_DEV( 0x05ac, 0x1204, 0x0000, 0x9999,
 		"Apple",
 		"Apple",
 		"iPod",
 		"iPod",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		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,
 UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999,
 		"Apple",
 		"Apple",
@@ -1358,6 +1358,21 @@ UNUSUAL_DEV(  0x1370, 0x6828, 0x0110, 0x0110,
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 		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>
 /* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
  * and Renato Perini <rperini@email.it>
  * and Renato Perini <rperini@email.it>
  */
  */