mirror of
https://github.com/torvalds/linux.git
synced 2024-11-18 18:11:56 +00:00
Merge branch 'for-greg' of git://gitorious.org/usb/usb into usb-linus
* 'for-greg' of git://gitorious.org/usb/usb: USB: musb: blackfin: work around anomaly 05000450 usb: musb: Fix the crash issue during reboot usb: musb: gadget: check the correct list_head usb: musb: temporarily make it bool USB: musb: dereferencing an iomem pointer USB: musb: silence printk format warning USB: musb: using 0 instead of NULL USB: musb: add missing unlock in cppi_interrupt() usb: musb: ux500: copy dma mask from platform device to musb device usb: musb: clear AUTOSET while clearing DMAENAB
This commit is contained in:
commit
86a45a023d
@ -14,7 +14,7 @@ config USB_MUSB_HDRC
|
|||||||
select TWL4030_USB if MACH_OMAP_3430SDP
|
select TWL4030_USB if MACH_OMAP_3430SDP
|
||||||
select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
|
select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
|
||||||
select USB_OTG_UTILS
|
select USB_OTG_UTILS
|
||||||
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
|
bool 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
|
||||||
help
|
help
|
||||||
Say Y here if your system has a dual role high speed USB
|
Say Y here if your system has a dual role high speed USB
|
||||||
controller based on the Mentor Graphics silicon IP. Then
|
controller based on the Mentor Graphics silicon IP. Then
|
||||||
@ -30,8 +30,8 @@ config USB_MUSB_HDRC
|
|||||||
|
|
||||||
If you do not know what this is, please say N.
|
If you do not know what this is, please say N.
|
||||||
|
|
||||||
To compile this driver as a module, choose M here; the
|
# To compile this driver as a module, choose M here; the
|
||||||
module will be called "musb-hdrc".
|
# module will be called "musb-hdrc".
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Platform Glue Layer"
|
prompt "Platform Glue Layer"
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
|
||||||
#include "musb_core.h"
|
#include "musb_core.h"
|
||||||
|
#include "musbhsdma.h"
|
||||||
#include "blackfin.h"
|
#include "blackfin.h"
|
||||||
|
|
||||||
struct bfin_glue {
|
struct bfin_glue {
|
||||||
@ -332,6 +333,27 @@ static int bfin_musb_set_mode(struct musb *musb, u8 musb_mode)
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bfin_musb_adjust_channel_params(struct dma_channel *channel,
|
||||||
|
u16 packet_sz, u8 *mode,
|
||||||
|
dma_addr_t *dma_addr, u32 *len)
|
||||||
|
{
|
||||||
|
struct musb_dma_channel *musb_channel = channel->private_data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Anomaly 05000450 might cause data corruption when using DMA
|
||||||
|
* MODE 1 transmits with short packet. So to work around this,
|
||||||
|
* we truncate all MODE 1 transfers down to a multiple of the
|
||||||
|
* max packet size, and then do the last short packet transfer
|
||||||
|
* (if there is any) using MODE 0.
|
||||||
|
*/
|
||||||
|
if (ANOMALY_05000450) {
|
||||||
|
if (musb_channel->transmit && *mode == 1)
|
||||||
|
*len = *len - (*len % packet_sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void bfin_musb_reg_init(struct musb *musb)
|
static void bfin_musb_reg_init(struct musb *musb)
|
||||||
{
|
{
|
||||||
if (ANOMALY_05000346) {
|
if (ANOMALY_05000346) {
|
||||||
@ -430,6 +452,8 @@ static const struct musb_platform_ops bfin_ops = {
|
|||||||
|
|
||||||
.vbus_status = bfin_musb_vbus_status,
|
.vbus_status = bfin_musb_vbus_status,
|
||||||
.set_vbus = bfin_musb_set_vbus,
|
.set_vbus = bfin_musb_set_vbus,
|
||||||
|
|
||||||
|
.adjust_channel_params = bfin_musb_adjust_channel_params,
|
||||||
};
|
};
|
||||||
|
|
||||||
static u64 bfin_dmamask = DMA_BIT_MASK(32);
|
static u64 bfin_dmamask = DMA_BIT_MASK(32);
|
||||||
|
@ -597,12 +597,12 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx)
|
|||||||
length = min(n_bds * maxpacket, length);
|
length = min(n_bds * maxpacket, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG(4, "TX DMA%d, pktSz %d %s bds %d dma 0x%x len %u\n",
|
DBG(4, "TX DMA%d, pktSz %d %s bds %d dma 0x%llx len %u\n",
|
||||||
tx->index,
|
tx->index,
|
||||||
maxpacket,
|
maxpacket,
|
||||||
rndis ? "rndis" : "transparent",
|
rndis ? "rndis" : "transparent",
|
||||||
n_bds,
|
n_bds,
|
||||||
addr, length);
|
(unsigned long long)addr, length);
|
||||||
|
|
||||||
cppi_rndis_update(tx, 0, musb->ctrl_base, rndis);
|
cppi_rndis_update(tx, 0, musb->ctrl_base, rndis);
|
||||||
|
|
||||||
@ -820,7 +820,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
|
|||||||
length = min(n_bds * maxpacket, length);
|
length = min(n_bds * maxpacket, length);
|
||||||
|
|
||||||
DBG(4, "RX DMA%d seg, maxp %d %s bds %d (cnt %d) "
|
DBG(4, "RX DMA%d seg, maxp %d %s bds %d (cnt %d) "
|
||||||
"dma 0x%x len %u %u/%u\n",
|
"dma 0x%llx len %u %u/%u\n",
|
||||||
rx->index, maxpacket,
|
rx->index, maxpacket,
|
||||||
onepacket
|
onepacket
|
||||||
? (is_rndis ? "rndis" : "onepacket")
|
? (is_rndis ? "rndis" : "onepacket")
|
||||||
@ -829,7 +829,8 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
|
|||||||
musb_readl(tibase,
|
musb_readl(tibase,
|
||||||
DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4))
|
DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4))
|
||||||
& 0xffff,
|
& 0xffff,
|
||||||
addr, length, rx->channel.actual_len, rx->buf_len);
|
(unsigned long long)addr, length,
|
||||||
|
rx->channel.actual_len, rx->buf_len);
|
||||||
|
|
||||||
/* only queue one segment at a time, since the hardware prevents
|
/* only queue one segment at a time, since the hardware prevents
|
||||||
* correct queue shutdown after unexpected short packets
|
* correct queue shutdown after unexpected short packets
|
||||||
@ -1039,9 +1040,9 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)
|
|||||||
if (!completed && (bd->hw_options & CPPI_OWN_SET))
|
if (!completed && (bd->hw_options & CPPI_OWN_SET))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
DBG(5, "C/RXBD %08x: nxt %08x buf %08x "
|
DBG(5, "C/RXBD %llx: nxt %08x buf %08x "
|
||||||
"off.len %08x opt.len %08x (%d)\n",
|
"off.len %08x opt.len %08x (%d)\n",
|
||||||
bd->dma, bd->hw_next, bd->hw_bufp,
|
(unsigned long long)bd->dma, bd->hw_next, bd->hw_bufp,
|
||||||
bd->hw_off_len, bd->hw_options,
|
bd->hw_off_len, bd->hw_options,
|
||||||
rx->channel.actual_len);
|
rx->channel.actual_len);
|
||||||
|
|
||||||
@ -1111,11 +1112,12 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)
|
|||||||
musb_ep_select(cppi->mregs, rx->index + 1);
|
musb_ep_select(cppi->mregs, rx->index + 1);
|
||||||
csr = musb_readw(regs, MUSB_RXCSR);
|
csr = musb_readw(regs, MUSB_RXCSR);
|
||||||
if (csr & MUSB_RXCSR_DMAENAB) {
|
if (csr & MUSB_RXCSR_DMAENAB) {
|
||||||
DBG(4, "list%d %p/%p, last %08x%s, csr %04x\n",
|
DBG(4, "list%d %p/%p, last %llx%s, csr %04x\n",
|
||||||
rx->index,
|
rx->index,
|
||||||
rx->head, rx->tail,
|
rx->head, rx->tail,
|
||||||
rx->last_processed
|
rx->last_processed
|
||||||
? rx->last_processed->dma
|
? (unsigned long long)
|
||||||
|
rx->last_processed->dma
|
||||||
: 0,
|
: 0,
|
||||||
completed ? ", completed" : "",
|
completed ? ", completed" : "",
|
||||||
csr);
|
csr);
|
||||||
@ -1167,8 +1169,11 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
|
|||||||
tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG);
|
tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG);
|
||||||
rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG);
|
rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG);
|
||||||
|
|
||||||
if (!tx && !rx)
|
if (!tx && !rx) {
|
||||||
|
if (cppi->irq)
|
||||||
|
spin_unlock_irqrestore(&musb->lock, flags);
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
DBG(4, "CPPI IRQ Tx%x Rx%x\n", tx, rx);
|
DBG(4, "CPPI IRQ Tx%x Rx%x\n", tx, rx);
|
||||||
|
|
||||||
@ -1199,7 +1204,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
|
|||||||
*/
|
*/
|
||||||
if (NULL == bd) {
|
if (NULL == bd) {
|
||||||
DBG(1, "null BD\n");
|
DBG(1, "null BD\n");
|
||||||
tx_ram->tx_complete = 0;
|
musb_writel(&tx_ram->tx_complete, 0, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1452,7 +1457,7 @@ static int cppi_channel_abort(struct dma_channel *channel)
|
|||||||
* compare mode by writing 1 to the tx_complete register.
|
* compare mode by writing 1 to the tx_complete register.
|
||||||
*/
|
*/
|
||||||
cppi_reset_tx(tx_ram, 1);
|
cppi_reset_tx(tx_ram, 1);
|
||||||
cppi_ch->head = 0;
|
cppi_ch->head = NULL;
|
||||||
musb_writel(&tx_ram->tx_complete, 0, 1);
|
musb_writel(&tx_ram->tx_complete, 0, 1);
|
||||||
cppi_dump_tx(5, cppi_ch, " (done teardown)");
|
cppi_dump_tx(5, cppi_ch, " (done teardown)");
|
||||||
|
|
||||||
|
@ -1030,6 +1030,7 @@ static void musb_shutdown(struct platform_device *pdev)
|
|||||||
struct musb *musb = dev_to_musb(&pdev->dev);
|
struct musb *musb = dev_to_musb(&pdev->dev);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
pm_runtime_get_sync(musb->controller);
|
||||||
spin_lock_irqsave(&musb->lock, flags);
|
spin_lock_irqsave(&musb->lock, flags);
|
||||||
musb_platform_disable(musb);
|
musb_platform_disable(musb);
|
||||||
musb_generic_disable(musb);
|
musb_generic_disable(musb);
|
||||||
@ -1040,6 +1041,7 @@ static void musb_shutdown(struct platform_device *pdev)
|
|||||||
musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
|
musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
|
||||||
musb_platform_exit(musb);
|
musb_platform_exit(musb);
|
||||||
|
|
||||||
|
pm_runtime_put(musb->controller);
|
||||||
/* FIXME power down */
|
/* FIXME power down */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,6 +261,7 @@ enum musb_g_ep0_state {
|
|||||||
* @try_ilde: tries to idle the IP
|
* @try_ilde: tries to idle the IP
|
||||||
* @vbus_status: returns vbus status if possible
|
* @vbus_status: returns vbus status if possible
|
||||||
* @set_vbus: forces vbus status
|
* @set_vbus: forces vbus status
|
||||||
|
* @channel_program: pre check for standard dma channel_program func
|
||||||
*/
|
*/
|
||||||
struct musb_platform_ops {
|
struct musb_platform_ops {
|
||||||
int (*init)(struct musb *musb);
|
int (*init)(struct musb *musb);
|
||||||
@ -274,6 +275,10 @@ struct musb_platform_ops {
|
|||||||
|
|
||||||
int (*vbus_status)(struct musb *musb);
|
int (*vbus_status)(struct musb *musb);
|
||||||
void (*set_vbus)(struct musb *musb, int on);
|
void (*set_vbus)(struct musb *musb, int on);
|
||||||
|
|
||||||
|
int (*adjust_channel_params)(struct dma_channel *channel,
|
||||||
|
u16 packet_sz, u8 *mode,
|
||||||
|
dma_addr_t *dma_addr, u32 *len);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -535,7 +535,7 @@ void musb_g_tx(struct musb *musb, u8 epnum)
|
|||||||
is_dma = 1;
|
is_dma = 1;
|
||||||
csr |= MUSB_TXCSR_P_WZC_BITS;
|
csr |= MUSB_TXCSR_P_WZC_BITS;
|
||||||
csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
|
csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
|
||||||
MUSB_TXCSR_TXPKTRDY);
|
MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET);
|
||||||
musb_writew(epio, MUSB_TXCSR, csr);
|
musb_writew(epio, MUSB_TXCSR, csr);
|
||||||
/* Ensure writebuffer is empty. */
|
/* Ensure writebuffer is empty. */
|
||||||
csr = musb_readw(epio, MUSB_TXCSR);
|
csr = musb_readw(epio, MUSB_TXCSR);
|
||||||
@ -1296,7 +1296,7 @@ static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* if the hardware doesn't have the request, easy ... */
|
/* if the hardware doesn't have the request, easy ... */
|
||||||
if (musb_ep->req_list.next != &request->list || musb_ep->busy)
|
if (musb_ep->req_list.next != &req->list || musb_ep->busy)
|
||||||
musb_g_giveback(musb_ep, request, -ECONNRESET);
|
musb_g_giveback(musb_ep, request, -ECONNRESET);
|
||||||
|
|
||||||
/* ... else abort the dma transfer ... */
|
/* ... else abort the dma transfer ... */
|
||||||
|
@ -169,6 +169,14 @@ static int dma_channel_program(struct dma_channel *channel,
|
|||||||
BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN ||
|
BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN ||
|
||||||
channel->status == MUSB_DMA_STATUS_BUSY);
|
channel->status == MUSB_DMA_STATUS_BUSY);
|
||||||
|
|
||||||
|
/* Let targets check/tweak the arguments */
|
||||||
|
if (musb->ops->adjust_channel_params) {
|
||||||
|
int ret = musb->ops->adjust_channel_params(channel,
|
||||||
|
packet_sz, &mode, &dma_addr, &len);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The DMA engine in RTL1.8 and above cannot handle
|
* The DMA engine in RTL1.8 and above cannot handle
|
||||||
* DMA addresses that are not aligned to a 4 byte boundary.
|
* DMA addresses that are not aligned to a 4 byte boundary.
|
||||||
|
@ -93,6 +93,8 @@ static int __init ux500_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
musb->dev.parent = &pdev->dev;
|
musb->dev.parent = &pdev->dev;
|
||||||
|
musb->dev.dma_mask = pdev->dev.dma_mask;
|
||||||
|
musb->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask;
|
||||||
|
|
||||||
glue->dev = &pdev->dev;
|
glue->dev = &pdev->dev;
|
||||||
glue->musb = musb;
|
glue->musb = musb;
|
||||||
|
Loading…
Reference in New Issue
Block a user