This series adds USB PHYs and EHCI host drivers for the Marvell PXA1928
SOC.
The OTG block is based on ChipIdea and works with the "chipidea,usb2"
compatible driver as is just by adding the PHY driver. Yay! After more
testing it turns out the EHCI host is also based on ChipIdea too. So
this version uses the ChipIdea driver for both. A couple of fixes are
needed to make the ChipIdea driver work with the PXA1928 EHCI host.
I don't think the work-around in patch 6 should affect other platforms,
but testing would be nice.
Rob
v2:
- Use ChipIdea driver for EHCI host, dropping the Marvell specific EHCI
driver
- Consolidate ChipIdea bindings to single common doc.
- rename phy driver files to phy-pxa-28nm-{usb2,hsic}.c
- Simplified work-around for HSIC phy/controller handshake.
Rob Herring (6):
dt-bindings: Add Marvell PXA1928 USB and HSIC PHY bindings
phy: Add Marvell USB 2.0 OTG 28nm PHY
phy: add Marvell HSIC 28nm PHY
dt-bindings: Consolidate ChipIdea USB ci13xxx bindings
usb: chipidea: allow multiple instances to use default
ci_default_pdata
usb: chipidea: add work-around for Marvell HSIC PHY startup
.../devicetree/bindings/phy/pxa1928-usb-phy.txt | 18 ++
.../devicetree/bindings/usb/ci-hdrc-imx.txt | 35 ---
.../devicetree/bindings/usb/ci-hdrc-qcom.txt | 17 --
.../devicetree/bindings/usb/ci-hdrc-usb2.txt | 22 +-
.../devicetree/bindings/usb/ci-hdrc-zevio.txt | 17 --
drivers/phy/Kconfig | 20 ++
drivers/phy/Makefile | 2 +
drivers/phy/phy-pxa-28nm-hsic.c | 193 ++++++++++++
drivers/phy/phy-pxa-28nm-usb2.c | 329 +++++++++++++++++++++
drivers/usb/chipidea/ci_hdrc_usb2.c | 10 +-
drivers/usb/chipidea/host.c | 12 +
11 files changed, 602 insertions(+), 73 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/pxa1928-usb-phy.txt
delete mode 100644 Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
delete mode 100644 Documentation/devicetree/bindings/usb/ci-hdrc-qcom.txt
delete mode 100644 Documentation/devicetree/bindings/usb/ci-hdrc-zevio.txt
create mode 100644 drivers/phy/phy-pxa-28nm-hsic.c
create mode 100644 drivers/phy/phy-pxa-28nm-usb2.c
--
2.1.0
Add PHY binding for Marvell PXA1928 SOC's USB and HSIC PHYs.
Signed-off-by: Rob Herring <[email protected]>
Cc: Pawel Moll <[email protected]>
Cc: Mark Rutland <[email protected]>
Cc: Ian Campbell <[email protected]>
Cc: Kumar Gala <[email protected]>
Cc: [email protected]
---
.../devicetree/bindings/phy/pxa1928-usb-phy.txt | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/pxa1928-usb-phy.txt
diff --git a/Documentation/devicetree/bindings/phy/pxa1928-usb-phy.txt b/Documentation/devicetree/bindings/phy/pxa1928-usb-phy.txt
new file mode 100644
index 0000000..660a13c
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/pxa1928-usb-phy.txt
@@ -0,0 +1,18 @@
+* Marvell PXA1928 USB and HSIC PHYs
+
+Required properties:
+- compatible: "marvell,pxa1928-usb-phy" or "marvell,pxa1928-hsic-phy"
+- reg: base address and length of the registers
+- clocks - A single clock. From common clock binding.
+- #phys-cells: should be 0. From commmon phy binding.
+- resets: reference to the reset controller
+
+Example:
+
+ usbphy: phy@7000 {
+ compatible = "marvell,pxa1928-usb-phy";
+ reg = <0x7000 0xe0>;
+ clocks = <&apmu_clocks PXA1928_CLK_USB>;
+ #phy-cells = <0>;
+ };
+
--
2.1.0
Add driver for USB 28nm PHY found in Marvell PXA1928 SOC.
Signed-off-by: Rob Herring <[email protected]>
Cc: Kishon Vijay Abraham I <[email protected]>
---
drivers/phy/Kconfig | 10 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-pxa-28nm-usb2.c | 329 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 340 insertions(+)
create mode 100644 drivers/phy/phy-pxa-28nm-usb2.c
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index a53bd5b..71409a1 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -52,6 +52,16 @@ config PHY_EXYNOS_MIPI_VIDEO
Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
and EXYNOS SoCs.
+config PHY_PXA_28NM_USB2
+ tristate "Marvell USB 2.0 28nm PHY Driver"
+ select GENERIC_PHY
+ help
+ Enable this to support Marvell USB 2.0 PHY driver for Marvell
+ SoC. This driver will do the PHY initialization and shutdown.
+ The PHY driver will be used by Marvell udc/ehci/otg driver.
+
+ To compile this driver as a module, choose M here.
+
config PHY_MVEBU_SATA
def_bool y
depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index f126251..8524307 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
+obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o
obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o
obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o
diff --git a/drivers/phy/phy-pxa-28nm-usb2.c b/drivers/phy/phy-pxa-28nm-usb2.c
new file mode 100644
index 0000000..c48d111
--- /dev/null
+++ b/drivers/phy/phy-pxa-28nm-usb2.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2015 Linaro, Ltd.
+ * Rob Herring <[email protected]>
+ *
+ * Based on vendor driver:
+ * Copyright (C) 2013 Marvell Inc.
+ * Author: Chao Xie <[email protected]>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+/* USB PXA1928 PHY mapping */
+#define PHY_28NM_PLL_REG0 0x0
+#define PHY_28NM_PLL_REG1 0x4
+#define PHY_28NM_CAL_REG 0x8
+#define PHY_28NM_TX_REG0 0x0c
+#define PHY_28NM_TX_REG1 0x10
+#define PHY_28NM_RX_REG0 0x14
+#define PHY_28NM_RX_REG1 0x18
+#define PHY_28NM_DIG_REG0 0x1c
+#define PHY_28NM_DIG_REG1 0x20
+#define PHY_28NM_TEST_REG0 0x24
+#define PHY_28NM_TEST_REG1 0x28
+#define PHY_28NM_MOC_REG 0x2c
+#define PHY_28NM_PHY_RESERVE 0x30
+#define PHY_28NM_OTG_REG 0x34
+#define PHY_28NM_CHRG_DET 0x38
+#define PHY_28NM_CTRL_REG0 0xc4
+#define PHY_28NM_CTRL_REG1 0xc8
+#define PHY_28NM_CTRL_REG2 0xd4
+#define PHY_28NM_CTRL_REG3 0xdc
+
+/* PHY_28NM_PLL_REG0 */
+#define PHY_28NM_PLL_READY BIT(31)
+
+#define PHY_28NM_PLL_SELLPFR_SHIFT 28
+#define PHY_28NM_PLL_SELLPFR_MASK (0x3 << 28)
+
+#define PHY_28NM_PLL_FBDIV_SHIFT 16
+#define PHY_28NM_PLL_FBDIV_MASK (0x1ff << 16)
+
+#define PHY_28NM_PLL_ICP_SHIFT 8
+#define PHY_28NM_PLL_ICP_MASK (0x7 << 8)
+
+#define PHY_28NM_PLL_REFDIV_SHIFT 0
+#define PHY_28NM_PLL_REFDIV_MASK 0x7f
+
+/* PHY_28NM_PLL_REG1 */
+#define PHY_28NM_PLL_PU_BY_REG BIT(1)
+
+#define PHY_28NM_PLL_PU_PLL BIT(0)
+
+/* PHY_28NM_CAL_REG */
+#define PHY_28NM_PLL_PLLCAL_DONE BIT(31)
+
+#define PHY_28NM_PLL_IMPCAL_DONE BIT(23)
+
+#define PHY_28NM_PLL_KVCO_SHIFT 16
+#define PHY_28NM_PLL_KVCO_MASK (0x7 << 16)
+
+#define PHY_28NM_PLL_CAL12_SHIFT 20
+#define PHY_28NM_PLL_CAL12_MASK (0x3 << 20)
+
+#define PHY_28NM_IMPCAL_VTH_SHIFT 8
+#define PHY_28NM_IMPCAL_VTH_MASK (0x7 << 8)
+
+#define PHY_28NM_PLLCAL_START_SHIFT 22
+#define PHY_28NM_IMPCAL_START_SHIFT 13
+
+/* PHY_28NM_TX_REG0 */
+#define PHY_28NM_TX_PU_BY_REG BIT(25)
+
+#define PHY_28NM_TX_PU_ANA BIT(24)
+
+#define PHY_28NM_TX_AMP_SHIFT 20
+#define PHY_28NM_TX_AMP_MASK (0x7 << 20)
+
+/* PHY_28NM_RX_REG0 */
+#define PHY_28NM_RX_SQ_THRESH_SHIFT 0
+#define PHY_28NM_RX_SQ_THRESH_MASK (0xf << 0)
+
+/* PHY_28NM_RX_REG1 */
+#define PHY_28NM_RX_SQCAL_DONE BIT(31)
+
+/* PHY_28NM_DIG_REG0 */
+#define PHY_28NM_DIG_BITSTAFFING_ERR BIT(31)
+#define PHY_28NM_DIG_SYNC_ERR BIT(30)
+
+#define PHY_28NM_DIG_SQ_FILT_SHIFT 16
+#define PHY_28NM_DIG_SQ_FILT_MASK (0x7 << 16)
+
+#define PHY_28NM_DIG_SQ_BLK_SHIFT 12
+#define PHY_28NM_DIG_SQ_BLK_MASK (0x7 << 12)
+
+#define PHY_28NM_DIG_SYNC_NUM_SHIFT 0
+#define PHY_28NM_DIG_SYNC_NUM_MASK (0x3 << 0)
+
+#define PHY_28NM_PLL_LOCK_BYPASS BIT(7)
+
+/* PHY_28NM_OTG_REG */
+#define PHY_28NM_OTG_CONTROL_BY_PIN BIT(5)
+#define PHY_28NM_OTG_PU_OTG BIT(4)
+
+#define PHY_28NM_CHGDTC_ENABLE_SWITCH_DM_SHIFT_28 13
+#define PHY_28NM_CHGDTC_ENABLE_SWITCH_DP_SHIFT_28 12
+#define PHY_28NM_CHGDTC_VSRC_CHARGE_SHIFT_28 10
+#define PHY_28NM_CHGDTC_VDAT_CHARGE_SHIFT_28 8
+#define PHY_28NM_CHGDTC_CDP_DM_AUTO_SWITCH_SHIFT_28 7
+#define PHY_28NM_CHGDTC_DP_DM_SWAP_SHIFT_28 6
+#define PHY_28NM_CHGDTC_PU_CHRG_DTC_SHIFT_28 5
+#define PHY_28NM_CHGDTC_PD_EN_SHIFT_28 4
+#define PHY_28NM_CHGDTC_DCP_EN_SHIFT_28 3
+#define PHY_28NM_CHGDTC_CDP_EN_SHIFT_28 2
+#define PHY_28NM_CHGDTC_TESTMON_CHRGDTC_SHIFT_28 0
+
+#define PHY_28NM_CTRL1_CHRG_DTC_OUT_SHIFT_28 4
+#define PHY_28NM_CTRL1_VBUSDTC_OUT_SHIFT_28 2
+
+#define PHY_28NM_CTRL3_OVERWRITE BIT(0)
+#define PHY_28NM_CTRL3_VBUS_VALID BIT(4)
+#define PHY_28NM_CTRL3_AVALID BIT(5)
+#define PHY_28NM_CTRL3_BVALID BIT(6)
+
+struct mv_usb2_phy {
+ struct phy *phy;
+ struct platform_device *pdev;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout)
+{
+ timeout += jiffies;
+ while (time_is_after_eq_jiffies(timeout)) {
+ if ((readl(reg) & mask) == mask)
+ return true;
+ msleep(1);
+ }
+ return false;
+}
+
+static int mv_usb2_phy_28nm_init(struct phy *phy)
+{
+ struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
+ struct platform_device *pdev = mv_phy->pdev;
+ void __iomem *base = mv_phy->base;
+ u32 reg;
+
+ clk_prepare_enable(mv_phy->clk);
+
+ /* PHY_28NM_PLL_REG0 */
+ reg = readl(base + PHY_28NM_PLL_REG0) &
+ ~(PHY_28NM_PLL_SELLPFR_MASK | PHY_28NM_PLL_FBDIV_MASK
+ | PHY_28NM_PLL_ICP_MASK | PHY_28NM_PLL_REFDIV_MASK);
+ writel(reg | (0x1 << PHY_28NM_PLL_SELLPFR_SHIFT
+ | 0xf0 << PHY_28NM_PLL_FBDIV_SHIFT
+ | 0x3 << PHY_28NM_PLL_ICP_SHIFT
+ | 0xd << PHY_28NM_PLL_REFDIV_SHIFT),
+ base + PHY_28NM_PLL_REG0);
+
+ /* PHY_28NM_PLL_REG1 */
+ reg = readl(base + PHY_28NM_PLL_REG1);
+ writel(reg | PHY_28NM_PLL_PU_PLL | PHY_28NM_PLL_PU_BY_REG,
+ base + PHY_28NM_PLL_REG1);
+
+ /* PHY_28NM_TX_REG0 */
+ reg = readl(base + PHY_28NM_TX_REG0) & ~PHY_28NM_TX_AMP_MASK;
+ writel(reg | PHY_28NM_TX_PU_BY_REG | 0x3 << PHY_28NM_TX_AMP_SHIFT |
+ PHY_28NM_TX_PU_ANA,
+ base + PHY_28NM_TX_REG0);
+
+ /* PHY_28NM_RX_REG0 */
+ reg = readl(base + PHY_28NM_RX_REG0) & ~PHY_28NM_RX_SQ_THRESH_MASK;
+ writel(reg | 0xa << PHY_28NM_RX_SQ_THRESH_SHIFT,
+ base + PHY_28NM_RX_REG0);
+
+ /* PHY_28NM_DIG_REG0 */
+ reg = readl(base + PHY_28NM_DIG_REG0) &
+ ~(PHY_28NM_DIG_BITSTAFFING_ERR | PHY_28NM_DIG_SYNC_ERR |
+ PHY_28NM_DIG_SQ_FILT_MASK | PHY_28NM_DIG_SQ_BLK_MASK |
+ PHY_28NM_DIG_SYNC_NUM_MASK);
+ writel(reg | (0x1 << PHY_28NM_DIG_SYNC_NUM_SHIFT |
+ PHY_28NM_PLL_LOCK_BYPASS),
+ base + PHY_28NM_DIG_REG0);
+
+ /* PHY_28NM_OTG_REG */
+ reg = readl(base + PHY_28NM_OTG_REG) | PHY_28NM_OTG_PU_OTG;
+ writel(reg & ~PHY_28NM_OTG_CONTROL_BY_PIN, base + PHY_28NM_OTG_REG);
+
+ /* Calibration Timing
+ * ____________________________
+ * CAL START ___|
+ * ____________________
+ * CAL_DONE ___________|
+ * | 400us |
+ */
+
+ /* Make sure PHY Calibration is ready */
+ if (!wait_for_reg(base + PHY_28NM_CAL_REG,
+ PHY_28NM_PLL_PLLCAL_DONE | PHY_28NM_PLL_IMPCAL_DONE,
+ HZ / 10)) {
+ dev_warn(&pdev->dev, "USB PHY PLL calibrate not done after 100mS.");
+ return -ETIMEDOUT;
+ }
+ if (!wait_for_reg(base + PHY_28NM_RX_REG1,
+ PHY_28NM_RX_SQCAL_DONE, HZ / 10)) {
+ dev_warn(&pdev->dev, "USB PHY RX SQ calibrate not done after 100mS.");
+ return -ETIMEDOUT;
+ }
+
+ /* Make sure PHY PLL is ready */
+ if (!wait_for_reg(base + PHY_28NM_PLL_REG0,
+ PHY_28NM_PLL_READY, HZ / 10)) {
+ dev_warn(&pdev->dev, "PLL_READY not set after 100mS.");
+ return -ETIMEDOUT;
+ }
+
+ writel(readl(base + PHY_28NM_CTRL_REG3) |
+ (PHY_28NM_CTRL3_OVERWRITE | PHY_28NM_CTRL3_VBUS_VALID
+ | PHY_28NM_CTRL3_AVALID | PHY_28NM_CTRL3_BVALID),
+ base + PHY_28NM_CTRL_REG3);
+
+ return 0;
+}
+
+static int mv_usb2_phy_28nm_power_off(struct phy *phy)
+{
+ struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
+ void __iomem *base = mv_phy->base;
+ unsigned int val;
+
+ writel(readl(base + PHY_28NM_CTRL_REG3) |
+ ~(PHY_28NM_CTRL3_OVERWRITE | PHY_28NM_CTRL3_VBUS_VALID
+ | PHY_28NM_CTRL3_AVALID | PHY_28NM_CTRL3_BVALID),
+ base + PHY_28NM_CTRL_REG3);
+
+ val = readw(base + PHY_28NM_PLL_REG1);
+ val &= ~PHY_28NM_PLL_PU_PLL;
+ writew(val, base + PHY_28NM_PLL_REG1);
+
+ /* power down PHY Analog part */
+ val = readw(base + PHY_28NM_TX_REG0);
+ val &= ~PHY_28NM_TX_PU_ANA;
+ writew(val, base + PHY_28NM_TX_REG0);
+
+ /* power down PHY OTG part */
+ val = readw(base + PHY_28NM_OTG_REG);
+ val &= ~PHY_28NM_OTG_PU_OTG;
+ writew(val, base + PHY_28NM_OTG_REG);
+
+ clk_disable_unprepare(mv_phy->clk);
+ return 0;
+}
+
+static const struct phy_ops usb_ops = {
+ .init = mv_usb2_phy_28nm_init,
+ .power_off = mv_usb2_phy_28nm_power_off,
+};
+
+static int mv_usb2_phy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct mv_usb2_phy *mv_phy;
+ struct resource *r;
+
+ mv_phy = devm_kzalloc(&pdev->dev, sizeof(*mv_phy), GFP_KERNEL);
+ if (!mv_phy)
+ return -ENOMEM;
+
+ mv_phy->pdev = pdev;
+
+ mv_phy->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(mv_phy->clk)) {
+ dev_err(&pdev->dev, "failed to get clock.\n");
+ return PTR_ERR(mv_phy->clk);
+ }
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mv_phy->base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(mv_phy->base))
+ return PTR_ERR(mv_phy->base);
+
+ mv_phy->phy = devm_phy_create(&pdev->dev, pdev->dev.of_node, &usb_ops);
+ if (IS_ERR(mv_phy->phy))
+ return PTR_ERR(mv_phy->phy);
+
+ phy_set_drvdata(mv_phy->phy, mv_phy);
+
+ phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id mv_usbphy_dt_match[] = {
+ { .compatible = "marvell,pxa1928-usb-phy", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mv_usbphy_dt_match);
+
+static struct platform_driver mv_usb2_phy_driver = {
+ .probe = mv_usb2_phy_probe,
+ .driver = {
+ .name = "mv-usb2-phy",
+ .of_match_table = of_match_ptr(mv_usbphy_dt_match),
+ },
+};
+module_platform_driver(mv_usb2_phy_driver);
+
+MODULE_AUTHOR("Rob Herring <[email protected]>");
+MODULE_DESCRIPTION("Marvell USB2 phy driver");
+MODULE_LICENSE("GPL v2");
--
2.1.0
Add PHY driver for the Marvell HSIC 28nm PHY. This PHY is found in PXA1928
SOC.
Signed-off-by: Rob Herring <[email protected]>
Cc: Kishon Vijay Abraham I <[email protected]>
---
drivers/phy/Kconfig | 10 +++
drivers/phy/Makefile | 1 +
drivers/phy/phy-pxa-28nm-hsic.c | 193 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 204 insertions(+)
create mode 100644 drivers/phy/phy-pxa-28nm-hsic.c
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 71409a1..7d56c44 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -52,6 +52,16 @@ config PHY_EXYNOS_MIPI_VIDEO
Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
and EXYNOS SoCs.
+config PHY_PXA_28NM_HSIC
+ tristate "Marvell USB HSIC 28nm PHY Driver"
+ select GENERIC_PHY
+ help
+ Enable this to support Marvell USB HSIC PHY driver for Marvell
+ SoC. This driver will do the PHY initialization and shutdown.
+ The PHY driver will be used by Marvell ehci driver.
+
+ To compile this driver as a module, choose M here.
+
config PHY_PXA_28NM_USB2
tristate "Marvell USB 2.0 28nm PHY Driver"
select GENERIC_PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 8524307..2c16963 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o
+obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o
obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o
diff --git a/drivers/phy/phy-pxa-28nm-hsic.c b/drivers/phy/phy-pxa-28nm-hsic.c
new file mode 100644
index 0000000..83e0d4d
--- /dev/null
+++ b/drivers/phy/phy-pxa-28nm-hsic.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2015 Linaro, Ltd.
+ * Rob Herring <[email protected]>
+ *
+ * Based on vendor driver:
+ * Copyright (C) 2013 Marvell Inc.
+ * Author: Chao Xie <[email protected]>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+#define PHY_28NM_HSIC_CTRL 0x08
+#define PHY_28NM_HSIC_IMPCAL_CAL 0x18
+#define PHY_28NM_HSIC_PLL_CTRL01 0x1c
+#define PHY_28NM_HSIC_PLL_CTRL2 0x20
+#define PHY_28NM_HSIC_INT 0x28
+
+#define PHY_28NM_HSIC_PLL_SELLPFR_SHIFT 26
+#define PHY_28NM_HSIC_PLL_FBDIV_SHIFT 0
+#define PHY_28NM_HSIC_PLL_REFDIV_SHIFT 9
+
+#define PHY_28NM_HSIC_S2H_PU_PLL BIT(10)
+#define PHY_28NM_HSIC_H2S_PLL_LOCK BIT(15)
+#define PHY_28NM_HSIC_S2H_HSIC_EN BIT(7)
+#define S2H_DRV_SE0_4RESUME BIT(14)
+#define PHY_28NM_HSIC_H2S_IMPCAL_DONE BIT(27)
+
+#define PHY_28NM_HSIC_CONNECT_INT BIT(1)
+#define PHY_28NM_HSIC_HS_READY_INT BIT(2)
+
+struct mv_hsic_phy {
+ struct phy *phy;
+ struct platform_device *pdev;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout)
+{
+ timeout += jiffies;
+ while (time_is_after_eq_jiffies(timeout)) {
+ if ((readl(reg) & mask) == mask)
+ return true;
+ msleep(1);
+ }
+ return false;
+}
+
+static int mv_hsic_phy_power_on(struct phy *phy)
+{
+ struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
+ struct platform_device *pdev = mv_phy->pdev;
+ void __iomem *base = mv_phy->base;
+
+ clk_prepare_enable(mv_phy->clk);
+
+ /* Set reference clock */
+ writel(0x1 << PHY_28NM_HSIC_PLL_SELLPFR_SHIFT |
+ 0xf0 << PHY_28NM_HSIC_PLL_FBDIV_SHIFT |
+ 0xd << PHY_28NM_HSIC_PLL_REFDIV_SHIFT,
+ base + PHY_28NM_HSIC_PLL_CTRL01);
+
+ /* Turn on PLL */
+ writel(readl(base + PHY_28NM_HSIC_PLL_CTRL2) |
+ PHY_28NM_HSIC_S2H_PU_PLL,
+ base + PHY_28NM_HSIC_PLL_CTRL2);
+
+ /* Make sure PHY PLL is locked */
+ if (!wait_for_reg(base + PHY_28NM_HSIC_PLL_CTRL2,
+ PHY_28NM_HSIC_H2S_PLL_LOCK, HZ / 10)) {
+ dev_err(&pdev->dev, "HSIC PHY PLL not locked after 100mS.");
+ return -ETIMEDOUT;
+ }
+
+ /* Avoid SE0 state when resume for some device will take it as reset */
+ writel(readl(base + PHY_28NM_HSIC_CTRL) & ~S2H_DRV_SE0_4RESUME,
+ base + PHY_28NM_HSIC_CTRL);
+
+ /* Enable HSIC PHY */
+ writel(readl(base + PHY_28NM_HSIC_CTRL) | PHY_28NM_HSIC_S2H_HSIC_EN,
+ base + PHY_28NM_HSIC_CTRL);
+
+ /* Calibration Timing
+ * ____________________________
+ * CAL START ___|
+ * ____________________
+ * CAL_DONE ___________|
+ * | 400us |
+ */
+
+ /* Make sure PHY Calibration is ready */
+ if (!wait_for_reg(base + PHY_28NM_HSIC_IMPCAL_CAL,
+ PHY_28NM_HSIC_H2S_IMPCAL_DONE, HZ / 10)) {
+ dev_warn(&pdev->dev, "HSIC PHY READY not set after 100mS.");
+ return -ETIMEDOUT;
+ }
+
+ /* Waiting for HSIC connect int*/
+ if (!wait_for_reg(base + PHY_28NM_HSIC_INT,
+ PHY_28NM_HSIC_CONNECT_INT, HZ / 5)) {
+ dev_warn(&pdev->dev, "HSIC wait for connect interrupt timeout.");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int mv_hsic_phy_power_off(struct phy *phy)
+{
+ struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
+ void __iomem *base = mv_phy->base;
+
+ writel(readl(base + PHY_28NM_HSIC_CTRL) & ~PHY_28NM_HSIC_S2H_HSIC_EN,
+ base + PHY_28NM_HSIC_CTRL);
+
+ clk_disable_unprepare(mv_phy->clk);
+ return 0;
+}
+
+static const struct phy_ops hsic_ops = {
+ .power_on = mv_hsic_phy_power_on,
+ .power_off = mv_hsic_phy_power_off,
+};
+
+static int mv_hsic_phy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct mv_hsic_phy *mv_phy;
+ struct resource *r;
+
+ mv_phy = devm_kzalloc(&pdev->dev, sizeof(*mv_phy), GFP_KERNEL);
+ if (!mv_phy)
+ return -ENOMEM;
+
+ mv_phy->pdev = pdev;
+
+ mv_phy->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(mv_phy->clk)) {
+ dev_err(&pdev->dev, "failed to get clock.\n");
+ return PTR_ERR(mv_phy->clk);
+ }
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mv_phy->base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(mv_phy->base))
+ return PTR_ERR(mv_phy->base);
+
+ mv_phy->phy = devm_phy_create(&pdev->dev, pdev->dev.of_node, &hsic_ops);
+ if (IS_ERR(mv_phy->phy))
+ return PTR_ERR(mv_phy->phy);
+
+ phy_set_drvdata(mv_phy->phy, mv_phy);
+
+ phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id mv_hsic_phy_dt_match[] = {
+ { .compatible = "marvell,pxa1928-hsic-phy", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mv_hsic_phy_dt_match);
+
+static struct platform_driver mv_hsic_phy_driver = {
+ .probe = mv_hsic_phy_probe,
+ .driver = {
+ .name = "mv-hsic-phy",
+ .of_match_table = of_match_ptr(mv_hsic_phy_dt_match),
+ },
+};
+module_platform_driver(mv_hsic_phy_driver);
+
+MODULE_AUTHOR("Rob Herring <[email protected]>");
+MODULE_DESCRIPTION("Marvell HSIC phy driver");
+MODULE_LICENSE("GPL v2");
--
2.1.0
Combine the ChipIdea USB binding into a single document to reduce
duplication and fragmentation. This marks use of the old PHY bindings as
deprecated. Future compatible bindings should use generic PHY binding.
Signed-off-by: Rob Herring <[email protected]>
Cc: Ivan T. Ivanov <[email protected]>
Cc: Peter Chen <[email protected]>
Cc: Daniel Tang <[email protected]>
Cc: Pawel Moll <[email protected]>
Cc: Mark Rutland <[email protected]>
Cc: Ian Campbell <[email protected]>
Cc: Kumar Gala <[email protected]>
Cc: [email protected]
---
.../devicetree/bindings/usb/ci-hdrc-imx.txt | 35 ----------------------
.../devicetree/bindings/usb/ci-hdrc-qcom.txt | 17 -----------
.../devicetree/bindings/usb/ci-hdrc-usb2.txt | 22 +++++++++++++-
.../devicetree/bindings/usb/ci-hdrc-zevio.txt | 17 -----------
4 files changed, 21 insertions(+), 70 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
delete mode 100644 Documentation/devicetree/bindings/usb/ci-hdrc-qcom.txt
delete mode 100644 Documentation/devicetree/bindings/usb/ci-hdrc-zevio.txt
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
deleted file mode 100644
index 38a5480..0000000
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-* Freescale i.MX ci13xxx usb controllers
-
-Required properties:
-- compatible: Should be "fsl,imx27-usb"
-- reg: Should contain registers location and length
-- interrupts: Should contain controller interrupt
-- fsl,usbphy: phandle of usb phy that connects to the port
-
-Recommended properies:
-- phy_type: the type of the phy connected to the core. Should be one
- of "utmi", "utmi_wide", "ulpi", "serial" or "hsic". Without this
- property the PORTSC register won't be touched
-- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
-
-Optional properties:
-- fsl,usbmisc: phandler of non-core register device, with one argument
- that indicate usb controller index
-- vbus-supply: regulator for vbus
-- disable-over-current: disable over current detect
-- external-vbus-divider: enables off-chip resistor divider for Vbus
-- maximum-speed: limit the maximum connection speed to "full-speed".
-- tpl-support: TPL (Targeted Peripheral List) feature for targeted hosts
-
-Examples:
-usb@02184000 { /* USB OTG */
- compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
- reg = <0x02184000 0x200>;
- interrupts = <0 43 0x04>;
- fsl,usbphy = <&usbphy1>;
- fsl,usbmisc = <&usbmisc 0>;
- disable-over-current;
- external-vbus-divider;
- maximum-speed = "full-speed";
- tpl-support;
-};
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-qcom.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-qcom.txt
deleted file mode 100644
index f2899b5..0000000
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-qcom.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Qualcomm CI13xxx (Chipidea) USB controllers
-
-Required properties:
-- compatible: should contain "qcom,ci-hdrc"
-- reg: offset and length of the register set in the memory map
-- interrupts: interrupt-specifier for the controller interrupt.
-- usb-phy: phandle for the PHY device
-- dr_mode: Should be "peripheral"
-
-Examples:
- gadget@f9a55000 {
- compatible = "qcom,ci-hdrc";
- reg = <0xf9a55000 0x400>;
- dr_mode = "peripheral";
- interrupts = <0 134 0>;
- usb-phy = <&usbphy0>;
- };
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index 27f8b1e..f074827 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -1,15 +1,35 @@
* USB2 ChipIdea USB controller for ci13xxx
Required properties:
-- compatible: should be "chipidea,usb2"
+- compatible: should be one of:
+ "fsl,imx27-usb"
+ "lsi,zevio-usb"
+ "qcom,ci-hdrc"
+ "chipidea,usb2"
- reg: base address and length of the registers
- interrupts: interrupt for the USB controller
+Recommended properies:
+- phy_type: the type of the phy connected to the core. Should be one
+ of "utmi", "utmi_wide", "ulpi", "serial" or "hsic". Without this
+ property the PORTSC register won't be touched.
+- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
+
+Deprecated properties:
+- usb-phy: phandle for the PHY device. Use "phys" instead.
+- fsl,usbphy: phandle of usb phy that connects to the port. Use "phys" instead.
+
Optional properties:
- clocks: reference to the USB clock
- phys: reference to the USB PHY
- phy-names: should be "usb-phy"
- vbus-supply: reference to the VBUS regulator
+- fsl,usbmisc: phandler of non-core register device, with one argument
+ that indicate usb controller index
+- disable-over-current: disable over current detect
+- external-vbus-divider: enables off-chip resistor divider for Vbus
+- maximum-speed: limit the maximum connection speed to "full-speed".
+- tpl-support: TPL (Targeted Peripheral List) feature for targeted hosts
Example:
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-zevio.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-zevio.txt
deleted file mode 100644
index abbcb2a..0000000
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-zevio.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-* LSI Zevio USB OTG Controller
-
-Required properties:
-- compatible: Should be "lsi,zevio-usb"
-- reg: Should contain registers location and length
-- interrupts: Should contain controller interrupt
-
-Optional properties:
-- vbus-supply: regulator for vbus
-
-Examples:
- usb0: usb@b0000000 {
- reg = <0xb0000000 0x1000>;
- compatible = "lsi,zevio-usb";
- interrupts = <8>;
- vbus-supply = <&vbus_reg>;
- };
--
2.1.0
Currently, ci_default_pdata is common to all instances of the driver and
gets modified by the core driver code. This is bad if there are multiple
instances of the device with different settings such as the phy type. Fix
this by making a copy of the default platform_data.
Signed-off-by: Rob Herring <[email protected]>
Cc: Peter Chen <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: [email protected]
---
drivers/usb/chipidea/ci_hdrc_usb2.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_usb2.c b/drivers/usb/chipidea/ci_hdrc_usb2.c
index 45844c9..73d9906 100644
--- a/drivers/usb/chipidea/ci_hdrc_usb2.c
+++ b/drivers/usb/chipidea/ci_hdrc_usb2.c
@@ -25,11 +25,13 @@ struct ci_hdrc_usb2_priv {
struct clk *clk;
};
-static struct ci_hdrc_platform_data ci_default_pdata = {
+static const struct ci_hdrc_platform_data ci_default_pdata = {
.capoffset = DEF_CAPOFFSET,
.flags = CI_HDRC_DISABLE_STREAMING,
};
+static const struct of_device_id ci_hdrc_usb2_of_match[];
+
static int ci_hdrc_usb2_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -37,8 +39,10 @@ static int ci_hdrc_usb2_probe(struct platform_device *pdev)
struct ci_hdrc_platform_data *ci_pdata = dev_get_platdata(dev);
int ret;
- if (!ci_pdata)
- ci_pdata = &ci_default_pdata;
+ if (!ci_pdata) {
+ ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL);
+ *ci_pdata = ci_default_pdata; /* struct copy */
+ }
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
--
2.1.0
The Marvell 28nm HSIC PHY requires the port to be forced to HS mode after
the port power is applied. This is done using the test mode in the PORTSC
register.
As HSIC is always HS, this work-around should be safe to do with all HSIC
PHYs. If not, a flag can also be added.
Signed-off-by: Rob Herring <[email protected]>
Cc: Peter Chen <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: [email protected]
---
drivers/usb/chipidea/host.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 21fe1a3..6cf87b8 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -37,12 +37,14 @@ static int (*orig_bus_suspend)(struct usb_hcd *hcd);
struct ehci_ci_priv {
struct regulator *reg_vbus;
+ struct ci_hdrc *ci;
};
static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct ehci_ci_priv *priv = (struct ehci_ci_priv *)ehci->priv;
+ struct ci_hdrc *ci = priv->ci;
struct device *dev = hcd->self.controller;
int ret = 0;
int port = HCS_N_PORTS(ehci->hcs_params);
@@ -64,6 +66,15 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
return ret;
}
}
+
+ if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
+ /*
+ * Marvell 28nm HSIC PHY requires forcing the port to HS mode.
+ * As HSIC is always HS, this should be safe for others.
+ */
+ hw_port_test_set(ci, 5);
+ hw_port_test_set(ci, 0);
+ }
return 0;
};
@@ -112,6 +123,7 @@ static int host_start(struct ci_hdrc *ci)
priv = (struct ehci_ci_priv *)ehci->priv;
priv->reg_vbus = NULL;
+ priv->ci = ci;
if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
if (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON) {
--
2.1.0
On Tue, May 19, 2015 at 09:10:03PM -0500, Rob Herring wrote:
> Combine the ChipIdea USB binding into a single document to reduce
> duplication and fragmentation. This marks use of the old PHY bindings as
> deprecated. Future compatible bindings should use generic PHY binding.
Thanks, Rob. These are what I plan to do in future too.
> diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
> index 27f8b1e..f074827 100644
> --- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
> +++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
> @@ -1,15 +1,35 @@
> * USB2 ChipIdea USB controller for ci13xxx
>
> Required properties:
> -- compatible: should be "chipidea,usb2"
> +- compatible: should be one of:
> + "fsl,imx27-usb"
> + "lsi,zevio-usb"
> + "qcom,ci-hdrc"
> + "chipidea,usb2"
> - reg: base address and length of the registers
> - interrupts: interrupt for the USB controller
>
> +Recommended properies:
> +- phy_type: the type of the phy connected to the core. Should be one
> + of "utmi", "utmi_wide", "ulpi", "serial" or "hsic". Without this
> + property the PORTSC register won't be touched.
> +- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
> +
> +Deprecated properties:
> +- usb-phy: phandle for the PHY device. Use "phys" instead.
> +- fsl,usbphy: phandle of usb phy that connects to the port. Use "phys" instead.
> +
> Optional properties:
> - clocks: reference to the USB clock
> - phys: reference to the USB PHY
> - phy-names: should be "usb-phy"
> - vbus-supply: reference to the VBUS regulator
> +- fsl,usbmisc: phandler of non-core register device, with one argument
> + that indicate usb controller index
> +- disable-over-current: disable over current detect
> +- external-vbus-divider: enables off-chip resistor divider for Vbus
The above property is only for fsl, we may need to differentiate
generic and vendor properties for reader.
--
Best Regards,
Peter Chen
On Tue, May 19, 2015 at 09:10:04PM -0500, Rob Herring wrote:
> Currently, ci_default_pdata is common to all instances of the driver and
> gets modified by the core driver code. This is bad if there are multiple
> instances of the device with different settings such as the phy type. Fix
> this by making a copy of the default platform_data.
>
> Signed-off-by: Rob Herring <[email protected]>
> Cc: Peter Chen <[email protected]>
> Cc: Greg Kroah-Hartman <[email protected]>
> Cc: [email protected]
> ---
> drivers/usb/chipidea/ci_hdrc_usb2.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_usb2.c b/drivers/usb/chipidea/ci_hdrc_usb2.c
> index 45844c9..73d9906 100644
> --- a/drivers/usb/chipidea/ci_hdrc_usb2.c
> +++ b/drivers/usb/chipidea/ci_hdrc_usb2.c
> @@ -25,11 +25,13 @@ struct ci_hdrc_usb2_priv {
> struct clk *clk;
> };
>
> -static struct ci_hdrc_platform_data ci_default_pdata = {
> +static const struct ci_hdrc_platform_data ci_default_pdata = {
> .capoffset = DEF_CAPOFFSET,
> .flags = CI_HDRC_DISABLE_STREAMING,
> };
>
> +static const struct of_device_id ci_hdrc_usb2_of_match[];
> +
unrelated change?
Others are ok.
> static int ci_hdrc_usb2_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -37,8 +39,10 @@ static int ci_hdrc_usb2_probe(struct platform_device *pdev)
> struct ci_hdrc_platform_data *ci_pdata = dev_get_platdata(dev);
> int ret;
>
> - if (!ci_pdata)
> - ci_pdata = &ci_default_pdata;
> + if (!ci_pdata) {
> + ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL);
> + *ci_pdata = ci_default_pdata; /* struct copy */
> + }
>
> priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> if (!priv)
> --
> 2.1.0
>
--
Best Regards,
Peter Chen
On Tue, May 19, 2015 at 09:10:05PM -0500, Rob Herring wrote:
> The Marvell 28nm HSIC PHY requires the port to be forced to HS mode after
> the port power is applied. This is done using the test mode in the PORTSC
> register.
>
> As HSIC is always HS, this work-around should be safe to do with all HSIC
> PHYs. If not, a flag can also be added.
I think a flag is needed, not sure all vendors can work well with that.
>
> Signed-off-by: Rob Herring <[email protected]>
> Cc: Peter Chen <[email protected]>
> Cc: Greg Kroah-Hartman <[email protected]>
> Cc: [email protected]
> ---
> drivers/usb/chipidea/host.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
> index 21fe1a3..6cf87b8 100644
> --- a/drivers/usb/chipidea/host.c
> +++ b/drivers/usb/chipidea/host.c
> @@ -37,12 +37,14 @@ static int (*orig_bus_suspend)(struct usb_hcd *hcd);
>
> struct ehci_ci_priv {
> struct regulator *reg_vbus;
> + struct ci_hdrc *ci;
> };
>
> static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
> {
> struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> struct ehci_ci_priv *priv = (struct ehci_ci_priv *)ehci->priv;
> + struct ci_hdrc *ci = priv->ci;
> struct device *dev = hcd->self.controller;
> int ret = 0;
> int port = HCS_N_PORTS(ehci->hcs_params);
> @@ -64,6 +66,15 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
> return ret;
> }
> }
> +
> + if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
> + /*
> + * Marvell 28nm HSIC PHY requires forcing the port to HS mode.
> + * As HSIC is always HS, this should be safe for others.
> + */
> + hw_port_test_set(ci, 5);
> + hw_port_test_set(ci, 0);
> + }
> return 0;
> };
>
> @@ -112,6 +123,7 @@ static int host_start(struct ci_hdrc *ci)
>
> priv = (struct ehci_ci_priv *)ehci->priv;
> priv->reg_vbus = NULL;
> + priv->ci = ci;
>
> if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
> if (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON) {
> --
> 2.1.0
>
--
Best Regards,
Peter Chen
On Wed, May 20, 2015 at 10:13 PM, Peter Chen <[email protected]> wrote:
> On Tue, May 19, 2015 at 09:10:05PM -0500, Rob Herring wrote:
>> The Marvell 28nm HSIC PHY requires the port to be forced to HS mode after
>> the port power is applied. This is done using the test mode in the PORTSC
>> register.
>>
>> As HSIC is always HS, this work-around should be safe to do with all HSIC
>> PHYs. If not, a flag can also be added.
>
> I think a flag is needed, not sure all vendors can work well with that.
Only i.MX6Sx uses HSIC in mainline. Is that something you can test? It
would be better to not add flags unless they are really needed.
Otherwise you end up with dozens of flags like SDHCI drivers have.
Rob
>
> On Wed, May 20, 2015 at 10:13 PM, Peter Chen <[email protected]>
> wrote:
> > On Tue, May 19, 2015 at 09:10:05PM -0500, Rob Herring wrote:
> >> The Marvell 28nm HSIC PHY requires the port to be forced to HS mode
> >> after the port power is applied. This is done using the test mode in
> >> the PORTSC register.
> >>
> >> As HSIC is always HS, this work-around should be safe to do with all
> >> HSIC PHYs. If not, a flag can also be added.
> >
> > I think a flag is needed, not sure all vendors can work well with that.
>
> Only i.MX6Sx uses HSIC in mainline. Is that something you can test? It would be
> better to not add flags unless they are really needed.
> Otherwise you end up with dozens of flags like SDHCI drivers have.
>
I will have a test for this, and show you the result later.
Peter
????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m????????????I?
On Thu, May 21, 2015 at 09:54:20AM +0000, Peter Chen wrote:
>
> >
> > On Wed, May 20, 2015 at 10:13 PM, Peter Chen <[email protected]>
> > wrote:
> > > On Tue, May 19, 2015 at 09:10:05PM -0500, Rob Herring wrote:
> > >> The Marvell 28nm HSIC PHY requires the port to be forced to HS mode
> > >> after the port power is applied. This is done using the test mode in
> > >> the PORTSC register.
> > >>
> > >> As HSIC is always HS, this work-around should be safe to do with all
> > >> HSIC PHYs. If not, a flag can also be added.
> > >
> > > I think a flag is needed, not sure all vendors can work well with that.
> >
> > Only i.MX6Sx uses HSIC in mainline. Is that something you can test? It would be
> > better to not add flags unless they are really needed.
> > Otherwise you end up with dozens of flags like SDHCI drivers have.
> >
>
> I will have a test for this, and show you the result later.
>
Since imx6sx HSIC support is not supported at mainline, I tested
this sequence at internal branch, it does not affect imx6's
hsic function, I am ok with this patch.
Tested-by: Peter Chen <[email protected]>
> Peter
> ��칻�&�~�&���+-��ݶ��w��˛���m�b��n������ܨ}���Ơz�&j:+v�������zZ+��+zf���h���~����i���z��w���?����&�)ߢf
--
Best Regards,
Peter Chen