summaryrefslogtreecommitdiff
path: root/arch/arm/mach-exynos4
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-04-19 16:50:26 +0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-04-19 16:50:38 +0400
commit50ee9339c7347c2b16fa79d43777f72e9f41ef5a (patch)
treece09aa147e5c8bb74c72c46cebfdbffeece6678f /arch/arm/mach-exynos4
parentf0e615c3cb72b42191b558c130409335812621d8 (diff)
parent98346f7db014614a4814eb60639f651f8bbc591d (diff)
downloadlinux-50ee9339c7347c2b16fa79d43777f72e9f41ef5a.tar.xz
Merge 2.6.39-rc4 into usb-next
This is needed to help resolve some xhci issues and other minor differences. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'arch/arm/mach-exynos4')
-rw-r--r--arch/arm/mach-exynos4/Kconfig1
-rw-r--r--arch/arm/mach-exynos4/Makefile2
-rw-r--r--arch/arm/mach-exynos4/cpu.c7
-rw-r--r--arch/arm/mach-exynos4/include/mach/map.h4
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-pmu.h3
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-usb-phy.h64
-rw-r--r--arch/arm/mach-exynos4/mach-nuri.c16
-rw-r--r--arch/arm/mach-exynos4/usb-phy.c136
8 files changed, 232 insertions, 1 deletions
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index e849f67be47d..805196207ce8 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -170,6 +170,7 @@ config MACH_NURI
select S3C_DEV_HSMMC3
select S3C_DEV_I2C1
select S3C_DEV_I2C5
+ select S5P_DEV_USB_EHCI
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_I2C5
select EXYNOS4_SETUP_SDHCI
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index 9be104f63c0b..777897551e42 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -54,3 +54,5 @@ obj-$(CONFIG_EXYNOS4_SETUP_I2C7) += setup-i2c7.o
obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o
obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
+
+obj-$(CONFIG_USB_SUPPORT) += usb-phy.o
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 793011391943..08813a6f66b1 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -97,7 +97,12 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
.length = SZ_4K,
.type = MT_DEVICE,
- },
+ }, {
+ .virtual = (unsigned long)S5P_VA_USB_HSPHY,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
+ .length = SZ_4K,
+ .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 6330b73b9ea7..0009e77a05fc 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -101,6 +101,9 @@
#define EXYNOS4_PA_SROMC 0x12570000
+#define EXYNOS4_PA_EHCI 0x12580000
+#define EXYNOS4_PA_HSPHY 0x125B0000
+
#define EXYNOS4_PA_UART 0x13800000
#define EXYNOS4_PA_IIC(x) (0x13860000 + ((x) * 0x10000))
@@ -143,6 +146,7 @@
#define S5P_PA_SROMC EXYNOS4_PA_SROMC
#define S5P_PA_SYSCON EXYNOS4_PA_SYSCON
#define S5P_PA_TIMER EXYNOS4_PA_TIMER
+#define S5P_PA_EHCI EXYNOS4_PA_EHCI
#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 62b0014d05e0..a9643371f8e7 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
@@ -33,6 +33,9 @@
#define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604)
#define S5P_WAKEUP_MASK S5P_PMUREG(0x0608)
+#define S5P_USBHOST_PHY_CONTROL S5P_PMUREG(0x0708)
+#define S5P_USBHOST_PHY_ENABLE (1 << 0)
+
#define S5P_MIPI_DPHY_CONTROL(n) S5P_PMUREG(0x0710 + (n) * 4)
#define S5P_MIPI_DPHY_ENABLE (1 << 0)
#define S5P_MIPI_DPHY_SRESETN (1 << 1)
diff --git a/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h b/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h
new file mode 100644
index 000000000000..703118d5173c
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PLAT_S5P_REGS_USB_PHY_H
+#define __PLAT_S5P_REGS_USB_PHY_H
+
+#define EXYNOS4_HSOTG_PHYREG(x) ((x) + S5P_VA_USB_HSPHY)
+
+#define EXYNOS4_PHYPWR EXYNOS4_HSOTG_PHYREG(0x00)
+#define PHY1_HSIC_NORMAL_MASK (0xf << 9)
+#define PHY1_HSIC1_SLEEP (1 << 12)
+#define PHY1_HSIC1_FORCE_SUSPEND (1 << 11)
+#define PHY1_HSIC0_SLEEP (1 << 10)
+#define PHY1_HSIC0_FORCE_SUSPEND (1 << 9)
+
+#define PHY1_STD_NORMAL_MASK (0x7 << 6)
+#define PHY1_STD_SLEEP (1 << 8)
+#define PHY1_STD_ANALOG_POWERDOWN (1 << 7)
+#define PHY1_STD_FORCE_SUSPEND (1 << 6)
+
+#define PHY0_NORMAL_MASK (0x39 << 0)
+#define PHY0_SLEEP (1 << 5)
+#define PHY0_OTG_DISABLE (1 << 4)
+#define PHY0_ANALOG_POWERDOWN (1 << 3)
+#define PHY0_FORCE_SUSPEND (1 << 0)
+
+#define EXYNOS4_PHYCLK EXYNOS4_HSOTG_PHYREG(0x04)
+#define PHY1_COMMON_ON_N (1 << 7)
+#define PHY0_COMMON_ON_N (1 << 4)
+#define PHY0_ID_PULLUP (1 << 2)
+#define CLKSEL_MASK (0x3 << 0)
+#define CLKSEL_SHIFT (0)
+#define CLKSEL_48M (0x0 << 0)
+#define CLKSEL_12M (0x2 << 0)
+#define CLKSEL_24M (0x3 << 0)
+
+#define EXYNOS4_RSTCON EXYNOS4_HSOTG_PHYREG(0x08)
+#define HOST_LINK_PORT_SWRST_MASK (0xf << 6)
+#define HOST_LINK_PORT2_SWRST (1 << 9)
+#define HOST_LINK_PORT1_SWRST (1 << 8)
+#define HOST_LINK_PORT0_SWRST (1 << 7)
+#define HOST_LINK_ALL_SWRST (1 << 6)
+
+#define PHY1_SWRST_MASK (0x7 << 3)
+#define PHY1_HSIC_SWRST (1 << 5)
+#define PHY1_STD_SWRST (1 << 4)
+#define PHY1_ALL_SWRST (1 << 3)
+
+#define PHY0_SWRST_MASK (0x7 << 0)
+#define PHY0_PHYLINK_SWRST (1 << 2)
+#define PHY0_HLINK_SWRST (1 << 1)
+#define PHY0_SWRST (1 << 0)
+
+#define EXYNOS4_PHY1CON EXYNOS4_HSOTG_PHYREG(0x34)
+#define FPENABLEN (1 << 0)
+
+#endif /* __PLAT_S5P_REGS_USB_PHY_H */
diff --git a/arch/arm/mach-exynos4/mach-nuri.c b/arch/arm/mach-exynos4/mach-nuri.c
index b79ad010d194..bb5d12f43af8 100644
--- a/arch/arm/mach-exynos4/mach-nuri.c
+++ b/arch/arm/mach-exynos4/mach-nuri.c
@@ -30,6 +30,8 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/sdhci.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
#include <mach/map.h>
@@ -262,6 +264,16 @@ static struct i2c_board_info i2c5_devs[] __initdata = {
/* max8997, To be updated */
};
+/* USB EHCI */
+static struct s5p_ehci_platdata nuri_ehci_pdata;
+
+static void __init nuri_ehci_init(void)
+{
+ struct s5p_ehci_platdata *pdata = &nuri_ehci_pdata;
+
+ s5p_ehci_set_platdata(pdata);
+}
+
static struct platform_device *nuri_devices[] __initdata = {
/* Samsung Platform Devices */
&emmc_fixed_voltage,
@@ -270,6 +282,7 @@ static struct platform_device *nuri_devices[] __initdata = {
&s3c_device_hsmmc3,
&s3c_device_wdt,
&s3c_device_timer[0],
+ &s5p_device_ehci,
/* NURI Devices */
&nuri_gpio_keys,
@@ -291,6 +304,9 @@ static void __init nuri_machine_init(void)
i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+ nuri_ehci_init();
+ clk_xusbxti.rate = 24000000;
+
/* Last */
platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
}
diff --git a/arch/arm/mach-exynos4/usb-phy.c b/arch/arm/mach-exynos4/usb-phy.c
new file mode 100644
index 000000000000..0883c1b824b9
--- /dev/null
+++ b/arch/arm/mach-exynos4/usb-phy.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <mach/regs-pmu.h>
+#include <mach/regs-usb-phy.h>
+#include <plat/cpu.h>
+#include <plat/usb-phy.h>
+
+static int exynos4_usb_phy1_init(struct platform_device *pdev)
+{
+ struct clk *otg_clk;
+ struct clk *xusbxti_clk;
+ u32 phyclk;
+ u32 rstcon;
+ int err;
+
+ 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;
+ }
+
+ 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;
+
+ xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
+ if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
+ switch (clk_get_rate(xusbxti_clk)) {
+ case 12 * MHZ:
+ phyclk |= CLKSEL_12M;
+ break;
+ case 24 * MHZ:
+ phyclk |= CLKSEL_24M;
+ break;
+ default:
+ case 48 * MHZ:
+ /* default reference clock */
+ break;
+ }
+ clk_put(xusbxti_clk);
+ }
+
+ writel(phyclk, EXYNOS4_PHYCLK);
+
+ /* floating prevention logic: disable */
+ writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
+
+ /* 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);
+
+ /* 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);
+ udelay(50);
+
+ clk_disable(otg_clk);
+ clk_put(otg_clk);
+
+ return 0;
+}
+
+static int exynos4_usb_phy1_exit(struct platform_device *pdev)
+{
+ struct clk *otg_clk;
+ int err;
+
+ 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;
+ }
+
+ writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
+ EXYNOS4_PHYPWR);
+
+ writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
+ S5P_USBHOST_PHY_CONTROL);
+
+ clk_disable(otg_clk);
+ clk_put(otg_clk);
+
+ return 0;
+}
+
+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;
+}
+
+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;
+}