Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f87c8e80 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 91f7b5c4 14e51f28
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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.

+1 −0
Original line number Diff line number Diff line
@@ -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 }
};

+1 −1
Original line number Diff line number Diff line
@@ -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();
+192 −53
Original line number Diff line number Diff line
@@ -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;
@@ -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;
		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",
@@ -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;
}
@@ -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;
}
@@ -2228,11 +2289,18 @@ static int proc_otg_show(struct seq_file *s)
{
	u32		tmp;
	u32		trans;
	char		*ctrl_name;

	tmp = OTG_REV_REG;
	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, transceiver_ctrl %05x\n",
		tmp >> 4, tmp & 0xf, trans);
	}
	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,
@@ -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)");
		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) {
@@ -2709,6 +2783,8 @@ 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,
@@ -2718,6 +2794,26 @@ static int __init omap_udc_probe(struct platform_device *pdev)
		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 @@ static int __init omap_udc_probe(struct platform_device *pdev)
			goto cleanup0;
		}
	}
known:
	INFO("hmc mode %d, %s transceiver\n", hmc, type);

	/* 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,
			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 @@ static int __init omap_udc_probe(struct platform_device *pdev)
	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 @@ static int __init omap_udc_probe(struct platform_device *pdev)
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);

+3 −0
Original line number Diff line number Diff line
@@ -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;
};

/*-------------------------------------------------------------------------*/
Loading