USB fixes for 3.14-rc4

Here are a number of USB fixes for reported issues for 3.14-rc4
 
 The majority of these are for USB gadget, phy, and musb driver issues.
 And there's a few new device ids thrown in for good measure.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iEYEABECAAYFAlMJLmIACgkQMUfUDdst+ylvXQCdGw8XA8m783daSRWNhjtSCZdP
 oq8An1mSq7W4Tj82EO91ulB5C9Q7+W4c
 =BixM
 -----END PGP SIGNATURE-----

Merge tag 'usb-3.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are a number of USB fixes for reported issues for 3.14-rc4

  The majority of these are for USB gadget, phy, and musb driver issues.
  And there's a few new device ids thrown in for good measure"

* tag 'usb-3.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: chipidea: need to mask when writting endptflush and endptprime
  usb: musb: correct use of schedule_delayed_work()
  usb: phy: msm: fix compilation errors when !CONFIG_PM_SLEEP
  usb: gadget: fix NULL pointer dereference
  usb: gadget: printer: using gadget_is_otg to check otg support at runtime
  phy: let phy_provider_register be the last step in registering PHY
  phy-core: Don't allow building phy-core as a module
  phy-core: Don't propagate -ENOSUPP from phy_pm_runtime_get_sync to caller
  phy-core: phy_get: Leave error logging to the caller
  phy,phy-bcm-kona-usb2.c: Add dependency on HAS_IOMEM
  usb: musb: correct use of schedule_delayed_work()
  usb: musb: do not sleep in atomic context
  USB: serial: option: blacklist interface 4 for Cinterion PHS8 and PXS8
  USB: EHCI: add delay during suspend to prevent erroneous wakeups
  usb: gadget: bcm63xx_udc: fix build failure on DMA channel code
  usb: musb: do not sleep in atomic context
  usb: gadget: s3c2410_udc: Fix build error
  usb: musb: core: Fix remote-wakeup resume
  usb: musb: host: Fix SuperSpeed hub enumeration
  usb: musb: fix obex in g_nokia.ko causing kernel panic
This commit is contained in:
Linus Torvalds 2014-02-23 10:40:22 -08:00
commit f9b080803e
19 changed files with 159 additions and 111 deletions

View File

@ -5,7 +5,7 @@
menu "PHY Subsystem" menu "PHY Subsystem"
config GENERIC_PHY config GENERIC_PHY
tristate "PHY Core" bool "PHY Core"
help help
Generic PHY support. Generic PHY support.
@ -61,6 +61,7 @@ config PHY_EXYNOS_DP_VIDEO
config BCM_KONA_USB2_PHY config BCM_KONA_USB2_PHY
tristate "Broadcom Kona USB2 PHY Driver" tristate "Broadcom Kona USB2 PHY Driver"
depends on GENERIC_PHY depends on GENERIC_PHY
depends on HAS_IOMEM
help help
Enable this to support the Broadcom Kona USB 2.0 PHY. Enable this to support the Broadcom Kona USB 2.0 PHY.

View File

@ -176,6 +176,8 @@ int phy_init(struct phy *phy)
dev_err(&phy->dev, "phy init failed --> %d\n", ret); dev_err(&phy->dev, "phy init failed --> %d\n", ret);
goto out; goto out;
} }
} else {
ret = 0; /* Override possible ret == -ENOTSUPP */
} }
++phy->init_count; ++phy->init_count;
@ -232,6 +234,8 @@ int phy_power_on(struct phy *phy)
dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
goto out; goto out;
} }
} else {
ret = 0; /* Override possible ret == -ENOTSUPP */
} }
++phy->power_count; ++phy->power_count;
mutex_unlock(&phy->mutex); mutex_unlock(&phy->mutex);
@ -404,17 +408,11 @@ struct phy *phy_get(struct device *dev, const char *string)
index = of_property_match_string(dev->of_node, "phy-names", index = of_property_match_string(dev->of_node, "phy-names",
string); string);
phy = of_phy_get(dev, index); phy = of_phy_get(dev, index);
if (IS_ERR(phy)) {
dev_err(dev, "unable to find phy\n");
return phy;
}
} else { } else {
phy = phy_lookup(dev, string); phy = phy_lookup(dev, string);
if (IS_ERR(phy)) { }
dev_err(dev, "unable to find phy\n"); if (IS_ERR(phy))
return phy; return phy;
}
}
if (!try_module_get(phy->ops->owner)) if (!try_module_get(phy->ops->owner))
return ERR_PTR(-EPROBE_DEFER); return ERR_PTR(-EPROBE_DEFER);

View File

@ -76,10 +76,6 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
if (IS_ERR(state->regs)) if (IS_ERR(state->regs))
return PTR_ERR(state->regs); return PTR_ERR(state->regs);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL); phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL);
if (IS_ERR(phy)) { if (IS_ERR(phy)) {
dev_err(dev, "failed to create Display Port PHY\n"); dev_err(dev, "failed to create Display Port PHY\n");
@ -87,6 +83,10 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
} }
phy_set_drvdata(phy, state); phy_set_drvdata(phy, state);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
return 0; return 0;
} }

View File

@ -134,11 +134,6 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
dev_set_drvdata(dev, state); dev_set_drvdata(dev, state);
spin_lock_init(&state->slock); spin_lock_init(&state->slock);
phy_provider = devm_of_phy_provider_register(dev,
exynos_mipi_video_phy_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
struct phy *phy = devm_phy_create(dev, struct phy *phy = devm_phy_create(dev,
&exynos_mipi_video_phy_ops, NULL); &exynos_mipi_video_phy_ops, NULL);
@ -152,6 +147,11 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
phy_set_drvdata(phy, &state->phys[i]); phy_set_drvdata(phy, &state->phys[i]);
} }
phy_provider = devm_of_phy_provider_register(dev,
exynos_mipi_video_phy_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
return 0; return 0;
} }

View File

@ -99,17 +99,17 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk)) if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk); return PTR_ERR(priv->clk);
phy_provider = devm_of_phy_provider_register(&pdev->dev,
of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL); phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL);
if (IS_ERR(phy)) if (IS_ERR(phy))
return PTR_ERR(phy); return PTR_ERR(phy);
phy_set_drvdata(phy, priv); phy_set_drvdata(phy, priv);
phy_provider = devm_of_phy_provider_register(&pdev->dev,
of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
/* The boot loader may of left it on. Turn it off. */ /* The boot loader may of left it on. Turn it off. */
phy_mvebu_sata_power_off(phy); phy_mvebu_sata_power_off(phy);

View File

@ -177,11 +177,6 @@ static int omap_usb2_probe(struct platform_device *pdev)
phy->phy.otg = otg; phy->phy.otg = otg;
phy->phy.type = USB_PHY_TYPE_USB2; phy->phy.type = USB_PHY_TYPE_USB2;
phy_provider = devm_of_phy_provider_register(phy->dev,
of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
control_node = of_parse_phandle(node, "ctrl-module", 0); control_node = of_parse_phandle(node, "ctrl-module", 0);
if (!control_node) { if (!control_node) {
dev_err(&pdev->dev, "Failed to get control device phandle\n"); dev_err(&pdev->dev, "Failed to get control device phandle\n");
@ -214,6 +209,11 @@ static int omap_usb2_probe(struct platform_device *pdev)
phy_set_drvdata(generic_phy, phy); phy_set_drvdata(generic_phy, phy);
phy_provider = devm_of_phy_provider_register(phy->dev,
of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k"); phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
if (IS_ERR(phy->wkupclk)) { if (IS_ERR(phy->wkupclk)) {
dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n"); dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");

View File

@ -695,11 +695,6 @@ static int twl4030_usb_probe(struct platform_device *pdev)
otg->set_host = twl4030_set_host; otg->set_host = twl4030_set_host;
otg->set_peripheral = twl4030_set_peripheral; otg->set_peripheral = twl4030_set_peripheral;
phy_provider = devm_of_phy_provider_register(twl->dev,
of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
phy = devm_phy_create(twl->dev, &ops, init_data); phy = devm_phy_create(twl->dev, &ops, init_data);
if (IS_ERR(phy)) { if (IS_ERR(phy)) {
dev_dbg(&pdev->dev, "Failed to create PHY\n"); dev_dbg(&pdev->dev, "Failed to create PHY\n");
@ -708,6 +703,11 @@ static int twl4030_usb_probe(struct platform_device *pdev)
phy_set_drvdata(phy, twl); phy_set_drvdata(phy, twl);
phy_provider = devm_of_phy_provider_register(twl->dev,
of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
/* init spinlock for workqueue */ /* init spinlock for workqueue */
spin_lock_init(&twl->lock); spin_lock_init(&twl->lock);

View File

@ -105,7 +105,7 @@ static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir)
do { do {
/* flush any pending transfer */ /* flush any pending transfer */
hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n)); hw_write(ci, OP_ENDPTFLUSH, ~0, BIT(n));
while (hw_read(ci, OP_ENDPTFLUSH, BIT(n))) while (hw_read(ci, OP_ENDPTFLUSH, BIT(n)))
cpu_relax(); cpu_relax();
} while (hw_read(ci, OP_ENDPTSTAT, BIT(n))); } while (hw_read(ci, OP_ENDPTSTAT, BIT(n)));
@ -205,7 +205,7 @@ static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl)
if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num)))
return -EAGAIN; return -EAGAIN;
hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n)); hw_write(ci, OP_ENDPTPRIME, ~0, BIT(n));
while (hw_read(ci, OP_ENDPTPRIME, BIT(n))) while (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
cpu_relax(); cpu_relax();

View File

@ -360,24 +360,30 @@ static inline void usb_dma_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
bcm_writel(val, udc->iudma_regs + off); bcm_writel(val, udc->iudma_regs + off);
} }
static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off) static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off, int chan)
{ {
return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off); return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
(ENETDMA_CHAN_WIDTH * chan));
} }
static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off) static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
int chan)
{ {
bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off); bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
(ENETDMA_CHAN_WIDTH * chan));
} }
static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off) static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off, int chan)
{ {
return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off); return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
(ENETDMA_CHAN_WIDTH * chan));
} }
static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off) static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
int chan)
{ {
bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off); bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
(ENETDMA_CHAN_WIDTH * chan));
} }
static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled) static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled)
@ -638,7 +644,7 @@ static void iudma_write(struct bcm63xx_udc *udc, struct iudma_ch *iudma,
} while (!last_bd); } while (!last_bd);
usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK, usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK,
ENETDMAC_CHANCFG_REG(iudma->ch_idx)); ENETDMAC_CHANCFG_REG, iudma->ch_idx);
} }
/** /**
@ -694,9 +700,9 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num)); bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num));
/* stop DMA, then wait for the hardware to wrap up */ /* stop DMA, then wait for the hardware to wrap up */
usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG(ch_idx)); usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG, ch_idx);
while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)) & while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx) &
ENETDMAC_CHANCFG_EN_MASK) { ENETDMAC_CHANCFG_EN_MASK) {
udelay(1); udelay(1);
@ -713,10 +719,10 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n", dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n",
ch_idx); ch_idx);
usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK, usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK,
ENETDMAC_CHANCFG_REG(ch_idx)); ENETDMAC_CHANCFG_REG, ch_idx);
} }
} }
usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG(ch_idx)); usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG, ch_idx);
/* don't leave "live" HW-owned entries for the next guy to step on */ /* don't leave "live" HW-owned entries for the next guy to step on */
for (d = iudma->bd_ring; d <= iudma->end_bd; d++) for (d = iudma->bd_ring; d <= iudma->end_bd; d++)
@ -728,11 +734,11 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
/* set up IRQs, UBUS burst size, and BD base for this channel */ /* set up IRQs, UBUS burst size, and BD base for this channel */
usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK, usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
ENETDMAC_IRMASK_REG(ch_idx)); ENETDMAC_IRMASK_REG, ch_idx);
usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG(ch_idx)); usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG, ch_idx);
usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG(ch_idx)); usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG, ch_idx);
usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG(ch_idx)); usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG, ch_idx);
} }
/** /**
@ -2035,7 +2041,7 @@ static irqreturn_t bcm63xx_udc_data_isr(int irq, void *dev_id)
spin_lock(&udc->lock); spin_lock(&udc->lock);
usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK, usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
ENETDMAC_IR_REG(iudma->ch_idx)); ENETDMAC_IR_REG, iudma->ch_idx);
bep = iudma->bep; bep = iudma->bep;
rc = iudma_read(udc, iudma); rc = iudma_read(udc, iudma);
@ -2175,18 +2181,18 @@ static int bcm63xx_iudma_dbg_show(struct seq_file *s, void *p)
seq_printf(s, " [ep%d]:\n", seq_printf(s, " [ep%d]:\n",
max_t(int, iudma_defaults[ch_idx].ep_num, 0)); max_t(int, iudma_defaults[ch_idx].ep_num, 0));
seq_printf(s, " cfg: %08x; irqstat: %08x; irqmask: %08x; maxburst: %08x\n", seq_printf(s, " cfg: %08x; irqstat: %08x; irqmask: %08x; maxburst: %08x\n",
usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)), usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx),
usb_dmac_readl(udc, ENETDMAC_IR_REG(ch_idx)), usb_dmac_readl(udc, ENETDMAC_IR_REG, ch_idx),
usb_dmac_readl(udc, ENETDMAC_IRMASK_REG(ch_idx)), usb_dmac_readl(udc, ENETDMAC_IRMASK_REG, ch_idx),
usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG(ch_idx))); usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG, ch_idx));
sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG(ch_idx)); sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG, ch_idx);
sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG(ch_idx)); sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG, ch_idx);
seq_printf(s, " base: %08x; index: %04x_%04x; desc: %04x_%04x %08x\n", seq_printf(s, " base: %08x; index: %04x_%04x; desc: %04x_%04x %08x\n",
usb_dmas_readl(udc, ENETDMAS_RSTART_REG(ch_idx)), usb_dmas_readl(udc, ENETDMAS_RSTART_REG, ch_idx),
sram2 >> 16, sram2 & 0xffff, sram2 >> 16, sram2 & 0xffff,
sram3 >> 16, sram3 & 0xffff, sram3 >> 16, sram3 & 0xffff,
usb_dmas_readl(udc, ENETDMAS_SRAM4_REG(ch_idx))); usb_dmas_readl(udc, ENETDMAS_SRAM4_REG, ch_idx));
seq_printf(s, " desc: %d/%d used", iudma->n_bds_used, seq_printf(s, " desc: %d/%d used", iudma->n_bds_used,
iudma->n_bds); iudma->n_bds);

View File

@ -585,7 +585,6 @@ static ssize_t ffs_epfile_io(struct file *file,
char __user *buf, size_t len, int read) char __user *buf, size_t len, int read)
{ {
struct ffs_epfile *epfile = file->private_data; struct ffs_epfile *epfile = file->private_data;
struct usb_gadget *gadget = epfile->ffs->gadget;
struct ffs_ep *ep; struct ffs_ep *ep;
char *data = NULL; char *data = NULL;
ssize_t ret, data_len; ssize_t ret, data_len;
@ -621,6 +620,12 @@ static ssize_t ffs_epfile_io(struct file *file,
/* Allocate & copy */ /* Allocate & copy */
if (!halt) { if (!halt) {
/*
* if we _do_ wait above, the epfile->ffs->gadget might be NULL
* before the waiting completes, so do not assign to 'gadget' earlier
*/
struct usb_gadget *gadget = epfile->ffs->gadget;
/* /*
* Controller may require buffer size to be aligned to * Controller may require buffer size to be aligned to
* maxpacketsize of an out endpoint. * maxpacketsize of an out endpoint.

View File

@ -1157,7 +1157,7 @@ static int __init printer_bind_config(struct usb_configuration *c)
usb_gadget_set_selfpowered(gadget); usb_gadget_set_selfpowered(gadget);
if (gadget->is_otg) { if (gadget_is_otg(gadget)) {
otg_descriptor.bmAttributes |= USB_OTG_HNP; otg_descriptor.bmAttributes |= USB_OTG_HNP;
printer_cfg_driver.descriptors = otg_desc; printer_cfg_driver.descriptors = otg_desc;
printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;

View File

@ -1629,7 +1629,7 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
ep->ep.desc = NULL; ep->ep.desc = NULL;
ep->halted = 0; ep->halted = 0;
INIT_LIST_HEAD(&ep->queue); INIT_LIST_HEAD(&ep->queue);
usb_ep_set_maxpacket_limit(&ep->ep, &ep->ep.maxpacket); usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket);
} }
} }

View File

@ -238,6 +238,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
int port; int port;
int mask; int mask;
int changed; int changed;
bool fs_idle_delay;
ehci_dbg(ehci, "suspend root hub\n"); ehci_dbg(ehci, "suspend root hub\n");
@ -272,6 +273,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
ehci->bus_suspended = 0; ehci->bus_suspended = 0;
ehci->owned_ports = 0; ehci->owned_ports = 0;
changed = 0; changed = 0;
fs_idle_delay = false;
port = HCS_N_PORTS(ehci->hcs_params); port = HCS_N_PORTS(ehci->hcs_params);
while (port--) { while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port]; u32 __iomem *reg = &ehci->regs->port_status [port];
@ -300,16 +302,32 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
} }
if (t1 != t2) { if (t1 != t2) {
/*
* On some controllers, Wake-On-Disconnect will
* generate false wakeup signals until the bus
* switches over to full-speed idle. For their
* sake, add a delay if we need one.
*/
if ((t2 & PORT_WKDISC_E) &&
ehci_port_speed(ehci, t2) ==
USB_PORT_STAT_HIGH_SPEED)
fs_idle_delay = true;
ehci_writel(ehci, t2, reg); ehci_writel(ehci, t2, reg);
changed = 1; changed = 1;
} }
} }
spin_unlock_irq(&ehci->lock);
if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) {
/*
* Wait for HCD to enter low-power mode or for the bus
* to switch to full-speed idle.
*/
usleep_range(5000, 5500);
}
if (changed && ehci->has_tdi_phy_lpm) { if (changed && ehci->has_tdi_phy_lpm) {
spin_unlock_irq(&ehci->lock);
msleep(5); /* 5 ms for HCD to enter low-power mode */
spin_lock_irq(&ehci->lock); spin_lock_irq(&ehci->lock);
port = HCS_N_PORTS(ehci->hcs_params); port = HCS_N_PORTS(ehci->hcs_params);
while (port--) { while (port--) {
u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port];
@ -322,8 +340,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
port, (t3 & HOSTPC_PHCD) ? port, (t3 & HOSTPC_PHCD) ?
"succeeded" : "failed"); "succeeded" : "failed");
} }
}
spin_unlock_irq(&ehci->lock); spin_unlock_irq(&ehci->lock);
}
/* Apparently some devices need a >= 1-uframe delay here */ /* Apparently some devices need a >= 1-uframe delay here */
if (ehci->bus_suspended) if (ehci->bus_suspended)

View File

@ -477,8 +477,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
musb->port1_status |= musb->port1_status |=
(USB_PORT_STAT_C_SUSPEND << 16) (USB_PORT_STAT_C_SUSPEND << 16)
| MUSB_PORT_STAT_RESUME; | MUSB_PORT_STAT_RESUME;
musb->rh_timer = jiffies
+ msecs_to_jiffies(20);
schedule_delayed_work( schedule_delayed_work(
&musb->finish_resume_work, 20); &musb->finish_resume_work,
msecs_to_jiffies(20));
musb->xceiv->state = OTG_STATE_A_HOST; musb->xceiv->state = OTG_STATE_A_HOST;
musb->is_active = 1; musb->is_active = 1;
@ -2157,11 +2160,19 @@ static void musb_restore_context(struct musb *musb)
void __iomem *musb_base = musb->mregs; void __iomem *musb_base = musb->mregs;
void __iomem *ep_target_regs; void __iomem *ep_target_regs;
void __iomem *epio; void __iomem *epio;
u8 power;
musb_writew(musb_base, MUSB_FRAME, musb->context.frame); musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
musb_writeb(musb_base, MUSB_POWER, musb->context.power);
/* Don't affect SUSPENDM/RESUME bits in POWER reg */
power = musb_readb(musb_base, MUSB_POWER);
power &= MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME;
musb->context.power &= ~(MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME);
power |= musb->context.power;
musb_writeb(musb_base, MUSB_POWER, power);
musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe); musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe); musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe); musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);

View File

@ -1183,6 +1183,9 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
csr = MUSB_CSR0_H_STATUSPKT csr = MUSB_CSR0_H_STATUSPKT
| MUSB_CSR0_TXPKTRDY; | MUSB_CSR0_TXPKTRDY;
/* disable ping token in status phase */
csr |= MUSB_CSR0_H_DIS_PING;
/* flag status stage */ /* flag status stage */
musb->ep0_stage = MUSB_EP0_STATUS; musb->ep0_stage = MUSB_EP0_STATUS;

View File

@ -135,7 +135,8 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
/* later, GetPortStatus will stop RESUME signaling */ /* later, GetPortStatus will stop RESUME signaling */
musb->port1_status |= MUSB_PORT_STAT_RESUME; musb->port1_status |= MUSB_PORT_STAT_RESUME;
schedule_delayed_work(&musb->finish_resume_work, 20); schedule_delayed_work(&musb->finish_resume_work,
msecs_to_jiffies(20));
} }
} }
@ -158,7 +159,6 @@ void musb_port_reset(struct musb *musb, bool do_reset)
*/ */
power = musb_readb(mbase, MUSB_POWER); power = musb_readb(mbase, MUSB_POWER);
if (do_reset) { if (do_reset) {
/* /*
* If RESUME is set, we must make sure it stays minimum 20 ms. * If RESUME is set, we must make sure it stays minimum 20 ms.
* Then we must clear RESUME and wait a bit to let musb start * Then we must clear RESUME and wait a bit to let musb start
@ -167,11 +167,22 @@ void musb_port_reset(struct musb *musb, bool do_reset)
* detected". * detected".
*/ */
if (power & MUSB_POWER_RESUME) { if (power & MUSB_POWER_RESUME) {
while (time_before(jiffies, musb->rh_timer)) long remain = (unsigned long) musb->rh_timer - jiffies;
msleep(1);
if (musb->rh_timer > 0 && remain > 0) {
/* take into account the minimum delay after resume */
schedule_delayed_work(
&musb->deassert_reset_work, remain);
return;
}
musb_writeb(mbase, MUSB_POWER, musb_writeb(mbase, MUSB_POWER,
power & ~MUSB_POWER_RESUME); power & ~MUSB_POWER_RESUME);
msleep(1);
/* Give the core 1 ms to clear MUSB_POWER_RESUME */
schedule_delayed_work(&musb->deassert_reset_work,
msecs_to_jiffies(1));
return;
} }
power &= 0xf0; power &= 0xf0;
@ -180,7 +191,8 @@ void musb_port_reset(struct musb *musb, bool do_reset)
musb->port1_status |= USB_PORT_STAT_RESET; musb->port1_status |= USB_PORT_STAT_RESET;
musb->port1_status &= ~USB_PORT_STAT_ENABLE; musb->port1_status &= ~USB_PORT_STAT_ENABLE;
schedule_delayed_work(&musb->deassert_reset_work, 50); schedule_delayed_work(&musb->deassert_reset_work,
msecs_to_jiffies(50));
} else { } else {
dev_dbg(musb->controller, "root port reset stopped\n"); dev_dbg(musb->controller, "root port reset stopped\n");
musb_writeb(mbase, MUSB_POWER, musb_writeb(mbase, MUSB_POWER,

View File

@ -659,7 +659,6 @@ static int omap2430_runtime_suspend(struct device *dev)
OTG_INTERFSEL); OTG_INTERFSEL);
omap2430_low_level_exit(musb); omap2430_low_level_exit(musb);
phy_power_off(musb->phy);
} }
return 0; return 0;
@ -674,7 +673,6 @@ static int omap2430_runtime_resume(struct device *dev)
omap2430_low_level_init(musb); omap2430_low_level_init(musb);
musb_writel(musb->mregs, OTG_INTERFSEL, musb_writel(musb->mregs, OTG_INTERFSEL,
musb->context.otg_interfsel); musb->context.otg_interfsel);
phy_power_on(musb->phy);
} }
return 0; return 0;

View File

@ -159,32 +159,6 @@ put_3p3:
return rc; return rc;
} }
#ifdef CONFIG_PM_SLEEP
#define USB_PHY_SUSP_DIG_VOL 500000
static int msm_hsusb_config_vddcx(int high)
{
int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
int min_vol;
int ret;
if (high)
min_vol = USB_PHY_VDD_DIG_VOL_MIN;
else
min_vol = USB_PHY_SUSP_DIG_VOL;
ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
if (ret) {
pr_err("%s: unable to set the voltage for regulator "
"HSUSB_VDDCX\n", __func__);
return ret;
}
pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
return ret;
}
#endif
static int msm_hsusb_ldo_set_mode(int on) static int msm_hsusb_ldo_set_mode(int on)
{ {
int ret = 0; int ret = 0;
@ -440,7 +414,32 @@ static int msm_otg_reset(struct usb_phy *phy)
#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000) #define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
#define PHY_RESUME_TIMEOUT_USEC (100 * 1000) #define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
#define USB_PHY_SUSP_DIG_VOL 500000
static int msm_hsusb_config_vddcx(int high)
{
int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
int min_vol;
int ret;
if (high)
min_vol = USB_PHY_VDD_DIG_VOL_MIN;
else
min_vol = USB_PHY_SUSP_DIG_VOL;
ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
if (ret) {
pr_err("%s: unable to set the voltage for regulator "
"HSUSB_VDDCX\n", __func__);
return ret;
}
pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
return ret;
}
static int msm_otg_suspend(struct msm_otg *motg) static int msm_otg_suspend(struct msm_otg *motg)
{ {
struct usb_phy *phy = &motg->phy; struct usb_phy *phy = &motg->phy;
@ -1733,22 +1732,18 @@ static int msm_otg_pm_resume(struct device *dev)
} }
#endif #endif
#ifdef CONFIG_PM
static const struct dev_pm_ops msm_otg_dev_pm_ops = { static const struct dev_pm_ops msm_otg_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume) SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume, SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
msm_otg_runtime_idle) msm_otg_runtime_idle)
}; };
#endif
static struct platform_driver msm_otg_driver = { static struct platform_driver msm_otg_driver = {
.remove = msm_otg_remove, .remove = msm_otg_remove,
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &msm_otg_dev_pm_ops, .pm = &msm_otg_dev_pm_ops,
#endif
}, },
}; };

View File

@ -1526,7 +1526,8 @@ static const struct usb_device_id option_ids[] = {
/* Cinterion */ /* Cinterion */
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX), { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist }, .driver_info = (kernel_ulong_t)&net_intf4_blacklist },