Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751189Ab2HGEgK (ORCPT ); Tue, 7 Aug 2012 00:36:10 -0400 Received: from mail-qa0-f53.google.com ([209.85.216.53]:62585 "EHLO mail-qa0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750858Ab2HGEgI (ORCPT ); Tue, 7 Aug 2012 00:36:08 -0400 MIME-Version: 1.0 In-Reply-To: <1344261462-14183-3-git-send-email-dongjin.kim@agreeyamobility.net> References: <1344261462-14183-1-git-send-email-dongjin.kim@agreeyamobility.net> <1344261462-14183-3-git-send-email-dongjin.kim@agreeyamobility.net> Date: Tue, 7 Aug 2012 13:36:07 +0900 X-Google-Sender-Auth: GoJMKDPznHRMETp3RWHzpKjWg6A Message-ID: Subject: Re: [PATCH] ARM: EXYNOS: Add USB HSIC device From: Kyungmin Park To: Dongjin Kim Cc: Tomasz Stanislawski , Kukjin Kim , Russell King , Sachin Kamat , Greg Kroah-Hartman , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Felipe Balbi , linux-samsung-soc@vger.kernel.org, Alan Stern , Hauke Mehrtens , Neil Zhang , Jongpill Lee , linux-arm-kernel@lists.infradead.org, Dongjin Kim Content-Type: text/plain; charset=ISO-8859-1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 26130 Lines: 815 Hi, Now another person try to use drivers/usb/phy for it. "usb: phy: samsung: Introducing usb phy driver for hsotg" Can you use it instead of previous one? Thank you, Kyungmin Park On 8/6/12, Dongjin Kim wrote: > This patch support to control USB HSIC of EXYNOS4, > edited based on Samsung's GT-i9100 ICS Opensource Update7. > > Change-Id: Ifba33c6a5166abf3644794eee6abe528bd71f521 > Signed-off-by: Dongjin Kim > --- > arch/arm/mach-exynos/common.c | 5 + > arch/arm/mach-exynos/include/mach/regs-pmu.h | 12 + > arch/arm/mach-exynos/include/mach/regs-usb-phy.h | 97 +++++ > arch/arm/mach-exynos/setup-usb-phy.c | 493 > ++++++++++++++++------ > drivers/usb/host/Kconfig | 14 + > 5 files changed, 501 insertions(+), 120 deletions(-) > > diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c > index 4eb39cd..94d58af 100644 > --- a/arch/arm/mach-exynos/common.c > +++ b/arch/arm/mach-exynos/common.c > @@ -179,6 +179,11 @@ static struct map_desc exynos4_iodesc[] __initdata = { > .length = SZ_4K, > .type = MT_DEVICE, > }, { > + .virtual = (unsigned long)S5P_VA_GPIO2, > + .pfn = __phys_to_pfn(EXYNOS4_PA_GPIO2), > + .length = SZ_4K, > + .type = MT_DEVICE, > + }, { > .virtual = (unsigned long)S5P_VA_DMC0, > .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0), > .length = SZ_64K, > diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h > b/arch/arm/mach-exynos/include/mach/regs-pmu.h > index 0bb21e2..d98c2fe 100644 > --- a/arch/arm/mach-exynos/include/mach/regs-pmu.h > +++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h > @@ -185,6 +185,15 @@ > #define S5P_PMU_LCD1_CONF S5P_PMUREG(0x3CA0) > > /* Only for EXYNOS4x12 */ > +#define S5P_USB_PHY_CONTROL S5P_PMUREG(0x0704) > +#define S5P_USB_PHY_ENABLE (0x1 << 0) > + > +#define S5P_HSIC_1_PHY_CONTROL S5P_PMUREG(0x0708) > +#define S5P_HSIC_1_PHY_ENABLE (0x1 << 0) > + > +#define S5P_HSIC_2_PHY_CONTROL S5P_PMUREG(0x070C) > +#define S5P_HSIC_2_PHY_ENABLE (0x1 << 0) > + > #define S5P_ISP_ARM_LOWPWR S5P_PMUREG(0x1050) > #define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR S5P_PMUREG(0x1054) > #define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR S5P_PMUREG(0x1058) > @@ -242,6 +251,9 @@ > > #define EXYNOS5_SYS_WDTRESET (1 << 20) > > +#define EXYNOS5_USBDEV_PHY_CONTROL S5P_PMUREG(0x0704) > +#define EXYNOS5_USBHOST_PHY_CONTROL S5P_PMUREG(0x0708) > + > #define EXYNOS5_ARM_CORE0_SYS_PWR_REG S5P_PMUREG(0x1000) > #define EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG S5P_PMUREG(0x1004) > #define EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG S5P_PMUREG(0x1008) > diff --git a/arch/arm/mach-exynos/include/mach/regs-usb-phy.h > b/arch/arm/mach-exynos/include/mach/regs-usb-phy.h > index 0727773..79021a0 100644 > --- a/arch/arm/mach-exynos/include/mach/regs-usb-phy.h > +++ b/arch/arm/mach-exynos/include/mach/regs-usb-phy.h > @@ -43,6 +43,43 @@ > #define EXYNOS4210_CLKSEL_12M (0x2 << 0) > #define EXYNOS4210_CLKSEL_24M (0x3 << 0) > > +#define EXYNOS4210_HSIC1_NORMAL_MASK (0x3 << 11) > +#define EXYNOS4210_HSIC1_SLEEP (1 << 12) > +#define EXYNOS4210_HSIC1_FORCE_SUSPEND (1 << 11) > +#define EXYNOS4210_HSIC0_NORMAL_MASK (0x3 << 9) > +#define EXYNOS4210_HSIC0_SLEEP (1 << 10) > +#define EXYNOS4210_HSIC0_FORCE_SUSPEND (1 << 9) > + > +#define EXYNOS4210_HOST_LINK_PORT_SWRST_MASK (0xf << 6) > +#define EXYNOS4210_HOST_LINK_PORT2_SWRST (1 << 9) > +#define EXYNOS4210_HOST_LINK_PORT1_SWRST (1 << 8) > +#define EXYNOS4210_HOST_LINK_PORT0_SWRST (1 << 7) > +#define EXYNOS4210_HOST_LINK_ALL_SWRST (1 << 6) > +#define EXYNOS4210_PHY1_SWRST_MASK (0x7 << 3) > +#define EXYNOS4210_PHY1_HSIC_SWRST (1 << 5) > +#define EXYNOS4210_PHY1_STD_SWRST (1 << 4) > +#define EXYNOS4210_PHY1_ALL_SWRST (1 << 3) > + > +#define EXYNOS4X12_HSIC1_NORMAL_MASK (0x7 << 12) > +#define EXYNOS4X12_HSIC1_SLEEP (1 << 14) > +#define EXYNOS4X12_HSIC1_ANALOG_POWERDOWN (1 << 13) > +#define EXYNOS4X12_HSIC1_FORCE_SUSPEND (1 << 12) > +#define EXYNOS4X12_HSIC0_NORMAL_MASK (0x7 << 9) > +#define EXYNOS4X12_HSIC0_SLEEP (1 << 11) > +#define EXYNOS4X12_HSIC0_ANALOG_POWERDOWN (1 << 10) > +#define EXYNOS4X12_HSIC0_FORCE_SUSPEND (1 << 9) > + > +#define EXYNOS4X12_HOST_LINK_PORT_SWRST_MASK (0xf << 7) > +#define EXYNOS4X12_HOST_LINK_PORT2_SWRST (1 << 10) > +#define EXYNOS4X12_HOST_LINK_PORT1_SWRST (1 << 9) > +#define EXYNOS4X12_HOST_LINK_PORT0_SWRST (1 << 8) > +#define EXYNOS4X12_HOST_LINK_ALL_SWRST (1 << 7) > +#define EXYNOS4X12_PHY1_SWRST_MASK (0xf << 3) > +#define EXYNOS4X12_PHY1_HSIC1_SWRST (1 << 6) > +#define EXYNOS4X12_PHY1_HSIC0_SWRST (1 << 5) > +#define EXYNOS4X12_PHY1_SWRST (1 << 4) > +#define EXYNOS4X12_HOST_PHY_SWRST (1 << 3) > + > #define EXYNOS4X12_CLKSEL_MASK (0x7 << 0) > #define EXYNOS4X12_CLKSEL_9600K (0x0 << 0) > #define EXYNOS4X12_CLKSEL_10M (0x1 << 0) > @@ -71,4 +108,64 @@ > #define EXYNOS4_PHY1CON EXYNOS4_HSOTG_PHYREG(0x34) > #define FPENABLEN (1 << 0) > > +/* For Exynos5 */ > +#define EXYNOS5_PHY_HOST_CTRL0 EXYNOS4_HSOTG_PHYREG(0x00) > +#define HOST_CTRL0_PHYSWRSTALL (0x1 << 31) > +#define HOST_CTRL0_REFCLKSEL(val) (val << 19) > +#define EXYNOS5_CLKSEL_50M (0x7) > +#define EXYNOS5_CLKSEL_24M (0x5) > +#define EXYNOS5_CLKSEL_20M (0x4) > +#define EXYNOS5_CLKSEL_19200K (0x3) > +#define EXYNOS5_CLKSEL_12M (0x2) > +#define EXYNOS5_CLKSEL_10M (0x1) > +#define EXYNOS5_CLKSEL_9600K (0x0) > +#define HOST_CTRL0_CLKSEL_SHIFT (16) > +#define HOST_CTRL0_FSEL_MASK (0x7 << 16) > + > +#define HOST_CTRL0_COMMONON_N (0x1 << 9) > +#define HOST_CTRL0_SIDDQ (0x1 << 6) > +#define HOST_CTRL0_FORCESLEEP (0x1 << 5) > +#define HOST_CTRL0_FORCESUSPEND (0x1 << 4) > +#define HOST_CTRL0_WORDINTERFACE (0x1 << 3) > +#define HOST_CTRL0_UTMISWRST (0x1 << 2) > +#define HOST_CTRL0_LINKSWRST (0x1 << 1) > +#define HOST_CTRL0_PHYSWRST (0x1 << 0) > + > +#define EXYNOS5_PHY_HOST_TUNE0 EXYNOS4_HSOTG_PHYREG(0x04) > +#define EXYNOS5_PHY_HOST_TEST0 EXYNOS4_HSOTG_PHYREG(0x08) > + > +#define EXYNOS5_PHY_HSIC_CTRL1 EXYNOS4_HSOTG_PHYREG(0x10) > +#define EXYNOS5_PHY_HSIC_CTRL2 EXYNOS4_HSOTG_PHYREG(0x20) > +#define HSIC_CTRL_REFCLKSEL(val) ((val&0x3) << 23) > +#define HSIC_CTRL_REFCLKDIV(val) ((val&0x7f) << 16) > +#define HSIC_CTRL_SIDDQ (0x1 << 6) > +#define HSIC_CTRL_FORCESLEEP (0x1 << 5) > +#define HSIC_CTRL_FORCESUSPEND (0x1 << 4) > +#define HSIC_CTRL_WORDINTERFACE (0x1 << 3) > +#define HSIC_CTRL_UTMISWRST (0x1 << 2) > +#define HSIC_CTRL_PHYSWRST (0x1 << 0) > + > +#define EXYNOS5_PHY_HOST_EHCICTRL EXYNOS4_HSOTG_PHYREG(0x30) > +#define EHCICTRL_ENAINCRXALIGN (0x1 << 29) > +#define EHCICTRL_ENAINCR4 (0x1 << 28) > +#define EHCICTRL_ENAINCR8 (0x1 << 27) > +#define EHCICTRL_ENAINCR16 (0x1 << 26) > + > +#define EXYNOS5_PHY_HOST_OHCICTRL EXYNOS4_HSOTG_PHYREG(0x34) > + > +#define EXYNOS5_PHY_OTG_SYS EXYNOS4_HSOTG_PHYREG(0x38) > +#define OTG_SYS_PHYLINK_SW_RESET (0x1 << 14) > +#define OTG_SYS_LINK_SW_RST_UOTG (0x1 << 13) > +#define OTG_SYS_PHY0_SW_RST (0x1 << 12) > +#define OTG_SYS_REF_CLK_SEL(val) ((val&0x3) << 9) > +#define OTG_SYS_REF_CLK_SEL_MASK (0x3 << 9) > +#define OTG_SYS_IP_PULLUP_UOTG (0x1 << 8) > +#define OTG_SYS_COMMON_ON (0x1 << 7) > +#define OTG_SYS_CLKSEL_SHIFT (4) > +#define OTG_SYS_CTRL0_FSEL_MASK (0x7 << 4) > +#define OTG_SYS_FORCE_SLEEP (0x1 << 3) > +#define OTG_SYS_OTGDISABLE (0x1 << 2) > +#define OTG_SYS_SIDDQ_UOTG (0x1 << 1) > +#define OTG_SYS_FORCE_SUSPEND (0x1 << 0) > + > #endif /* __PLAT_S5P_REGS_USB_PHY_H */ > diff --git a/arch/arm/mach-exynos/setup-usb-phy.c > b/arch/arm/mach-exynos/setup-usb-phy.c > index b81cc56..c725745 100644 > --- a/arch/arm/mach-exynos/setup-usb-phy.c > +++ b/arch/arm/mach-exynos/setup-usb-phy.c > @@ -1,5 +1,6 @@ > /* > * Copyright (C) 2011 Samsung Electronics Co.Ltd > + * Author: Yulgon Kim > * Author: Joonyoung Shim > * > * This program is free software; you can redistribute it and/or modify > it > @@ -19,205 +20,457 @@ > #include > #include > > +#define ETC6PUD (S5P_VA_GPIO2 + 0x228) > +#define EXYNOS4_USB_CFG (S3C_VA_SYS + 0x21C) > + > +#define PHY_ENABLE (1 << 0) > +#define PHY_DISABLE (0) > + > +enum usb_host_type { > + HOST_PHY_EHCI = (0x1 << 0), > + HOST_PHY_OHCI = (0x1 << 1), > +}; > + > +enum usb_phy_type { > + USB_PHY = (0x1 << 0), > + USB_PHY0 = (0x1 << 0), > + USB_PHY1 = (0x1 << 1), > + USB_PHY_HSIC0 = (0x1 << 1), > + USB_PHY_HSIC1 = (0x1 << 2), > +}; > + > static atomic_t host_usage; > +static DEFINE_MUTEX(phy_lock); > +static struct clk *phy_clk; > > static int exynos4_usb_host_phy_is_on(void) > { > return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1; > } > > -static void exynos4210_usb_phy_clkset(struct platform_device *pdev) > +static int exynos4_usb_phy20_is_on(void) > { > - struct clk *xusbxti_clk; > - u32 phyclk; > + return exynos4_usb_host_phy_is_on(); > +} > + > +static int exynos_usb_phy_clock_enable(struct platform_device *pdev) > +{ > + int err; > + > + if (!phy_clk) { > + if (soc_is_exynos4210() || > + soc_is_exynos4212() || soc_is_exynos4412()) > + phy_clk = clk_get(&pdev->dev, "otg"); > + else > + phy_clk = clk_get(&pdev->dev, "usbhost"); > + > + if (IS_ERR(phy_clk)) { > + dev_err(&pdev->dev, "Failed to get phy clock\n"); > + return PTR_ERR(phy_clk); > + } > + } > + > + err = clk_enable(phy_clk); > + > + return err; > +} > > - xusbxti_clk = clk_get(&pdev->dev, "xusbxti"); > - if (xusbxti_clk && !IS_ERR(xusbxti_clk)) { > - if (soc_is_exynos4210()) { > - /* set clock frequency for PLL */ > - phyclk = readl(EXYNOS4_PHYCLK) & ~EXYNOS4210_CLKSEL_MASK; > - > - switch (clk_get_rate(xusbxti_clk)) { > - case 12 * MHZ: > - phyclk |= EXYNOS4210_CLKSEL_12M; > - break; > - case 48 * MHZ: > - phyclk |= EXYNOS4210_CLKSEL_48M; > - break; > - default: > - case 24 * MHZ: > - phyclk |= EXYNOS4210_CLKSEL_24M; > - break; > - } > - writel(phyclk, EXYNOS4_PHYCLK); > - } else if (soc_is_exynos4212() || soc_is_exynos4412()) { > - /* set clock frequency for PLL */ > - phyclk = readl(EXYNOS4_PHYCLK) & ~EXYNOS4X12_CLKSEL_MASK; > - > - switch (clk_get_rate(xusbxti_clk)) { > - case 9600 * KHZ: > - phyclk |= EXYNOS4X12_CLKSEL_9600K; > - break; > - case 10 * MHZ: > - phyclk |= EXYNOS4X12_CLKSEL_10M; > - break; > - case 12 * MHZ: > - phyclk |= EXYNOS4X12_CLKSEL_12M; > - break; > - case 19200 * KHZ: > - phyclk |= EXYNOS4X12_CLKSEL_19200K; > - break; > - case 20 * MHZ: > - phyclk |= EXYNOS4X12_CLKSEL_20M; > - break; > - default: > - case 24 * MHZ: > - /* default reference clock */ > - phyclk |= EXYNOS4X12_CLKSEL_24M; > - break; > - } > - writel(phyclk, EXYNOS4_PHYCLK); > +static int exynos_usb_phy_clock_disable(struct platform_device *pdev) > +{ > + if (!phy_clk) { > + if (soc_is_exynos4210() || > + soc_is_exynos4212() || soc_is_exynos4412()) > + phy_clk = clk_get(&pdev->dev, "otg"); > + else > + phy_clk = clk_get(&pdev->dev, "usbhost"); > + if (IS_ERR(phy_clk)) { > + dev_err(&pdev->dev, "Failed to get phy clock\n"); > + return PTR_ERR(phy_clk); > } > - clk_put(xusbxti_clk); > } > + > + clk_disable(phy_clk); > + > + return 0; > } > > -static int exynos4210_usb_phy0_init(struct platform_device *pdev) > +static u32 exynos_usb_phy_set_clock(struct platform_device *pdev) > { > + struct clk *ref_clk; > + u32 refclk_freq = 0; > + > + if (soc_is_exynos4210() || soc_is_exynos4212() || soc_is_exynos4412()) > + ref_clk = clk_get(&pdev->dev, "xusbxti"); > + else > + ref_clk = clk_get(&pdev->dev, "ext_xtal"); > + > + if (IS_ERR(ref_clk)) { > + dev_err(&pdev->dev, "Failed to get reference clock\n"); > + return PTR_ERR(ref_clk); > + } > + > + if (soc_is_exynos4210()) { > + switch (clk_get_rate(ref_clk)) { > + case 12 * MHZ: > + refclk_freq = EXYNOS4210_CLKSEL_12M; > + break; > + case 48 * MHZ: > + refclk_freq = EXYNOS4210_CLKSEL_48M; > + break; > + case 24 * MHZ: > + default: > + /* default reference clock */ > + refclk_freq = EXYNOS4210_CLKSEL_24M; > + break; > + } > + } else if (soc_is_exynos4212() | soc_is_exynos4412()) { > + switch (clk_get_rate(ref_clk)) { > + case 96 * 100000: > + refclk_freq = EXYNOS4X12_CLKSEL_9600K; > + break; > + case 10 * MHZ: > + refclk_freq = EXYNOS4X12_CLKSEL_10M; > + break; > + case 12 * MHZ: > + refclk_freq = EXYNOS4X12_CLKSEL_12M; > + break; > + case 192 * 100000: > + refclk_freq = EXYNOS4X12_CLKSEL_19200K; > + break; > + case 20 * MHZ: > + refclk_freq = EXYNOS4X12_CLKSEL_20M; > + break; > + case 24 * MHZ: > + default: > + /* default reference clock */ > + refclk_freq = EXYNOS4X12_CLKSEL_24M; > + break; > + } > + } else { > + switch (clk_get_rate(ref_clk)) { > + case 96 * 100000: > + refclk_freq = EXYNOS5_CLKSEL_9600K; > + break; > + case 10 * MHZ: > + refclk_freq = EXYNOS5_CLKSEL_10M; > + break; > + case 12 * MHZ: > + refclk_freq = EXYNOS5_CLKSEL_12M; > + break; > + case 192 * 100000: > + refclk_freq = EXYNOS5_CLKSEL_19200K; > + break; > + case 20 * MHZ: > + refclk_freq = EXYNOS5_CLKSEL_20M; > + break; > + case 50 * MHZ: > + refclk_freq = EXYNOS5_CLKSEL_50M; > + break; > + case 24 * MHZ: > + default: > + /* default reference clock */ > + refclk_freq = EXYNOS5_CLKSEL_24M; > + break; > + } > + } > + clk_put(ref_clk); > + > + return refclk_freq; > +} > + > +static void exynos_usb_phy_control(enum usb_phy_type phy_type , int on) > +{ > + if (soc_is_exynos4210()) { > + if (phy_type & USB_PHY0) > + writel(on, S5P_USBDEVICE_PHY_CONTROL); > + if (phy_type & USB_PHY1) > + writel(on, S5P_USBHOST_PHY_CONTROL); > + } else if (soc_is_exynos4212() | soc_is_exynos4412()) { > + if (phy_type & USB_PHY) > + writel(on, S5P_USB_PHY_CONTROL); > +#ifdef CONFIG_USB_S5P_HSIC0 > + if (phy_type & USB_PHY_HSIC0) > + writel(on, S5P_HSIC_1_PHY_CONTROL); > +#endif > +#ifdef CONFIG_USB_S5P_HSIC1 > + if (phy_type & USB_PHY_HSIC1) > + writel(on, S5P_HSIC_2_PHY_CONTROL); > +#endif > + } else { > + if (phy_type & USB_PHY0) > + writel(on, EXYNOS5_USBDEV_PHY_CONTROL); > + if (phy_type & USB_PHY1) > + writel(on, EXYNOS5_USBHOST_PHY_CONTROL); > + } > +} > + > +static int exynos4_usb_phy0_init(struct platform_device *pdev) > +{ > + u32 phypwr; > + u32 phyclk; > u32 rstcon; > > - writel(readl(S5P_USBDEVICE_PHY_CONTROL) | S5P_USBDEVICE_PHY_ENABLE, > - S5P_USBDEVICE_PHY_CONTROL); > + exynos_usb_phy_control(USB_PHY0, PHY_ENABLE); > > - exynos4210_usb_phy_clkset(pdev); > + /* set clock frequency for PLL */ > + phyclk = exynos_usb_phy_set_clock(pdev); > + phyclk &= ~(PHY0_COMMON_ON_N); > + writel(phyclk, EXYNOS4_PHYCLK); > > - /* set to normal PHY0 */ > - writel((readl(EXYNOS4_PHYPWR) & ~PHY0_NORMAL_MASK), EXYNOS4_PHYPWR); > + /* set to normal of PHY0 */ > + phypwr = readl(EXYNOS4_PHYPWR) & ~PHY0_NORMAL_MASK; > + writel(phypwr, EXYNOS4_PHYPWR); > > - /* reset PHY0 and Link */ > + /* reset all ports of both PHY and Link */ > rstcon = readl(EXYNOS4_RSTCON) | PHY0_SWRST_MASK; > writel(rstcon, EXYNOS4_RSTCON); > udelay(10); > - > rstcon &= ~PHY0_SWRST_MASK; > writel(rstcon, EXYNOS4_RSTCON); > > return 0; > } > > -static int exynos4210_usb_phy0_exit(struct platform_device *pdev) > +static int exynos4_usb_phy0_exit(struct platform_device *pdev) > { > - writel((readl(EXYNOS4_PHYPWR) | PHY0_ANALOG_POWERDOWN | > - PHY0_OTG_DISABLE), EXYNOS4_PHYPWR); > + /* unset to normal of PHY0 */ > + writel((readl(EXYNOS4_PHYPWR) | PHY0_NORMAL_MASK), > + EXYNOS4_PHYPWR); > > - writel(readl(S5P_USBDEVICE_PHY_CONTROL) & ~S5P_USBDEVICE_PHY_ENABLE, > - S5P_USBDEVICE_PHY_CONTROL); > + exynos_usb_phy_control(USB_PHY0, PHY_DISABLE); > > return 0; > } > > -static int exynos4210_usb_phy1_init(struct platform_device *pdev) > +static int exynos4_usb_phy1_init(struct platform_device *pdev) > { > - struct clk *otg_clk; > + u32 phypwr; > + u32 phyclk; > u32 rstcon; > - int err; > > atomic_inc(&host_usage); > > - otg_clk = clk_get(&pdev->dev, "otg"); > - if (IS_ERR(otg_clk)) { > - dev_err(&pdev->dev, "Failed to get otg clock\n"); > - return PTR_ERR(otg_clk); > + if (exynos4_usb_host_phy_is_on()) { > + dev_err(&pdev->dev, "Already power on PHY\n"); > + return 0; > } > > - err = clk_enable(otg_clk); > - if (err) { > - clk_put(otg_clk); > - return err; > - } > + /* > + * set XuhostOVERCUR to in-active by controlling ET6PUD[15:14] > + * 0x0 : pull-up/down disabled > + * 0x1 : pull-down enabled > + * 0x2 : reserved > + * 0x3 : pull-up enabled > + */ > + writel((__raw_readl(ETC6PUD) & ~(0x3 << 14)) | (0x3 << 14), > + ETC6PUD); > > - if (exynos4_usb_host_phy_is_on()) > - return 0; > + exynos_usb_phy_control(USB_PHY1, PHY_ENABLE); > > - writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE, > - S5P_USBHOST_PHY_CONTROL); > + /* set clock frequency for PLL */ > + phyclk = exynos_usb_phy_set_clock(pdev); > + phyclk &= ~(PHY1_COMMON_ON_N); > + writel(phyclk, EXYNOS4_PHYCLK); > > - exynos4210_usb_phy_clkset(pdev); > + /* set to normal HSIC 0 and 1 of PHY1 */ > + phypwr = readl(EXYNOS4_PHYPWR); > + phypwr &= ~(PHY1_STD_NORMAL_MASK > + | EXYNOS4210_HSIC0_NORMAL_MASK); > + writel(phypwr, EXYNOS4_PHYPWR); > > /* floating prevention logic: disable */ > writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON); > > - /* set to normal HSIC 0 and 1 of PHY1 */ > - writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK), > - EXYNOS4_PHYPWR); > - > - /* set to normal standard USB of PHY1 */ > - writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR); > - > /* reset all ports of both PHY and Link */ > - rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK | > - PHY1_SWRST_MASK; > + rstcon = readl(EXYNOS4_RSTCON) > + | EXYNOS4210_HOST_LINK_PORT_SWRST_MASK > + | EXYNOS4210_PHY1_SWRST_MASK; > writel(rstcon, EXYNOS4_RSTCON); > udelay(10); > > - rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK); > + rstcon &= ~(EXYNOS4210_HOST_LINK_PORT_SWRST_MASK > + | EXYNOS4210_PHY1_SWRST_MASK); > writel(rstcon, EXYNOS4_RSTCON); > udelay(80); > > - clk_disable(otg_clk); > - clk_put(otg_clk); > + return 0; > +} > + > +static int exynos4_usb_phy1_exit(struct platform_device *pdev) > +{ > + u32 phypwr; > + > + if (atomic_dec_return(&host_usage) > 0) { > + dev_info(&pdev->dev, "still being used\n"); > + return -EBUSY; > + } > + > + phypwr = readl(EXYNOS4_PHYPWR) > + | PHY1_STD_NORMAL_MASK > + | EXYNOS4210_HSIC0_NORMAL_MASK; > + writel(phypwr, EXYNOS4_PHYPWR); > + > + exynos_usb_phy_control(USB_PHY1, PHY_DISABLE); > > return 0; > } > > -static int exynos4210_usb_phy1_exit(struct platform_device *pdev) > +static int exynos4_usb_phy20_init(struct platform_device *pdev) > { > - struct clk *otg_clk; > - int err; > + u32 phypwr, phyclk, rstcon; > > - if (atomic_dec_return(&host_usage) > 0) > - return 0; > + atomic_inc(&host_usage); > > - otg_clk = clk_get(&pdev->dev, "otg"); > - if (IS_ERR(otg_clk)) { > - dev_err(&pdev->dev, "Failed to get otg clock\n"); > - return PTR_ERR(otg_clk); > + if (exynos4_usb_phy20_is_on()) { > + dev_err(&pdev->dev, "Already power on PHY\n"); > + return 0; > } > > - err = clk_enable(otg_clk); > - if (err) { > - clk_put(otg_clk); > - return err; > + /* > + * set XuhostOVERCUR to in-active by controlling ET6PUD[15:14] > + * 0x0 : pull-up/down disabled > + * 0x1 : pull-down enabled > + * 0x2 : reserved > + * 0x3 : pull-up enabled > + */ > + writel((__raw_readl(ETC6PUD) & ~(0x3 << 14)) | (0x3 << 14), > + ETC6PUD); > + > + exynos_usb_phy_control(USB_PHY > + | USB_PHY_HSIC0, > + PHY_ENABLE); > + > + /* set clock frequency for PLL */ > + phyclk = exynos_usb_phy_set_clock(pdev); > + /* COMMON Block configuration during suspend */ > + phyclk &= ~(PHY0_COMMON_ON_N | PHY1_COMMON_ON_N); > + writel(phyclk, EXYNOS4_PHYCLK); > + > + /* set to normal of Device */ > + phypwr = readl(EXYNOS4_PHYPWR) & ~PHY0_NORMAL_MASK; > + writel(phypwr, EXYNOS4_PHYPWR); > + > + /* set to normal of Host */ > + phypwr = readl(EXYNOS4_PHYPWR); > + phypwr &= ~(PHY1_STD_NORMAL_MASK > + | EXYNOS4X12_HSIC0_NORMAL_MASK); > + writel(phypwr, EXYNOS4_PHYPWR); > + > + /* reset both PHY and Link of Device */ > + rstcon = readl(EXYNOS4_RSTCON) | PHY0_SWRST_MASK; > + writel(rstcon, EXYNOS4_RSTCON); > + udelay(10); > + rstcon &= ~PHY0_SWRST_MASK; > + writel(rstcon, EXYNOS4_RSTCON); > + > + /* reset both PHY and Link of Host */ > + rstcon = readl(EXYNOS4_RSTCON) > + | EXYNOS4X12_HOST_LINK_PORT_SWRST_MASK > + | EXYNOS4X12_PHY1_SWRST_MASK; > + writel(rstcon, EXYNOS4_RSTCON); > + udelay(10); > + > + rstcon &= ~(EXYNOS4X12_HOST_LINK_PORT_SWRST_MASK > + | EXYNOS4X12_PHY1_SWRST_MASK); > + writel(rstcon, EXYNOS4_RSTCON); > + udelay(80); > + > + return 0; > +} > + > +static int exynos4_usb_phy20_exit(struct platform_device *pdev) > +{ > + u32 phypwr; > + > + if (atomic_dec_return(&host_usage) > 0) { > + dev_info(&pdev->dev, "still being used\n"); > + return -EBUSY; > } > > - writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN), > + /* unset to normal of Device */ > + writel((readl(EXYNOS4_PHYPWR) | PHY0_NORMAL_MASK), > EXYNOS4_PHYPWR); > > - writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE, > - S5P_USBHOST_PHY_CONTROL); > + /* unset to normal of Host */ > + phypwr = readl(EXYNOS4_PHYPWR) > + | PHY1_STD_NORMAL_MASK > + | EXYNOS4X12_HSIC0_NORMAL_MASK; > + writel(phypwr, EXYNOS4_PHYPWR); > > - clk_disable(otg_clk); > - clk_put(otg_clk); > + exynos_usb_phy_control(USB_PHY > + | USB_PHY_HSIC0, > + PHY_DISABLE); > + > + return 0; > +} > + > +static int exynos_usb_dev_phy20_init(struct platform_device *pdev) > +{ > + if (soc_is_exynos4212() || soc_is_exynos4412()) > + exynos4_usb_phy20_init(pdev); > + > + writel(0, EXYNOS4_USB_CFG); > + > + return 0; > +} > + > +static int exynos_usb_dev_phy20_exit(struct platform_device *pdev) > +{ > + if (soc_is_exynos4212() || soc_is_exynos4412()) > + exynos4_usb_phy20_exit(pdev); > > return 0; > } > > int s5p_usb_phy_init(struct platform_device *pdev, int type) > { > - if (type == S5P_USB_PHY_DEVICE) > - return exynos4210_usb_phy0_init(pdev); > - else if (type == S5P_USB_PHY_HOST) > - return exynos4210_usb_phy1_init(pdev); > + int ret = -EINVAL; > + > + if (exynos_usb_phy_clock_enable(pdev)) > + return ret; > + > + mutex_lock(&phy_lock); > + if (type == S5P_USB_PHY_HOST) { > + if (soc_is_exynos4210()) > + ret = exynos4_usb_phy1_init(pdev); > + else if (soc_is_exynos4212() || soc_is_exynos4412()) > + ret = exynos4_usb_phy20_init(pdev); > + } else if (type == S5P_USB_PHY_DEVICE) { > + if (soc_is_exynos4210()) > + ret = exynos4_usb_phy0_init(pdev); > + else > + ret = exynos_usb_dev_phy20_init(pdev); > + } > + > + mutex_unlock(&phy_lock); > + exynos_usb_phy_clock_disable(pdev); > > - return -EINVAL; > + return ret; > } > > int s5p_usb_phy_exit(struct platform_device *pdev, int type) > { > - if (type == S5P_USB_PHY_DEVICE) > - return exynos4210_usb_phy0_exit(pdev); > - else if (type == S5P_USB_PHY_HOST) > - return exynos4210_usb_phy1_exit(pdev); > + int ret = -EINVAL; > + > + if (exynos_usb_phy_clock_enable(pdev)) > + return ret; > + > + mutex_lock(&phy_lock); > + > + if (type == S5P_USB_PHY_HOST) { > + if (soc_is_exynos4210()) > + ret = exynos4_usb_phy1_exit(pdev); > + else if (soc_is_exynos4212() || soc_is_exynos4412()) > + ret = exynos4_usb_phy20_exit(pdev); > + } else if (type == S5P_USB_PHY_DEVICE) { > + if (soc_is_exynos4210()) > + ret = exynos4_usb_phy0_exit(pdev); > + else > + ret = exynos_usb_dev_phy20_exit(pdev); > + } > + > + mutex_unlock(&phy_lock); > + exynos_usb_phy_clock_disable(pdev); > > - return -EINVAL; > + return ret; > } > diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig > index 075d2ec..5f69041 100644 > --- a/drivers/usb/host/Kconfig > +++ b/drivers/usb/host/Kconfig > @@ -199,6 +199,20 @@ config USB_EHCI_S5P > help > Enable support for the S5P SOC's on-chip EHCI controller. > > +config USB_S5P_HSIC0 > + boolean "S5P HSIC0 support" > + depends on USB_EHCI_HCD && PLAT_S5P && USB_EHCI_S5P > + default n > + help > + Enable support for the S5P SOC's on-chip HSIC PHY. > + > +config USB_S5P_HSIC1 > + boolean "S5P HSIC1 support" > + depends on USB_EHCI_HCD && PLAT_S5P && USB_EHCI_S5P > + default n > + help > + Enable support for the S5P SOC's on-chip HSIC PHY. > + > config USB_EHCI_MV > bool "EHCI support for Marvell on-chip controller" > depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP) > -- > 1.7.9.5 > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/