Commit 6e0abdbc authored by Juha Yrjola's avatar Juha Yrjola

Merge branch 'master' of /home/git/linux-omap-2.6

parents 40cedbdb 6c4a8512
......@@ -508,7 +508,6 @@ void musb_g_tx(struct musb *pThis, u8 bEnd)
if (!pRequest) {
DBG(4, "%s idle now\n",
pEnd->end_point.name);
musb_platform_try_idle(pThis);
break;
}
}
......@@ -974,8 +973,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
pEnd->dma ? "dma, " : "",
pEnd->wPacketSize);
pThis->status |= MUSB_VBUS_STATUS_CHG;
schedule_work(&pThis->irq_work);
sysfs_notify(&pThis->controller->kobj, NULL, "cable");
fail:
spin_unlock_irqrestore(&pThis->Lock, flags);
......@@ -1018,8 +1016,7 @@ static int musb_gadget_disable(struct usb_ep *ep)
/* abort all pending DMA and requests */
nuke(pEnd, -ESHUTDOWN);
pThis->status |= MUSB_VBUS_STATUS_CHG; /* FIXME not for ep_disable!! */
schedule_work(&pThis->irq_work);
sysfs_notify(&pThis->controller->kobj, NULL, "cable");
spin_unlock_irqrestore(&(pThis->Lock), flags);
......@@ -1664,6 +1661,9 @@ int __devinit musb_gadget_setup(struct musb *pThis)
musb_g_init_endpoints(pThis);
pThis->is_active = 0;
musb_platform_try_idle(pThis);
status = device_register(&pThis->g.dev);
if (status != 0)
the_gadget = NULL;
......@@ -1746,6 +1746,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
*/
pThis->xceiv.gadget = &pThis->g;
pThis->xceiv.state = OTG_STATE_B_IDLE;
pThis->is_active = 1;
/* FIXME this ignores the softconnect flag. Drivers are
* allowed hold the peripheral inactive until for example
......@@ -1857,6 +1858,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
musb->pGadgetDriver = NULL;
musb->g.dev.driver = NULL;
musb->is_active = 0;
musb_platform_try_idle(musb);
} else
retval = -EINVAL;
......@@ -1944,6 +1946,8 @@ void musb_g_disconnect(struct musb *pThis)
case OTG_STATE_B_SRP_INIT:
break;
}
pThis->is_active = 0;
}
void musb_g_reset(struct musb *pThis)
......@@ -1977,6 +1981,7 @@ __acquires(pThis->Lock)
? USB_SPEED_HIGH : USB_SPEED_FULL;
/* start in USB_STATE_DEFAULT */
pThis->is_active = 1;
MUSB_DEV_MODE(pThis);
pThis->bAddress = 0;
pThis->ep0_state = MGC_END0_STAGE_SETUP;
......
......@@ -754,11 +754,11 @@ static int musb_proc_read(char *page, char **start,
}
}
musb_platform_try_idle(pThis);
spin_unlock_irqrestore(&pThis->Lock, flags);
*eof = 1;
musb_platform_try_idle(pThis);
return (buffer - page) - off;
}
......
......@@ -197,9 +197,6 @@ enum musb_g_ep0_state {
MGC_END0_STAGE_ACKWAIT, /* after zlp, before statusin */
} __attribute__ ((packed));
/* driver and cable VBUS status states for musb_irq_work */
#define MUSB_VBUS_STATUS_CHG (1 << 0)
/* failure codes */
#define MUSB_ERR_WAITING 1
#define MUSB_ERR_VBUS -1
......@@ -395,7 +392,6 @@ struct musb {
spinlock_t Lock;
struct clk *clock;
irqreturn_t (*isr)(int, void *, struct pt_regs *);
struct work_struct irq_work;
#ifdef CONFIG_USB_MUSB_HDRC_HCD
......@@ -450,10 +446,11 @@ struct musb {
u8 board_mode; /* enum musb_mode */
int (*board_set_power)(int state);
u8 status; /* status change flags for musb_irq_work */
s8 bFailCode; /* one of MUSB_ERR_* failure code */
/* active means connected and not suspended */
unsigned is_active:1;
unsigned bIsMultipoint:1;
unsigned bIsDevice:1;
unsigned bIsHost:1;
......
......@@ -212,6 +212,7 @@ static void otg_timeout(unsigned long ptr)
default:
WARN("timeout in state %d, now what?\n", pMachine->bState);
}
musb_platform_try_idle(musb);
spin_unlock_irqrestore(&musb->Lock, flags);
}
......
......@@ -384,6 +384,7 @@ static irqreturn_t musb_stage0_irq(struct musb * pThis, u8 bIntrUSB,
if (bIntrUSB & MGC_M_INTR_RESUME) {
handled = IRQ_HANDLED;
DBG(3, "RESUME\n");
pThis->is_active = 1;
if (devctl & MGC_M_DEVCTL_HM) {
#ifdef CONFIG_USB_MUSB_HDRC_HCD
......@@ -458,6 +459,7 @@ static irqreturn_t musb_stage0_irq(struct musb * pThis, u8 bIntrUSB,
if (bIntrUSB & MGC_M_INTR_CONNECT) {
handled = IRQ_HANDLED;
pThis->is_active = 1;
pThis->bEnd0Stage = MGC_END0_START;
......@@ -527,6 +529,8 @@ static irqreturn_t musb_stage0_irq(struct musb * pThis, u8 bIntrUSB,
otg_input_changed(pThis, devctl, TRUE, FALSE,
(power & MGC_M_POWER_SUSPENDM)
? TRUE : FALSE);
sysfs_notify(&pThis->controller->kobj, NULL, "cable");
}
handled = IRQ_HANDLED;
......@@ -598,6 +602,7 @@ static irqreturn_t musb_stage2_irq(struct musb * pThis, u8 bIntrUSB,
DBG(1, "DISCONNECT as %s, devctl %02x\n",
MUSB_MODE(pThis), devctl);
handled = IRQ_HANDLED;
pThis->is_active = 0;
/* need to check it against pThis, because devctl is going
* to report ID low as soon as the device gets disconnected
......@@ -609,6 +614,8 @@ static irqreturn_t musb_stage2_irq(struct musb * pThis, u8 bIntrUSB,
/* REVISIT all OTG state machine transitions */
otg_input_changed_X(pThis, FALSE, FALSE);
sysfs_notify(&pThis->controller->kobj, NULL, "cable");
}
if (bIntrUSB & MGC_M_INTR_SUSPEND) {
......@@ -618,9 +625,15 @@ static irqreturn_t musb_stage2_irq(struct musb * pThis, u8 bIntrUSB,
/* peripheral suspend, may trigger HNP */
if (!(devctl & MGC_M_DEVCTL_HM)) {
musb_g_suspend(pThis);
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
pThis->is_active = is_otg_enabled(pThis)
&& pThis->xceiv.gadget->b_hnp_enable;
#else
pThis->is_active = 0;
#endif
otg_input_changed(pThis, devctl, FALSE, FALSE, TRUE);
musb_platform_try_idle(pThis);
}
} else
pThis->is_active = 0;
}
return handled;
......@@ -1416,7 +1429,6 @@ musb_cable_show(struct device *dev, struct device_attribute *attr, char *buf)
v2 = "connected";
else
v2 = "disconnected";
musb_platform_try_idle(musb);
#else
/* NOTE: board-specific issues, like too-big capacitors keeping
* VBUS high for a long time after power has been removed, can
......@@ -1440,6 +1452,7 @@ musb_cable_show(struct device *dev, struct device_attribute *attr, char *buf)
} else /* VBUS level below A-Valid */
v2 = "disconnected";
#endif
musb_platform_try_idle(musb);
spin_unlock_irqrestore(&musb->Lock, flags);
return sprintf(buf, "%s%s\n", v1, v2);
......@@ -1448,25 +1461,6 @@ static DEVICE_ATTR(cable, S_IRUGO, musb_cable_show, NULL);
#endif
static void musb_irq_work(void *data)
{
struct musb *musb = (struct musb *)data;
unsigned long flags;
u8 event = 0;
spin_lock_irqsave(&musb->Lock, flags);
if (musb->status & MUSB_VBUS_STATUS_CHG) {
musb->status &= ~MUSB_VBUS_STATUS_CHG;
event = 1;
}
musb_platform_try_idle(musb);
spin_unlock_irqrestore(&musb->Lock, flags);
#ifdef CONFIG_SYSFS
if (event)
sysfs_notify(&musb->controller->kobj, NULL, "cable");
#endif
}
/* --------------------------------------------------------------------------
* Init support
*/
......@@ -1654,6 +1648,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
goto fail2;
}
pThis->nIrq = nIrq;
device_init_wakeup(dev, 1);
pr_info("%s: USB %s mode controller at %p using %s, IRQ %d\n",
musb_driver_name,
......@@ -1668,11 +1663,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
? "DMA" : "PIO",
pThis->nIrq);
// FIXME:
// - convert to the HCD framework
// - if (board_mode == MUSB_OTG) do startup with peripheral
// - ... involves refcounting updates
#ifdef CONFIG_USB_MUSB_HDRC_HCD
/* host side needs more setup, except for no-host modes */
if (pThis->board_mode != MUSB_PERIPHERAL) {
......@@ -1737,11 +1727,11 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb_debug_create("driver/musb_hdrc", pThis);
else {
fail:
device_init_wakeup(dev, 0);
musb_free(pThis);
return status;
}
INIT_WORK(&pThis->irq_work, musb_irq_work, pThis);
#ifdef CONFIG_SYSFS
device_create_file(dev, &dev_attr_mode);
device_create_file(dev, &dev_attr_cable);
......@@ -1796,15 +1786,12 @@ static int __devexit musb_remove(struct platform_device *pdev)
usb_remove_hcd(musb_to_hcd(musb));
#endif
musb_free(musb);
device_init_wakeup(&pdev->dev, 0);
return 0;
}
#ifdef CONFIG_PM
/* REVISIT when power savings matter on DaVinci, look at turning
* off its phy clock during system suspend iff wakeup is disabled
*/
static int musb_suspend(struct platform_device *pdev, pm_message_t message)
{
unsigned long flags;
......@@ -1821,11 +1808,10 @@ static int musb_suspend(struct platform_device *pdev, pm_message_t message)
*/
} else if (is_host_active(musb)) {
/* we know all the children are suspended; sometimes
* they will even be wakeup-enabled
* they will even be wakeup-enabled.
*/
}
musb_platform_try_idle(musb);
clk_disable(musb->clock);
spin_unlock_irqrestore(&musb->Lock, flags);
return 0;
......
This diff is collapsed.
......@@ -103,9 +103,20 @@
#define TUSB_PRCM_MNGMT_5V_CPEN (1 << 2)
#define TUSB_PRCM_MNGMT_PM_IDLE (1 << 1)
#define TUSB_PRCM_MNGMT_DEV_IDLE (1 << 0)
#define TUSB_PRCM_MNGMT_PM_CLEAR_MASK ((0x3 << 3) | (0x3 << 0))
#define TUSB_PRCM_MNGMT_CPEN_MASK ((1 << 9) | (0x3 << 3))
#define TUSB_PRCM_MNGMT_SUSPEND_MASK ((1 << 10) | (0x3 << 0))
#define TUSB_PRCM_MNGMT_PM_CLEAR_MASK \
( TUSB_PRCM_MNGMT_15_SW_EN \
| TUSB_PRCM_MNGMT_33_SW_EN \
| TUSB_PRCM_MNGMT_PM_IDLE \
| TUSB_PRCM_MNGMT_DEV_IDLE )
#define TUSB_PRCM_MNGMT_CPEN_MASK \
( TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN \
| TUSB_PRCM_MNGMT_15_SW_EN \
| TUSB_PRCM_MNGMT_33_SW_EN )
#define TUSB_PRCM_MNGMT_SUSPEND_MASK \
( TUSB_PRCM_MNGMT_OTG_SESS_END_EN \
| TUSB_PRCM_MNGMT_PM_IDLE \
| TUSB_PRCM_MNGMT_DEV_IDLE )
/* Wake-up source clear and mask registers */
#define TUSB_PRCM_WAKEUP_SOURCE (TUSB_SYS_REG_BASE + 0x020)
......
......@@ -145,7 +145,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
struct musb_hw_ep *hw_ep = chdat->hw_ep;
void __iomem *ep_conf = hw_ep->conf;
void __iomem *musb_base = musb->pRegs;
unsigned long transferred, flags;
unsigned long remaining, flags;
int ch;
spin_lock_irqsave(&musb->Lock, flags);
......@@ -158,17 +158,19 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
if (ch_status != OMAP_DMA_BLOCK_IRQ)
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
DBG(3, "ep%i %s dma callback ch: %i status: %x\n",
DBG(2, "ep%i %s dma callback ch: %i status: %x\n",
chdat->epnum, chdat->tx ? "tx" : "rx",
ch, ch_status);
if (chdat->tx)
transferred = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
else
transferred = musb_readl(ep_conf, TUSB_EP_RX_OFFSET);
remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET);
transferred = TUSB_EP_CONFIG_XFR_SIZE(transferred);
channel->dwActualLength = chdat->transfer_len - transferred;
remaining = TUSB_EP_CONFIG_XFR_SIZE(remaining);
channel->dwActualLength = chdat->transfer_len - remaining;
DBG(2, "remaining %lu/%lu\n", remaining, chdat->transfer_len);
if (!dmareq_works())
tusb_omap_free_shared_dmareq(chdat);
......@@ -192,7 +194,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
u16 csr;
if (chdat->tx) {
DBG(3, "terminating short tx packet\n");
DBG(2, "terminating short tx packet\n");
MGC_SelectEnd(musb_base, chdat->epnum);
csr = musb_readw(hw_ep->regs, MGC_O_HDRC_TXCSR);
csr |= MGC_M_TXCSR_MODE | MGC_M_TXCSR_TXPKTRDY;
......@@ -221,53 +223,27 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
s8 dmareq;
s8 sync_dev;
if (len < 32) {
DBG(3, "dma too short for ep%i %s dma_addr: %08x len: %u\n",
chdat->epnum, chdat->tx ? "tx" : "rx", dma_addr, len);
if (unlikely(dma_addr & 0x1))
return FALSE;
}
#if 0
if ((len % 32 != 0)) {
transfer_len = len / 32;
transfer_len *= 32;
DBG(3, "ep%i short %s dma: %lu/%lu %lu remainder\n",
chdat->epnum, chdat->tx ? "tx" : "rx",
transfer_len, len, len - transfer_len);
} else
transfer_len = len;
#else
if ((len % 32) != 0) {
DBG(3, "bad dma length for ep%i %s dma_addr: %08x len: %u\n",
chdat->epnum, chdat->tx ? "tx" : "rx", dma_addr, len);
if (len < 32)
return FALSE;
} else
transfer_len = len;
#endif
if (dma_addr & 0x1) {
DBG(3, "unaligned dma address for ep%i %s: %08x\n",
chdat->epnum, chdat->tx ? "tx" : "rx", dma_addr);
if ((len % 32 != 0))
return FALSE;
}
else
transfer_len = len;
if (dmareq_works()) {
/* FIXME: Check for allocated dma ch */
ch = chdat->ch;
dmareq = chdat->dmareq;
sync_dev = chdat->sync_dev;
} else {
if (tusb_omap_use_shared_dmareq(chdat) != 0)
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
DBG(3, "could not get dma for ep%i\n", chdat->epnum);
return FALSE;
/* FIXME: Check for allocated dma ch */
}
ch = tusb_dma->ch;
dmareq = tusb_dma->dmareq;
sync_dev = tusb_dma->sync_dev;
omap_set_dma_callback(ch, tusb_omap_dma_cb, channel);
}
......@@ -278,26 +254,32 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
chdat->dma_addr = (void __iomem *)dma_addr;
channel->bStatus = MGC_DMA_STATUS_BUSY;
DBG(3, "ep%i %s dma ch%i dma: %08x len: %u packet_sz: %i rndis: %d\n",
chdat->epnum, chdat->tx ? "tx" : "rx",
ch, dma_addr, transfer_len, packet_sz, rndis_mode);
/* Since we're recycling dma areas, we need to clean or invalidate */
if (chdat->tx)
consistent_sync(phys_to_virt(dma_addr), len,
DMA_TO_DEVICE);
else
consistent_sync(phys_to_virt(dma_addr), len,
DMA_FROM_DEVICE);
if (chdat->tx) {
consistent_sync(phys_to_virt(dma_addr), len, DMA_TO_DEVICE);
} else
consistent_sync(phys_to_virt(dma_addr), len, DMA_FROM_DEVICE);
/* Use 16-bit transfer if dma_addr is not 32-bit aligned */
if ((dma_addr & 0x3) == 0) {
dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
dma_params.elem_count = 8; /* Elements in frame */
} else {
dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
dma_params.elem_count = 16; /* Elements in frame */
fifo = hw_ep->fifo_async;
}
dma_params.frame_count = transfer_len / 32; /* Burst sz frame */
DBG(2, "ep%i %s dma ch%i dma: %08x len: %u(%u) packet_sz: %i\n",
chdat->epnum, chdat->tx ? "tx" : "rx",
ch, dma_addr, transfer_len, len, packet_sz);
/*
* Prepare omap DMA for transfer
*/
if (chdat->tx) {
dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
dma_params.elem_count = 8; /* 8x32-bit burst */
dma_params.frame_count = transfer_len / 32; /* Burst sz */
dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
dma_params.src_start = (unsigned long)dma_addr;
dma_params.src_ei = 0;
......@@ -306,23 +288,19 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
dma_params.dst_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
dma_params.dst_start = (unsigned long)fifo;
dma_params.dst_ei = 1;
dma_params.dst_fi = -31; /* Loop 32 byte window */
dma_params.dst_fi = -31; /* Loop 32 byte window */
dma_params.trigger = sync_dev;
dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
dma_params.src_or_dst_synch = 0; /* Dest sync */
src_burst = OMAP_DMA_DATA_BURST_16;
dst_burst = OMAP_DMA_DATA_BURST_8;
src_burst = OMAP_DMA_DATA_BURST_16; /* 16x32 read */
dst_burst = OMAP_DMA_DATA_BURST_8; /* 8x32 write */
} else {
dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
dma_params.elem_count = 8; /* 8x32-bit burst */
dma_params.frame_count = transfer_len / 32; /* Burst sz */
dma_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
dma_params.src_start = (unsigned long)fifo;
dma_params.src_ei = 1;
dma_params.src_fi = -31; /* Loop 32 byte window */
dma_params.src_fi = -31; /* Loop 32 byte window */
dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
dma_params.dst_start = (unsigned long)dma_addr;
......@@ -337,25 +315,11 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
dst_burst = OMAP_DMA_DATA_BURST_16; /* 16x32 write */
}
/* Use 16x16 transfer if addresses not 32-bit aligned */
if ((dma_params.src_start & 0x2) || (dma_params.dst_start & 0x2)) {
DBG(3, "using 16x16 async dma from 0x%08lx to 0x%08lx\n",
dma_params.src_start, dma_params.dst_start);
dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
dma_params.elem_count = 16; /* 16x16-bit burst */
fifo = hw_ep->fifo_async;
/* REVISIT: Check if 16x16 sync dma might also work */
if (chdat->tx)
dma_params.dst_start = (unsigned long) fifo;
else
dma_params.src_start =(unsigned long) fifo;
} else {
DBG(3, "ep%i %s using 16x32 sync dma from 0x%08lx to 0x%08lx\n",
chdat->epnum, chdat->tx ? "tx" : "rx",
dma_params.src_start, dma_params.dst_start);
}
DBG(2, "ep%i %s using %i-bit %s dma from 0x%08lx to 0x%08lx\n",
chdat->epnum, chdat->tx ? "tx" : "rx",
(dma_params.data_type == OMAP_DMA_DATA_TYPE_S32) ? 32 : 16,
((dma_addr & 0x3) == 0) ? "sync" : "async",
dma_params.src_start, dma_params.dst_start);
omap_set_dma_params(ch, &dma_params);
omap_set_dma_src_burst_mode(ch, src_burst);
......
......@@ -58,11 +58,15 @@ static void musb_port_suspend(struct musb *musb, u8 bSuspend)
musb_writeb(pBase, MGC_O_HDRC_POWER,
power | MGC_M_POWER_SUSPENDM);
musb->port1_status |= USB_PORT_STAT_SUSPEND;
musb->is_active = is_otg_enabled(musb)
&& musb->xceiv.host->b_hnp_enable;
musb_platform_try_idle(musb);
} else if (power & MGC_M_POWER_SUSPENDM) {
DBG(3, "Root port resumed\n");
musb_writeb(pBase, MGC_O_HDRC_POWER,
power | MGC_M_POWER_RESUME);
musb->is_active = 1;
musb_writeb(pBase, MGC_O_HDRC_POWER, power);
musb->port1_status &= ~USB_PORT_STAT_SUSPEND;
musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
......@@ -134,6 +138,7 @@ void musb_root_disconnect(struct musb *musb)
);
musb->port1_status |= USB_PORT_STAT_C_CONNECTION << 16;
usb_hcd_poll_rh_status(musb_to_hcd(musb));
musb->is_active = 0;
switch (musb->xceiv.state) {
case OTG_STATE_A_HOST:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment