From 195e9e4691ad0544746540852e03d7c8c6c877ea Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 15 Dec 2009 11:08:42 +0200 Subject: USB: musb: use resource_size() it makes ioremap() usage looks cleaner. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 5eb9318cff77..1927fa9f01b2 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2134,7 +2134,7 @@ static int __init musb_probe(struct platform_device *pdev) if (!iomem || irq == 0) return -ENODEV; - base = ioremap(iomem->start, iomem->end - iomem->start + 1); + base = ioremap(iomem->start, resource_size(iomem)); if (!base) { dev_err(dev, "ioremap failed\n"); return -ENOMEM; -- cgit v1.2.1 From b3b1cc3ba62374e71155ba8c09ee481c3c2d923e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 15 Dec 2009 11:08:43 +0200 Subject: USB: musb: move two printk to dev_err trivial cleanup, no functional changes. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 1927fa9f01b2..91c31f2e0edc 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1696,7 +1696,7 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr, unsigned long val; if (sscanf(buf, "%lu", &val) < 1) { - printk(KERN_ERR "Invalid VBUS timeout ms value\n"); + dev_err(dev, "Invalid VBUS timeout ms value\n"); return -EINVAL; } @@ -1746,7 +1746,7 @@ musb_srp_store(struct device *dev, struct device_attribute *attr, if (sscanf(buf, "%hu", &srp) != 1 || (srp != 1)) { - printk(KERN_ERR "SRP: Value must be 1\n"); + dev_err(dev, "SRP: Value must be 1\n"); return -EINVAL; } -- cgit v1.2.1 From 94375751d1d8af70df08beebdc32595f9e4537e1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 15 Dec 2009 11:08:38 +0200 Subject: USB: musb: move to sysfs_groups it's easier to keep up and add more sysfs entries as necessary. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 91c31f2e0edc..52295bcf2313 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1759,6 +1759,19 @@ static DEVICE_ATTR(srp, 0644, NULL, musb_srp_store); #endif /* CONFIG_USB_GADGET_MUSB_HDRC */ +static struct attribute *musb_attributes[] = { + &dev_attr_mode.attr, + &dev_attr_vbus.attr, +#ifdef CONFIG_USB_GADGET_MUSB_HDRC + &dev_attr_srp.attr, +#endif + NULL +}; + +static const struct attribute_group musb_attr_group = { + .attrs = musb_attributes, +}; + #endif /* sysfs */ /* Only used to provide driver mode change events */ @@ -1833,11 +1846,7 @@ static void musb_free(struct musb *musb) */ #ifdef CONFIG_SYSFS - device_remove_file(musb->controller, &dev_attr_mode); - device_remove_file(musb->controller, &dev_attr_vbus); -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - device_remove_file(musb->controller, &dev_attr_srp); -#endif + sysfs_remove_group(&musb->controller->kobj, &musb_attr_group); #endif #ifdef CONFIG_USB_GADGET_MUSB_HDRC @@ -2079,12 +2088,7 @@ bad_config: } #ifdef CONFIG_SYSFS - status = device_create_file(dev, &dev_attr_mode); - status = device_create_file(dev, &dev_attr_vbus); -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - status = device_create_file(dev, &dev_attr_srp); -#endif /* CONFIG_USB_GADGET_MUSB_HDRC */ - status = 0; + status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); #endif if (status) goto fail2; @@ -2092,13 +2096,6 @@ bad_config: return 0; fail2: -#ifdef CONFIG_SYSFS - device_remove_file(musb->controller, &dev_attr_mode); - device_remove_file(musb->controller, &dev_attr_vbus); -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - device_remove_file(musb->controller, &dev_attr_srp); -#endif -#endif musb_platform_exit(musb); fail: dev_err(musb->controller, -- cgit v1.2.1 From 7ed069c12c866c5c06e4e05d26878797e3731829 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 15 Dec 2009 11:08:39 +0200 Subject: USB: musb: remove some of the never defined defines just makes the musb init code a bit cleaner. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 24 ------------------------ drivers/usb/musb/musb_core.h | 16 ++++------------ 2 files changed, 4 insertions(+), 36 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 52295bcf2313..b7e2d1b09ac1 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1314,9 +1314,6 @@ enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, }; */ static int __init musb_core_init(u16 musb_type, struct musb *musb) { -#ifdef MUSB_AHB_ID - u32 data; -#endif u8 reg; char *type; char aInfo[90], aRevision[32], aDate[12]; @@ -1332,19 +1329,11 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) strcat(aInfo, ", dyn FIFOs"); if (reg & MUSB_CONFIGDATA_MPRXE) { strcat(aInfo, ", bulk combine"); -#ifdef C_MP_RX musb->bulk_combine = true; -#else - strcat(aInfo, " (X)"); /* no driver support */ -#endif } if (reg & MUSB_CONFIGDATA_MPTXE) { strcat(aInfo, ", bulk split"); -#ifdef C_MP_TX musb->bulk_split = true; -#else - strcat(aInfo, " (X)"); /* no driver support */ -#endif } if (reg & MUSB_CONFIGDATA_HBRXE) { strcat(aInfo, ", HB-ISO Rx"); @@ -1360,20 +1349,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) printk(KERN_DEBUG "%s: ConfigData=0x%02x (%s)\n", musb_driver_name, reg, aInfo); -#ifdef MUSB_AHB_ID - data = musb_readl(mbase, 0x404); - sprintf(aDate, "%04d-%02x-%02x", (data & 0xffff), - (data >> 16) & 0xff, (data >> 24) & 0xff); - /* FIXME ID2 and ID3 are unused */ - data = musb_readl(mbase, 0x408); - printk(KERN_DEBUG "ID2=%lx\n", (long unsigned)data); - data = musb_readl(mbase, 0x40c); - printk(KERN_DEBUG "ID3=%lx\n", (long unsigned)data); - reg = musb_readb(mbase, 0x400); - musb_type = ('M' == reg) ? MUSB_CONTROLLER_MHDRC : MUSB_CONTROLLER_HDRC; -#else aDate[0] = 0; -#endif if (MUSB_CONTROLLER_MHDRC == musb_type) { musb->is_multipoint = 1; type = "M"; diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 03d50909b078..2ac0e6f7dd9d 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -412,21 +412,13 @@ struct musb { unsigned hb_iso_rx:1; /* high bandwidth iso rx? */ unsigned hb_iso_tx:1; /* high bandwidth iso tx? */ -#ifdef C_MP_TX - unsigned bulk_split:1; + unsigned bulk_split:1; #define can_bulk_split(musb,type) \ - (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split) -#else -#define can_bulk_split(musb, type) 0 -#endif + (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split) -#ifdef C_MP_RX - unsigned bulk_combine:1; + unsigned bulk_combine:1; #define can_bulk_combine(musb,type) \ - (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine) -#else -#define can_bulk_combine(musb, type) 0 -#endif + (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine) #ifdef CONFIG_USB_GADGET_MUSB_HDRC /* is_suspended means USB B_PERIPHERAL suspend */ -- cgit v1.2.1 From 3b151526eda87901532390e11bba0dd59119f667 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Mon, 28 Dec 2009 13:40:34 +0200 Subject: USB: musb: Add new fifo table for a OMAP3 errata We have observed MSC data read corruption when USB LAN device is also connected and it's interface is up. Silicon team has confirmed an errata where in all the active transfers should use FIFO space either in first 8K or next 8K. So far we have observed the issue in above use case scenario. As a workaround to it, adding a new FIFO config (5) fitting well within first 8K which can be used for such use cases. Signed-off-by: Ajay Kumar Gupta Acked-by: Anand Gadiyar Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index b7e2d1b09ac1..c4893267b4e2 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1095,6 +1095,36 @@ static struct fifo_cfg __initdata mode_4_cfg[] = { { .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, }; +/* mode 5 - fits in 8KB */ +static struct fifo_cfg __initdata mode_5_cfg[] = { +{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, +{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, +{ .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, +{ .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, +{ .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, +{ .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 32, }, +{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 32, }, +{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 512, }, +{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, +{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, +}; /* * configure a fifo; for non-shared endpoints, this may be called @@ -1210,6 +1240,10 @@ static int __init ep_config_from_table(struct musb *musb) cfg = mode_4_cfg; n = ARRAY_SIZE(mode_4_cfg); break; + case 5: + cfg = mode_5_cfg; + n = ARRAY_SIZE(mode_5_cfg); + break; } printk(KERN_DEBUG "%s: setup fifo_mode %d\n", -- cgit v1.2.1 From 452f0394376d2cc882e4c4a593fc290c042799a9 Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Mon, 28 Dec 2009 13:40:35 +0200 Subject: usb: musb: hsdma: add wrapper for reading DMA count Add a wrapper for reading the DMA count register, analogous to the one for writing to this register. Signed-off-by: Anand Gadiyar Cc: Vikram Pandita Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musbhsdma.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h index 1299d92dc83f..613f95a058f7 100644 --- a/drivers/usb/musb/musbhsdma.h +++ b/drivers/usb/musb/musbhsdma.h @@ -55,6 +55,10 @@ MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), \ addr) +#define musb_read_hsdma_count(mbase, bchannel) \ + musb_readl(mbase, \ + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT)) + #define musb_write_hsdma_count(mbase, bchannel, len) \ musb_writel(mbase, \ MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \ @@ -96,6 +100,19 @@ static inline void musb_write_hsdma_addr(void __iomem *mbase, ((u16)(((u32) dma_addr >> 16) & 0xFFFF))); } +static inline u32 musb_read_hsdma_count(void __iomem *mbase, u8 bchannel) +{ + u32 count = musb_readw(mbase, + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_HIGH)); + + count = count << 16; + + count |= musb_readw(mbase, + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW)); + + return count; +} + static inline void musb_write_hsdma_count(void __iomem *mbase, u8 bchannel, u32 len) { -- cgit v1.2.1 From f933a0c0fe0ea5f49a35bcd45e3e4850e0606cba Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Mon, 28 Dec 2009 13:40:36 +0200 Subject: usb: musb: workaround MUSB DMA_INTR sometimes reads zero MUSB DMA_INTR register may sometimes read zero when infact there was a pending interrupt. Workaround this by reading the DMA_COUNT values for all enabled channels when this condition occurs. Flag these channels as the ones needing to be serviced. Additionally, the absence of a debug print meant we would never catch a spurious DMA interrupt in MUSB. So this patch adds a debug print in the IRQ handler. Signed-off-by: Anand Gadiyar Cc: Ajay Kumar Gupta Cc: David Brownell Cc: Sergei Shtylyov Cc: Vikram Pandita Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musbhsdma.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index a237550f91bf..2fa7d5c00f31 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -250,20 +250,39 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) u8 bchannel; u8 int_hsdma; - u32 addr; + u32 addr, count; u16 csr; spin_lock_irqsave(&musb->lock, flags); int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); - if (!int_hsdma) - goto done; #ifdef CONFIG_BLACKFIN /* Clear DMA interrupt flags */ musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); #endif + if (!int_hsdma) { + DBG(2, "spurious DMA irq\n"); + + for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) { + musb_channel = (struct musb_dma_channel *) + &(controller->channel[bchannel]); + channel = &musb_channel->channel; + if (channel->status == MUSB_DMA_STATUS_BUSY) { + count = musb_read_hsdma_count(mbase, bchannel); + + if (count == 0) + int_hsdma |= (1 << bchannel); + } + } + + DBG(2, "int_hsdma = 0x%x\n", int_hsdma); + + if (!int_hsdma) + goto done; + } + for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) { if (int_hsdma & (1 << bchannel)) { musb_channel = (struct musb_dma_channel *) -- cgit v1.2.1 From 5274dab6cb99c529b2e7f16bbc8ff9a79be46e7f Mon Sep 17 00:00:00 2001 From: Swaminathan S Date: Mon, 28 Dec 2009 13:40:37 +0200 Subject: usb: musb: workaround toggle bug when doing bulk transfer after isoc This patch implements the work around for a Mentor controller related bug where it's observed a BULK Tx toggle error on the bus when a BULK IO gets scheduled on an endpoint that was earlier used for handling ISOC transaction and needed to start on 1 toggle. When such a situation arises even if the TXCSR toggle bits are programmed correctly by the musb driver the data gets transmitted with 0 toggle which leads to toggle error on the bus and the BULK transaction fails. In case of MSC write, the device gets reset by the Host. This Mentor bug is observed on almost all Mentor versions (1.3, 1.5, 1.8). Confirmed on DM644x, DM355, DM365, OMAPL13x platforms. Signed-off-by: Swaminathan S Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 74c4c3698f1e..c3fdd6d69f5e 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1771,6 +1771,9 @@ static int musb_schedule( int best_end, epnum; struct musb_hw_ep *hw_ep = NULL; struct list_head *head = NULL; + u8 toggle; + u8 txtype; + struct urb *urb = next_urb(qh); /* use fixed hardware for control and bulk */ if (qh->type == USB_ENDPOINT_XFER_CONTROL) { @@ -1809,6 +1812,27 @@ static int musb_schedule( diff -= (qh->maxpacket * qh->hb_mult); if (diff >= 0 && best_diff > diff) { + + /* + * Mentor controller has a bug in that if we schedule + * a BULK Tx transfer on an endpoint that had earlier + * handled ISOC then the BULK transfer has to start on + * a zero toggle. If the BULK transfer starts on a 1 + * toggle then this transfer will fail as the mentor + * controller starts the Bulk transfer on a 0 toggle + * irrespective of the programming of the toggle bits + * in the TXCSR register. Check for this condition + * while allocating the EP for a Tx Bulk transfer. If + * so skip this EP. + */ + hw_ep = musb->endpoints + epnum; + toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in); + txtype = (musb_readb(hw_ep->regs, MUSB_TXTYPE) + >> 4) & 0x3; + if (!is_in && (qh->type == USB_ENDPOINT_XFER_BULK) && + toggle && (txtype == USB_ENDPOINT_XFER_ISOC)) + continue; + best_diff = diff; best_end = epnum; } -- cgit v1.2.1 From 565969237ab6e73ce7192684d00d5b890ee308fa Mon Sep 17 00:00:00 2001 From: Swaminathan S Date: Mon, 28 Dec 2009 13:40:38 +0200 Subject: usb: musb: Fix cppi_channel_abort() function to handle Tx abort correctly This patch fixes the Tx abort/teardown logic. We now wait for the teardown completion interrupt and acknowledge the same by setting the tx_complete register to 0. This change is needed to ensure that abort processing works on DM365 platform. Without this change after completion of abort processing the system is overwhelmed with continuous stream of abort interrupts. This change has been tested on all CPPI3.x platforms (DM644x, DM646x, DM35x, DM36x). Signed-off-by: Swaminathan S Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/cppi_dma.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index a44a450c860d..3c69a76ec392 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -1191,8 +1191,13 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) bd = tx_ch->head; + /* + * If Head is null then this could mean that a abort interrupt + * that needs to be acknowledged. + */ if (NULL == bd) { DBG(1, "null BD\n"); + tx_ram->tx_complete = 0; continue; } @@ -1412,15 +1417,6 @@ static int cppi_channel_abort(struct dma_channel *channel) if (cppi_ch->transmit) { struct cppi_tx_stateram __iomem *tx_ram; - int enabled; - - /* mask interrupts raised to signal teardown complete. */ - enabled = musb_readl(tibase, DAVINCI_TXCPPI_INTENAB_REG) - & (1 << cppi_ch->index); - if (enabled) - musb_writel(tibase, DAVINCI_TXCPPI_INTCLR_REG, - (1 << cppi_ch->index)); - /* REVISIT put timeouts on these controller handshakes */ cppi_dump_tx(6, cppi_ch, " (teardown)"); @@ -1435,7 +1431,6 @@ static int cppi_channel_abort(struct dma_channel *channel) do { value = musb_readl(&tx_ram->tx_complete, 0); } while (0xFFFFFFFC != value); - musb_writel(&tx_ram->tx_complete, 0, 0xFFFFFFFC); /* FIXME clean up the transfer state ... here? * the completion routine should get called with @@ -1448,23 +1443,15 @@ static int cppi_channel_abort(struct dma_channel *channel) musb_writew(regs, MUSB_TXCSR, value); musb_writew(regs, MUSB_TXCSR, value); - /* While we scrub the TX state RAM, ensure that we clean - * up any interrupt that's currently asserted: + /* * 1. Write to completion Ptr value 0x1(bit 0 set) * (write back mode) - * 2. Write to completion Ptr value 0x0(bit 0 cleared) - * (compare mode) - * Value written is compared(for bits 31:2) and when - * equal, interrupt is deasserted. + * 2. Wait for abort interrupt and then put the channel in + * compare mode by writing 1 to the tx_complete register. */ cppi_reset_tx(tx_ram, 1); - musb_writel(&tx_ram->tx_complete, 0, 0); - - /* re-enable interrupt */ - if (enabled) - musb_writel(tibase, DAVINCI_TXCPPI_INTENAB_REG, - (1 << cppi_ch->index)); - + cppi_ch->head = 0; + musb_writel(&tx_ram->tx_complete, 0, 1); cppi_dump_tx(5, cppi_ch, " (done teardown)"); /* REVISIT tx side _should_ clean up the same way -- cgit v1.2.1 From 1ca9e9ca314c4757409a7f4e9c1f12229a175834 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Mon, 28 Dec 2009 13:40:39 +0200 Subject: usb: musb: clean up commit 'workaround Blackfin FIFO anomalies' The version applied had a few comments which are now done. Thanks to Sergei for pointing out. Signed-off-by: Bryan Wu Signed-off-by: Cliff Cai Signed-off-by: Mike Frysinger Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/blackfin.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index ad26e6569665..bcee1339d4fd 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -30,7 +30,6 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) void __iomem *fifo = hw_ep->fifo; void __iomem *epio = hw_ep->regs; u8 epnum = hw_ep->epnum; - u16 dma_reg = 0; prefetch((u8 *)src); @@ -42,15 +41,17 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) dump_fifo_data(src, len); if (!ANOMALY_05000380 && epnum != 0) { - flush_dcache_range((unsigned int)src, - (unsigned int)(src + len)); + u16 dma_reg; + + flush_dcache_range((unsigned long)src, + (unsigned long)(src + len)); /* Setup DMA address register */ - dma_reg = (u16) ((u32) src & 0xFFFF); + dma_reg = (u32)src; bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); SSYNC(); - dma_reg = (u16) (((u32) src >> 16) & 0xFFFF); + dma_reg = (u32)src >> 16; bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); SSYNC(); @@ -79,12 +80,9 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) SSYNC(); if (unlikely((unsigned long)src & 0x01)) - outsw_8((unsigned long)fifo, src, - len & 0x01 ? (len >> 1) + 1 : len >> 1); + outsw_8((unsigned long)fifo, src, (len + 1) >> 1); else - outsw((unsigned long)fifo, src, - len & 0x01 ? (len >> 1) + 1 : len >> 1); - + outsw((unsigned long)fifo, src, (len + 1) >> 1); } } /* @@ -94,19 +92,19 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) { void __iomem *fifo = hw_ep->fifo; u8 epnum = hw_ep->epnum; - u16 dma_reg = 0; if (ANOMALY_05000467 && epnum != 0) { + u16 dma_reg; - invalidate_dcache_range((unsigned int)dst, - (unsigned int)(dst + len)); + invalidate_dcache_range((unsigned long)dst, + (unsigned long)(dst + len)); /* Setup DMA address register */ - dma_reg = (u16) ((u32) dst & 0xFFFF); + dma_reg = (u32)dst; bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); SSYNC(); - dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF); + dma_reg = (u32)dst >> 16; bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); SSYNC(); -- cgit v1.2.1 From 1c25fda4a09e8229800979986ef399401053b46e Mon Sep 17 00:00:00 2001 From: Arnaud Mandy Date: Mon, 28 Dec 2009 13:40:40 +0200 Subject: usb: musb: handle irqs in the order dictated by programming guide MUSB's programming guide dictates how we should handle its irqs and in which order. Follow that. Signed-off-by: Arnaud Mandy Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 255 ++++++++++++++++++++----------------------- 1 file changed, 116 insertions(+), 139 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index c4893267b4e2..bd14e816df93 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -557,6 +557,69 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, handled = IRQ_HANDLED; } + + if (int_usb & MUSB_INTR_SUSPEND) { + DBG(1, "SUSPEND (%s) devctl %02x power %02x\n", + otg_state_string(musb), devctl, power); + handled = IRQ_HANDLED; + + switch (musb->xceiv->state) { +#ifdef CONFIG_USB_MUSB_OTG + case OTG_STATE_A_PERIPHERAL: + /* We also come here if the cable is removed, since + * this silicon doesn't report ID-no-longer-grounded. + * + * We depend on T(a_wait_bcon) to shut us down, and + * hope users don't do anything dicey during this + * undesired detour through A_WAIT_BCON. + */ + musb_hnp_stop(musb); + usb_hcd_resume_root_hub(musb_to_hcd(musb)); + musb_root_disconnect(musb); + musb_platform_try_idle(musb, jiffies + + msecs_to_jiffies(musb->a_wait_bcon + ? : OTG_TIME_A_WAIT_BCON)); + + break; +#endif + case OTG_STATE_B_IDLE: + if (!musb->is_active) + break; + case OTG_STATE_B_PERIPHERAL: + musb_g_suspend(musb); + musb->is_active = is_otg_enabled(musb) + && musb->xceiv->gadget->b_hnp_enable; + if (musb->is_active) { +#ifdef CONFIG_USB_MUSB_OTG + musb->xceiv->state = OTG_STATE_B_WAIT_ACON; + DBG(1, "HNP: Setting timer for b_ase0_brst\n"); + mod_timer(&musb->otg_timer, jiffies + + msecs_to_jiffies( + OTG_TIME_B_ASE0_BRST)); +#endif + } + break; + case OTG_STATE_A_WAIT_BCON: + if (musb->a_wait_bcon != 0) + musb_platform_try_idle(musb, jiffies + + msecs_to_jiffies(musb->a_wait_bcon)); + break; + case OTG_STATE_A_HOST: + musb->xceiv->state = OTG_STATE_A_SUSPEND; + musb->is_active = is_otg_enabled(musb) + && musb->xceiv->host->b_hnp_enable; + break; + case OTG_STATE_B_HOST: + /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ + DBG(1, "REVISIT: SUSPEND as B_HOST\n"); + break; + default: + /* "should not happen" */ + musb->is_active = 0; + break; + } + } + if (int_usb & MUSB_INTR_CONNECT) { struct usb_hcd *hcd = musb_to_hcd(musb); @@ -625,10 +688,61 @@ b_host: } #endif /* CONFIG_USB_MUSB_HDRC_HCD */ + if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) { + DBG(1, "DISCONNECT (%s) as %s, devctl %02x\n", + otg_state_string(musb), + MUSB_MODE(musb), devctl); + handled = IRQ_HANDLED; + + switch (musb->xceiv->state) { +#ifdef CONFIG_USB_MUSB_HDRC_HCD + case OTG_STATE_A_HOST: + case OTG_STATE_A_SUSPEND: + usb_hcd_resume_root_hub(musb_to_hcd(musb)); + musb_root_disconnect(musb); + if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) + musb_platform_try_idle(musb, jiffies + + msecs_to_jiffies(musb->a_wait_bcon)); + break; +#endif /* HOST */ +#ifdef CONFIG_USB_MUSB_OTG + case OTG_STATE_B_HOST: + /* REVISIT this behaves for "real disconnect" + * cases; make sure the other transitions from + * from B_HOST act right too. The B_HOST code + * in hnp_stop() is currently not used... + */ + musb_root_disconnect(musb); + musb_to_hcd(musb)->self.is_b_host = 0; + musb->xceiv->state = OTG_STATE_B_PERIPHERAL; + MUSB_DEV_MODE(musb); + musb_g_disconnect(musb); + break; + case OTG_STATE_A_PERIPHERAL: + musb_hnp_stop(musb); + musb_root_disconnect(musb); + /* FALLTHROUGH */ + case OTG_STATE_B_WAIT_ACON: + /* FALLTHROUGH */ +#endif /* OTG */ +#ifdef CONFIG_USB_GADGET_MUSB_HDRC + case OTG_STATE_B_PERIPHERAL: + case OTG_STATE_B_IDLE: + musb_g_disconnect(musb); + break; +#endif /* GADGET */ + default: + WARNING("unhandled DISCONNECT transition (%s)\n", + otg_state_string(musb)); + break; + } + } + /* mentor saves a bit: bus reset and babble share the same irq. * only host sees babble; only peripheral sees bus reset. */ if (int_usb & MUSB_INTR_RESET) { + handled = IRQ_HANDLED; if (is_host_capable() && (devctl & MUSB_DEVCTL_HM) != 0) { /* * Looks like non-HS BABBLE can be ignored, but @@ -641,7 +755,7 @@ b_host: DBG(1, "BABBLE devctl: %02x\n", devctl); else { ERR("Stopping host session -- babble\n"); - musb_writeb(mbase, MUSB_DEVCTL, 0); + musb_writeb(musb->mregs, MUSB_DEVCTL, 0); } } else if (is_peripheral_capable()) { DBG(1, "BUS RESET as %s\n", otg_state_string(musb)); @@ -686,29 +800,7 @@ b_host: otg_state_string(musb)); } } - - handled = IRQ_HANDLED; } - schedule_work(&musb->irq_work); - - return handled; -} - -/* - * Interrupt Service Routine to record USB "global" interrupts. - * Since these do not happen often and signify things of - * paramount importance, it seems OK to check them individually; - * the order of the tests is specified in the manual - * - * @param musb instance pointer - * @param int_usb register contents - * @param devctl - * @param power - */ -static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, - u8 devctl, u8 power) -{ - irqreturn_t handled = IRQ_NONE; #if 0 /* REVISIT ... this would be for multiplexing periodic endpoints, or @@ -755,117 +847,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, } #endif - if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) { - DBG(1, "DISCONNECT (%s) as %s, devctl %02x\n", - otg_state_string(musb), - MUSB_MODE(musb), devctl); - handled = IRQ_HANDLED; - - switch (musb->xceiv->state) { -#ifdef CONFIG_USB_MUSB_HDRC_HCD - case OTG_STATE_A_HOST: - case OTG_STATE_A_SUSPEND: - usb_hcd_resume_root_hub(musb_to_hcd(musb)); - musb_root_disconnect(musb); - if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) - musb_platform_try_idle(musb, jiffies - + msecs_to_jiffies(musb->a_wait_bcon)); - break; -#endif /* HOST */ -#ifdef CONFIG_USB_MUSB_OTG - case OTG_STATE_B_HOST: - /* REVISIT this behaves for "real disconnect" - * cases; make sure the other transitions from - * from B_HOST act right too. The B_HOST code - * in hnp_stop() is currently not used... - */ - musb_root_disconnect(musb); - musb_to_hcd(musb)->self.is_b_host = 0; - musb->xceiv->state = OTG_STATE_B_PERIPHERAL; - MUSB_DEV_MODE(musb); - musb_g_disconnect(musb); - break; - case OTG_STATE_A_PERIPHERAL: - musb_hnp_stop(musb); - musb_root_disconnect(musb); - /* FALLTHROUGH */ - case OTG_STATE_B_WAIT_ACON: - /* FALLTHROUGH */ -#endif /* OTG */ -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - case OTG_STATE_B_PERIPHERAL: - case OTG_STATE_B_IDLE: - musb_g_disconnect(musb); - break; -#endif /* GADGET */ - default: - WARNING("unhandled DISCONNECT transition (%s)\n", - otg_state_string(musb)); - break; - } - - schedule_work(&musb->irq_work); - } - - if (int_usb & MUSB_INTR_SUSPEND) { - DBG(1, "SUSPEND (%s) devctl %02x power %02x\n", - otg_state_string(musb), devctl, power); - handled = IRQ_HANDLED; - - switch (musb->xceiv->state) { -#ifdef CONFIG_USB_MUSB_OTG - case OTG_STATE_A_PERIPHERAL: - /* We also come here if the cable is removed, since - * this silicon doesn't report ID-no-longer-grounded. - * - * We depend on T(a_wait_bcon) to shut us down, and - * hope users don't do anything dicey during this - * undesired detour through A_WAIT_BCON. - */ - musb_hnp_stop(musb); - usb_hcd_resume_root_hub(musb_to_hcd(musb)); - musb_root_disconnect(musb); - musb_platform_try_idle(musb, jiffies - + msecs_to_jiffies(musb->a_wait_bcon - ? : OTG_TIME_A_WAIT_BCON)); - break; -#endif - case OTG_STATE_B_PERIPHERAL: - musb_g_suspend(musb); - musb->is_active = is_otg_enabled(musb) - && musb->xceiv->gadget->b_hnp_enable; - if (musb->is_active) { -#ifdef CONFIG_USB_MUSB_OTG - musb->xceiv->state = OTG_STATE_B_WAIT_ACON; - DBG(1, "HNP: Setting timer for b_ase0_brst\n"); - mod_timer(&musb->otg_timer, jiffies - + msecs_to_jiffies( - OTG_TIME_B_ASE0_BRST)); -#endif - } - break; - case OTG_STATE_A_WAIT_BCON: - if (musb->a_wait_bcon != 0) - musb_platform_try_idle(musb, jiffies - + msecs_to_jiffies(musb->a_wait_bcon)); - break; - case OTG_STATE_A_HOST: - musb->xceiv->state = OTG_STATE_A_SUSPEND; - musb->is_active = is_otg_enabled(musb) - && musb->xceiv->host->b_hnp_enable; - break; - case OTG_STATE_B_HOST: - /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ - DBG(1, "REVISIT: SUSPEND as B_HOST\n"); - break; - default: - /* "should not happen" */ - musb->is_active = 0; - break; - } - schedule_work(&musb->irq_work); - } - + schedule_work(&musb->irq_work); return handled; } @@ -1597,11 +1579,6 @@ irqreturn_t musb_interrupt(struct musb *musb) ep_num++; } - /* finish handling "global" interrupts after handling fifos */ - if (musb->int_usb) - retval |= musb_stage2_irq(musb, - musb->int_usb, devctl, power); - return retval; } -- cgit v1.2.1 From 51bf0d0e6cc1f9679a973f61d07cb48e71f9c992 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Mon, 28 Dec 2009 13:40:41 +0200 Subject: usb: musb: save dynfifo in musb struct Save dynamic FIFO read only information for later uses during musb_save/restore_context functions. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 4 +++- drivers/usb/musb/musb_core.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index bd14e816df93..4c8962f976b2 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1341,8 +1341,10 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) reg = musb_read_configdata(mbase); strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8"); - if (reg & MUSB_CONFIGDATA_DYNFIFO) + if (reg & MUSB_CONFIGDATA_DYNFIFO) { strcat(aInfo, ", dyn FIFOs"); + musb->dyn_fifo = true; + } if (reg & MUSB_CONFIGDATA_MPRXE) { strcat(aInfo, ", bulk combine"); musb->bulk_combine = true; diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 2ac0e6f7dd9d..eaa01140183e 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -411,6 +411,7 @@ struct musb { unsigned hb_iso_rx:1; /* high bandwidth iso rx? */ unsigned hb_iso_tx:1; /* high bandwidth iso tx? */ + unsigned dyn_fifo:1; /* dynamic FIFO supported? */ unsigned bulk_split:1; #define can_bulk_split(musb,type) \ -- cgit v1.2.1 From 5fc4e77911f457b6aa910c704eebe3a58d334116 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Mon, 28 Dec 2009 13:40:42 +0200 Subject: usb: musb: Add 'extvbus' in musb_hdrc_platform_data Some of the board might use external Vbus power supply on musb interface which would require to program ULPI_BUSCONTROL register. Adding 'extvbus' flag which can be set from such boards which will be checked at musb driver files before programming ULPI_BUSCONTROL. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 8 ++++++++ drivers/usb/musb/musb_regs.h | 5 +++++ 2 files changed, 13 insertions(+) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 4c8962f976b2..074d380bf883 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2031,6 +2031,7 @@ bad_config: /* host side needs more setup */ if (is_host_enabled(musb)) { struct usb_hcd *hcd = musb_to_hcd(musb); + u8 busctl; otg_set_host(musb->xceiv, &hcd->self); @@ -2038,6 +2039,13 @@ bad_config: hcd->self.otg_port = 1; musb->xceiv->host = &hcd->self; hcd->power_budget = 2 * (plat->power ? : 250); + + /* program PHY to use external vBus if required */ + if (plat->extvbus) { + busctl = musb_readb(musb->mregs, MUSB_ULPI_BUSCONTROL); + busctl |= MUSB_ULPI_USE_EXTVBUS; + musb_writeb(musb->mregs, MUSB_ULPI_BUSCONTROL, busctl); + } } /* For the host-only role, we can activate right away. diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 473a94ef905f..9a8621ac5ac2 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -72,6 +72,10 @@ #define MUSB_DEVCTL_HR 0x02 #define MUSB_DEVCTL_SESSION 0x01 +/* MUSB ULPI VBUSCONTROL */ +#define MUSB_ULPI_USE_EXTVBUS 0x01 +#define MUSB_ULPI_USE_EXTVBUSIND 0x02 + /* TESTMODE */ #define MUSB_TEST_FORCE_HOST 0x80 #define MUSB_TEST_FIFO_ACCESS 0x40 @@ -246,6 +250,7 @@ /* REVISIT: vctrl/vstatus: optional vendor utmi+phy register at 0x68 */ #define MUSB_HWVERS 0x6C /* 8 bit */ +#define MUSB_ULPI_BUSCONTROL 0x70 /* 8 bit */ #define MUSB_EPINFO 0x78 /* 8 bit */ #define MUSB_RAMINFO 0x79 /* 8 bit */ -- cgit v1.2.1 From 94089d56e456d2814c379538919180957a254e4a Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 9 Jan 2010 21:57:44 +0100 Subject: USB: musb: don't dereference NULL tusb_dma in dma_controller_destroy() Test whether tusb_dma is not NULL before dereferencing Signed-off-by: Roel Kluin Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/tusb6010_omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index e13c77052e5e..1c868096bd6f 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -648,7 +648,7 @@ void dma_controller_destroy(struct dma_controller *c) } } - if (!tusb_dma->multichannel && tusb_dma && tusb_dma->ch >= 0) + if (tusb_dma && !tusb_dma->multichannel && tusb_dma->ch >= 0) omap_free_dma(tusb_dma->ch); kfree(tusb_dma); -- cgit v1.2.1 From 4f712e010b2da1cc01c178922f2eb5aaeae461b6 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Thu, 21 Jan 2010 15:33:52 +0200 Subject: usb: musb: Add context save and restore support Adding support for MUSB register save and restore during system suspend and resume. Changes: - Added musb_save/restore_context() functions - Added platform specific musb_platform_save/restore_context() to handle platform specific jobs. - Maintaining BlackFin compatibility by adding read/write functions for registers which are not available in BlackFin Tested system suspend and resume on OMAP3EVM board. Signed-off-by: Anand Gadiyar Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 146 +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/musb/musb_core.h | 39 ++++++++++++ drivers/usb/musb/musb_regs.h | 90 ++++++++++++++++++++++++++ drivers/usb/musb/omap2430.c | 16 +++++ 4 files changed, 291 insertions(+) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 074d380bf883..2c53da771318 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2167,6 +2167,148 @@ static int __exit musb_remove(struct platform_device *pdev) #ifdef CONFIG_PM +static struct musb_context_registers musb_context; + +void musb_save_context(struct musb *musb) +{ + int i; + void __iomem *musb_base = musb->mregs; + + if (is_host_enabled(musb)) { + musb_context.frame = musb_readw(musb_base, MUSB_FRAME); + musb_context.testmode = musb_readb(musb_base, MUSB_TESTMODE); + } + musb_context.power = musb_readb(musb_base, MUSB_POWER); + musb_context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); + musb_context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); + musb_context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); + musb_context.index = musb_readb(musb_base, MUSB_INDEX); + musb_context.devctl = musb_readb(musb_base, MUSB_DEVCTL); + + for (i = 0; i < MUSB_C_NUM_EPS; ++i) { + musb_writeb(musb_base, MUSB_INDEX, i); + musb_context.index_regs[i].txmaxp = + musb_readw(musb_base, 0x10 + MUSB_TXMAXP); + musb_context.index_regs[i].txcsr = + musb_readw(musb_base, 0x10 + MUSB_TXCSR); + musb_context.index_regs[i].rxmaxp = + musb_readw(musb_base, 0x10 + MUSB_RXMAXP); + musb_context.index_regs[i].rxcsr = + musb_readw(musb_base, 0x10 + MUSB_RXCSR); + + if (musb->dyn_fifo) { + musb_context.index_regs[i].txfifoadd = + musb_read_txfifoadd(musb_base); + musb_context.index_regs[i].rxfifoadd = + musb_read_rxfifoadd(musb_base); + musb_context.index_regs[i].txfifosz = + musb_read_txfifosz(musb_base); + musb_context.index_regs[i].rxfifosz = + musb_read_rxfifosz(musb_base); + } + if (is_host_enabled(musb)) { + musb_context.index_regs[i].txtype = + musb_readb(musb_base, 0x10 + MUSB_TXTYPE); + musb_context.index_regs[i].txinterval = + musb_readb(musb_base, 0x10 + MUSB_TXINTERVAL); + musb_context.index_regs[i].rxtype = + musb_readb(musb_base, 0x10 + MUSB_RXTYPE); + musb_context.index_regs[i].rxinterval = + musb_readb(musb_base, 0x10 + MUSB_RXINTERVAL); + + musb_context.index_regs[i].txfunaddr = + musb_read_txfunaddr(musb_base, i); + musb_context.index_regs[i].txhubaddr = + musb_read_txhubaddr(musb_base, i); + musb_context.index_regs[i].txhubport = + musb_read_txhubport(musb_base, i); + + musb_context.index_regs[i].rxfunaddr = + musb_read_rxfunaddr(musb_base, i); + musb_context.index_regs[i].rxhubaddr = + musb_read_rxhubaddr(musb_base, i); + musb_context.index_regs[i].rxhubport = + musb_read_rxhubport(musb_base, i); + } + } + + musb_writeb(musb_base, MUSB_INDEX, musb_context.index); + + musb_platform_save_context(&musb_context); +} + +void musb_restore_context(struct musb *musb) +{ + int i; + void __iomem *musb_base = musb->mregs; + void __iomem *ep_target_regs; + + musb_platform_restore_context(&musb_context); + + if (is_host_enabled(musb)) { + musb_writew(musb_base, MUSB_FRAME, musb_context.frame); + musb_writeb(musb_base, MUSB_TESTMODE, musb_context.testmode); + } + musb_writeb(musb_base, MUSB_POWER, musb_context.power); + musb_writew(musb_base, MUSB_INTRTXE, musb_context.intrtxe); + musb_writew(musb_base, MUSB_INTRRXE, musb_context.intrrxe); + musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe); + musb_writeb(musb_base, MUSB_DEVCTL, musb_context.devctl); + + for (i = 0; i < MUSB_C_NUM_EPS; ++i) { + musb_writeb(musb_base, MUSB_INDEX, i); + musb_writew(musb_base, 0x10 + MUSB_TXMAXP, + musb_context.index_regs[i].txmaxp); + musb_writew(musb_base, 0x10 + MUSB_TXCSR, + musb_context.index_regs[i].txcsr); + musb_writew(musb_base, 0x10 + MUSB_RXMAXP, + musb_context.index_regs[i].rxmaxp); + musb_writew(musb_base, 0x10 + MUSB_RXCSR, + musb_context.index_regs[i].rxcsr); + + if (musb->dyn_fifo) { + musb_write_txfifosz(musb_base, + musb_context.index_regs[i].txfifosz); + musb_write_rxfifosz(musb_base, + musb_context.index_regs[i].rxfifosz); + musb_write_txfifoadd(musb_base, + musb_context.index_regs[i].txfifoadd); + musb_write_rxfifoadd(musb_base, + musb_context.index_regs[i].rxfifoadd); + } + + if (is_host_enabled(musb)) { + musb_writeb(musb_base, 0x10 + MUSB_TXTYPE, + musb_context.index_regs[i].txtype); + musb_writeb(musb_base, 0x10 + MUSB_TXINTERVAL, + musb_context.index_regs[i].txinterval); + musb_writeb(musb_base, 0x10 + MUSB_RXTYPE, + musb_context.index_regs[i].rxtype); + musb_writeb(musb_base, 0x10 + MUSB_RXINTERVAL, + + musb_context.index_regs[i].rxinterval); + musb_write_txfunaddr(musb_base, i, + musb_context.index_regs[i].txfunaddr); + musb_write_txhubaddr(musb_base, i, + musb_context.index_regs[i].txhubaddr); + musb_write_txhubport(musb_base, i, + musb_context.index_regs[i].txhubport); + + ep_target_regs = + musb_read_target_reg_base(i, musb_base); + + musb_write_rxfunaddr(ep_target_regs, + musb_context.index_regs[i].rxfunaddr); + musb_write_rxhubaddr(ep_target_regs, + musb_context.index_regs[i].rxhubaddr); + musb_write_rxhubport(ep_target_regs, + musb_context.index_regs[i].rxhubport); + } + } + + musb_writeb(musb_base, MUSB_INDEX, musb_context.index); +} + static int musb_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -2188,6 +2330,8 @@ static int musb_suspend(struct device *dev) */ } + musb_save_context(musb); + if (musb->set_clock) musb->set_clock(musb->clock, 0); else @@ -2209,6 +2353,8 @@ static int musb_resume_noirq(struct device *dev) else clk_enable(musb->clock); + musb_restore_context(musb); + /* for static cmos like DaVinci, register values were preserved * unless for some reason the whole soc powered down or the USB * module got reset through the PSC (vs just being disabled). diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index eaa01140183e..3d66c3e01dbd 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -454,6 +454,45 @@ struct musb { #endif }; +#ifdef CONFIG_PM +struct musb_csr_regs { + /* FIFO registers */ + u16 txmaxp, txcsr, rxmaxp, rxcsr; + u16 rxfifoadd, txfifoadd; + u8 txtype, txinterval, rxtype, rxinterval; + u8 rxfifosz, txfifosz; + u8 txfunaddr, txhubaddr, txhubport; + u8 rxfunaddr, rxhubaddr, rxhubport; +}; + +struct musb_context_registers { + +#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430) + u32 otg_sysconfig, otg_forcestandby; +#endif + u8 power; + u16 intrtxe, intrrxe; + u8 intrusbe; + u16 frame; + u8 index, testmode; + + u8 devctl, misc; + + struct musb_csr_regs index_regs[MUSB_C_NUM_EPS]; +}; + +#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430) +extern void musb_platform_save_context(struct musb_context_registers + *musb_context); +extern void musb_platform_restore_context(struct musb_context_registers + *musb_context); +#else +#define musb_platform_save_context(x) do {} while (0) +#define musb_platform_restore_context(x) do {} while (0) +#endif + +#endif + static inline void musb_set_vbus(struct musb *musb, int is_on) { musb->board_set_vbus(musb, is_on); diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 9a8621ac5ac2..895fb057e443 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -326,6 +326,26 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) musb_writew(mbase, MUSB_RXFIFOADD, c_off); } +static inline u8 musb_read_txfifosz(void __iomem *mbase) +{ + return musb_readb(mbase, MUSB_TXFIFOSZ); +} + +static inline u16 musb_read_txfifoadd(void __iomem *mbase) +{ + return musb_readw(mbase, MUSB_TXFIFOADD); +} + +static inline u8 musb_read_rxfifosz(void __iomem *mbase) +{ + return musb_readb(mbase, MUSB_RXFIFOSZ); +} + +static inline u16 musb_read_rxfifoadd(void __iomem *mbase) +{ + return musb_readw(mbase, MUSB_RXFIFOADD); +} + static inline u8 musb_read_configdata(void __iomem *mbase) { musb_writeb(mbase, MUSB_INDEX, 0); @@ -381,6 +401,36 @@ static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum, qh_h_port_reg); } +static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum) +{ + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXFUNCADDR)); +} + +static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum) +{ + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBADDR)); +} + +static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum) +{ + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBPORT)); +} + +static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum) +{ + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR)); +} + +static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum) +{ + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR)); +} + +static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum) +{ + return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT)); +} + #else /* CONFIG_BLACKFIN */ #define USB_BASE USB_FADDR @@ -460,6 +510,22 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) { } +static inline u8 musb_read_txfifosz(void __iomem *mbase) +{ +} + +static inline u16 musb_read_txfifoadd(void __iomem *mbase) +{ +} + +static inline u8 musb_read_rxfifosz(void __iomem *mbase) +{ +} + +static inline u16 musb_read_rxfifoadd(void __iomem *mbase) +{ +} + static inline u8 musb_read_configdata(void __iomem *mbase) { return 0; @@ -505,6 +571,30 @@ static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum, { } +static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum) +{ +} + +static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum) +{ +} + +static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum) +{ +} + +static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum) +{ +} + +static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum) +{ +} + +static inline void musb_read_txhubport(void __iomem *mbase, u8 epnum) +{ +} + #endif /* CONFIG_BLACKFIN */ #endif /* __MUSB_REGS_H__ */ diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 83beeac5e7bf..15a3f27b5747 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -255,6 +255,22 @@ int __init musb_platform_init(struct musb *musb) return 0; } +#ifdef CONFIG_PM +void musb_platform_save_context(struct musb_context_registers + *musb_context) +{ + musb_context->otg_sysconfig = omap_readl(OTG_SYSCONFIG); + musb_context->otg_forcestandby = omap_readl(OTG_FORCESTDBY); +} + +void musb_platform_restore_context(struct musb_context_registers + *musb_context) +{ + omap_writel(musb_context->otg_sysconfig, OTG_SYSCONFIG); + omap_writel(musb_context->otg_forcestandby, OTG_FORCESTDBY); +} +#endif + int musb_platform_suspend(struct musb *musb) { u32 l; -- cgit v1.2.1 From 8573e6a673fc99bd89a6c08ef9841d8b52f9d3c5 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 21 Jan 2010 15:33:53 +0200 Subject: USB: musb: get rid of omap_readl/writel we have those addresses already ioremaped, so let's use our __raw_readl/writel wrappers. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 4 ++-- drivers/usb/musb/musb_core.h | 12 +++++------ drivers/usb/musb/omap2430.c | 48 +++++++++++++++++++++++--------------------- drivers/usb/musb/omap2430.h | 32 +++++++++++++---------------- 4 files changed, 47 insertions(+), 49 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 2c53da771318..a6dc18cde27b 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2234,7 +2234,7 @@ void musb_save_context(struct musb *musb) musb_writeb(musb_base, MUSB_INDEX, musb_context.index); - musb_platform_save_context(&musb_context); + musb_platform_save_context(musb, &musb_context); } void musb_restore_context(struct musb *musb) @@ -2243,7 +2243,7 @@ void musb_restore_context(struct musb *musb) void __iomem *musb_base = musb->mregs; void __iomem *ep_target_regs; - musb_platform_restore_context(&musb_context); + musb_platform_restore_context(musb, &musb_context); if (is_host_enabled(musb)) { musb_writew(musb_base, MUSB_FRAME, musb_context.frame); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 3d66c3e01dbd..74a55b95ecbb 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -482,13 +482,13 @@ struct musb_context_registers { }; #if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430) -extern void musb_platform_save_context(struct musb_context_registers - *musb_context); -extern void musb_platform_restore_context(struct musb_context_registers - *musb_context); +extern void musb_platform_save_context(struct musb *musb, + struct musb_context_registers *musb_context); +extern void musb_platform_restore_context(struct musb *musb, + struct musb_context_registers *musb_context); #else -#define musb_platform_save_context(x) do {} while (0) -#define musb_platform_restore_context(x) do {} while (0) +#define musb_platform_save_context(m, x) do {} while (0) +#define musb_platform_restore_context(m, x) do {} while (0) #endif #endif diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 15a3f27b5747..3fe16867b5a8 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -220,7 +220,7 @@ int __init musb_platform_init(struct musb *musb) musb_platform_resume(musb); - l = omap_readl(OTG_SYSCONFIG); + l = musb_readl(musb->mregs, OTG_SYSCONFIG); l &= ~ENABLEWAKEUP; /* disable wakeup */ l &= ~NOSTDBY; /* remove possible nostdby */ l |= SMARTSTDBY; /* enable smart standby */ @@ -233,17 +233,19 @@ int __init musb_platform_init(struct musb *musb) */ if (!cpu_is_omap3430()) l |= AUTOIDLE; /* enable auto idle */ - omap_writel(l, OTG_SYSCONFIG); + musb_writel(musb->mregs, OTG_SYSCONFIG, l); - l = omap_readl(OTG_INTERFSEL); + l = musb_readl(musb->mregs, OTG_INTERFSEL); l |= ULPI_12PIN; - omap_writel(l, OTG_INTERFSEL); + musb_writel(musb->mregs, OTG_INTERFSEL, l); pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", - omap_readl(OTG_REVISION), omap_readl(OTG_SYSCONFIG), - omap_readl(OTG_SYSSTATUS), omap_readl(OTG_INTERFSEL), - omap_readl(OTG_SIMENABLE)); + musb_readl(musb->mregs, OTG_REVISION), + musb_readl(musb->mregs, OTG_SYSCONFIG), + musb_readl(musb->mregs, OTG_SYSSTATUS), + musb_readl(musb->mregs, OTG_INTERFSEL), + musb_readl(musb->mregs, OTG_SIMENABLE)); omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1); @@ -256,18 +258,18 @@ int __init musb_platform_init(struct musb *musb) } #ifdef CONFIG_PM -void musb_platform_save_context(struct musb_context_registers - *musb_context) +void musb_platform_save_context(struct musb *musb, + struct musb_context_registers *musb_context) { - musb_context->otg_sysconfig = omap_readl(OTG_SYSCONFIG); - musb_context->otg_forcestandby = omap_readl(OTG_FORCESTDBY); + musb_context->otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG); + musb_context->otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY); } -void musb_platform_restore_context(struct musb_context_registers - *musb_context) +void musb_platform_restore_context(struct musb *musb, + struct musb_context_registers *musb_context) { - omap_writel(musb_context->otg_sysconfig, OTG_SYSCONFIG); - omap_writel(musb_context->otg_forcestandby, OTG_FORCESTDBY); + musb_writel(musb->mregs, OTG_SYSCONFIG, musb_context->otg_sysconfig); + musb_writel(musb->mregs, OTG_FORCESTDBY, musb_context->otg_forcestandby); } #endif @@ -279,13 +281,13 @@ int musb_platform_suspend(struct musb *musb) return 0; /* in any role */ - l = omap_readl(OTG_FORCESTDBY); + l = musb_readl(musb->mregs, OTG_FORCESTDBY); l |= ENABLEFORCE; /* enable MSTANDBY */ - omap_writel(l, OTG_FORCESTDBY); + musb_writel(musb->mregs, OTG_FORCESTDBY, l); - l = omap_readl(OTG_SYSCONFIG); + l = musb_readl(musb->mregs, OTG_SYSCONFIG); l |= ENABLEWAKEUP; /* enable wakeup */ - omap_writel(l, OTG_SYSCONFIG); + musb_writel(musb->mregs, OTG_SYSCONFIG, l); otg_set_suspend(musb->xceiv, 1); @@ -311,13 +313,13 @@ static int musb_platform_resume(struct musb *musb) else clk_enable(musb->clock); - l = omap_readl(OTG_SYSCONFIG); + l = musb_readl(musb->mregs, OTG_SYSCONFIG); l &= ~ENABLEWAKEUP; /* disable wakeup */ - omap_writel(l, OTG_SYSCONFIG); + musb_writel(musb->mregs, OTG_SYSCONFIG, l); - l = omap_readl(OTG_FORCESTDBY); + l = musb_readl(musb->mregs, OTG_FORCESTDBY); l &= ~ENABLEFORCE; /* disable MSTANDBY */ - omap_writel(l, OTG_FORCESTDBY); + musb_writel(musb->mregs, OTG_FORCESTDBY, l); return 0; } diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h index fbede7798aed..40b3c02ae9f0 100644 --- a/drivers/usb/musb/omap2430.h +++ b/drivers/usb/musb/omap2430.h @@ -10,47 +10,43 @@ #ifndef __MUSB_OMAP243X_H__ #define __MUSB_OMAP243X_H__ -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) -#include #include /* * OMAP2430-specific definitions */ -#define MENTOR_BASE_OFFSET 0 -#if defined(CONFIG_ARCH_OMAP2430) -#define OMAP_HSOTG_BASE (OMAP243X_HS_BASE) -#elif defined(CONFIG_ARCH_OMAP3430) -#define OMAP_HSOTG_BASE (OMAP34XX_HSUSB_OTG_BASE) -#endif -#define OMAP_HSOTG(offset) (OMAP_HSOTG_BASE + 0x400 + (offset)) -#define OTG_REVISION OMAP_HSOTG(0x0) -#define OTG_SYSCONFIG OMAP_HSOTG(0x4) +#define OTG_REVISION 0x400 + +#define OTG_SYSCONFIG 0x404 # define MIDLEMODE 12 /* bit position */ # define FORCESTDBY (0 << MIDLEMODE) # define NOSTDBY (1 << MIDLEMODE) # define SMARTSTDBY (2 << MIDLEMODE) + # define SIDLEMODE 3 /* bit position */ # define FORCEIDLE (0 << SIDLEMODE) # define NOIDLE (1 << SIDLEMODE) # define SMARTIDLE (2 << SIDLEMODE) + # define ENABLEWAKEUP (1 << 2) # define SOFTRST (1 << 1) # define AUTOIDLE (1 << 0) -#define OTG_SYSSTATUS OMAP_HSOTG(0x8) + +#define OTG_SYSSTATUS 0x408 # define RESETDONE (1 << 0) -#define OTG_INTERFSEL OMAP_HSOTG(0xc) + +#define OTG_INTERFSEL 0x40c # define EXTCP (1 << 2) -# define PHYSEL 0 /* bit position */ +# define PHYSEL 0 /* bit position */ # define UTMI_8BIT (0 << PHYSEL) # define ULPI_12PIN (1 << PHYSEL) # define ULPI_8PIN (2 << PHYSEL) -#define OTG_SIMENABLE OMAP_HSOTG(0x10) + +#define OTG_SIMENABLE 0x410 # define TM1 (1 << 0) -#define OTG_FORCESTDBY OMAP_HSOTG(0x14) -# define ENABLEFORCE (1 << 0) -#endif /* CONFIG_ARCH_OMAP2430 */ +#define OTG_FORCESTDBY 0x414 +# define ENABLEFORCE (1 << 0) #endif /* __MUSB_OMAP243X_H__ */ -- cgit v1.2.1 From ad517e9ed8723363ebff0c5b413cbaa503aeb0ce Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 21 Jan 2010 15:33:54 +0200 Subject: USB: musb: we already tested for dyn_fifo ... and even added a flag to struct musb, so let's use that. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index a6dc18cde27b..3e9b3b0e9c0d 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1398,21 +1398,10 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) musb->nr_endpoints = 1; musb->epmask = 1; - if (reg & MUSB_CONFIGDATA_DYNFIFO) { - if (musb->config->dyn_fifo) - status = ep_config_from_table(musb); - else { - ERR("reconfigure software for Dynamic FIFOs\n"); - status = -ENODEV; - } - } else { - if (!musb->config->dyn_fifo) - status = ep_config_from_hw(musb); - else { - ERR("reconfigure software for static FIFOs\n"); - return -ENODEV; - } - } + if (musb->dyn_fifo) + status = ep_config_from_table(musb); + else + status = ep_config_from_hw(musb); if (status < 0) return status; -- cgit v1.2.1 From 3d268645d50989bc874fadf20db6fd6d17b380dc Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 21 Jan 2010 15:33:56 +0200 Subject: USB: musb: tusb6010: use resource_size Trivial patch, no functional changes. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/tusb6010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 88b587c703e9..ab776a8d98ca 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1118,7 +1118,7 @@ int __init musb_platform_init(struct musb *musb) } musb->sync = mem->start; - sync = ioremap(mem->start, mem->end - mem->start + 1); + sync = ioremap(mem->start, resource_size(mem)); if (!sync) { pr_debug("ioremap for sync failed\n"); ret = -ENOMEM; -- cgit v1.2.1 From da5108e1a350c84b185b5f11aa58fea93a204fe0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 21 Jan 2010 15:33:57 +0200 Subject: USB: musb: unmap base if we can't probe when probe() fails, we should iounmap() the mapped address. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 3e9b3b0e9c0d..de7b3770f6ee 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2110,6 +2110,7 @@ static int __init musb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int irq = platform_get_irq(pdev, 0); + int status; struct resource *iomem; void __iomem *base; @@ -2127,7 +2128,12 @@ static int __init musb_probe(struct platform_device *pdev) /* clobbered by use_dma=n */ orig_dma_mask = dev->dma_mask; #endif - return musb_init_controller(dev, irq, base); + + status = musb_init_controller(dev, irq, base); + if (status < 0) + iounmap(base); + + return status; } static int __exit musb_remove(struct platform_device *pdev) -- cgit v1.2.1 From ab3bbfa1af64a978ffff45861a1b694313a03537 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 21 Jan 2010 15:33:58 +0200 Subject: USB: musb: only print info message if probe() is successful we were printing the info about musb probe too early where it was still possible for things to go wrong. Move the down right before the return 0 statement. While at that also convert pr_info to dev_info. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index de7b3770f6ee..0f13dedc50a1 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2004,19 +2004,6 @@ bad_config: musb->irq_wake = 0; } - pr_info("%s: USB %s mode controller at %p using %s, IRQ %d\n", - musb_driver_name, - ({char *s; - switch (musb->board_mode) { - case MUSB_HOST: s = "Host"; break; - case MUSB_PERIPHERAL: s = "Peripheral"; break; - default: s = "OTG"; break; - }; s; }), - ctrl, - (is_dma_capable() && musb->dma_controller) - ? "DMA" : "PIO", - musb->nIrq); - /* host side needs more setup */ if (is_host_enabled(musb)) { struct usb_hcd *hcd = musb_to_hcd(musb); @@ -2079,6 +2066,18 @@ bad_config: if (status) goto fail2; + dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n", + ({char *s; + switch (musb->board_mode) { + case MUSB_HOST: s = "Host"; break; + case MUSB_PERIPHERAL: s = "Peripheral"; break; + default: s = "OTG"; break; + }; s; }), + ctrl, + (is_dma_capable() && musb->dma_controller) + ? "DMA" : "PIO", + musb->nIrq); + return 0; fail2: -- cgit v1.2.1 From 0ded2f146acfaf71e5f4c15b80cf89b3af48134c Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Thu, 28 Jan 2010 20:43:44 -0500 Subject: USB: musb: set version of Blackfin version All current Blackfin parts are using RTL v1.9, but they don't expose the hardware registers to probe this dynamically. So hardcode the version to v1.9 for now. Need to move the local hwvers related defines higher up in the header so that sub-musb headers may utilize them. Signed-off-by: Cliff Cai Signed-off-by: Mike Frysinger Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.h | 16 +++++++++------- drivers/usb/musb/musb_regs.h | 6 +++++- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 74a55b95ecbb..17e7115493ff 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -52,6 +52,15 @@ struct musb; struct musb_hw_ep; struct musb_ep; +/* Helper defines for struct musb->hwvers */ +#define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) +#define MUSB_HWVERS_MINOR(x) (x & 0x3ff) +#define MUSB_HWVERS_RC 0x8000 +#define MUSB_HWVERS_1300 0x52C +#define MUSB_HWVERS_1400 0x590 +#define MUSB_HWVERS_1800 0x720 +#define MUSB_HWVERS_1900 0x784 +#define MUSB_HWVERS_2000 0x800 #include "musb_debug.h" #include "musb_dma.h" @@ -322,13 +331,6 @@ struct musb { struct clk *clock; irqreturn_t (*isr)(int, void *); struct work_struct irq_work; -#define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) -#define MUSB_HWVERS_MINOR(x) (x & 0x3ff) -#define MUSB_HWVERS_RC 0x8000 -#define MUSB_HWVERS_1300 0x52C -#define MUSB_HWVERS_1400 0x590 -#define MUSB_HWVERS_1800 0x720 -#define MUSB_HWVERS_2000 0x800 u16 hwvers; /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 895fb057e443..292894a2c247 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -533,7 +533,11 @@ static inline u8 musb_read_configdata(void __iomem *mbase) static inline u16 musb_read_hwvers(void __iomem *mbase) { - return 0; + /* + * This register is invisible on Blackfin, actually the MUSB + * RTL version of Blackfin is 1.9, so just harcode its value. + */ + return MUSB_HWVERS_1900; } static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase) -- cgit v1.2.1 From 9f445cb29918dc488b7a9a92ef018599cce33df7 Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Thu, 28 Jan 2010 20:44:18 -0500 Subject: USB: musb: disable double buffering for older RTL versions Trying to use double buffer modes in RTL versions <2.0 may result in infinite hangs or data corruption. So avoid them with older versions. Signed-off-by: Cliff Cai Signed-off-by: Mike Frysinger Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 17 +++++++++++++++-- drivers/usb/musb/musb_host.c | 10 ++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index cbcf14a236e6..41de3a903152 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -895,7 +895,14 @@ static int musb_gadget_enable(struct usb_ep *ep, /* REVISIT if can_bulk_split(), use by updating "tmp"; * likewise high bandwidth periodic tx */ - musb_writew(regs, MUSB_TXMAXP, tmp); + /* Set TXMAXP with the FIFO size of the endpoint + * to disable double buffering mode. Currently, It seems that double + * buffering has problem if musb RTL revision number < 2.0. + */ + if (musb->hwvers < MUSB_HWVERS_2000) + musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); + else + musb_writew(regs, MUSB_TXMAXP, tmp); csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG; if (musb_readw(regs, MUSB_TXCSR) @@ -925,7 +932,13 @@ static int musb_gadget_enable(struct usb_ep *ep, /* REVISIT if can_bulk_combine() use by updating "tmp" * likewise high bandwidth periodic rx */ - musb_writew(regs, MUSB_RXMAXP, tmp); + /* Set RXMAXP with the FIFO size of the endpoint + * to disable double buffering mode. + */ + if (musb->hwvers < MUSB_HWVERS_2000) + musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx); + else + musb_writew(regs, MUSB_RXMAXP, tmp); /* force shared fifo to OUT-only mode */ if (hw_ep->is_shared_fifo) { diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index c3fdd6d69f5e..3421cf9858b5 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -605,8 +605,14 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg); musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg); /* NOTE: bulk combining rewrites high bits of maxpacket */ - musb_writew(ep->regs, MUSB_RXMAXP, - qh->maxpacket | ((qh->hb_mult - 1) << 11)); + /* Set RXMAXP with the FIFO size of the endpoint + * to disable double buffer mode. + */ + if (musb->hwvers < MUSB_HWVERS_2000) + musb_writew(ep->regs, MUSB_RXMAXP, ep->max_packet_sz_rx); + else + musb_writew(ep->regs, MUSB_RXMAXP, + qh->maxpacket | ((qh->hb_mult - 1) << 11)); ep->rx_reinit = 0; } -- cgit v1.2.1 From 08e6c972da616d057b63fd3f89ce0eb539952f06 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 2 Feb 2010 14:47:17 -0800 Subject: USB: musb: test always evaluates to false The removed part always evaluates to false. Signed-off-by: Roel Kluin Cc: Felipe Balbi Cc: Greg Kroah-Hartman Acked-by: David Brownell Signed-off-by: Andrew Morton --- drivers/usb/musb/musb_gadget.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 41de3a903152..a9f288cd70ed 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1710,8 +1710,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) return -EINVAL; /* driver must be initialized to support peripheral mode */ - if (!musb || !(musb->board_mode == MUSB_OTG - || musb->board_mode != MUSB_OTG)) { + if (!musb) { DBG(1, "%s, no dev??\n", __func__); return -ENODEV; } -- cgit v1.2.1