diff options
author | Jaewon Kim <jaewon02.kim@samsung.com> | 2015-04-13 22:30:37 +0900 |
---|---|---|
committer | Seung-Woo Kim <sw0312.kim@samsung.com> | 2016-12-14 13:42:52 +0900 |
commit | 9037a6614e69b913c8280acb98468078baef9504 (patch) | |
tree | 720df4bb627d9795d3dc70f4b03a6758cfe61792 /drivers/phy | |
parent | f89e69cf4bb93367d32880e2300edfc65b57ea5a (diff) |
phy: exynos5250-usb2: add USB2.0 PHY for Exynos5433 SoC
Exynos5433 USB2.0 PHY register layout similar as Exynos5250.
But Exynos5433 has only one USB2.0 Host and one HSIC.
Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
Diffstat (limited to 'drivers/phy')
-rw-r--r-- | drivers/phy/phy-exynos5250-usb2.c | 134 | ||||
-rw-r--r-- | drivers/phy/phy-samsung-usb2.c | 4 | ||||
-rw-r--r-- | drivers/phy/phy-samsung-usb2.h | 1 |
3 files changed, 139 insertions, 0 deletions
diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/phy-exynos5250-usb2.c index 2ed1735a076a..41018257fe64 100644 --- a/drivers/phy/phy-exynos5250-usb2.c +++ b/drivers/phy/phy-exynos5250-usb2.c @@ -124,6 +124,9 @@ #define EXYNOS_5250_USB_ISOL_HOST_OFFSET 0x708 #define EXYNOS_5250_USB_ISOL_HOST BIT(0) +#define EXYNOS_5433_USB_ISOL_HOST_OFFSET 0x708 +#define EXYNOS_5433_USB_ISOL_HOST BIT(0) + /* Mode swtich register */ #define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230 #define EXYNOS_5250_MODE_SWITCH_MASK 1 @@ -138,6 +141,12 @@ enum exynos4x12_phy_id { EXYNOS5250_NUM_PHYS, }; +enum exynos5250_phy_id { + EXYNOS5433_HOST, + EXYNOS5433_HSIC, + EXYNOS5433_NUM_PHYS, +}; + /* * exynos5250_rate_to_clk() converts the supplied clock rate to the value that * can be written to the phy register. @@ -365,6 +374,109 @@ static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst) return 0; } +static int exynos5433_power_on(struct samsung_usb2_phy_instance *inst) +{ + struct samsung_usb2_phy_driver *drv = inst->drv; + u32 ctrl0; + u32 ehci; + u32 ohci; + u32 hsic; + + /* Host registers configuration */ + ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); + /* The clock */ + ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK; + ctrl0 |= drv->ref_reg_val << + EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT; + + /* Reset */ + ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST | + EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL | + EXYNOS_5250_HOSTPHYCTRL0_SIDDQ | + EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND | + EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP); + ctrl0 |= EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST | + EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST | + EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N; + writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); + udelay(10); + ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST | + EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST); + writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); + + /* HSIC phy configuration */ + hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 | + EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT | + EXYNOS_5250_HSICPHYCTRLX_PHYSWRST); + writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1); + writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2); + udelay(10); + hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST; + writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1); + writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2); + /* The following delay is necessary for the reset sequence to be + * completed */ + udelay(80); + + /* Enable EHCI DMA burst */ + ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL); + ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN | + EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 | + EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 | + EXYNOS_5250_HOSTEHCICTRL_ENAINCR16; + writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL); + + /* OHCI settings */ + ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL); + /* Following code is based on the old driver */ + ohci |= 0x1 << 3; + writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL); + + /* Bypass PMU(Power Management Unit) Isolation */ + regmap_update_bits(drv->reg_pmu, + EXYNOS_5433_USB_ISOL_HOST_OFFSET, + EXYNOS_5433_USB_ISOL_HOST, + EXYNOS_5433_USB_ISOL_HOST); + + return 0; +} + +static int exynos5433_power_off(struct samsung_usb2_phy_instance *inst) +{ + struct samsung_usb2_phy_driver *drv = inst->drv; + u32 ctrl0; + u32 hsic; + + /* Enable PMU(Power Management Unit) Isolation */ + regmap_update_bits(drv->reg_pmu, + EXYNOS_5433_USB_ISOL_HOST_OFFSET, + EXYNOS_5433_USB_ISOL_HOST, + (unsigned int)~(EXYNOS_5433_USB_ISOL_HOST)); + + switch (inst->cfg->id) { + case EXYNOS5433_HOST: + ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); + ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ | + EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND | + EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP | + EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST | + EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL); + writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); + break; + case EXYNOS5433_HSIC: + hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 | + EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT | + EXYNOS_5250_HSICPHYCTRLX_SIDDQ | + EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP | + EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND + ); + writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1); + writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2); + break; + } + + return 0; +} static const struct samsung_usb2_common_phy exynos5250_phys[] = { { @@ -393,9 +505,31 @@ static const struct samsung_usb2_common_phy exynos5250_phys[] = { }, }; +static const struct samsung_usb2_common_phy exynos5433_phys[] = { + { + .label = "host", + .id = EXYNOS5433_HOST, + .power_on = exynos5433_power_on, + .power_off = exynos5433_power_off, + }, + { + .label = "hsic", + .id = EXYNOS5433_HSIC, + .power_on = exynos5433_power_on, + .power_off = exynos5433_power_off + }, +}; + const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = { .has_mode_switch = 1, .num_phys = EXYNOS5250_NUM_PHYS, .phys = exynos5250_phys, .rate_to_clk = exynos5250_rate_to_clk, }; + +const struct samsung_usb2_phy_config exynos5433_usb2_phy_config = { + .has_mode_switch = 0, + .num_phys = EXYNOS5433_NUM_PHYS, + .phys = exynos5433_phys, + .rate_to_clk = exynos5250_rate_to_clk, +}; diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c index 55b6994932e3..ff35bb49b80f 100644 --- a/drivers/phy/phy-samsung-usb2.c +++ b/drivers/phy/phy-samsung-usb2.c @@ -116,6 +116,10 @@ static const struct of_device_id samsung_usb2_phy_of_match[] = { .compatible = "samsung,exynos5250-usb2-phy", .data = &exynos5250_usb2_phy_config, }, + { + .compatible = "samsung,exynos5433-usb2-phy", + .data = &exynos5433_usb2_phy_config, + }, #endif #ifdef CONFIG_PHY_S5PV210_USB2 { diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h index 44bead9b8f34..bc78dd895bb4 100644 --- a/drivers/phy/phy-samsung-usb2.h +++ b/drivers/phy/phy-samsung-usb2.h @@ -67,5 +67,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 exynos5433_usb2_phy_config; extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config; #endif |