summaryrefslogtreecommitdiff
path: root/drivers/phy
diff options
context:
space:
mode:
authorJaewon Kim <jaewon02.kim@samsung.com>2015-04-13 22:30:37 +0900
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-12-14 13:42:52 +0900
commit9037a6614e69b913c8280acb98468078baef9504 (patch)
tree720df4bb627d9795d3dc70f4b03a6758cfe61792 /drivers/phy
parentf89e69cf4bb93367d32880e2300edfc65b57ea5a (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.c134
-rw-r--r--drivers/phy/phy-samsung-usb2.c4
-rw-r--r--drivers/phy/phy-samsung-usb2.h1
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