ARM: EXYNOS: Add USB OHCI device
authorJingoo Han <jg1.han@samsung.com>
Fri, 23 Dec 2011 02:19:36 +0000 (11:19 +0900)
committerKukjin Kim <kgene.kim@samsung.com>
Fri, 23 Dec 2011 02:21:28 +0000 (11:21 +0900)
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/dev-ohci.c [new file with mode: 0644]
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/include/mach/ohci.h [new file with mode: 0644]
arch/arm/mach-exynos/setup-usb-phy.c
arch/arm/plat-samsung/include/plat/devs.h

index 724ec0f3560ddf5cb00cff43147e1ec3f98bfe3d..a1d1a060b8929c1e02078170cd148d50bb3b7bbd 100644 (file)
@@ -82,6 +82,11 @@ config EXYNOS4_DEV_DWMCI
        help
          Compile in platform device definitions for DWMCI
 
+config EXYNOS4_DEV_USB_OHCI
+       bool
+       help
+         Compile in platform device definition for USB OHCI
+
 config EXYNOS4_SETUP_I2C1
        bool
        help
index 59069a35e40b922a11d3b93ac1dafdb250da92c5..f5f3b799492349c5b69de5cf6664c01b32b6a22a 100644 (file)
@@ -44,6 +44,7 @@ obj-$(CONFIG_EXYNOS4_DEV_AHCI)                += dev-ahci.o
 obj-$(CONFIG_EXYNOS4_DEV_PD)           += dev-pd.o
 obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)       += dev-sysmmu.o
 obj-$(CONFIG_EXYNOS4_DEV_DWMCI)                += dev-dwmci.o
+obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI)     += dev-ohci.o
 
 obj-$(CONFIG_EXYNOS4_SETUP_FIMC)       += setup-fimc.o
 obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)      += setup-fimd0.o
diff --git a/arch/arm/mach-exynos/dev-ohci.c b/arch/arm/mach-exynos/dev-ohci.c
new file mode 100644 (file)
index 0000000..b8e7530
--- /dev/null
@@ -0,0 +1,52 @@
+/* linux/arch/arm/mach-exynos/dev-ohci.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * EXYNOS - OHCI support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+#include <mach/ohci.h>
+
+#include <plat/devs.h>
+#include <plat/usb-phy.h>
+
+static struct resource exynos4_ohci_resource[] = {
+       [0] = DEFINE_RES_MEM(EXYNOS4_PA_OHCI, SZ_256),
+       [1] = DEFINE_RES_IRQ(IRQ_USB_HOST),
+};
+
+static u64 exynos4_ohci_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_ohci = {
+       .name           = "exynos-ohci",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(exynos4_ohci_resource),
+       .resource       = exynos4_ohci_resource,
+       .dev            = {
+               .dma_mask               = &exynos4_ohci_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+
+void __init exynos4_ohci_set_platdata(struct exynos4_ohci_platdata *pd)
+{
+       struct exynos4_ohci_platdata *npd;
+
+       npd = s3c_set_platdata(pd, sizeof(struct exynos4_ohci_platdata),
+                       &exynos4_device_ohci);
+
+       if (!npd->phy_init)
+               npd->phy_init = s5p_usb_phy_init;
+       if (!npd->phy_exit)
+               npd->phy_exit = s5p_usb_phy_exit;
+}
index 058541d45af0906692eb9c6850beb0e903892efe..01e1cf3f9341603692ec29fe75f16b48bddf5585 100644 (file)
 #define EXYNOS4_PA_SROMC               0x12570000
 
 #define EXYNOS4_PA_EHCI                        0x12580000
+#define EXYNOS4_PA_OHCI                        0x12590000
 #define EXYNOS4_PA_HSPHY               0x125B0000
 #define EXYNOS4_PA_MFC                 0x13400000
 
diff --git a/arch/arm/mach-exynos/include/mach/ohci.h b/arch/arm/mach-exynos/include/mach/ohci.h
new file mode 100644 (file)
index 0000000..c256c59
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ *             http://www.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 __MACH_EXYNOS_OHCI_H
+#define __MACH_EXYNOS_OHCI_H
+
+struct exynos4_ohci_platdata {
+       int (*phy_init)(struct platform_device *pdev, int type);
+       int (*phy_exit)(struct platform_device *pdev, int type);
+};
+
+extern void exynos4_ohci_set_platdata(struct exynos4_ohci_platdata *pd);
+
+#endif /* __MACH_EXYNOS_OHCI_H */
index 39aca045f6604ae1b7c4125ee85646ef34df95f0..41743d21e8c6a337ecac51c5499af410c8d7048a 100644 (file)
 #include <plat/cpu.h>
 #include <plat/usb-phy.h>
 
+static atomic_t host_usage;
+
+static int exynos4_usb_host_phy_is_on(void)
+{
+       return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1;
+}
+
 static int exynos4_usb_phy1_init(struct platform_device *pdev)
 {
        struct clk *otg_clk;
@@ -27,6 +34,8 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev)
        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");
@@ -39,6 +48,9 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev)
                return err;
        }
 
+       if (exynos4_usb_host_phy_is_on())
+               return 0;
+
        writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
                        S5P_USBHOST_PHY_CONTROL);
 
@@ -95,6 +107,9 @@ static int exynos4_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");
index ab633c9c2aec51666d69e86b71a2b84c38b98ebf..a2ff27e3ec301734868ed31dd7921b68d604a14c 100644 (file)
@@ -129,6 +129,7 @@ extern struct platform_device exynos4_device_dwmci;
 extern struct platform_device exynos4_device_i2s0;
 extern struct platform_device exynos4_device_i2s1;
 extern struct platform_device exynos4_device_i2s2;
+extern struct platform_device exynos4_device_ohci;
 extern struct platform_device exynos4_device_pcm0;
 extern struct platform_device exynos4_device_pcm1;
 extern struct platform_device exynos4_device_pcm2;