lkml.org 
[lkml]   [2013]   [Feb]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
SubjectRe: [PATCH] usb: phy: Add USB host phy support on Exyno4412
From
Hi,

Can split patch into two parts?
One for USB tree, another for samsung tree.

Thank you,
Kyungmin Park

On Tue, Feb 5, 2013 at 9:37 AM, Dongjin Kim <tobetter@gmail.com> wrote:
> This patch adds host phy support for Samsung's Exynos4412 SoC to
> samsung-usbphy driver and its device node.
>
> Cc: Praveen Paneri <p.paneri@samsung.com>
> Signed-off-by: Dongjin Kim <tobetter@gmail.com>
> ---
> arch/arm/boot/dts/exynos4412.dtsi | 13 ++++
> drivers/usb/phy/samsung-usbphy.c | 156 ++++++++++++++++++++++++++++++++++++-
> 2 files changed, 167 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
> index 387aa27..c01d841 100644
> --- a/arch/arm/boot/dts/exynos4412.dtsi
> +++ b/arch/arm/boot/dts/exynos4412.dtsi
> @@ -33,4 +33,17 @@
> #address-cells = <1>;
> #size-cells = <0>;
> };
> +
> + usbphy@125B0000 {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + compatible = "samsung,exynos4412-usbphy";
> + reg = <0x125B0000 0x100>;
> + status = "disabled";
> + ranges;
> +
> + usbphy-sys {
> + reg = <0x10020704 0xc>;
> + };
> + };
> };
> diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
> index 6ea5537..c800fa4 100644
> --- a/drivers/usb/phy/samsung-usbphy.c
> +++ b/drivers/usb/phy/samsung-usbphy.c
> @@ -47,7 +47,7 @@
>
> #define PHYCLK_MODE_USB11 (0x1 << 6)
> #define PHYCLK_EXT_OSC (0x1 << 5)
> -#define PHYCLK_COMMON_ON_N (0x1 << 4)
> +#define PHYCLK_COMMON_ON_N_PHY0 (0x1 << 4)
> #define PHYCLK_ID_PULL (0x1 << 2)
> #define PHYCLK_CLKSEL_MASK (0x3 << 0)
> #define PHYCLK_CLKSEL_48M (0x0 << 0)
> @@ -60,6 +60,22 @@
> #define RSTCON_HLINK_SWRST (0x1 << 1)
> #define RSTCON_SWRST (0x1 << 0)
>
> +/* For Exynos4412 */
> +#define PHYCLK_COMMON_ON_N_PHY1 (0x1 << 7)
> +
> +#define PHYPWR_NORMAL_MASK_HSIC1 (0x7 << 12)
> +#define PHYPWR_NORMAL_MASK_HSIC0 (0x7 << 9)
> +#define PHYPWR_NORMAL_MASK_PHY1 (0x7 << 6)
> +
> +#define PHYPWR_ANALOG_POWERDOWN_PHY1 (0x1 << 7)
> +
> +#define RSTCON_HLINK_SWRST_MASK (0xf << 7)
> +#define RSTCON_PHY1_SWRST_MASK (0xf << 3)
> +#define RSTCON_PHY0_SWRST_MASK (0x7 << 0)
> +
> +#define EXYNOS4_PHY_HSIC_CTRL0 (0x04)
> +#define EXYNOS4_PHY_HSIC_CTRL1 (0x08)
> +
> /* EXYNOS5 */
> #define EXYNOS5_PHY_HOST_CTRL0 (0x00)
>
> @@ -174,6 +190,7 @@
> enum samsung_cpu_type {
> TYPE_S3C64XX,
> TYPE_EXYNOS4210,
> + TYPE_EXYNOS4412,
> TYPE_EXYNOS5250,
> };
>
> @@ -322,6 +339,17 @@ static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
> en_mask = sphy->drv_data->hostphy_en_mask;
> }
> break;
> + case TYPE_EXYNOS4412:
> + if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
> + reg = sphy->pmuregs +
> + sphy->drv_data->devphy_reg_offset;
> + en_mask = sphy->drv_data->devphy_en_mask;
> + } else if (sphy->phy_type == USB_PHY_TYPE_HOST) {
> + reg = sphy->pmuregs +
> + sphy->drv_data->hostphy_reg_offset;
> + en_mask = sphy->drv_data->hostphy_en_mask;
> + }
> + break;
> default:
> dev_err(sphy->dev, "Invalid SoC type\n");
> return;
> @@ -422,6 +450,29 @@ static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
> refclk_freq = FSEL_CLKSEL_24M;
> break;
> }
> + } else if (sphy->drv_data->cpu_type == TYPE_EXYNOS4412) {
> + switch (clk_get_rate(ref_clk)) {
> + case 9600 * KHZ:
> + refclk_freq = FSEL_CLKSEL_9600K;
> + break;
> + case 10 * MHZ:
> + refclk_freq = FSEL_CLKSEL_10M;
> + break;
> + case 12 * MHZ:
> + refclk_freq = FSEL_CLKSEL_12M;
> + break;
> + case 19200 * KHZ:
> + refclk_freq = FSEL_CLKSEL_19200K;
> + break;
> + case 20 * MHZ:
> + refclk_freq = FSEL_CLKSEL_20M;
> + break;
> + case 24 * MHZ:
> + default:
> + /* default reference clock */
> + refclk_freq = FSEL_CLKSEL_24M;
> + break;
> + }
> } else {
> switch (clk_get_rate(ref_clk)) {
> case 12 * MHZ:
> @@ -561,6 +612,69 @@ static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
> writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
> }
>
> +static bool exynos4_phyhost_is_on(void *regs)
> +{
> + u32 reg;
> +
> + reg = readl(regs + SAMSUNG_PHYPWR);
> +
> + return !(reg & PHYPWR_ANALOG_POWERDOWN_PHY1);
> +}
> +
> +static void samsung_exynos4412_usbphy_enable(struct samsung_usbphy *sphy)
> +{
> + void __iomem *regs = sphy->regs;
> + u32 phypwr;
> + u32 phyclk;
> + u32 rstcon;
> +
> + /*
> + * phy_usage helps in keeping usage count for phy
> + * so that the first consumer enabling the phy is also
> + * the last consumer to disable it.
> + */
> +
> + atomic_inc(&sphy->phy_usage);
> +
> + if (exynos4_phyhost_is_on(regs)) {
> + dev_info(sphy->dev, "Already power on PHY\n");
> + return;
> + }
> +
> + writel(EXYNOS_USBPHY_ENABLE, sphy->pmuregs + EXYNOS4_PHY_HSIC_CTRL0);
> + writel(EXYNOS_USBPHY_ENABLE, sphy->pmuregs + EXYNOS4_PHY_HSIC_CTRL1);
> +
> + /* Common block configuration during suspend */
> + phyclk = sphy->ref_clk_freq
> + & ~(PHYCLK_COMMON_ON_N_PHY0 | PHYCLK_COMMON_ON_N_PHY1);
> + writel(phyclk, regs + SAMSUNG_PHYCLK);
> +
> + /* set to normal of Device */
> + phypwr = readl(regs + SAMSUNG_PHYPWR) & ~PHYPWR_NORMAL_MASK_PHY0;
> + writel(phypwr, regs + SAMSUNG_PHYPWR);
> +
> + /* set to normal of Host */
> + phypwr &= ~(PHYPWR_NORMAL_MASK_HSIC0 | PHYPWR_NORMAL_MASK_HSIC1
> + | PHYPWR_NORMAL_MASK_PHY1);
> + writel(phypwr, regs + SAMSUNG_PHYPWR);
> +
> + /* reset both PHY and Link of Device */
> + rstcon = readl(regs + SAMSUNG_RSTCON) | RSTCON_PHY0_SWRST_MASK;
> + writel(rstcon, regs + SAMSUNG_RSTCON);
> + udelay(10);
> + rstcon &= ~RSTCON_PHY0_SWRST_MASK;
> + writel(rstcon, regs + SAMSUNG_RSTCON);
> +
> + /* reset both PHY and Link of Host */
> + rstcon = readl(regs + SAMSUNG_RSTCON)
> + | (RSTCON_HLINK_SWRST_MASK | RSTCON_PHY1_SWRST_MASK);
> + writel(rstcon, regs + SAMSUNG_RSTCON);
> + udelay(10);
> + rstcon &= ~(RSTCON_HLINK_SWRST_MASK | RSTCON_PHY1_SWRST_MASK);
> + writel(rstcon, regs + SAMSUNG_RSTCON);
> + udelay(80);
> +}
> +
> static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
> {
> void __iomem *regs = sphy->regs;
> @@ -575,7 +689,7 @@ static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
>
> switch (sphy->drv_data->cpu_type) {
> case TYPE_S3C64XX:
> - phyclk &= ~PHYCLK_COMMON_ON_N;
> + phyclk &= ~PHYCLK_COMMON_ON_N_PHY0;
> phypwr &= ~PHYPWR_NORMAL_MASK;
> rstcon |= RSTCON_SWRST;
> break;
> @@ -631,6 +745,28 @@ static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
> writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
> }
>
> +static void samsung_exynos4412_usbphy_disable(struct samsung_usbphy *sphy)
> +{
> + void __iomem *regs = sphy->regs;
> + u32 phypwr;
> +
> + if (atomic_dec_return(&sphy->phy_usage) > 0) {
> + dev_info(sphy->dev, "still being used\n");
> + return;
> + }
> +
> + /* unset to normal of Host and Device */
> + phypwr = readl(regs + SAMSUNG_PHYPWR);
> + phypwr |= (PHYPWR_NORMAL_MASK_HSIC0
> + | PHYPWR_NORMAL_MASK_HSIC1
> + | PHYPWR_NORMAL_MASK_PHY1
> + | PHYPWR_NORMAL_MASK_PHY0);
> + writel(phypwr, regs + SAMSUNG_PHYPWR);
> +
> + writel(0, sphy->pmuregs + EXYNOS4_PHY_HSIC_CTRL0);
> + writel(0, sphy->pmuregs + EXYNOS4_PHY_HSIC_CTRL1);
> +}
> +
> static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
> {
> void __iomem *regs = sphy->regs;
> @@ -696,6 +832,8 @@ static int samsung_usbphy_init(struct usb_phy *phy)
> /* Initialize usb phy registers */
> if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
> samsung_exynos5_usbphy_enable(sphy);
> + else if (sphy->drv_data->cpu_type == TYPE_EXYNOS4412)
> + samsung_exynos4412_usbphy_enable(sphy);
> else
> samsung_usbphy_enable(sphy);
>
> @@ -739,6 +877,8 @@ static void samsung_usbphy_shutdown(struct usb_phy *phy)
> /* De-initialize usb phy registers */
> if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
> samsung_exynos5_usbphy_disable(sphy);
> + else if (sphy->drv_data->cpu_type == TYPE_EXYNOS4412)
> + samsung_exynos4412_usbphy_disable(sphy);
> else
> samsung_usbphy_disable(sphy);
>
> @@ -872,6 +1012,12 @@ static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
> .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
> };
>
> +static const struct samsung_usbphy_drvdata usbphy_exynos4412 = {
> + .cpu_type = TYPE_EXYNOS4412,
> + .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
> + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
> +};
> +
> static struct samsung_usbphy_drvdata usbphy_exynos5 = {
> .cpu_type = TYPE_EXYNOS5250,
> .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
> @@ -887,6 +1033,9 @@ static const struct of_device_id samsung_usbphy_dt_match[] = {
> .compatible = "samsung,exynos4210-usbphy",
> .data = &usbphy_exynos4,
> }, {
> + .compatible = "samsung,exynos4412-usbphy",
> + .data = &usbphy_exynos4412,
> + }, {
> .compatible = "samsung,exynos5250-usbphy",
> .data = &usbphy_exynos5
> },
> @@ -903,6 +1052,9 @@ static struct platform_device_id samsung_usbphy_driver_ids[] = {
> .name = "exynos4210-usbphy",
> .driver_data = (unsigned long)&usbphy_exynos4,
> }, {
> + .name = "exynos4412-usbphy",
> + .driver_data = (unsigned long)&usbphy_exynos4412,
> + }, {
> .name = "exynos5250-usbphy",
> .driver_data = (unsigned long)&usbphy_exynos5,
> },
> --
> 1.7.10.4
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


\
 
 \ /
  Last update: 2013-02-05 02:43    [W:0.055 / U:0.380 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site