From eddf3808185f64b7474d0a85c903f599e613e673 Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Tue, 2 Jul 2013 16:14:44 +0200 Subject: [PATCH] usb: ehci-s5p: Add support for HSIC to the Exynos 4x12 SoC family Add support for HSIC to the Exynos 4x12 SoC family. Signed-off-by: Kamil Debski Signed-off-by: Kyungmin Park --- drivers/usb/phy/phy-samsung-usb.h | 16 +++++++++++++- drivers/usb/phy/phy-samsung-usb2.c | 44 ++++++++++++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h index 585d12f..3614a0f 100644 --- a/drivers/usb/phy/phy-samsung-usb.h +++ b/drivers/usb/phy/phy-samsung-usb.h @@ -28,6 +28,11 @@ #define PHYPWR_FORCE_SUSPEND (0x1 << 1) /* For Exynos4 */ #define PHYPWR_NORMAL_MASK_PHY0 (0x39 << 0) +#define PHYPWR_NORMAL_MASK_PHY1 (0x7 << 6) +#define PHYPWR_NORMAL_MASK_HSIC0_4210 (0x3 << 9) +#define PHYPWR_NORMAL_MASK_HSIC1_4210 (0x3 << 11) +#define PHYPWR_NORMAL_MASK_HSIC0_4X12 (0x7 << 9) +#define PHYPWR_NORMAL_MASK_HSIC1_4X12 (0x7 << 12) #define PHYPWR_SLEEP_PHY0 (0x1 << 5) #define SAMSUNG_PHYCLK (0x04) @@ -46,6 +51,13 @@ #define RSTCON_PHYLINK_SWRST (0x1 << 2) #define RSTCON_HLINK_SWRST (0x1 << 1) #define RSTCON_SWRST (0x1 << 0) +/* This following values will also reset some fields marked as "reserved" + The question is... was it intentional? */ +#define RSTCON_SWRST_HOST_4X12 (0xff << 3) +#define RSTCON_SWRST_HOST_4210 (0x7f << 3) + +#define EXYNOS4_PHY1CON (0x34) +#define PHY1CON_FPENABLEN (0x1 << 0) /* EXYNOS5 */ #define EXYNOS5_PHY_HOST_CTRL0 (0x00) @@ -233,7 +245,9 @@ #define KHZ (1000) #endif -#define EXYNOS_USBHOST_PHY_CTRL_OFFSET (0x4) +#define EXYNOS5_USBHOST_PHY_CTRL_OFFSET (0x4) +#define EXYNOS4x12_HSIC1_PHY_CTRL_OFFSET (0x4) +#define EXYNOS4x12_HSIC2_PHY_CTRL_OFFSET (0x8) #define S3C64XX_USBPHY_ENABLE (0x1 << 16) #define EXYNOS_USBPHY_ENABLE (0x1 << 0) #define EXYNOS_USB20PHY_CFG_HOST_LINK (0x1 << 0) diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c index 03180c0..cebf34b 100644 --- a/drivers/usb/phy/phy-samsung-usb2.c +++ b/drivers/usb/phy/phy-samsung-usb2.c @@ -68,6 +68,7 @@ static void samsung_exynos5_usb2phy_enable(struct samsung_usbphy *sphy) * the last consumer to disable it. */ + atomic_inc(&sphy->phy_usage); if (exynos5_phyhost_is_on(regs)) { @@ -164,22 +165,41 @@ static void samsung_usb2phy_enable(struct samsung_usbphy *sphy) u32 phypwr; u32 phyclk; u32 rstcon; + u32 rstbits; /* set clock frequency for PLL */ phyclk = sphy->ref_clk_freq; phypwr = readl(regs + SAMSUNG_PHYPWR); rstcon = readl(regs + SAMSUNG_RSTCON); + rstbits = 0; switch (sphy->drv_data->cpu_type) { case TYPE_S3C64XX: phyclk &= ~PHYCLK_COMMON_ON_N; phypwr &= ~PHYPWR_NORMAL_MASK; - rstcon |= RSTCON_SWRST; + rstbits = RSTCON_SWRST; break; case TYPE_EXYNOS4210: - case TYPE_EXYNOS4X12: phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; - rstcon |= RSTCON_SWRST; + rstbits = RSTCON_SWRST; + break; + case TYPE_EXYNOS4X12: + if (sphy->phy_type == USB_PHY_TYPE_HOST) { + phypwr &= ~PHYPWR_NORMAL_MASK_PHY1; + phypwr &= ~PHYPWR_NORMAL_MASK_HSIC0_4X12; + phypwr &= ~PHYPWR_NORMAL_MASK_HSIC1_4X12; + rstbits = RSTCON_SWRST_HOST_4X12; + /* The following register (0x125b0034) is not documented + * for Exynos4412, however it is documented for S5PC210. + * There is means that is should not be used, but hey, + * who knows? */ + writel(PHY1CON_FPENABLEN, regs + EXYNOS4_PHY1CON); + } else { + phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; + rstbits |= RSTCON_SWRST; + } + break; + default: break; } @@ -188,9 +208,11 @@ static void samsung_usb2phy_enable(struct samsung_usbphy *sphy) /* Configure PHY0 for normal operation*/ writel(phypwr, regs + SAMSUNG_PHYPWR); /* reset all ports of PHY and Link */ + /* Keep track of which bits are reset with rstbits. */ + rstcon |= rstbits; writel(rstcon, regs + SAMSUNG_RSTCON); udelay(10); - rstcon &= ~RSTCON_SWRST; + rstcon &= ~rstbits; writel(rstcon, regs + SAMSUNG_RSTCON); } @@ -241,8 +263,17 @@ static void samsung_usb2phy_disable(struct samsung_usbphy *sphy) phypwr |= PHYPWR_NORMAL_MASK; break; case TYPE_EXYNOS4210: - case TYPE_EXYNOS4X12: phypwr |= PHYPWR_NORMAL_MASK_PHY0; + break; + case TYPE_EXYNOS4X12: + if (sphy->phy_type == USB_PHY_TYPE_HOST) { + phypwr |= PHYPWR_NORMAL_MASK_PHY1; + phypwr |= PHYPWR_NORMAL_MASK_HSIC0_4X12; + phypwr |= PHYPWR_NORMAL_MASK_HSIC1_4X12; + } else { + phypwr |= PHYPWR_NORMAL_MASK_PHY0; + } + break; default: break; } @@ -457,6 +488,7 @@ static const struct samsung_usbphy_drvdata usb2phy_exynos4x12 = { .cpu_type = TYPE_EXYNOS4X12, .devphy_en_mask = EXYNOS_USBPHY_ENABLE, .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, + .hostphy_reg_offset = EXYNOS4x12_HSIC1_PHY_CTRL_OFFSET, .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, .set_isolation = samsung_usbphy_set_isolation_4210, .phy_enable = samsung_usb2phy_enable, @@ -466,7 +498,7 @@ static const struct samsung_usbphy_drvdata usb2phy_exynos4x12 = { static struct samsung_usbphy_drvdata usb2phy_exynos5 = { .cpu_type = TYPE_EXYNOS5250, .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, - .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET, + .hostphy_reg_offset = EXYNOS5_USBHOST_PHY_CTRL_OFFSET, .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, .set_isolation = samsung_usbphy_set_isolation_4210, .phy_enable = samsung_exynos5_usb2phy_enable, -- 2.7.4