2013-05-13 18:26:27

by Dongjin Kim

[permalink] [raw]
Subject: [PATCH] usb: phy: samsung: adding usbphy for Exynos4X12

This patch adds usb host phy (USB 2.0 PHY) support for Samsung Exynos4X12 SoC.
New functions, samsung_exynos4x12_usb2phy_enable/_disable and selecting
reference clock, for Exynos4X12 are added. Since it has different register
set up with Exynos4210 or Exynos5250, "samsung,exynos4x12-usb2phy" is added.

Signed-off-by: Dongjin Kim <[email protected]>
---
.../devicetree/bindings/usb/samsung-usbphy.txt | 5 ++
drivers/usb/phy/phy-samsung-usb.c | 30 ++++++-
drivers/usb/phy/phy-samsung-usb.h | 18 ++++
drivers/usb/phy/phy-samsung-usb2.c | 90 ++++++++++++++++++++
4 files changed, 140 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
index 33fd354..f805878 100644
--- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
+++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
@@ -18,6 +18,11 @@ Exynos4210:
- clock-names: names of clock correseponding IDs clock property as requested
by the controller driver.

+Exynos4x12:
+- compatible : should be "samsung,exynos4x12-usb2phy"
+- reg : base physical address of the phy registers and length of memory mapped
+ region.
+
Exynos5250:
- compatible : should be "samsung,exynos5250-usb2phy"
- reg : base physical address of the phy registers and length of memory mapped
diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c
index 7b118ee5..efb26de 100644
--- a/drivers/usb/phy/phy-samsung-usb.c
+++ b/drivers/usb/phy/phy-samsung-usb.c
@@ -91,10 +91,11 @@ void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
*/
break;
case TYPE_EXYNOS4210:
+ case TYPE_EXYNOS4X12:
/*
- * Fall through since exynos4210 and exynos5250 have similar
- * register architecture: two separate registers for host and
- * device phy control with enable bit at position 0.
+ * Fall through since exynos4210/4x12 and exynos5250 have
+ * similar register architecture: two separateregistersfor
+ * host and device phy control with enable bit at position 0.
*/
case TYPE_EXYNOS5250:
if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
@@ -210,6 +211,29 @@ int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
refclk_freq = FSEL_CLKSEL_24M;
break;
}
+ } else if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12) {
+ 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:
diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h
index 70a9cae..ad86bce 100644
--- a/drivers/usb/phy/phy-samsung-usb.h
+++ b/drivers/usb/phy/phy-samsung-usb.h
@@ -47,6 +47,23 @@
#define RSTCON_HLINK_SWRST (0x1 << 1)
#define RSTCON_SWRST (0x1 << 0)

+/* For Exynos4x12 */
+#define PHYCLK_COMMON_ON_N_PHY0 (0x1 << 4)
+#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 EXYNOS4X12_PHY_HSIC_CTRL0 (0x04)
+#define EXYNOS4X12_PHY_HSIC_CTRL1 (0x08)
+
/* EXYNOS5 */
#define EXYNOS5_PHY_HOST_CTRL0 (0x00)

@@ -241,6 +258,7 @@
enum samsung_cpu_type {
TYPE_S3C64XX,
TYPE_EXYNOS4210,
+ TYPE_EXYNOS4X12,
TYPE_EXYNOS5250,
};

diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c
index 45ffe03..b95d05d 100644
--- a/drivers/usb/phy/phy-samsung-usb2.c
+++ b/drivers/usb/phy/phy-samsung-usb2.c
@@ -158,6 +158,59 @@ static void samsung_exynos5_usb2phy_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_exynos4x12_usb2phy_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 + EXYNOS4X12_PHY_HSIC_CTRL0);
+ writel(EXYNOS_USBPHY_ENABLE, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL1);
+
+ /* Common block configuration during suspend */
+ phyclk = sphy->ref_clk_freq
+ & ~(PHYCLK_COMMON_ON_N_PHY1);
+ writel(phyclk, regs + SAMSUNG_PHYCLK);
+
+ /* Enable normal mode of Host */
+ phypwr = readl(regs + SAMSUNG_PHYPWR);
+ phypwr &= ~(PHYPWR_NORMAL_MASK_HSIC0 | PHYPWR_NORMAL_MASK_HSIC1
+ | PHYPWR_NORMAL_MASK_PHY1);
+ writel(phypwr, regs + SAMSUNG_PHYPWR);
+
+ /* 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_usb2phy_enable(struct samsung_usbphy *sphy)
{
void __iomem *regs = sphy->regs;
@@ -228,6 +281,27 @@ static void samsung_exynos5_usb2phy_disable(struct samsung_usbphy *sphy)
writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
}

+static void samsung_exynos4x12_usb2phy_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_NORMAL_MASK_PHY1
+ | PHYPWR_NORMAL_MASK_HSIC1
+ | PHYPWR_NORMAL_MASK_HSIC0);
+ writel(phypwr, regs + SAMSUNG_PHYPWR);
+
+ writel(0, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL0);
+ writel(0, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL1);
+}
+
static void samsung_usb2phy_disable(struct samsung_usbphy *sphy)
{
void __iomem *regs = sphy->regs;
@@ -293,6 +367,8 @@ static int samsung_usb2phy_init(struct usb_phy *phy)
/* Initialize usb phy registers */
if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
samsung_exynos5_usb2phy_enable(sphy);
+ else if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12)
+ samsung_exynos4x12_usb2phy_enable(sphy);
else
samsung_usb2phy_enable(sphy);

@@ -336,6 +412,8 @@ static void samsung_usb2phy_shutdown(struct usb_phy *phy)
/* De-initialize usb phy registers */
if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
samsung_exynos5_usb2phy_disable(sphy);
+ if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12)
+ samsung_exynos4x12_usb2phy_disable(sphy);
else
samsung_usb2phy_disable(sphy);

@@ -451,6 +529,12 @@ static const struct samsung_usbphy_drvdata usb2phy_exynos4 = {
.hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
};

+static const struct samsung_usbphy_drvdata usb2phy_exynos4x12 = {
+ .cpu_type = TYPE_EXYNOS4X12,
+ .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
+ .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
+};
+
static struct samsung_usbphy_drvdata usb2phy_exynos5 = {
.cpu_type = TYPE_EXYNOS5250,
.hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
@@ -466,6 +550,9 @@ static const struct of_device_id samsung_usbphy_dt_match[] = {
.compatible = "samsung,exynos4210-usb2phy",
.data = &usb2phy_exynos4,
}, {
+ .compatible = "samsung,exynos4x12-usb2phy",
+ .data = &usb2phy_exynos4x12,
+ }, {
.compatible = "samsung,exynos5250-usb2phy",
.data = &usb2phy_exynos5
},
@@ -482,6 +569,9 @@ static struct platform_device_id samsung_usbphy_driver_ids[] = {
.name = "exynos4210-usb2phy",
.driver_data = (unsigned long)&usb2phy_exynos4,
}, {
+ .name = "exynos4x12-usb2phy",
+ .driver_data = (unsigned long)&usb2phy_exynos4x12,
+ }, {
.name = "exynos5250-usb2phy",
.driver_data = (unsigned long)&usb2phy_exynos5,
},
--
1.7.9.5


2013-05-13 19:40:38

by Vivek Gautam

[permalink] [raw]
Subject: Re: [PATCH] usb: phy: samsung: adding usbphy for Exynos4X12

Hi Dongjin,


On Mon, May 13, 2013 at 11:55 PM, Dongjin Kim <[email protected]> wrote:
> This patch adds usb host phy (USB 2.0 PHY) support for Samsung Exynos4X12 SoC.
> New functions, samsung_exynos4x12_usb2phy_enable/_disable and selecting
> reference clock, for Exynos4X12 are added. Since it has different register
> set up with Exynos4210 or Exynos5250, "samsung,exynos4x12-usb2phy" is added.

A patch-set for 4x12 from Tomasz too.
[PATCH 0/6] Samsung USB PHY SoC support cleanup
@ http://www.mail-archive.com/[email protected]/msg18177.html


Hi Tomasz,

Planning to re-spin that series ?

>
> Signed-off-by: Dongjin Kim <[email protected]>
> ---
> .../devicetree/bindings/usb/samsung-usbphy.txt | 5 ++
> drivers/usb/phy/phy-samsung-usb.c | 30 ++++++-
> drivers/usb/phy/phy-samsung-usb.h | 18 ++++
> drivers/usb/phy/phy-samsung-usb2.c | 90 ++++++++++++++++++++
> 4 files changed, 140 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> index 33fd354..f805878 100644
> --- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> +++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> @@ -18,6 +18,11 @@ Exynos4210:
> - clock-names: names of clock correseponding IDs clock property as requested
> by the controller driver.
>
> +Exynos4x12:
> +- compatible : should be "samsung,exynos4x12-usb2phy"
> +- reg : base physical address of the phy registers and length of memory mapped
> + region.
> +
> Exynos5250:
> - compatible : should be "samsung,exynos5250-usb2phy"
> - reg : base physical address of the phy registers and length of memory mapped
> diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c
> index 7b118ee5..efb26de 100644
> --- a/drivers/usb/phy/phy-samsung-usb.c
> +++ b/drivers/usb/phy/phy-samsung-usb.c
> @@ -91,10 +91,11 @@ void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
> */
> break;
> case TYPE_EXYNOS4210:
> + case TYPE_EXYNOS4X12:
> /*
> - * Fall through since exynos4210 and exynos5250 have similar
> - * register architecture: two separate registers for host and
> - * device phy control with enable bit at position 0.
> + * Fall through since exynos4210/4x12 and exynos5250 have
> + * similar register architecture: two separateregistersfor
> + * host and device phy control with enable bit at position 0.
> */
> case TYPE_EXYNOS5250:
> if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
> @@ -210,6 +211,29 @@ int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
> refclk_freq = FSEL_CLKSEL_24M;
> break;
> }
> + } else if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12) {
> + 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:
> diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h
> index 70a9cae..ad86bce 100644
> --- a/drivers/usb/phy/phy-samsung-usb.h
> +++ b/drivers/usb/phy/phy-samsung-usb.h
> @@ -47,6 +47,23 @@
> #define RSTCON_HLINK_SWRST (0x1 << 1)
> #define RSTCON_SWRST (0x1 << 0)
>
> +/* For Exynos4x12 */
> +#define PHYCLK_COMMON_ON_N_PHY0 (0x1 << 4)
> +#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 EXYNOS4X12_PHY_HSIC_CTRL0 (0x04)
> +#define EXYNOS4X12_PHY_HSIC_CTRL1 (0x08)
> +
> /* EXYNOS5 */
> #define EXYNOS5_PHY_HOST_CTRL0 (0x00)
>
> @@ -241,6 +258,7 @@
> enum samsung_cpu_type {
> TYPE_S3C64XX,
> TYPE_EXYNOS4210,
> + TYPE_EXYNOS4X12,
> TYPE_EXYNOS5250,
> };
>
> diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c
> index 45ffe03..b95d05d 100644
> --- a/drivers/usb/phy/phy-samsung-usb2.c
> +++ b/drivers/usb/phy/phy-samsung-usb2.c
> @@ -158,6 +158,59 @@ static void samsung_exynos5_usb2phy_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_exynos4x12_usb2phy_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 + EXYNOS4X12_PHY_HSIC_CTRL0);
> + writel(EXYNOS_USBPHY_ENABLE, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL1);
> +
> + /* Common block configuration during suspend */
> + phyclk = sphy->ref_clk_freq
> + & ~(PHYCLK_COMMON_ON_N_PHY1);
> + writel(phyclk, regs + SAMSUNG_PHYCLK);
> +
> + /* Enable normal mode of Host */
> + phypwr = readl(regs + SAMSUNG_PHYPWR);
> + phypwr &= ~(PHYPWR_NORMAL_MASK_HSIC0 | PHYPWR_NORMAL_MASK_HSIC1
> + | PHYPWR_NORMAL_MASK_PHY1);
> + writel(phypwr, regs + SAMSUNG_PHYPWR);
> +
> + /* 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_usb2phy_enable(struct samsung_usbphy *sphy)
> {
> void __iomem *regs = sphy->regs;
> @@ -228,6 +281,27 @@ static void samsung_exynos5_usb2phy_disable(struct samsung_usbphy *sphy)
> writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
> }
>
> +static void samsung_exynos4x12_usb2phy_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_NORMAL_MASK_PHY1
> + | PHYPWR_NORMAL_MASK_HSIC1
> + | PHYPWR_NORMAL_MASK_HSIC0);
> + writel(phypwr, regs + SAMSUNG_PHYPWR);
> +
> + writel(0, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL0);
> + writel(0, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL1);
> +}
> +
> static void samsung_usb2phy_disable(struct samsung_usbphy *sphy)
> {
> void __iomem *regs = sphy->regs;
> @@ -293,6 +367,8 @@ static int samsung_usb2phy_init(struct usb_phy *phy)
> /* Initialize usb phy registers */
> if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
> samsung_exynos5_usb2phy_enable(sphy);
> + else if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12)
> + samsung_exynos4x12_usb2phy_enable(sphy);
> else
> samsung_usb2phy_enable(sphy);
>
> @@ -336,6 +412,8 @@ static void samsung_usb2phy_shutdown(struct usb_phy *phy)
> /* De-initialize usb phy registers */
> if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
> samsung_exynos5_usb2phy_disable(sphy);
> + if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12)
> + samsung_exynos4x12_usb2phy_disable(sphy);
> else
> samsung_usb2phy_disable(sphy);
>
> @@ -451,6 +529,12 @@ static const struct samsung_usbphy_drvdata usb2phy_exynos4 = {
> .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
> };
>
> +static const struct samsung_usbphy_drvdata usb2phy_exynos4x12 = {
> + .cpu_type = TYPE_EXYNOS4X12,
> + .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
> + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
> +};
> +
> static struct samsung_usbphy_drvdata usb2phy_exynos5 = {
> .cpu_type = TYPE_EXYNOS5250,
> .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
> @@ -466,6 +550,9 @@ static const struct of_device_id samsung_usbphy_dt_match[] = {
> .compatible = "samsung,exynos4210-usb2phy",
> .data = &usb2phy_exynos4,
> }, {
> + .compatible = "samsung,exynos4x12-usb2phy",
> + .data = &usb2phy_exynos4x12,
> + }, {
> .compatible = "samsung,exynos5250-usb2phy",
> .data = &usb2phy_exynos5
> },
> @@ -482,6 +569,9 @@ static struct platform_device_id samsung_usbphy_driver_ids[] = {
> .name = "exynos4210-usb2phy",
> .driver_data = (unsigned long)&usb2phy_exynos4,
> }, {
> + .name = "exynos4x12-usb2phy",
> + .driver_data = (unsigned long)&usb2phy_exynos4x12,
> + }, {
> .name = "exynos5250-usb2phy",
> .driver_data = (unsigned long)&usb2phy_exynos5,
> },
> --
> 1.7.9.5
>
> _______________________________________________
> devicetree-discuss mailing list
> [email protected]
> https://lists.ozlabs.org/listinfo/devicetree-discuss



--
Best Regards
Vivek

2013-05-13 19:45:17

by Tomasz Figa

[permalink] [raw]
Subject: Re: [PATCH] usb: phy: samsung: adding usbphy for Exynos4X12

Hi Vivek,

On Tuesday 14 of May 2013 01:10:32 Vivek Gautam wrote:
> Hi Dongjin,
>
> On Mon, May 13, 2013 at 11:55 PM, Dongjin Kim <[email protected]>
wrote:
> > This patch adds usb host phy (USB 2.0 PHY) support for Samsung
> > Exynos4X12 SoC. New functions,
> > samsung_exynos4x12_usb2phy_enable/_disable and selecting reference
> > clock, for Exynos4X12 are added. Since it has different register set
> > up with Exynos4210 or Exynos5250, "samsung,exynos4x12-usb2phy" is
> > added.
> A patch-set for 4x12 from Tomasz too.
> [PATCH 0/6] Samsung USB PHY SoC support cleanup
> @ http://www.mail-archive.com/[email protected]/msg18177.html
>
>
> Hi Tomasz,
>
> Planning to re-spin that series ?

Hmm, I thought it has been merged, but it seems like somehow it hasn't. I
wonder why...

Well, I'll rebase and send the series again then. Thanks for notification.

Best regards,
Tomasz

>
> > Signed-off-by: Dongjin Kim <[email protected]>
> > ---
> >
> > .../devicetree/bindings/usb/samsung-usbphy.txt | 5 ++
> > drivers/usb/phy/phy-samsung-usb.c | 30 ++++++-
> > drivers/usb/phy/phy-samsung-usb.h | 18 ++++
> > drivers/usb/phy/phy-samsung-usb2.c | 90
> > ++++++++++++++++++++ 4 files changed, 140 insertions(+), 3
> > deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> > b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt index
> > 33fd354..f805878 100644
> > --- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> > +++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> >
> > @@ -18,6 +18,11 @@ Exynos4210:
> > - clock-names: names of clock correseponding IDs clock property as
> > requested>
> > by the controller driver.
> >
> > +Exynos4x12:
> > +- compatible : should be "samsung,exynos4x12-usb2phy"
> > +- reg : base physical address of the phy registers and length of
> > memory mapped + region.
> > +
> >
> > Exynos5250:
> > - compatible : should be "samsung,exynos5250-usb2phy"
> > - reg : base physical address of the phy registers and length of
> > memory mapped>
> > diff --git a/drivers/usb/phy/phy-samsung-usb.c
> > b/drivers/usb/phy/phy-samsung-usb.c index 7b118ee5..efb26de 100644
> > --- a/drivers/usb/phy/phy-samsung-usb.c
> > +++ b/drivers/usb/phy/phy-samsung-usb.c
> > @@ -91,10 +91,11 @@ void samsung_usbphy_set_isolation(struct
> > samsung_usbphy *sphy, bool on)>
> > */
> >
> > break;
> >
> > case TYPE_EXYNOS4210:
> > + case TYPE_EXYNOS4X12:
> > /*
> >
> > - * Fall through since exynos4210 and exynos5250 have
> > similar - * register architecture: two separate
> > registers for host and - * device phy control with
> > enable bit at position 0. + * Fall through since
> > exynos4210/4x12 and exynos5250 have + * similar
> > register architecture: two separateregistersfor + *
> > host and device phy control with enable bit at position 0.>
> > */
> >
> > case TYPE_EXYNOS5250:
> > if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
> >
> > @@ -210,6 +211,29 @@ int samsung_usbphy_get_refclk_freq(struct
> > samsung_usbphy *sphy)>
> > refclk_freq = FSEL_CLKSEL_24M;
> > break;
> >
> > }
> >
> > + } else if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12) {
> > + 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:
> > diff --git a/drivers/usb/phy/phy-samsung-usb.h
> > b/drivers/usb/phy/phy-samsung-usb.h index 70a9cae..ad86bce 100644
> > --- a/drivers/usb/phy/phy-samsung-usb.h
> > +++ b/drivers/usb/phy/phy-samsung-usb.h
> > @@ -47,6 +47,23 @@
> >
> > #define RSTCON_HLINK_SWRST (0x1 << 1)
> > #define RSTCON_SWRST (0x1 << 0)
> >
> > +/* For Exynos4x12 */
> > +#define PHYCLK_COMMON_ON_N_PHY0 (0x1 << 4)
> > +#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 EXYNOS4X12_PHY_HSIC_CTRL0 (0x04)
> > +#define EXYNOS4X12_PHY_HSIC_CTRL1 (0x08)
> > +
> >
> > /* EXYNOS5 */
> > #define EXYNOS5_PHY_HOST_CTRL0 (0x00)
> >
> > @@ -241,6 +258,7 @@
> >
> > enum samsung_cpu_type {
> >
> > TYPE_S3C64XX,
> > TYPE_EXYNOS4210,
> >
> > + TYPE_EXYNOS4X12,
> >
> > TYPE_EXYNOS5250,
> >
> > };
> >
> > diff --git a/drivers/usb/phy/phy-samsung-usb2.c
> > b/drivers/usb/phy/phy-samsung-usb2.c index 45ffe03..b95d05d 100644
> > --- a/drivers/usb/phy/phy-samsung-usb2.c
> > +++ b/drivers/usb/phy/phy-samsung-usb2.c
> > @@ -158,6 +158,59 @@ static void samsung_exynos5_usb2phy_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_exynos4x12_usb2phy_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 +
> > EXYNOS4X12_PHY_HSIC_CTRL0); + writel(EXYNOS_USBPHY_ENABLE,
> > sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL1); +
> > + /* Common block configuration during suspend */
> > + phyclk = sphy->ref_clk_freq
> > + & ~(PHYCLK_COMMON_ON_N_PHY1);
> > + writel(phyclk, regs + SAMSUNG_PHYCLK);
> > +
> > + /* Enable normal mode of Host */
> > + phypwr = readl(regs + SAMSUNG_PHYPWR);
> > + phypwr &= ~(PHYPWR_NORMAL_MASK_HSIC0 |
> > PHYPWR_NORMAL_MASK_HSIC1
> > + | PHYPWR_NORMAL_MASK_PHY1);
> > + writel(phypwr, regs + SAMSUNG_PHYPWR);
> > +
> > + /* 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_usb2phy_enable(struct samsung_usbphy *sphy)
> > {
> >
> > void __iomem *regs = sphy->regs;
> >
> > @@ -228,6 +281,27 @@ static void
> > samsung_exynos5_usb2phy_disable(struct samsung_usbphy *sphy)>
> > writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
> >
> > }
> >
> > +static void samsung_exynos4x12_usb2phy_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_NORMAL_MASK_PHY1
> > + | PHYPWR_NORMAL_MASK_HSIC1
> > + | PHYPWR_NORMAL_MASK_HSIC0);
> > + writel(phypwr, regs + SAMSUNG_PHYPWR);
> > +
> > + writel(0, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL0);
> > + writel(0, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL1);
> > +}
> > +
> >
> > static void samsung_usb2phy_disable(struct samsung_usbphy *sphy)
> > {
> >
> > void __iomem *regs = sphy->regs;
> >
> > @@ -293,6 +367,8 @@ static int samsung_usb2phy_init(struct usb_phy
> > *phy)>
> > /* Initialize usb phy registers */
> > if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
> >
> > samsung_exynos5_usb2phy_enable(sphy);
> >
> > + else if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12)
> > + samsung_exynos4x12_usb2phy_enable(sphy);
> >
> > else
> >
> > samsung_usb2phy_enable(sphy);
> >
> > @@ -336,6 +412,8 @@ static void samsung_usb2phy_shutdown(struct
> > usb_phy *phy)>
> > /* De-initialize usb phy registers */
> > if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
> >
> > samsung_exynos5_usb2phy_disable(sphy);
> >
> > + if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12)
> > + samsung_exynos4x12_usb2phy_disable(sphy);
> >
> > else
> >
> > samsung_usb2phy_disable(sphy);
> >
> > @@ -451,6 +529,12 @@ static const struct samsung_usbphy_drvdata
> > usb2phy_exynos4 = {>
> > .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
> >
> > };
> >
> > +static const struct samsung_usbphy_drvdata usb2phy_exynos4x12 = {
> > + .cpu_type = TYPE_EXYNOS4X12,
> > + .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
> > + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
> > +};
> > +
> >
> > static struct samsung_usbphy_drvdata usb2phy_exynos5 = {
> >
> > .cpu_type = TYPE_EXYNOS5250,
> > .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
> >
> > @@ -466,6 +550,9 @@ static const struct of_device_id
> > samsung_usbphy_dt_match[] = {>
> > .compatible = "samsung,exynos4210-usb2phy",
> > .data = &usb2phy_exynos4,
> >
> > }, {
> >
> > + .compatible = "samsung,exynos4x12-usb2phy",
> > + .data = &usb2phy_exynos4x12,
> > + }, {
> >
> > .compatible = "samsung,exynos5250-usb2phy",
> > .data = &usb2phy_exynos5
> >
> > },
> >
> > @@ -482,6 +569,9 @@ static struct platform_device_id
> > samsung_usbphy_driver_ids[] = {>
> > .name = "exynos4210-usb2phy",
> > .driver_data = (unsigned long)&usb2phy_exynos4,
> >
> > }, {
> >
> > + .name = "exynos4x12-usb2phy",
> > + .driver_data = (unsigned long)&usb2phy_exynos4x12,
> > + }, {
> >
> > .name = "exynos5250-usb2phy",
> > .driver_data = (unsigned long)&usb2phy_exynos5,
> >
> > },
> >
> > --
> > 1.7.9.5
> >
> > _______________________________________________
> > devicetree-discuss mailing list
> > [email protected]
> > https://lists.ozlabs.org/listinfo/devicetree-discuss