diff options
author | Bhuvana Kakunoori <bhuvana.kakunoori@linaro.org> | 2011-08-05 11:39:36 +0530 |
---|---|---|
committer | Angus Ainslie <angus.ainslie@linaro.org> | 2011-08-18 17:15:37 -0600 |
commit | f6b6d021c38c79525e9c9d92b643bd554f8273a0 (patch) | |
tree | 0fecb12dd8e2e4fa08760f2275b7813a2aa5f355 | |
parent | 83000329b33dedc0ad1dc13e1714e1b3a4c8b077 (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/Kconfig | 4 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/cpu.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/include/mach/map.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/include/mach/regs-pmu.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/setup-usb-phy.c | 85 |
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); |