aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBhuvana Kakunoori <bhuvana.kakunoori@linaro.org>2011-08-05 11:39:36 +0530
committerAngus Ainslie <angus.ainslie@linaro.org>2011-08-18 17:15:37 -0600
commitf6b6d021c38c79525e9c9d92b643bd554f8273a0 (patch)
tree0fecb12dd8e2e4fa08760f2275b7813a2aa5f355
parent83000329b33dedc0ad1dc13e1714e1b3a4c8b077 (diff)
ARM: EXYNOS4: Add support for USB Gadget Device
Adds support for USB Gadget Device on Exynos4 SoCs. In addition, USB PHY0 configuration for USB Device Controller is added in setup-usb-phy.c Signed-off-by: Bhuvana Kakunoori <bhuvana.kakunoori@linaro.org> Signed-off-by: Pankaj Dubey <pankaj.dubey@samung.com>
-rw-r--r--arch/arm/mach-exynos4/Kconfig4
-rw-r--r--arch/arm/mach-exynos4/cpu.c7
-rw-r--r--arch/arm/mach-exynos4/include/mach/map.h3
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-pmu.h1
-rw-r--r--arch/arm/mach-exynos4/setup-usb-phy.c85
5 files changed, 69 insertions, 31 deletions
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 286d6cd8bd9e..a351725c8251 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -162,6 +162,7 @@ config MACH_SMDKV310
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
select S3C_DEV_HSMMC3
+ select S5P_DEV_USB_HSDEVICE
select EXYNOS4_DEV_AHCI
select SAMSUNG_DEV_KEYPAD
select SAMSUNG_DEV_TS
@@ -171,6 +172,7 @@ config MACH_SMDKV310
select EXYNOS4_SETUP_KEYPAD
select EXYNOS4_SETUP_TS
select EXYNOS4_SETUP_SDHCI
+ select EXYNOS4_SETUP_USB_PHY
help
Machine support for Samsung SMDKV310
@@ -243,6 +245,8 @@ config MACH_ORIGEN
select EXYNOS4_SETUP_SDHCI
select EXYNOS4_SETUP_I2C0
select EXYNOS4_SETUP_I2C1
+ select S5P_DEV_USB_HSDEVICE
+ select EXYNOS4_SETUP_USB_PHY
help
Machine support for ORIGEN based on Samsung EXYNOS4210
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 3b8a7c3f2050..e945bee44a53 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -114,7 +114,12 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
.length = SZ_4K,
.type = MT_DEVICE,
- }
+ }, {
+ .virtual = (unsigned long)S3C_VA_HSDEVICE,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_HSDEVICE),
+ .length = SZ_64K,
+ .type = MT_DEVICE,
+ },
};
static void exynos4_idle(void)
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 40da20abe097..033ec76fe640 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -99,6 +99,8 @@
#define EXYNOS4_PA_MIPI_CSIS0 0x11880000
#define EXYNOS4_PA_MIPI_CSIS1 0x11890000
+#define EXYNOS4_PA_HSDEVICE 0x12480000
+
#define EXYNOS4_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000))
#define EXYNOS4_PA_SATA 0x12560000
@@ -157,6 +159,7 @@
#define S5P_PA_SYSCON EXYNOS4_PA_SYSCON
#define S5P_PA_TIMER EXYNOS4_PA_TIMER
#define S5P_PA_EHCI EXYNOS4_PA_EHCI
+#define S5P_PA_HSDEVICE EXYNOS4_PA_HSDEVICE
#define SAMSUNG_PA_KEYPAD EXYNOS4_PA_KEYPAD
diff --git a/arch/arm/mach-exynos4/include/mach/regs-pmu.h b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
index a9643371f8e7..526e551437a4 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
@@ -33,6 +33,7 @@
#define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604)
#define S5P_WAKEUP_MASK S5P_PMUREG(0x0608)
+#define S5P_USBDEVICE_PHY_CONTROL S5P_PMUREG(0x0704)
#define S5P_USBHOST_PHY_CONTROL S5P_PMUREG(0x0708)
#define S5P_USBHOST_PHY_ENABLE (1 << 0)
diff --git a/arch/arm/mach-exynos4/setup-usb-phy.c b/arch/arm/mach-exynos4/setup-usb-phy.c
index 0883c1b824b9..bec562662149 100644
--- a/arch/arm/mach-exynos4/setup-usb-phy.c
+++ b/arch/arm/mach-exynos4/setup-usb-phy.c
@@ -14,12 +14,14 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <linux/usb/ch9.h>
#include <mach/regs-pmu.h>
#include <mach/regs-usb-phy.h>
#include <plat/cpu.h>
#include <plat/usb-phy.h>
+#include <plat/regs-otg.h>
-static int exynos4_usb_phy1_init(struct platform_device *pdev)
+static int exynos4_usb_phy1_init(struct platform_device *pdev, int type)
{
struct clk *otg_clk;
struct clk *xusbxti_clk;
@@ -39,9 +41,6 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev)
return err;
}
- writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
- S5P_USBHOST_PHY_CONTROL);
-
/* set clock frequency for PLL */
phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
@@ -64,24 +63,43 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev)
writel(phyclk, EXYNOS4_PHYCLK);
- /* floating prevention logic: disable */
- writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
+ if (type == S5P_USB_PHY_HOST) {
+ writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
+ S5P_USBHOST_PHY_CONTROL);
+
+ writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
- /* set to normal HSIC 0 and 1 of PHY1 */
- writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK),
+ /* 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);
+ /* 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;
- writel(rstcon, EXYNOS4_RSTCON);
- udelay(10);
+ /* reset all ports of both PHY and Link */
+ rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK |
+ PHY1_SWRST_MASK;
+
+ writel(rstcon, EXYNOS4_RSTCON);
+ udelay(10);
+
+ rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
+ writel(rstcon, EXYNOS4_RSTCON);
+ } else if (type == S5P_USB_PHY_DEVICE) {
+ writel(readl(S5P_USBDEVICE_PHY_CONTROL) | (0x1<<0),
+ S5P_USBDEVICE_PHY_CONTROL);
+ writel((readl(EXYNOS4_PHYPWR) & ~(0x7<<3)&~(0x1<<0)),
+ EXYNOS4_PHYPWR);
+ writel((readl(EXYNOS4_PHYCLK) & ~(0x5<<2))|(0x3<<0),
+ EXYNOS4_PHYCLK);
+ writel((readl(EXYNOS4_RSTCON) & ~(0x3<<1))|(0x1<<0),
+ EXYNOS4_RSTCON);
+ udelay(10);
+ writel(readl(EXYNOS4_RSTCON) & ~(0x7<<0),
+ EXYNOS4_RSTCON);
+ }
- rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
- writel(rstcon, EXYNOS4_RSTCON);
udelay(50);
clk_disable(otg_clk);
@@ -90,7 +108,7 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev)
return 0;
}
-static int exynos4_usb_phy1_exit(struct platform_device *pdev)
+static int exynos4_usb_phy1_exit(struct platform_device *pdev, int type)
{
struct clk *otg_clk;
int err;
@@ -107,11 +125,20 @@ static int exynos4_usb_phy1_exit(struct platform_device *pdev)
return err;
}
- writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
- EXYNOS4_PHYPWR);
+ if (type == S5P_USB_PHY_HOST) {
+ writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
+ EXYNOS4_PHYPWR);
- writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
- S5P_USBHOST_PHY_CONTROL);
+ writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
+ S5P_USBHOST_PHY_CONTROL);
+ } else if (type == S5P_USB_PHY_DEVICE) {
+ writel(readl(EXYNOS4_PHYPWR) | (0x3<<3),
+ EXYNOS4_PHYPWR);
+
+ writel(readl(S5P_USBDEVICE_PHY_CONTROL) & ~(1<<0),
+ S5P_USBDEVICE_PHY_CONTROL);
+
+ }
clk_disable(otg_clk);
clk_put(otg_clk);
@@ -121,16 +148,14 @@ static int exynos4_usb_phy1_exit(struct platform_device *pdev)
int s5p_usb_phy_init(struct platform_device *pdev, int type)
{
- if (type == S5P_USB_PHY_HOST)
- return exynos4_usb_phy1_init(pdev);
-
- return -EINVAL;
+ return exynos4_usb_phy1_init(pdev, type);
}
int s5p_usb_phy_exit(struct platform_device *pdev, int type)
{
- if (type == S5P_USB_PHY_HOST)
- return exynos4_usb_phy1_exit(pdev);
-
- return -EINVAL;
+ return exynos4_usb_phy1_exit(pdev, type);
}
+
+/* USB Control request data struct must be located here for DMA transfer */
+struct usb_ctrlrequest usb_ctrl __attribute__((aligned(8)));
+EXPORT_SYMBOL(usb_ctrl);