USB fixes for 4.2-rc4
Here's a few USB and PHY fixes for 4.2-rc4. Nothing major, the shortlog has the full details. All of these have been in linux-next successfully. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iEYEABECAAYFAlW0QPkACgkQMUfUDdst+ym+bQCgj/ka2wRF+7+zr3EyZpn0TJc2 a7wAn3lwAjE0AZOZhg7qS3HcoMi9Q1GV =hLdX -----END PGP SIGNATURE----- Merge tag 'usb-4.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "Here's a few USB and PHY fixes for 4.2-rc4. Nothing major, the shortlog has the full details. All of these have been in linux-next successfully" * tag 'usb-4.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (21 commits) USB: OHCI: fix bad #define in ohci-tmio.c cdc-acm: Destroy acm_minors IDR on module exit usb-storage: Add ignore-device quirk for gm12u320 based usb mini projectors usb-storage: ignore ZTE MF 823 card reader in mode 0x1225 USB: OHCI: Fix race between ED unlink and URB submission usb: core: lpm: set lpm_capable for root hub device xhci: do not report PLC when link is in internal resume state xhci: prevent bus_suspend if SS port resuming in phase 1 xhci: report U3 when link is in resume state xhci: Calculate old endpoints correctly on device reset usb: xhci: Bugfix for NULL pointer deference in xhci_endpoint_init() function xhci: Workaround to get D3 working in Intel xHCI xhci: call BIOS workaround to enable runtime suspend on Intel Braswell usb: dwc3: Reset the transfer resource index on SET_INTERFACE usb: gadget: udc: core: Fix argument of dma_map_single for IOMMU usb: gadget: mv_udc_core: fix phy_regs I/O memory leak usb: ulpi: ulpi_init should be executed in subsys_initcall phy: berlin-usb: fix divider for BG2 phy: berlin-usb: fix divider for BG2CD phy/pxa: add HAS_IOMEM dependency ...
This commit is contained in:
commit
26ae19a388
|
@ -56,6 +56,7 @@ config PHY_EXYNOS_MIPI_VIDEO
|
||||||
|
|
||||||
config PHY_PXA_28NM_HSIC
|
config PHY_PXA_28NM_HSIC
|
||||||
tristate "Marvell USB HSIC 28nm PHY Driver"
|
tristate "Marvell USB HSIC 28nm PHY Driver"
|
||||||
|
depends on HAS_IOMEM
|
||||||
select GENERIC_PHY
|
select GENERIC_PHY
|
||||||
help
|
help
|
||||||
Enable this to support Marvell USB HSIC PHY driver for Marvell
|
Enable this to support Marvell USB HSIC PHY driver for Marvell
|
||||||
|
@ -66,6 +67,7 @@ config PHY_PXA_28NM_HSIC
|
||||||
|
|
||||||
config PHY_PXA_28NM_USB2
|
config PHY_PXA_28NM_USB2
|
||||||
tristate "Marvell USB 2.0 28nm PHY Driver"
|
tristate "Marvell USB 2.0 28nm PHY Driver"
|
||||||
|
depends on HAS_IOMEM
|
||||||
select GENERIC_PHY
|
select GENERIC_PHY
|
||||||
help
|
help
|
||||||
Enable this to support Marvell USB 2.0 PHY driver for Marvell
|
Enable this to support Marvell USB 2.0 PHY driver for Marvell
|
||||||
|
|
|
@ -105,9 +105,9 @@
|
||||||
|
|
||||||
static const u32 phy_berlin_pll_dividers[] = {
|
static const u32 phy_berlin_pll_dividers[] = {
|
||||||
/* Berlin 2 */
|
/* Berlin 2 */
|
||||||
CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
|
|
||||||
/* Berlin 2CD */
|
|
||||||
CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55),
|
CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55),
|
||||||
|
/* Berlin 2CD/Q */
|
||||||
|
CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct phy_berlin_usb_priv {
|
struct phy_berlin_usb_priv {
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/phy/omap_control_phy.h>
|
#include <linux/phy/omap_control_phy.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/spinlock.h>
|
|
||||||
|
|
||||||
#define PLL_STATUS 0x00000004
|
#define PLL_STATUS 0x00000004
|
||||||
#define PLL_GO 0x00000008
|
#define PLL_GO 0x00000008
|
||||||
|
@ -83,10 +82,6 @@ struct ti_pipe3 {
|
||||||
struct clk *refclk;
|
struct clk *refclk;
|
||||||
struct clk *div_clk;
|
struct clk *div_clk;
|
||||||
struct pipe3_dpll_map *dpll_map;
|
struct pipe3_dpll_map *dpll_map;
|
||||||
bool enabled;
|
|
||||||
spinlock_t lock; /* serialize clock enable/disable */
|
|
||||||
/* the below flag is needed specifically for SATA */
|
|
||||||
bool refclk_enabled;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pipe3_dpll_map dpll_map_usb[] = {
|
static struct pipe3_dpll_map dpll_map_usb[] = {
|
||||||
|
@ -137,6 +132,9 @@ static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy);
|
||||||
|
static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy);
|
||||||
|
|
||||||
static int ti_pipe3_power_off(struct phy *x)
|
static int ti_pipe3_power_off(struct phy *x)
|
||||||
{
|
{
|
||||||
struct ti_pipe3 *phy = phy_get_drvdata(x);
|
struct ti_pipe3 *phy = phy_get_drvdata(x);
|
||||||
|
@ -217,6 +215,7 @@ static int ti_pipe3_init(struct phy *x)
|
||||||
u32 val;
|
u32 val;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
ti_pipe3_enable_clocks(phy);
|
||||||
/*
|
/*
|
||||||
* Set pcie_pcs register to 0x96 for proper functioning of phy
|
* Set pcie_pcs register to 0x96 for proper functioning of phy
|
||||||
* as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table
|
* as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table
|
||||||
|
@ -250,33 +249,35 @@ static int ti_pipe3_exit(struct phy *x)
|
||||||
u32 val;
|
u32 val;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
/* SATA DPLL can't be powered down due to Errata i783 and PCIe
|
/* SATA DPLL can't be powered down due to Errata i783 */
|
||||||
* does not have internal DPLL
|
if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata"))
|
||||||
*/
|
|
||||||
if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") ||
|
|
||||||
of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Put DPLL in IDLE mode */
|
/* PCIe doesn't have internal DPLL */
|
||||||
val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
|
if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
|
||||||
val |= PLL_IDLE;
|
/* Put DPLL in IDLE mode */
|
||||||
ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
|
val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
|
||||||
|
val |= PLL_IDLE;
|
||||||
|
ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
|
||||||
|
|
||||||
/* wait for LDO and Oscillator to power down */
|
/* wait for LDO and Oscillator to power down */
|
||||||
timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME);
|
timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME);
|
||||||
do {
|
do {
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
|
val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
|
||||||
if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
|
if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
|
||||||
break;
|
break;
|
||||||
} while (!time_after(jiffies, timeout));
|
} while (!time_after(jiffies, timeout));
|
||||||
|
|
||||||
if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
|
if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
|
||||||
dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n",
|
dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n",
|
||||||
val);
|
val);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ti_pipe3_disable_clocks(phy);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static struct phy_ops ops = {
|
static struct phy_ops ops = {
|
||||||
|
@ -306,7 +307,6 @@ static int ti_pipe3_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
phy->dev = &pdev->dev;
|
phy->dev = &pdev->dev;
|
||||||
spin_lock_init(&phy->lock);
|
|
||||||
|
|
||||||
if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
|
if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
|
||||||
match = of_match_device(ti_pipe3_id_table, &pdev->dev);
|
match = of_match_device(ti_pipe3_id_table, &pdev->dev);
|
||||||
|
@ -402,6 +402,10 @@ static int ti_pipe3_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
platform_set_drvdata(pdev, phy);
|
platform_set_drvdata(pdev, phy);
|
||||||
pm_runtime_enable(phy->dev);
|
pm_runtime_enable(phy->dev);
|
||||||
|
/* Prevent auto-disable of refclk for SATA PHY due to Errata i783 */
|
||||||
|
if (of_device_is_compatible(node, "ti,phy-pipe3-sata"))
|
||||||
|
if (!IS_ERR(phy->refclk))
|
||||||
|
clk_prepare_enable(phy->refclk);
|
||||||
|
|
||||||
generic_phy = devm_phy_create(phy->dev, NULL, &ops);
|
generic_phy = devm_phy_create(phy->dev, NULL, &ops);
|
||||||
if (IS_ERR(generic_phy))
|
if (IS_ERR(generic_phy))
|
||||||
|
@ -413,63 +417,33 @@ static int ti_pipe3_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(phy_provider))
|
if (IS_ERR(phy_provider))
|
||||||
return PTR_ERR(phy_provider);
|
return PTR_ERR(phy_provider);
|
||||||
|
|
||||||
pm_runtime_get(&pdev->dev);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ti_pipe3_remove(struct platform_device *pdev)
|
static int ti_pipe3_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
if (!pm_runtime_suspended(&pdev->dev))
|
|
||||||
pm_runtime_put(&pdev->dev);
|
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
|
||||||
static int ti_pipe3_enable_refclk(struct ti_pipe3 *phy)
|
|
||||||
{
|
{
|
||||||
if (!IS_ERR(phy->refclk) && !phy->refclk_enabled) {
|
int ret = 0;
|
||||||
int ret;
|
|
||||||
|
|
||||||
|
if (!IS_ERR(phy->refclk)) {
|
||||||
ret = clk_prepare_enable(phy->refclk);
|
ret = clk_prepare_enable(phy->refclk);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
|
dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
phy->refclk_enabled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ti_pipe3_disable_refclk(struct ti_pipe3 *phy)
|
|
||||||
{
|
|
||||||
if (!IS_ERR(phy->refclk))
|
|
||||||
clk_disable_unprepare(phy->refclk);
|
|
||||||
|
|
||||||
phy->refclk_enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&phy->lock, flags);
|
|
||||||
if (phy->enabled)
|
|
||||||
goto err1;
|
|
||||||
|
|
||||||
ret = ti_pipe3_enable_refclk(phy);
|
|
||||||
if (ret)
|
|
||||||
goto err1;
|
|
||||||
|
|
||||||
if (!IS_ERR(phy->wkupclk)) {
|
if (!IS_ERR(phy->wkupclk)) {
|
||||||
ret = clk_prepare_enable(phy->wkupclk);
|
ret = clk_prepare_enable(phy->wkupclk);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
|
dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
|
||||||
goto err2;
|
goto disable_refclk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,96 +451,33 @@ static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
|
||||||
ret = clk_prepare_enable(phy->div_clk);
|
ret = clk_prepare_enable(phy->div_clk);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
|
dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
|
||||||
goto err3;
|
goto disable_wkupclk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
phy->enabled = true;
|
|
||||||
spin_unlock_irqrestore(&phy->lock, flags);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err3:
|
disable_wkupclk:
|
||||||
if (!IS_ERR(phy->wkupclk))
|
if (!IS_ERR(phy->wkupclk))
|
||||||
clk_disable_unprepare(phy->wkupclk);
|
clk_disable_unprepare(phy->wkupclk);
|
||||||
|
|
||||||
err2:
|
disable_refclk:
|
||||||
if (!IS_ERR(phy->refclk))
|
if (!IS_ERR(phy->refclk))
|
||||||
clk_disable_unprepare(phy->refclk);
|
clk_disable_unprepare(phy->refclk);
|
||||||
|
|
||||||
ti_pipe3_disable_refclk(phy);
|
|
||||||
err1:
|
|
||||||
spin_unlock_irqrestore(&phy->lock, flags);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy)
|
static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&phy->lock, flags);
|
|
||||||
if (!phy->enabled) {
|
|
||||||
spin_unlock_irqrestore(&phy->lock, flags);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IS_ERR(phy->wkupclk))
|
if (!IS_ERR(phy->wkupclk))
|
||||||
clk_disable_unprepare(phy->wkupclk);
|
clk_disable_unprepare(phy->wkupclk);
|
||||||
/* Don't disable refclk for SATA PHY due to Errata i783 */
|
if (!IS_ERR(phy->refclk))
|
||||||
if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata"))
|
clk_disable_unprepare(phy->refclk);
|
||||||
ti_pipe3_disable_refclk(phy);
|
|
||||||
if (!IS_ERR(phy->div_clk))
|
if (!IS_ERR(phy->div_clk))
|
||||||
clk_disable_unprepare(phy->div_clk);
|
clk_disable_unprepare(phy->div_clk);
|
||||||
phy->enabled = false;
|
|
||||||
spin_unlock_irqrestore(&phy->lock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ti_pipe3_runtime_suspend(struct device *dev)
|
|
||||||
{
|
|
||||||
struct ti_pipe3 *phy = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
ti_pipe3_disable_clocks(phy);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ti_pipe3_runtime_resume(struct device *dev)
|
|
||||||
{
|
|
||||||
struct ti_pipe3 *phy = dev_get_drvdata(dev);
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
ret = ti_pipe3_enable_clocks(phy);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ti_pipe3_suspend(struct device *dev)
|
|
||||||
{
|
|
||||||
struct ti_pipe3 *phy = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
ti_pipe3_disable_clocks(phy);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ti_pipe3_resume(struct device *dev)
|
|
||||||
{
|
|
||||||
struct ti_pipe3 *phy = dev_get_drvdata(dev);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = ti_pipe3_enable_clocks(phy);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
pm_runtime_disable(dev);
|
|
||||||
pm_runtime_set_active(dev);
|
|
||||||
pm_runtime_enable(dev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const struct dev_pm_ops ti_pipe3_pm_ops = {
|
|
||||||
SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend,
|
|
||||||
ti_pipe3_runtime_resume, NULL)
|
|
||||||
SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume)
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct of_device_id ti_pipe3_id_table[] = {
|
static const struct of_device_id ti_pipe3_id_table[] = {
|
||||||
{
|
{
|
||||||
.compatible = "ti,phy-usb3",
|
.compatible = "ti,phy-usb3",
|
||||||
|
@ -592,7 +503,6 @@ static struct platform_driver ti_pipe3_driver = {
|
||||||
.remove = ti_pipe3_remove,
|
.remove = ti_pipe3_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "ti-pipe3",
|
.name = "ti-pipe3",
|
||||||
.pm = &ti_pipe3_pm_ops,
|
|
||||||
.of_match_table = ti_pipe3_id_table,
|
.of_match_table = ti_pipe3_id_table,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1944,6 +1944,7 @@ static void __exit acm_exit(void)
|
||||||
usb_deregister(&acm_driver);
|
usb_deregister(&acm_driver);
|
||||||
tty_unregister_driver(acm_tty_driver);
|
tty_unregister_driver(acm_tty_driver);
|
||||||
put_tty_driver(acm_tty_driver);
|
put_tty_driver(acm_tty_driver);
|
||||||
|
idr_destroy(&acm_minors);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(acm_init);
|
module_init(acm_init);
|
||||||
|
|
|
@ -242,7 +242,7 @@ static int __init ulpi_init(void)
|
||||||
{
|
{
|
||||||
return bus_register(&ulpi_bus);
|
return bus_register(&ulpi_bus);
|
||||||
}
|
}
|
||||||
module_init(ulpi_init);
|
subsys_initcall(ulpi_init);
|
||||||
|
|
||||||
static void __exit ulpi_exit(void)
|
static void __exit ulpi_exit(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1022,9 +1022,12 @@ static int register_root_hub(struct usb_hcd *hcd)
|
||||||
dev_name(&usb_dev->dev), retval);
|
dev_name(&usb_dev->dev), retval);
|
||||||
return (retval < 0) ? retval : -EMSGSIZE;
|
return (retval < 0) ? retval : -EMSGSIZE;
|
||||||
}
|
}
|
||||||
if (usb_dev->speed == USB_SPEED_SUPER) {
|
|
||||||
|
if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) {
|
||||||
retval = usb_get_bos_descriptor(usb_dev);
|
retval = usb_get_bos_descriptor(usb_dev);
|
||||||
if (retval < 0) {
|
if (!retval) {
|
||||||
|
usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev);
|
||||||
|
} else if (usb_dev->speed == USB_SPEED_SUPER) {
|
||||||
mutex_unlock(&usb_bus_list_lock);
|
mutex_unlock(&usb_bus_list_lock);
|
||||||
dev_dbg(parent_dev, "can't read %s bos descriptor %d\n",
|
dev_dbg(parent_dev, "can't read %s bos descriptor %d\n",
|
||||||
dev_name(&usb_dev->dev), retval);
|
dev_name(&usb_dev->dev), retval);
|
||||||
|
|
|
@ -122,7 +122,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev)
|
||||||
return usb_get_intfdata(hdev->actconfig->interface[0]);
|
return usb_get_intfdata(hdev->actconfig->interface[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_device_supports_lpm(struct usb_device *udev)
|
int usb_device_supports_lpm(struct usb_device *udev)
|
||||||
{
|
{
|
||||||
/* USB 2.1 (and greater) devices indicate LPM support through
|
/* USB 2.1 (and greater) devices indicate LPM support through
|
||||||
* their USB 2.0 Extended Capabilities BOS descriptor.
|
* their USB 2.0 Extended Capabilities BOS descriptor.
|
||||||
|
|
|
@ -65,6 +65,7 @@ extern int usb_hub_init(void);
|
||||||
extern void usb_hub_cleanup(void);
|
extern void usb_hub_cleanup(void);
|
||||||
extern int usb_major_init(void);
|
extern int usb_major_init(void);
|
||||||
extern void usb_major_cleanup(void);
|
extern void usb_major_cleanup(void);
|
||||||
|
extern int usb_device_supports_lpm(struct usb_device *udev);
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
|
||||||
|
|
|
@ -727,6 +727,10 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
|
||||||
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY");
|
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY");
|
||||||
ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
|
ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
|
||||||
break;
|
break;
|
||||||
|
case USB_REQ_SET_INTERFACE:
|
||||||
|
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE");
|
||||||
|
dwc->start_config_issued = false;
|
||||||
|
/* Fall through */
|
||||||
default:
|
default:
|
||||||
dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver");
|
dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver");
|
||||||
ret = dwc3_ep0_delegate_req(dwc, ctrl);
|
ret = dwc3_ep0_delegate_req(dwc, ctrl);
|
||||||
|
|
|
@ -2167,7 +2167,7 @@ static int mv_udc_probe(struct platform_device *pdev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
udc->phy_regs = ioremap(r->start, resource_size(r));
|
udc->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
|
||||||
if (udc->phy_regs == NULL) {
|
if (udc->phy_regs == NULL) {
|
||||||
dev_err(&pdev->dev, "failed to map phy I/O memory\n");
|
dev_err(&pdev->dev, "failed to map phy I/O memory\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
|
@ -60,13 +60,15 @@ static DEFINE_MUTEX(udc_lock);
|
||||||
int usb_gadget_map_request(struct usb_gadget *gadget,
|
int usb_gadget_map_request(struct usb_gadget *gadget,
|
||||||
struct usb_request *req, int is_in)
|
struct usb_request *req, int is_in)
|
||||||
{
|
{
|
||||||
|
struct device *dev = gadget->dev.parent;
|
||||||
|
|
||||||
if (req->length == 0)
|
if (req->length == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (req->num_sgs) {
|
if (req->num_sgs) {
|
||||||
int mapped;
|
int mapped;
|
||||||
|
|
||||||
mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs,
|
mapped = dma_map_sg(dev, req->sg, req->num_sgs,
|
||||||
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||||
if (mapped == 0) {
|
if (mapped == 0) {
|
||||||
dev_err(&gadget->dev, "failed to map SGs\n");
|
dev_err(&gadget->dev, "failed to map SGs\n");
|
||||||
|
@ -75,11 +77,11 @@ int usb_gadget_map_request(struct usb_gadget *gadget,
|
||||||
|
|
||||||
req->num_mapped_sgs = mapped;
|
req->num_mapped_sgs = mapped;
|
||||||
} else {
|
} else {
|
||||||
req->dma = dma_map_single(&gadget->dev, req->buf, req->length,
|
req->dma = dma_map_single(dev, req->buf, req->length,
|
||||||
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||||
|
|
||||||
if (dma_mapping_error(&gadget->dev, req->dma)) {
|
if (dma_mapping_error(dev, req->dma)) {
|
||||||
dev_err(&gadget->dev, "failed to map buffer\n");
|
dev_err(dev, "failed to map buffer\n");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,12 +97,12 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (req->num_mapped_sgs) {
|
if (req->num_mapped_sgs) {
|
||||||
dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs,
|
dma_unmap_sg(gadget->dev.parent, req->sg, req->num_mapped_sgs,
|
||||||
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||||
|
|
||||||
req->num_mapped_sgs = 0;
|
req->num_mapped_sgs = 0;
|
||||||
} else {
|
} else {
|
||||||
dma_unmap_single(&gadget->dev, req->dma, req->length,
|
dma_unmap_single(gadget->dev.parent, req->dma, req->length,
|
||||||
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -981,10 +981,6 @@ static void finish_unlinks(struct ohci_hcd *ohci)
|
||||||
int completed, modified;
|
int completed, modified;
|
||||||
__hc32 *prev;
|
__hc32 *prev;
|
||||||
|
|
||||||
/* Is this ED already invisible to the hardware? */
|
|
||||||
if (ed->state == ED_IDLE)
|
|
||||||
goto ed_idle;
|
|
||||||
|
|
||||||
/* only take off EDs that the HC isn't using, accounting for
|
/* only take off EDs that the HC isn't using, accounting for
|
||||||
* frame counter wraps and EDs with partially retired TDs
|
* frame counter wraps and EDs with partially retired TDs
|
||||||
*/
|
*/
|
||||||
|
@ -1012,12 +1008,10 @@ static void finish_unlinks(struct ohci_hcd *ohci)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ED's now officially unlinked, hc doesn't see */
|
/* ED's now officially unlinked, hc doesn't see */
|
||||||
ed->state = ED_IDLE;
|
|
||||||
ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
|
ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
|
||||||
ed->hwNextED = 0;
|
ed->hwNextED = 0;
|
||||||
wmb();
|
wmb();
|
||||||
ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE);
|
ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE);
|
||||||
ed_idle:
|
|
||||||
|
|
||||||
/* reentrancy: if we drop the schedule lock, someone might
|
/* reentrancy: if we drop the schedule lock, someone might
|
||||||
* have modified this list. normally it's just prepending
|
* have modified this list. normally it's just prepending
|
||||||
|
@ -1088,6 +1082,7 @@ static void finish_unlinks(struct ohci_hcd *ohci)
|
||||||
if (list_empty(&ed->td_list)) {
|
if (list_empty(&ed->td_list)) {
|
||||||
*last = ed->ed_next;
|
*last = ed->ed_next;
|
||||||
ed->ed_next = NULL;
|
ed->ed_next = NULL;
|
||||||
|
ed->state = ED_IDLE;
|
||||||
list_del(&ed->in_use_list);
|
list_del(&ed->in_use_list);
|
||||||
} else if (ohci->rh_state == OHCI_RH_RUNNING) {
|
} else if (ohci->rh_state == OHCI_RH_RUNNING) {
|
||||||
*last = ed->ed_next;
|
*last = ed->ed_next;
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
#define CCR_PM_CKRNEN 0x0002
|
#define CCR_PM_CKRNEN 0x0002
|
||||||
#define CCR_PM_USBPW1 0x0004
|
#define CCR_PM_USBPW1 0x0004
|
||||||
#define CCR_PM_USBPW2 0x0008
|
#define CCR_PM_USBPW2 0x0008
|
||||||
#define CCR_PM_USBPW3 0x0008
|
#define CCR_PM_USBPW3 0x0010
|
||||||
#define CCR_PM_PMEE 0x0100
|
#define CCR_PM_PMEE 0x0100
|
||||||
#define CCR_PM_PMES 0x8000
|
#define CCR_PM_PMES 0x8000
|
||||||
|
|
||||||
|
|
|
@ -484,10 +484,13 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci,
|
||||||
u32 pls = status_reg & PORT_PLS_MASK;
|
u32 pls = status_reg & PORT_PLS_MASK;
|
||||||
|
|
||||||
/* resume state is a xHCI internal state.
|
/* resume state is a xHCI internal state.
|
||||||
* Do not report it to usb core.
|
* Do not report it to usb core, instead, pretend to be U3,
|
||||||
|
* thus usb core knows it's not ready for transfer
|
||||||
*/
|
*/
|
||||||
if (pls == XDEV_RESUME)
|
if (pls == XDEV_RESUME) {
|
||||||
|
*status |= USB_SS_PORT_LS_U3;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* When the CAS bit is set then warm reset
|
/* When the CAS bit is set then warm reset
|
||||||
* should be performed on port
|
* should be performed on port
|
||||||
|
@ -588,7 +591,14 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
|
||||||
status |= USB_PORT_STAT_C_RESET << 16;
|
status |= USB_PORT_STAT_C_RESET << 16;
|
||||||
/* USB3.0 only */
|
/* USB3.0 only */
|
||||||
if (hcd->speed == HCD_USB3) {
|
if (hcd->speed == HCD_USB3) {
|
||||||
if ((raw_port_status & PORT_PLC))
|
/* Port link change with port in resume state should not be
|
||||||
|
* reported to usbcore, as this is an internal state to be
|
||||||
|
* handled by xhci driver. Reporting PLC to usbcore may
|
||||||
|
* cause usbcore clearing PLC first and port change event
|
||||||
|
* irq won't be generated.
|
||||||
|
*/
|
||||||
|
if ((raw_port_status & PORT_PLC) &&
|
||||||
|
(raw_port_status & PORT_PLS_MASK) != XDEV_RESUME)
|
||||||
status |= USB_PORT_STAT_C_LINK_STATE << 16;
|
status |= USB_PORT_STAT_C_LINK_STATE << 16;
|
||||||
if ((raw_port_status & PORT_WRC))
|
if ((raw_port_status & PORT_WRC))
|
||||||
status |= USB_PORT_STAT_C_BH_RESET << 16;
|
status |= USB_PORT_STAT_C_BH_RESET << 16;
|
||||||
|
@ -1120,10 +1130,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
|
||||||
spin_lock_irqsave(&xhci->lock, flags);
|
spin_lock_irqsave(&xhci->lock, flags);
|
||||||
|
|
||||||
if (hcd->self.root_hub->do_remote_wakeup) {
|
if (hcd->self.root_hub->do_remote_wakeup) {
|
||||||
if (bus_state->resuming_ports) {
|
if (bus_state->resuming_ports || /* USB2 */
|
||||||
|
bus_state->port_remote_wakeup) { /* USB3 */
|
||||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||||
xhci_dbg(xhci, "suspend failed because "
|
xhci_dbg(xhci, "suspend failed because a port is resuming\n");
|
||||||
"a port is resuming\n");
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1427,10 +1427,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
||||||
/* Attempt to use the ring cache */
|
/* Attempt to use the ring cache */
|
||||||
if (virt_dev->num_rings_cached == 0)
|
if (virt_dev->num_rings_cached == 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
virt_dev->num_rings_cached--;
|
||||||
virt_dev->eps[ep_index].new_ring =
|
virt_dev->eps[ep_index].new_ring =
|
||||||
virt_dev->ring_cache[virt_dev->num_rings_cached];
|
virt_dev->ring_cache[virt_dev->num_rings_cached];
|
||||||
virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL;
|
virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL;
|
||||||
virt_dev->num_rings_cached--;
|
|
||||||
xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring,
|
xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring,
|
||||||
1, type);
|
1, type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,15 @@
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
|
|
||||||
#include "xhci.h"
|
#include "xhci.h"
|
||||||
#include "xhci-trace.h"
|
#include "xhci-trace.h"
|
||||||
|
|
||||||
|
#define PORT2_SSIC_CONFIG_REG2 0x883c
|
||||||
|
#define PROG_DONE (1 << 30)
|
||||||
|
#define SSIC_PORT_UNUSED (1 << 31)
|
||||||
|
|
||||||
/* Device for a quirk */
|
/* Device for a quirk */
|
||||||
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
|
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
|
||||||
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
|
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
|
||||||
|
@ -176,20 +181,63 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* In some Intel xHCI controllers, in order to get D3 working,
|
||||||
|
* through a vendor specific SSIC CONFIG register at offset 0x883c,
|
||||||
|
* SSIC PORT need to be marked as "unused" before putting xHCI
|
||||||
|
* into D3. After D3 exit, the SSIC port need to be marked as "used".
|
||||||
|
* Without this change, xHCI might not enter D3 state.
|
||||||
* Make sure PME works on some Intel xHCI controllers by writing 1 to clear
|
* Make sure PME works on some Intel xHCI controllers by writing 1 to clear
|
||||||
* the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
|
* the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
|
||||||
*/
|
*/
|
||||||
static void xhci_pme_quirk(struct xhci_hcd *xhci)
|
static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
|
||||||
{
|
{
|
||||||
|
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||||
|
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
||||||
u32 val;
|
u32 val;
|
||||||
void __iomem *reg;
|
void __iomem *reg;
|
||||||
|
|
||||||
|
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
|
||||||
|
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
|
||||||
|
|
||||||
|
reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
|
||||||
|
|
||||||
|
/* Notify SSIC that SSIC profile programming is not done */
|
||||||
|
val = readl(reg) & ~PROG_DONE;
|
||||||
|
writel(val, reg);
|
||||||
|
|
||||||
|
/* Mark SSIC port as unused(suspend) or used(resume) */
|
||||||
|
val = readl(reg);
|
||||||
|
if (suspend)
|
||||||
|
val |= SSIC_PORT_UNUSED;
|
||||||
|
else
|
||||||
|
val &= ~SSIC_PORT_UNUSED;
|
||||||
|
writel(val, reg);
|
||||||
|
|
||||||
|
/* Notify SSIC that SSIC profile programming is done */
|
||||||
|
val = readl(reg) | PROG_DONE;
|
||||||
|
writel(val, reg);
|
||||||
|
readl(reg);
|
||||||
|
}
|
||||||
|
|
||||||
reg = (void __iomem *) xhci->cap_regs + 0x80a4;
|
reg = (void __iomem *) xhci->cap_regs + 0x80a4;
|
||||||
val = readl(reg);
|
val = readl(reg);
|
||||||
writel(val | BIT(28), reg);
|
writel(val | BIT(28), reg);
|
||||||
readl(reg);
|
readl(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI
|
||||||
|
static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
static const u8 intel_dsm_uuid[] = {
|
||||||
|
0xb7, 0x0c, 0x34, 0xac, 0x01, 0xe9, 0xbf, 0x45,
|
||||||
|
0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23,
|
||||||
|
};
|
||||||
|
acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1, NULL);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
|
||||||
|
#endif /* CONFIG_ACPI */
|
||||||
|
|
||||||
/* called during probe() after chip reset completes */
|
/* called during probe() after chip reset completes */
|
||||||
static int xhci_pci_setup(struct usb_hcd *hcd)
|
static int xhci_pci_setup(struct usb_hcd *hcd)
|
||||||
{
|
{
|
||||||
|
@ -263,6 +311,9 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
HCC_MAX_PSA(xhci->hcc_params) >= 4)
|
HCC_MAX_PSA(xhci->hcc_params) >= 4)
|
||||||
xhci->shared_hcd->can_do_streams = 1;
|
xhci->shared_hcd->can_do_streams = 1;
|
||||||
|
|
||||||
|
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
||||||
|
xhci_pme_acpi_rtd3_enable(dev);
|
||||||
|
|
||||||
/* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
|
/* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
|
||||||
pm_runtime_put_noidle(&dev->dev);
|
pm_runtime_put_noidle(&dev->dev);
|
||||||
|
|
||||||
|
@ -307,7 +358,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
|
||||||
pdev->no_d3cold = true;
|
pdev->no_d3cold = true;
|
||||||
|
|
||||||
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
||||||
xhci_pme_quirk(xhci);
|
xhci_pme_quirk(hcd, true);
|
||||||
|
|
||||||
return xhci_suspend(xhci, do_wakeup);
|
return xhci_suspend(xhci, do_wakeup);
|
||||||
}
|
}
|
||||||
|
@ -340,7 +391,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
|
||||||
usb_enable_intel_xhci_ports(pdev);
|
usb_enable_intel_xhci_ports(pdev);
|
||||||
|
|
||||||
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
||||||
xhci_pme_quirk(xhci);
|
xhci_pme_quirk(hcd, false);
|
||||||
|
|
||||||
retval = xhci_resume(xhci, hibernated);
|
retval = xhci_resume(xhci, hibernated);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -1546,6 +1546,9 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
||||||
usb_hcd_resume_root_hub(hcd);
|
usb_hcd_resume_root_hub(hcd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hcd->speed == HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE)
|
||||||
|
bus_state->port_remote_wakeup &= ~(1 << faked_port_index);
|
||||||
|
|
||||||
if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) {
|
if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) {
|
||||||
xhci_dbg(xhci, "port resume event for port %d\n", port_id);
|
xhci_dbg(xhci, "port resume event for port %d\n", port_id);
|
||||||
|
|
||||||
|
|
|
@ -3453,6 +3453,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (virt_dev->tt_info)
|
||||||
|
old_active_eps = virt_dev->tt_info->active_eps;
|
||||||
|
|
||||||
if (virt_dev->udev != udev) {
|
if (virt_dev->udev != udev) {
|
||||||
/* If the virt_dev and the udev does not match, this virt_dev
|
/* If the virt_dev and the udev does not match, this virt_dev
|
||||||
* may belong to another udev.
|
* may belong to another udev.
|
||||||
|
|
|
@ -285,6 +285,7 @@ struct xhci_op_regs {
|
||||||
#define XDEV_U0 (0x0 << 5)
|
#define XDEV_U0 (0x0 << 5)
|
||||||
#define XDEV_U2 (0x2 << 5)
|
#define XDEV_U2 (0x2 << 5)
|
||||||
#define XDEV_U3 (0x3 << 5)
|
#define XDEV_U3 (0x3 << 5)
|
||||||
|
#define XDEV_INACTIVE (0x6 << 5)
|
||||||
#define XDEV_RESUME (0xf << 5)
|
#define XDEV_RESUME (0xf << 5)
|
||||||
/* true: port has power (see HCC_PPC) */
|
/* true: port has power (see HCC_PPC) */
|
||||||
#define PORT_POWER (1 << 9)
|
#define PORT_POWER (1 << 9)
|
||||||
|
|
|
@ -2065,6 +2065,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
|
||||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||||
US_FL_NO_READ_DISC_INFO ),
|
US_FL_NO_READ_DISC_INFO ),
|
||||||
|
|
||||||
|
/* Reported by Oliver Neukum <oneukum@suse.com>
|
||||||
|
* This device morphes spontaneously into another device if the access
|
||||||
|
* pattern of Windows isn't followed. Thus writable media would be dirty
|
||||||
|
* if the initial instance is used. So the device is limited to its
|
||||||
|
* virtual CD.
|
||||||
|
* And yes, the concept that BCD goes up to 9 is not heeded */
|
||||||
|
UNUSUAL_DEV( 0x19d2, 0x1225, 0x0000, 0xffff,
|
||||||
|
"ZTE,Incorporated",
|
||||||
|
"ZTE WCDMA Technologies MSM",
|
||||||
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||||
|
US_FL_SINGLE_LUN ),
|
||||||
|
|
||||||
/* Reported by Sven Geggus <sven-usbst@geggus.net>
|
/* Reported by Sven Geggus <sven-usbst@geggus.net>
|
||||||
* This encrypted pen drive returns bogus data for the initial READ(10).
|
* This encrypted pen drive returns bogus data for the initial READ(10).
|
||||||
*/
|
*/
|
||||||
|
@ -2074,6 +2086,17 @@ UNUSUAL_DEV( 0x1b1c, 0x1ab5, 0x0200, 0x0200,
|
||||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||||
US_FL_INITIAL_READ10 ),
|
US_FL_INITIAL_READ10 ),
|
||||||
|
|
||||||
|
/* Reported by Hans de Goede <hdegoede@redhat.com>
|
||||||
|
* These are mini projectors using USB for both power and video data transport
|
||||||
|
* The usb-storage interface is a virtual windows driver CD, which the gm12u320
|
||||||
|
* driver automatically converts into framebuffer & kms dri device nodes.
|
||||||
|
*/
|
||||||
|
UNUSUAL_DEV( 0x1de1, 0xc102, 0x0000, 0xffff,
|
||||||
|
"Grain-media Technology Corp.",
|
||||||
|
"USB3.0 Device GM12U320",
|
||||||
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||||
|
US_FL_IGNORE_DEVICE ),
|
||||||
|
|
||||||
/* Patch by Richard Schütz <r.schtz@t-online.de>
|
/* Patch by Richard Schütz <r.schtz@t-online.de>
|
||||||
* This external hard drive enclosure uses a JMicron chip which
|
* This external hard drive enclosure uses a JMicron chip which
|
||||||
* needs the US_FL_IGNORE_RESIDUE flag to work properly. */
|
* needs the US_FL_IGNORE_RESIDUE flag to work properly. */
|
||||||
|
|
Loading…
Reference in New Issue