phy: samsung: Add support for the Exynos5420 variant of the USB2 PHY
authorMarek Szyprowski <m.szyprowski@samsung.com>
Fri, 20 Nov 2020 08:56:36 +0000 (09:56 +0100)
committerVinod Koul <vkoul@kernel.org>
Mon, 30 Nov 2020 10:50:59 +0000 (16:20 +0530)
Exynos5420 differs a bit from Exynos5250 in USB2 PHY related registers in
the PMU region. Add a variant for the Exynos5420 case. Till now, USB2 PHY
worked only because the bootloader enabled the PHY, but then driver messed
USB 3.0 DRD related registers during the suspend/resume cycle.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Link: https://lore.kernel.org/r/20201120085637.7299-2-m.szyprowski@samsung.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Documentation/devicetree/bindings/phy/samsung-phy.txt
drivers/phy/samsung/Kconfig
drivers/phy/samsung/phy-exynos5250-usb2.c
drivers/phy/samsung/phy-samsung-usb2.c
drivers/phy/samsung/phy-samsung-usb2.h

index 7510830..8f51aee 100644 (file)
@@ -47,6 +47,7 @@ Required properties:
        - "samsung,exynos4210-usb2-phy"
        - "samsung,exynos4x12-usb2-phy"
        - "samsung,exynos5250-usb2-phy"
+       - "samsung,exynos5420-usb2-phy"
        - "samsung,s5pv210-usb2-phy"
 - reg : a list of registers used by phy driver
        - first and obligatory is the location of phy modules registers
index e20d2fc..0f51d3b 100644 (file)
@@ -64,7 +64,12 @@ config PHY_EXYNOS4X12_USB2
 config PHY_EXYNOS5250_USB2
        bool
        depends on PHY_SAMSUNG_USB2
-       default SOC_EXYNOS5250 || SOC_EXYNOS5420
+       default SOC_EXYNOS5250
+
+config PHY_EXYNOS5420_USB2
+       bool
+       depends on PHY_SAMSUNG_USB2
+       default SOC_EXYNOS5420
 
 config PHY_S5PV210_USB2
        bool "Support for S5PV210"
index 4f53b71..e198010 100644 (file)
 
 /* Isolation, configured in the power management unit */
 #define EXYNOS_5250_USB_ISOL_OTG_OFFSET                0x704
-#define EXYNOS_5250_USB_ISOL_OTG               BIT(0)
 #define EXYNOS_5250_USB_ISOL_HOST_OFFSET       0x708
-#define EXYNOS_5250_USB_ISOL_HOST              BIT(0)
+#define EXYNOS_5420_USB_ISOL_HOST_OFFSET       0x70C
+#define EXYNOS_5250_USB_ISOL_ENABLE            BIT(0)
 
 /* Mode swtich register */
 #define EXYNOS_5250_MODE_SWITCH_OFFSET         0x230
@@ -132,7 +132,6 @@ enum exynos4x12_phy_id {
        EXYNOS5250_HOST,
        EXYNOS5250_HSIC0,
        EXYNOS5250_HSIC1,
-       EXYNOS5250_NUM_PHYS,
 };
 
 /*
@@ -176,20 +175,19 @@ static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)
 {
        struct samsung_usb2_phy_driver *drv = inst->drv;
        u32 offset;
-       u32 mask;
+       u32 mask = EXYNOS_5250_USB_ISOL_ENABLE;
 
-       switch (inst->cfg->id) {
-       case EXYNOS5250_DEVICE:
+       if (drv->cfg == &exynos5250_usb2_phy_config &&
+           inst->cfg->id == EXYNOS5250_DEVICE)
                offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;
-               mask = EXYNOS_5250_USB_ISOL_OTG;
-               break;
-       case EXYNOS5250_HOST:
+       else if (drv->cfg == &exynos5250_usb2_phy_config &&
+                inst->cfg->id == EXYNOS5250_HOST)
                offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;
-               mask = EXYNOS_5250_USB_ISOL_HOST;
-               break;
-       default:
+       else if (drv->cfg == &exynos5420_usb2_phy_config &&
+                inst->cfg->id == EXYNOS5250_HOST)
+               offset = EXYNOS_5420_USB_ISOL_HOST_OFFSET;
+       else
                return;
-       }
 
        regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
 }
@@ -390,9 +388,31 @@ static const struct samsung_usb2_common_phy exynos5250_phys[] = {
        },
 };
 
+static const struct samsung_usb2_common_phy exynos5420_phys[] = {
+       {
+               .label          = "host",
+               .id             = EXYNOS5250_HOST,
+               .power_on       = exynos5250_power_on,
+               .power_off      = exynos5250_power_off,
+       },
+       {
+               .label          = "hsic",
+               .id             = EXYNOS5250_HSIC0,
+               .power_on       = exynos5250_power_on,
+               .power_off      = exynos5250_power_off,
+       },
+};
+
 const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = {
        .has_mode_switch        = 1,
-       .num_phys               = EXYNOS5250_NUM_PHYS,
+       .num_phys               = ARRAY_SIZE(exynos5250_phys),
        .phys                   = exynos5250_phys,
        .rate_to_clk            = exynos5250_rate_to_clk,
 };
+
+const struct samsung_usb2_phy_config exynos5420_usb2_phy_config = {
+       .has_mode_switch        = 1,
+       .num_phys               = ARRAY_SIZE(exynos5420_phys),
+       .phys                   = exynos5420_phys,
+       .rate_to_clk            = exynos5250_rate_to_clk,
+};
index f79f605..3908153 100644 (file)
@@ -128,6 +128,12 @@ static const struct of_device_id samsung_usb2_phy_of_match[] = {
                .data = &exynos5250_usb2_phy_config,
        },
 #endif
+#ifdef CONFIG_PHY_EXYNOS5420_USB2
+       {
+               .compatible = "samsung,exynos5420-usb2-phy",
+               .data = &exynos5420_usb2_phy_config,
+       },
+#endif
 #ifdef CONFIG_PHY_S5PV210_USB2
        {
                .compatible = "samsung,s5pv210-usb2-phy",
index 77fb23b..ebaf43b 100644 (file)
@@ -66,5 +66,6 @@ extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
+extern const struct samsung_usb2_phy_config exynos5420_usb2_phy_config;
 extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config;
 #endif