Skip to contentSkip to conversation

EXYNOS5: USB: Add USB 2.0 and USB 3.0 support for exynos5

PATCH New Vivek Gautam 4 participants 16 messages Jul 21, 2012 – Aug 1, 2012

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

v2 cover EXYNOS5: USB: Add USB 2.0 and USB 3.0 support for exynos5

Changes from v1:
EXYNOS4: USB: Generalising setup-usb-phy driver for exynos
1) Make function exynos_usb_clock_enable() as static.
2) Remove the check for 'usb_clk' in exynos_usb_clock_enable().

ARM: EXYNOS5: Add PHY initialization code for usb 2.0
1) Set HOST_CTRL0_COMMONON_N and reset OTG_SYS_COMMON_ON bits for host and otg power saving in suspend mode.

Ajay Kumar (2):
ARM: EXYNOS5: Add machine data for USB 2.0
ARM: EXYNOS5: Add OHCI device from device tree

Vivek Gautam (6):
EXYNOS4: USB: Generalising setup-usb-phy driver for exynos
ARM: EXYNOS5: Add EHCI device from device tree
ARM: EXYNOS5: Add PHY initialization code for usb 2.0
ARM: EXYNOS5: Add machine data for USB3.0
ARM: EXYNOS5: Add XHCI device from device tree
ARM: EXYNOS5: Add PHY initialization code for usb 3.0

 .../devicetree/bindings/usb/exynos-usb.txt         |   60 +++
 arch/arm/boot/dts/exynos5250-smdk5250.dts          |    4 +
 arch/arm/boot/dts/exynos5250.dtsi                  |   18 +
 arch/arm/mach-exynos/Kconfig                       |    1 +
 arch/arm/mach-exynos/clock-exynos5.c               |   24 ++
 arch/arm/mach-exynos/common.c                      |   10 +
 arch/arm/mach-exynos/include/mach/map.h            |    3 +
 arch/arm/mach-exynos/include/mach/regs-pmu.h       |    4 +
 arch/arm/mach-exynos/include/mach/regs-usb-phy.h   |   86 ++++
 arch/arm/mach-exynos/mach-exynos5-dt.c             |   26 ++
 arch/arm/mach-exynos/setup-usb-phy.c               |  411 ++++++++++++++++++--
 arch/arm/plat-samsung/include/plat/map-s5p.h       |    2 +
 .../include/plat/regs-usb3-exynos-drd-phy.h        |   75 ++++
 arch/arm/plat-samsung/include/plat/usb-phy.h       |    1 +
 drivers/usb/Kconfig                                |    1 +
 15 files changed, 693 insertions(+), 33 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/exynos-usb.txt
 create mode 100644 arch/arm/plat-samsung/include/plat/regs-usb3-exynos-drd-phy.h
#1 lore raw

PATCH v2 1/8 EXYNOS4: USB: Generalising setup-usb-phy driver for exynos

This patch updates the setup-usb-phy in order to accomodate exynos5 support later.

---
 arch/arm/mach-exynos/setup-usb-phy.c |   54 +++++++++++++++++----------------
 1 files changed, 28 insertions(+), 26 deletions(-)
arch/arm/mach-exynos/setup-usb-phy.c +28 -26
index b81cc56..1a4ea07 100644
@@ -26,10 +26,29 @@ 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 struct clk *exynos_usb_clock_enable(struct platform_device *pdev)
+{
+	struct clk *usb_clk = NULL;
+	int err = 0;
+
+	usb_clk = clk_get(&pdev->dev, "otg");
+	if (IS_ERR(usb_clk)) {
+		dev_err(&pdev->dev, "Failed to get otg clock\n");
+		return NULL;
+	}
+
+	err = clk_enable(usb_clk);
+	if (err) {
+		clk_put(usb_clk);
+		return NULL;
+	}
+	return usb_clk;
+}
+
+static int exynos4210_usb_phy_clkset(struct platform_device *pdev)
 {
 	struct clk *xusbxti_clk;
-	u32 phyclk;
+	u32 phyclk = 0;
 
 	xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
 	if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
@@ -80,6 +99,7 @@ static void exynos4210_usb_phy_clkset(struct platform_device *pdev)
 		}
 		clk_put(xusbxti_clk);
 	}
+	return phyclk;
 }
 
 static int exynos4210_usb_phy0_init(struct platform_device *pdev)
@@ -120,21 +140,12 @@ static int exynos4210_usb_phy1_init(struct platform_device *pdev)
 {
 	struct clk *otg_clk;
 	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);
-	}
-
-	err = clk_enable(otg_clk);
-	if (err) {
-		clk_put(otg_clk);
-		return err;
-	}
+	otg_clk = exynos_usb_clock_enable(pdev);
+	if (otg_clk == NULL)
+		dev_err(&pdev->dev, "Failed to enable otg clock\n");
 
 	if (exynos4_usb_host_phy_is_on())
 		return 0;
@@ -173,22 +184,13 @@ static int exynos4210_usb_phy1_init(struct platform_device *pdev)
 static int exynos4210_usb_phy1_exit(struct platform_device *pdev)
 {
 	struct clk *otg_clk;
-	int err;
 
 	if (atomic_dec_return(&host_usage) > 0)
 		return 0;
 
-	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);
-	}
-
-	err = clk_enable(otg_clk);
-	if (err) {
-		clk_put(otg_clk);
-		return err;
-	}
+	otg_clk = exynos_usb_clock_enable(pdev);
+	if (otg_clk == NULL)
+		dev_err(&pdev->dev, "Failed to enable otg clock\n");
 
 	writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
 			EXYNOS4_PHYPWR);
Signature · 1 line
1.7.0.4
#2 lore raw

PATCH v2 2/8 ARM: EXYNOS5: Add machine data for USB 2.0

In reply to Vivek Gautam

From: Ajay Kumar <[email protected]>

This patch adds address mapping of USB 2.0 PHY for exynos5

---
 arch/arm/mach-exynos/common.c           |    5 +++++
 arch/arm/mach-exynos/include/mach/map.h |    2 ++
 2 files changed, 7 insertions(+), 0 deletions(-)
arch/arm/mach-exynos/common.c +5 -0
index 4eb39cd..92d5e61 100644
@@ -275,6 +275,11 @@ static struct map_desc exynos5_iodesc[] __initdata = {
 		.pfn		= __phys_to_pfn(EXYNOS5_PA_GIC_DIST),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_USB_HSPHY,
+		.pfn		= __phys_to_pfn(EXYNOS5_PA_USB_PHY),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
 	},
 };
 
arch/arm/mach-exynos/include/mach/map.h +2 -0
index c72b675..331ae57 100644
@@ -192,6 +192,8 @@
 #define EXYNOS4_PA_UART			0x13800000
 #define EXYNOS5_PA_UART			0x12C00000
 
+#define EXYNOS5_PA_USB_PHY		0x12130000
+
 #define EXYNOS4_PA_VP			0x12C00000
 #define EXYNOS4_PA_MIXER		0x12C10000
 #define EXYNOS4_PA_SDO			0x12C20000
Signature · 1 line
1.7.0.4
#3 lore raw

PATCH v2 2/8 ARM: EXYNOS5: Add machine data for USB 2.0

Quoted 16 lines · Vivek Gautam

From: Ajay Kumar <[email protected]>

This patch adds address mapping of USB 2.0 PHY for exynos5

---
 arch/arm/mach-exynos/common.c           |    5 +++++
 arch/arm/mach-exynos/include/mach/map.h |    2 ++
 2 files changed, 7 insertions(+), 0 deletions(-)
arch/arm/mach-exynos/common.c +0 -0
index 4eb39cd..92d5e61 100644

arch/arm/mach-exynos/common.c static struct map_desc exynos5_iodesc[] __initdata = { · line 284

Quoted 10 lines
arch/arm/mach-exynos/common.c +5 -0
@@ -275,6 +275,11 @@ static struct map_desc exynos5_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS5_PA_GIC_DIST),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_USB_HSPHY,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_USB_PHY),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
        },
 };

Can you pleae explain why this is done in the changelog?

We try hard to do such mappings from the device driver instead, so I'm surprised that this is necessary fo rthe USB phy.

Arnd

#4 lore raw

PATCH v2 2/8 ARM: EXYNOS5: Add machine data for USB 2.0

Quoted 30 lines · Arnd Bergmann
Quoted 4 lines · Vivek Gautam

From: Ajay Kumar <[email protected]>

This patch adds address mapping of USB 2.0 PHY for exynos5

Review

Quoted 8 lines
---
 arch/arm/mach-exynos/common.c           |    5 +++++
 arch/arm/mach-exynos/include/mach/map.h |    2 ++
 2 files changed, 7 insertions(+), 0 deletions(-)
(quoted diff) +0 -0

b/arch/arm/mach-exynos/common.c

arch/arm/mach-exynos/common.c static struct map_desc exynos5_iodesc[] __initdata

Quoted 4 lines

index 4eb39cd..92d5e61 100644

arch/arm/mach-exynos/common.c +0 -0
@@ -275,6 +275,11 @@ static struct map_desc exynos5_iodesc[] __initdata

= {

arch/arm/mach-exynos/common.c static struct map_desc exynos5_iodesc[] __initdata = { · line 284

Quoted 10 lines
arch/arm/mach-exynos/common.c +5 -0
                .pfn            = __phys_to_pfn(EXYNOS5_PA_GIC_DIST),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_USB_HSPHY,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_USB_PHY),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
        },
 };
Quoted 5 lines

Can you pleae explain why this is done in the changelog?

We try hard to do such mappings from the device driver instead, so I'm surprised that this is necessary fo rthe USB phy.

We are doing the mapping for device address in the driver, but this memory mapping for USB PHY registers that need to be programmed by the software is done here. This is similar to what we see for exynos4 also. Is it something
that i can still change? Please suggest.

Quoted 8 lines

Arnd

_______________________________________________
devicetree-discuss mailing list
[email protected]
https://lists.ozlabs.org/listinfo/devicetree-discuss

Best regards
Vivek

_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#5 lore raw

PATCH v2 2/8 ARM: EXYNOS5: Add machine data for USB 2.0

Quoted 11 lines · Vivek Gautam
Quoted 5 lines

Can you pleae explain why this is done in the changelog?

We try hard to do such mappings from the device driver instead, so I'm surprised that this is necessary fo rthe USB phy.

We are doing the mapping for device address in the driver, but this memory mapping for USB PHY registers that need to be programmed by the software is done here. This is similar to what we see for exynos4 also. Is it something
that i can still change? Please suggest.

Yes, I think the USB PHY handling for all exynos chips should be changed from an ad-hoc method to a more formal device driver. As I commented in another patch of this series, I think the main problem is that treat the USB PHY as a property of the "platform", which it really isn't.

We have a bunch of other USB PHY drivers for other platforms that are inside of the drivers/usb hierarchy. For all I know, there is no formal USB PHY driver API yet, and it seems that it would be a good idea to introduce one now, but for now, just move the code to drivers/usb/phy/ and make it one file per different kind of PHY.

Arnd

#6 lore raw

PATCH v2 2/8 ARM: EXYNOS5: Add machine data for USB 2.0

Quoted 17 lines · Arnd Bergmann
Quoted 10 lines · Vivek Gautam
Quoted 5 lines

Can you pleae explain why this is done in the changelog?

We try hard to do such mappings from the device driver instead, so I'm surprised that this is necessary fo rthe USB phy.

We are doing the mapping for device address in the driver, but this memory mapping for USB PHY registers that need to be programmed by the software is done here. This is similar to what we see for exynos4 also. Is it something
that i can still change? Please suggest.

Yes, I think the USB PHY handling for all exynos chips should be changed from an ad-hoc method to a more formal device driver. As I commented in another patch of this series, I think the main problem is that treat the USB PHY as a property of the "platform", which it really isn't.

Quoted 6 lines

We have a bunch of other USB PHY drivers for other platforms that are inside of the drivers/usb hierarchy. For all I know, there is no formal USB PHY driver API yet, and it seems that it would be a good idea to introduce one now, but for now, just move the code to drivers/usb/phy/ and make it one file per different kind of PHY.

Totally agree. I think that two PHY drivers need for usb2.0 PHY and usb3.0 PHY in drivers/usb/phy directory. First, let's make usb2.0 PHY driver for samsung SoCs from phy control codes of arch/arm, then add to support usb2.0 PHY for exynos5 and make usb3.0 PHY driver for exynos.

Thanks.

#7 lore raw

PATCH v2 3/8 ARM: EXYNOS5: Add OHCI device from device tree

In reply to Vivek Gautam

From: Ajay Kumar <[email protected]>

This patch adds OHCI device from device tree for exynos5 and adds platform data.

---
 .../devicetree/bindings/usb/exynos-usb.txt         |   19 +++++++++++++++++++
 arch/arm/boot/dts/exynos5250.dtsi                  |    6 ++++++
 arch/arm/mach-exynos/mach-exynos5-dt.c             |    9 +++++++++
 3 files changed, 34 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/exynos-usb.txt
Documentation/devicetree/bindings/usb/exynos-usb.txt new file +19 -0
new file mode 100644
index 0000000..63b80b9
@@ -0,0 +1,19 @@
+Samsung Exynos SoC USB controller
+
+The device node for USB controller for Samsung SOC have
+following properties
+
+OHCI
+Required properties:
+ - compatible: should be "samsung,exynos-ohci" for USB 2.0
+   OHCI companion controller in host mode.
+ - reg: physical base address of the controller and length
+   of memory mapped.
+ - interrupts: interrupt number to the cpu.
+
+ohci {
+	compatible = "samsung,exynos-ohci";
+	reg = <0x12120000 0x100>;
+	interrupts = <0 71 0>;
+};
+
arch/arm/boot/dts/exynos5250.dtsi +6 -0
index a3a2eb2..3c73d15 100644
@@ -58,6 +58,12 @@
 		interrupts = <0 42 0>;
 	};
 
+	ohci {
+		compatible = "samsung,exynos-ohci";
+		reg = <0x12120000 0x100>;
+		interrupts = <0 71 0>;
+	};
+
 	rtc {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x101E0000 0x100>;
arch/arm/mach-exynos/mach-exynos5-dt.c +9 -0
index ef770bc..39a4b34 100644
@@ -15,12 +15,19 @@
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 #include <mach/map.h>
+#include <mach/ohci.h>
 
 #include <plat/cpu.h>
 #include <plat/regs-serial.h>
+#include <plat/usb-phy.h>
 
 #include "common.h"
 
+static struct exynos4_ohci_platdata smdk5250_ohci_pdata = {
+	.phy_init = s5p_usb_phy_init,
+	.phy_exit = s5p_usb_phy_exit,
+};
+
 /*
  * The following lookup table is used to override device names when devices
  * are registered from device tree. This is temporarily added to enable
@@ -56,6 +63,8 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
+	OF_DEV_AUXDATA("samsung,exynos-ohci", 0x12120000,
+				"exynos-ohci", &smdk5250_ohci_pdata),
 	{},
 };
 
Signature · 1 line
1.7.0.4
#8 lore raw

PATCH v2 4/8 ARM: EXYNOS5: Add EHCI device from device tree

In reply to Vivek Gautam

This patch adds EHCI device from device tree for exynos5 and adds platform data.

---
 .../devicetree/bindings/usb/exynos-usb.txt         |   22 ++++++++++++++++++++
 arch/arm/boot/dts/exynos5250-smdk5250.dts          |    4 +++
 arch/arm/boot/dts/exynos5250.dtsi                  |    6 +++++
 arch/arm/mach-exynos/mach-exynos5-dt.c             |    8 +++++++
 4 files changed, 40 insertions(+), 0 deletions(-)
Documentation/devicetree/bindings/usb/exynos-usb.txt +22 -0
index 63b80b9..45dadca 100644
@@ -17,3 +17,25 @@ ohci {
 	interrupts = <0 71 0>;
 };
 
+EHCI
+Required properties:
+ - compatible:	should be "samsung,exynos-ehci" for USB 2.0
+   EHCI controller in host mode.
+ - reg: physical base address of the controller and length
+   of memory mapped.
+ - interrupts: interrupt number to the cpu.
+
+Optional properties:
+ - samsung,vbus-gpio:  if present, specifies the GPIO
+   that needs to be pulled up for the bus to be powered.
+
+ehci {
+	compatible = "samsung,exynos-ehci";
+	reg = <0x12110000 0x100>;
+	interrupts = <0 71 0>;
+};
+
+ehci {
+	samsung,vbus-gpio = <&gpx2 6 1 3 3>;
+};
+
arch/arm/boot/dts/exynos5250-smdk5250.dts +4 -0
index 8a5e348..bf18286 100644
@@ -109,4 +109,8 @@
 	spi_2: spi@12d40000 {
 		status = "disabled";
 	};
+
+	ehci {
+		samsung,vbus-gpio = <&gpx2 6 1 3 3>;
+	};
 };
arch/arm/boot/dts/exynos5250.dtsi +6 -0
index 3c73d15..988f52a 100644
@@ -64,6 +64,12 @@
 		interrupts = <0 71 0>;
 	};
 
+	ehci {
+		compatible = "samsung,exynos-ehci";
+		reg = <0x12110000 0x100>;
+		interrupts = <0 71 0>;
+	};
+
 	rtc {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x101E0000 0x100>;
arch/arm/mach-exynos/mach-exynos5-dt.c +8 -0
index 39a4b34..0cc626e 100644
@@ -20,6 +20,7 @@
 #include <plat/cpu.h>
 #include <plat/regs-serial.h>
 #include <plat/usb-phy.h>
+#include <plat/ehci.h>
 
 #include "common.h"
 
@@ -28,6 +29,11 @@ static struct exynos4_ohci_platdata smdk5250_ohci_pdata = {
 	.phy_exit = s5p_usb_phy_exit,
 };
 
+static struct s5p_ehci_platdata smdk5250_ehci_pdata = {
+	.phy_init = s5p_usb_phy_init,
+	.phy_exit = s5p_usb_phy_exit,
+};
+
 /*
  * The following lookup table is used to override device names when devices
  * are registered from device tree. This is temporarily added to enable
@@ -65,6 +71,8 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
 	OF_DEV_AUXDATA("samsung,exynos-ohci", 0x12120000,
 				"exynos-ohci", &smdk5250_ohci_pdata),
+	OF_DEV_AUXDATA("samsung,exynos-ehci", 0x12110000,
+				"s5p-ehci", &smdk5250_ehci_pdata),
 	{},
 };
 
Signature · 1 line
1.7.0.4
#9 lore raw

PATCH v2 4/8 ARM: EXYNOS5: Add EHCI device from device tree

arch/arm/mach-exynos/mach-exynos5-dt.c static struct exynos4_ohci_platdata smdk5250_ohci_pdata = { · line 39

Quoted 12 lines · Vivek Gautam
arch/arm/mach-exynos/mach-exynos5-dt.c +5 -0
@@ -28,6 +29,11 @@ static struct exynos4_ohci_platdata smdk5250_ohci_pdata = {
        .phy_exit = s5p_usb_phy_exit,
 };
 
+static struct s5p_ehci_platdata smdk5250_ehci_pdata = {
+       .phy_init = s5p_usb_phy_init,
+       .phy_exit = s5p_usb_phy_exit,
+};
+
 /*
  * The following lookup table is used to override device names when devices
  * are registered from device tree. This is temporarily added to enable

I'm a bit confused of the purpose of setting the function pointers here when the pointers are always to the same s5p_usb_phy_init/s5p_usb_phy_exit identifiers, but you have different definitions of those functions depending on which platforms you are building for.

What is the idea here? Are you going to unify the three definitions of s5p_usb_phy_init, or is that function going away eventually when we get to the point of building exynos/s5p/s3c64xx into the same kernel binary?

Arnd

#10 lore raw

PATCH v2 4/8 ARM: EXYNOS5: Add EHCI device from device tree

Hi,

Quoted 21 lines · Arnd Bergmann

Review static struct exynos4_ohci_platdata

Quoted 1 line · Vivek Gautam
(quoted diff) +0 -0
@@ -28,6 +29,11 @@ static struct exynos4_ohci_platdata

smdk5250_ohci_pdata = {

arch/arm/mach-exynos/mach-exynos5-dt.c static struct exynos4_ohci_platdata smdk5250_ohci_pdata = {

Quoted 10 lines
arch/arm/mach-exynos/mach-exynos5-dt.c +5 -0
        .phy_exit = s5p_usb_phy_exit,
 };
 
+static struct s5p_ehci_platdata smdk5250_ehci_pdata = {
+       .phy_init = s5p_usb_phy_init,
+       .phy_exit = s5p_usb_phy_exit,
+};
+
 /*
  * The following lookup table is used to override device names when

devices

arch/arm/mach-exynos/mach-exynos5-dt.c static struct exynos4_ohci_platdata smdk5250_ohci_pdata = { · line 39

Quoted 1 line
arch/arm/mach-exynos/mach-exynos5-dt.c +0 -0
  * are registered from device tree. This is temporarily added to enable

I'm a bit confused of the purpose of setting the function pointers here when the pointers are always to the same s5p_usb_phy_init/s5p_usb_phy_exit identifiers, but you have different definitions of those functions depending on which platforms you are building for.

Quoted 6 lines

What is the idea here? Are you going to unify the three definitions of s5p_usb_phy_init, or is that function going away eventually when we get to the point of building exynos/s5p/s3c64xx into the same kernel binary?

Should we be differentiating here between the calls at runtime for

different SOCs.
In that case, yes i think we need a way here to have a solution here so that the function call
goes differently for different soc while in runtime. I will work on this and get back asap.

Quoted 7 lines

Arnd

_______________________________________________
devicetree-discuss mailing list
[email protected]
https://lists.ozlabs.org/listinfo/devicetree-discuss

Best regards
Vivek

_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#11 lore raw

PATCH v2 5/8 ARM: EXYNOS5: Add PHY initialization code for usb 2.0

In reply to Vivek Gautam

This patch adds PHY setup functions usb 2.0 support on exynos5

---
 arch/arm/mach-exynos/Kconfig                     |    1 +
 arch/arm/mach-exynos/include/mach/regs-usb-phy.h |   86 ++++++++
 arch/arm/mach-exynos/setup-usb-phy.c             |  232 +++++++++++++++++++++-
 3 files changed, 311 insertions(+), 8 deletions(-)
arch/arm/mach-exynos/Kconfig +1 -0
index e698ca0..e0bc441 100644
@@ -416,6 +416,7 @@ config MACH_EXYNOS5_DT
 	select SOC_EXYNOS5250
 	select USE_OF
 	select ARM_AMBA
+	select EXYNOS4_SETUP_USB_PHY
 	help
 	  Machine support for Samsung Exynos4 machine with device tree enabled.
 	  Select this if a fdt blob is available for the EXYNOS4 SoC based board.
arch/arm/mach-exynos/include/mach/regs-usb-phy.h +86 -0

96 lines not on this page · raw message

arch/arm/mach-exynos/setup-usb-phy.c +224 -8

281 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#12 lore raw

PATCH v2 5/8 ARM: EXYNOS5: Add PHY initialization code for usb 2.0

Quoted 9 lines · Vivek Gautam

This patch adds PHY setup functions usb 2.0 support on exynos5

---
 arch/arm/mach-exynos/Kconfig                     |    1 +
 arch/arm/mach-exynos/include/mach/regs-usb-phy.h |   86 ++++++++
 arch/arm/mach-exynos/setup-usb-phy.c             |  232 +++++++++++++++++++++-
 3 files changed, 311 insertions(+), 8 deletions(-)

This looks very much like a new device driver, not some code you can just stick into platform code. We're trying hard to move driver code out of the platform directories, so please don't add any new stuff for a driver and soc that doesn't have to deal with legacy code.

arch/arm/mach-exynos/setup-usb-phy.c line 40

Quoted 12 lines

static int exynos4_usb_host_phy_is_on(void)
{

arch/arm/mach-exynos/setup-usb-phy.c +8 -1
-	return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1;
+	if (soc_is_exynos5250()) {
+		return (readl(EXYNOS5_PHY_HOST_CTRL0) &
+				HOST_CTRL0_PHYSWRSTALL) ? 0 : 1;
+	} else {
+		return (readl(EXYNOS4_PHYPWR) &
+				PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1;
+	}
+}

Never hardcode register locations like this.
Also you clearly have two SoC that do different things here, so putting them into the same function is a bit strange.

Quoted 4 lines

static struct clk *exynos_usb_clock_enable(struct platform_device *pdev)

arch/arm/mach-exynos/setup-usb-phy.c +0 -0
@@ -31,7 +56,10 @@ static struct clk *exynos_usb_clock_enable(struct platform_device *pdev)
 	struct clk *usb_clk = NULL;

arch/arm/mach-exynos/setup-usb-phy.c static struct clk *exynos_usb_clock_enable(struct platform_device *pdev) · line 65

Quoted 10 lines
arch/arm/mach-exynos/setup-usb-phy.c +4 -1
 	int err = 0;
 
-	usb_clk = clk_get(&pdev->dev, "otg");
+	if (soc_is_exynos5250())
+		usb_clk = clk_get(&pdev->dev, "usbhost");
+	else
+		usb_clk = clk_get(&pdev->dev, "otg");
 	if (IS_ERR(usb_clk)) {
 		dev_err(&pdev->dev, "Failed to get otg clock\n");
 		return NULL;

Why do you have different names for the same clock on different SoCs?

If the clock has the same purpose, just give it the same name.

arch/arm/mach-exynos/setup-usb-phy.c static int exynos4210_usb_phy_clkset(struct platform_device *pdev) · line 88

Quoted 13 lines
arch/arm/mach-exynos/setup-usb-phy.c +5 -1
@@ -50,7 +78,11 @@ static int exynos4210_usb_phy_clkset(struct platform_device *pdev)
 	struct clk *xusbxti_clk;
 	u32 phyclk = 0;
 
-	xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
+	if (soc_is_exynos5250())
+		xusbxti_clk = clk_get(&pdev->dev, "ext_xtal");
+	else
+		xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
+
 	if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
 		if (soc_is_exynos4210()) {
 			/* set clock frequency for PLL */

same here.

Quoted 5 lines
arch/arm/mach-exynos/setup-usb-phy.c +0 -1
@@ -218,8 +431,11 @@ 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)

arch/arm/mach-exynos/setup-usb-phy.c int s5p_usb_phy_exit(struct platform_device *pdev, int type) · line 441

Quoted 10 lines
arch/arm/mach-exynos/setup-usb-phy.c +6 -2
-		return exynos4210_usb_phy1_exit(pdev);
-
+	else if (type == S5P_USB_PHY_HOST) {
+		if (soc_is_exynos5250())
+			return exynos5_usb_phy20_exit(pdev);
+		else
+			return exynos4210_usb_phy1_exit(pdev);
+	}
 	return -EINVAL;
 }

You are doing completely different things here. None of these are actually s5p, so better make these different functions for each soc.

If you have a driver that has some common code and some hardware specific code, we generally structure the code so that the entry points are different for the each kind of hardware and they call into common code from there.

This code is done in the opposite way and should be changed over time, so please don't add to the mess.

Arnd

#13 lore raw

PATCH v2 6/8 ARM: EXYNOS5: Add machine data for USB3.0

In reply to Vivek Gautam

This patch adds clock definitions and address mapping of PHY for USB3.0 in exynos5

---
 arch/arm/mach-exynos/clock-exynos5.c         |   24 ++++++++++++++++++++++++
 arch/arm/mach-exynos/common.c                |    5 +++++
 arch/arm/mach-exynos/include/mach/map.h      |    1 +
 arch/arm/mach-exynos/include/mach/regs-pmu.h |    4 ++++
 arch/arm/plat-samsung/include/plat/map-s5p.h |    2 ++
 drivers/usb/Kconfig                          |    1 +
 6 files changed, 37 insertions(+), 0 deletions(-)
arch/arm/mach-exynos/clock-exynos5.c +24 -0
index 774533c..af1b917 100644
@@ -668,6 +668,11 @@ static struct clk exynos5_init_clocks_off[] = {
 		.enable		= exynos5_clk_ip_fsys_ctrl ,
 		.ctrlbit	= (1 << 18),
 	}, {
+		.name		= "usbdrd30",
+		.parent		= &exynos5_clk_aclk_200.clk,
+		.enable		= exynos5_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 19),
+	}, {
 		.name		= "usbotg",
 		.enable		= exynos5_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 7),
@@ -909,6 +914,16 @@ struct clksrc_sources exynos5_clkset_group = {
 	.nr_sources	= ARRAY_SIZE(exynos5_clkset_group_list),
 };
 
+struct clk *exynos5_clkset_usbdrd30_list[] = {
+	[0] = &exynos5_clk_mout_mpll.clk,
+	[1] = &exynos5_clk_mout_cpll.clk,
+};
+
+struct clksrc_sources exynos5_clkset_usbdrd30 = {
+	.sources        = exynos5_clkset_usbdrd30_list,
+	.nr_sources     = ARRAY_SIZE(exynos5_clkset_usbdrd30_list),
+};
+
 /* Possible clock sources for aclk_266_gscl_sub Mux */
 static struct clk *clk_src_gscl_266_list[] = {
 	[0] = &clk_ext_xtal_mux,
@@ -1199,6 +1214,15 @@ static struct clksrc_clk exynos5_clksrcs[] = {
 			.parent		= &exynos5_clk_mout_cpll.clk,
 		},
 		.reg_div = { .reg = EXYNOS5_CLKDIV_GEN, .shift = 4, .size = 3 },
+	}, {
+		.clk    = {
+			.name           = "sclk_usbdrd30",
+			.enable         = exynos5_clksrc_mask_fsys_ctrl,
+			.ctrlbit        = (1 << 28),
+		},
+		.sources = &exynos5_clkset_usbdrd30,
+		.reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 28, .size = 1 },
+		.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS0, .shift = 24, .size = 4 },
 	},
 };
 
arch/arm/mach-exynos/common.c +5 -0
index 92d5e61..c17f1df 100644
@@ -280,6 +280,11 @@ static struct map_desc exynos5_iodesc[] __initdata = {
 		.pfn		= __phys_to_pfn(EXYNOS5_PA_USB_PHY),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual        = (unsigned long)S5P_VA_DRD_PHY,
+		.pfn            = __phys_to_pfn(EXYNOS5_PA_DRD_PHY),
+		.length         = SZ_4K,
+		.type           = MT_DEVICE,
 	},
 };
 
arch/arm/mach-exynos/include/mach/map.h +1 -0
index 331ae57..b95b245 100644
@@ -193,6 +193,7 @@
 #define EXYNOS5_PA_UART			0x12C00000
 
 #define EXYNOS5_PA_USB_PHY		0x12130000
+#define EXYNOS5_PA_DRD_PHY		0x12100000
 
 #define EXYNOS4_PA_VP			0x12C00000
 #define EXYNOS4_PA_MIXER		0x12C10000
arch/arm/mach-exynos/include/mach/regs-pmu.h +4 -0
index d4e392b..67132b4 100644
@@ -39,6 +39,10 @@
 #define S5P_HDMI_PHY_CONTROL			S5P_PMUREG(0x0700)
 #define S5P_HDMI_PHY_ENABLE			(1 << 0)
 
+/* only for EXYNOS5250*/
+#define S5P_USBDRD_PHY_CONTROL			S5P_PMUREG(0x0704)
+#define S5P_USBDRD_PHY_ENABLE			(1 << 0)
+
 #define S5P_DAC_PHY_CONTROL			S5P_PMUREG(0x070C)
 #define S5P_DAC_PHY_ENABLE			(1 << 0)
 
arch/arm/plat-samsung/include/plat/map-s5p.h +2 -0
index c2d7bda..836863a 100644
@@ -40,6 +40,8 @@
 #define S5P_VA_GIC_CPU		S3C_ADDR(0x02810000)
 #define S5P_VA_GIC_DIST		S3C_ADDR(0x02820000)
 
+#define S5P_VA_DRD_PHY		S3C_ADDR(0x03000000)
+
 #define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
 #define VA_VIC0			VA_VIC(0)
 #define VA_VIC1			VA_VIC(1)
drivers/usb/Kconfig +1 -0
index a7773a3..e9cbe34 100644
@@ -53,6 +53,7 @@ config USB_ARCH_HAS_EHCI
 # some non-PCI HCDs implement xHCI
 config USB_ARCH_HAS_XHCI
 	boolean
+	default y if ARCH_EXYNOS5
 	default PCI
 
 menuconfig USB_SUPPORT
Signature · 1 line
1.7.0.4
#14 lore raw

PATCH v2 7/8 ARM: EXYNOS5: Add XHCI device from device tree

In reply to Vivek Gautam

This patch adds EHCI device from device tree for exynos5 and adds platform data.

---
 .../devicetree/bindings/usb/exynos-usb.txt         |   19 +++++++++++++++++++
 arch/arm/boot/dts/exynos5250.dtsi                  |    6 ++++++
 arch/arm/mach-exynos/mach-exynos5-dt.c             |    9 +++++++++
 3 files changed, 34 insertions(+), 0 deletions(-)
Documentation/devicetree/bindings/usb/exynos-usb.txt +19 -0
index 45dadca..b2349fe 100644
@@ -39,3 +39,22 @@ ehci {
 	samsung,vbus-gpio = <&gpx2 6 1 3 3>;
 };
 
+XHCI
+Required properties:
+ - compatible:	should be "samsung,exynos-xhci" for USB 3.0
+   DWC3 controller in host mode.
+ - reg: physical base address of the controller and length
+   of memory mapped.
+ - interrupts: interrupt number to the cpu.
+ - samsung,vbus-gpio:  if present, specifies the GPIO
+   that needs to be pulled up for the bus to be powered.
+
+Optional properties:
+ - samsung,vbus-gpio:  if present, specifies the GPIO
+   that needs to be pulled up for the bus to be powered.
+
+xhci {
+	compatible = "samsung,exynos-xhci";
+	reg = <0x12000000 0x10000>;
+	interrupts = <0 72 0>;
+};
arch/arm/boot/dts/exynos5250.dtsi +6 -0
index 988f52a..bc36584 100644
@@ -70,6 +70,12 @@
 		interrupts = <0 71 0>;
 	};
 
+	xhci {
+		compatible = "samsung,exynos-xhci";
+		reg = <0x12000000 0x10000>;
+		interrupts = <0 72 0>;
+	};
+
 	rtc {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x101E0000 0x100>;
arch/arm/mach-exynos/mach-exynos5-dt.c +9 -0
index 0cc626e..fc1ed3f 100644
@@ -10,6 +10,7 @@
 */
 
 #include <linux/of_platform.h>
+#include <linux/platform_data/dwc3-exynos.h>
 #include <linux/serial_core.h>
 
 #include <asm/mach/arch.h>
@@ -34,6 +35,12 @@ static struct s5p_ehci_platdata smdk5250_ehci_pdata = {
 	.phy_exit = s5p_usb_phy_exit,
 };
 
+static struct dwc3_exynos_data smdk5250_xhci_pdata = {
+	.phy_type = S5P_USB_PHY_DRD,
+	.phy_init = s5p_usb_phy_init,
+	.phy_exit = s5p_usb_phy_exit,
+};
+
 /*
  * The following lookup table is used to override device names when devices
  * are registered from device tree. This is temporarily added to enable
@@ -73,6 +80,8 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
 				"exynos-ohci", &smdk5250_ohci_pdata),
 	OF_DEV_AUXDATA("samsung,exynos-ehci", 0x12110000,
 				"s5p-ehci", &smdk5250_ehci_pdata),
+	OF_DEV_AUXDATA("samsung,exynos-xhci", 0x12000000,
+				"exynos-dwc3", &smdk5250_xhci_pdata),
 	{},
 };
 
Signature · 1 line
1.7.0.4
#15 lore raw

PATCH v2 8/8 ARM: EXYNOS5: Add PHY initialization code for usb 3.0

In reply to Vivek Gautam

This patch adds PHY setup functions for usb 3.0 support on exynos5

---
 arch/arm/mach-exynos/setup-usb-phy.c               |  127 ++++++++++++++++++++
 .../include/plat/regs-usb3-exynos-drd-phy.h        |   75 ++++++++++++
 arch/arm/plat-samsung/include/plat/usb-phy.h       |    1 +
 3 files changed, 203 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-samsung/include/plat/regs-usb3-exynos-drd-phy.h
arch/arm/mach-exynos/setup-usb-phy.c +127 -0
index e6f2f84..b90871d 100644
@@ -18,12 +18,14 @@
 #include <mach/regs-usb-phy.h>
 #include <plat/cpu.h>
 #include <plat/usb-phy.h>
+#include <plat/regs-usb3-exynos-drd-phy.h>
 
 #define PHY_ENABLE	1
 #define PHY_DISABLE	0
 
 enum usb_phy_type {
 	USB_PHY		= (0x1 << 0),
+	USB_PHY_DRD	= (0x1 << 1),
 };
 
 static atomic_t host_usage;
@@ -161,11 +163,44 @@ static int exynos4210_usb_phy_clkset(struct platform_device *pdev)
 	return phyclk;
 }
 
+static u32 exynos_usb_phy30_set_clock(struct platform_device *pdev)
+{
+	u32 reg, refclk;
+
+	refclk = exynos4210_usb_phy_clkset(pdev);
+	reg = EXYNOS_USB3_PHYCLKRST_REFCLKSEL(3) |
+	      EXYNOS_USB3_PHYCLKRST_FSEL(refclk);
+
+	switch (refclk) {
+	case EXYNOS5_CLKSEL_50M:
+		reg |= (EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER(0x02) |
+			EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL(0x00));
+		break;
+	case EXYNOS5_CLKSEL_20M:
+		reg |= (EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER(0x7d) |
+			EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL(0x00));
+		break;
+	case EXYNOS5_CLKSEL_19200K:
+		reg |= (EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER(0x02) |
+			EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL(0x88));
+		break;
+	case EXYNOS5_CLKSEL_24M:
+	default:
+		reg |= (EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER(0x68) |
+			EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL(0x88));
+		break;
+	}
+
+	return reg;
+}
+
 static void exynos_usb_phy_control(enum usb_phy_type phy_type , int on)
 {
 	if (soc_is_exynos5250()) {
 		if (phy_type & USB_PHY)
 			writel(on, S5P_USBHOST_PHY_CONTROL);
+		if (phy_type & USB_PHY_DRD)
+			writel(on, S5P_USBDRD_PHY_CONTROL);
 	}
 }
 
@@ -413,6 +448,88 @@ static int exynos5_usb_phy20_exit(struct platform_device *pdev)
 	return 0;
 }
 
+static int exynos5_usb_phy30_init(struct platform_device *pdev)
+{
+	struct clk *host_clk;
+	u32 reg;
+
+	host_clk = exynos_usb_clock_enable(pdev);
+	if (host_clk == NULL) {
+		dev_err(&pdev->dev, "Failed to enable USB3.0 host clock this time\n");
+		return -1;
+	}
+
+	exynos_usb_phy_control(USB_PHY_DRD, PHY_ENABLE);
+
+	/* Reset USB 3.0 PHY */
+	writel(0x00000000, EXYNOS_USB3_PHYREG0);
+	writel(0x24d4e6e4, EXYNOS_USB3_PHYPARAM0);
+	writel(0x03fff81c, EXYNOS_USB3_PHYPARAM1);
+	writel(0x00000000, EXYNOS_USB3_PHYRESUME);
+
+	writel(0x08000040, EXYNOS_USB3_LINKSYSTEM);
+	writel(0x00000004, EXYNOS_USB3_PHYBATCHG);
+
+	/* PHYTEST POWERDOWN Control */
+	reg = readl(EXYNOS_USB3_PHYTEST);
+	reg &= ~(EXYNOS_USB3_PHYTEST_POWERDOWN_SSP |
+		 EXYNOS_USB3_PHYTEST_POWERDOWN_HSP);
+	writel(reg, EXYNOS_USB3_PHYTEST);
+
+	/* UTMI Power Control */
+	writel(EXYNOS_USB3_PHYUTMI_OTGDISABLE, EXYNOS_USB3_PHYUTMI);
+
+	reg = exynos_usb_phy30_set_clock(pdev);
+
+	reg |= (EXYNOS_USB3_PHYCLKRST_PORTRESET |
+		/* Digital power supply in normal operating mode */
+		EXYNOS_USB3_PHYCLKRST_RETENABLEN |
+		/* Enable ref clock for SS function */
+		EXYNOS_USB3_PHYCLKRST_REF_SSP_EN |
+		/* Enable spread spectrum */
+		EXYNOS_USB3_PHYCLKRST_SSC_EN) |
+		EXYNOS_USB3_PHYCLKRST_COMMONONN;
+	writel(reg, EXYNOS_USB3_PHYCLKRST);
+
+	udelay(10);
+
+	reg &= ~(EXYNOS_USB3_PHYCLKRST_PORTRESET);
+	writel(reg, EXYNOS_USB3_PHYCLKRST);
+
+	clk_disable(host_clk);
+	clk_put(host_clk);
+	return 0;
+}
+
+static int exynos5_usb_phy30_exit(struct platform_device *pdev)
+{
+	struct clk *host_clk;
+	u32 reg;
+
+	host_clk = exynos_usb_clock_enable(pdev);
+	if (host_clk == NULL) {
+		dev_err(&pdev->dev, "Failed to enable USB3.0 host clock this time\n");
+		return -1;
+	}
+
+	reg = EXYNOS_USB3_PHYUTMI_OTGDISABLE |
+		EXYNOS_USB3_PHYUTMI_FORCESUSPEND |
+		EXYNOS_USB3_PHYUTMI_FORCESLEEP;
+	writel(reg, EXYNOS_USB3_PHYUTMI);
+
+	/* Control PHYTEST to remove leakage current */
+	reg = readl(EXYNOS_USB3_PHYTEST);
+	reg |= (EXYNOS_USB3_PHYTEST_POWERDOWN_SSP |
+		 EXYNOS_USB3_PHYTEST_POWERDOWN_HSP);
+	writel(reg, EXYNOS_USB3_PHYTEST);
+
+	exynos_usb_phy_control(USB_PHY_DRD, PHY_DISABLE);
+
+	clk_disable(host_clk);
+	clk_put(host_clk);
+	return 0;
+}
+
 int s5p_usb_phy_init(struct platform_device *pdev, int type)
 {
 	if (type == S5P_USB_PHY_DEVICE)
@@ -422,6 +539,11 @@ int s5p_usb_phy_init(struct platform_device *pdev, int type)
 			return exynos5_usb_phy20_init(pdev);
 		else
 			return exynos4210_usb_phy1_init(pdev);
+	} else if (type == S5P_USB_PHY_DRD) {
+		if (soc_is_exynos5250())
+			return exynos5_usb_phy30_init(pdev);
+		else
+			dev_err(&pdev->dev, "USB 3.0 DRD not present\n");
 	}
 
 	return -EINVAL;
@@ -436,6 +558,11 @@ int s5p_usb_phy_exit(struct platform_device *pdev, int type)
 			return exynos5_usb_phy20_exit(pdev);
 		else
 			return exynos4210_usb_phy1_exit(pdev);
+	} else if (type == S5P_USB_PHY_DRD) {
+		if (soc_is_exynos5250())
+			return exynos5_usb_phy30_exit(pdev);
+		else
+			dev_err(&pdev->dev, "USB 3.0 DRD not present\n");
 	}
 	return -EINVAL;
 }
arch/arm/plat-samsung/include/plat/regs-usb3-exynos-drd-phy.h new file +75 -0

75 lines not on this page · raw message

arch/arm/plat-samsung/include/plat/usb-phy.h +1 -0
index 959bcdb..f784101 100644
@@ -14,6 +14,7 @@
 enum s5p_usb_phy_type {
 	S5P_USB_PHY_DEVICE,
 	S5P_USB_PHY_HOST,
+	S5P_USB_PHY_DRD,
 };
 
 extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
Signature · 1 line
1.7.0.4