ARM: S3C64XX: Add usb otg phy control
authorJoonyoung Shim <jy0922.shim@samsung.com>
Wed, 7 Mar 2012 12:23:47 +0000 (04:23 -0800)
committerKukjin Kim <kgene.kim@samsung.com>
Fri, 9 Mar 2012 15:31:30 +0000 (07:31 -0800)
This patch supports to control usb otg phy of S3C64XX. Currently, the
driver for usb otg controls usb otg phy but it can be removed by this
patch.

Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
[Rebased on the newest git/kgene/linux-samsung #for-next]
Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Acked-by: Mark Brown<broonie@opensource.wolfsonmicro.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
arch/arm/mach-s3c64xx/Kconfig
arch/arm/mach-s3c64xx/Makefile
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-smartq.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-s3c64xx/setup-usb-phy.c [new file with mode: 0644]
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h
arch/arm/plat-samsung/include/plat/udc-hs.h

index dd20c66..326ea3a 100644 (file)
@@ -83,6 +83,11 @@ config S3C64XX_SETUP_SPI
        help
         Common setup code for SPI GPIO configurations
 
+config S3C64XX_SETUP_USB_PHY
+       bool
+       help
+         Common setup code for USB PHY controller
+
 # S36400 Macchine support
 
 config MACH_SMDK6400
@@ -157,6 +162,7 @@ config MACH_SMDK6410
        select S3C64XX_SETUP_IDE
        select S3C64XX_SETUP_FB_24BPP
        select S3C64XX_SETUP_KEYPAD
+       select S3C64XX_SETUP_USB_PHY
        help
          Machine support for the Samsung SMDK6410
 
@@ -256,6 +262,7 @@ config MACH_SMARTQ
        select S3C_DEV_USB_HOST
        select S3C64XX_SETUP_SDHCI
        select S3C64XX_SETUP_FB_24BPP
+       select S3C64XX_SETUP_USB_PHY
        select SAMSUNG_DEV_ADC
        select SAMSUNG_DEV_PWM
        select SAMSUNG_DEV_TS
@@ -283,6 +290,7 @@ config MACH_WLF_CRAGG_6410
        select S3C64XX_SETUP_FB_24BPP
        select S3C64XX_SETUP_KEYPAD
        select S3C64XX_SETUP_SPI
+       select S3C64XX_SETUP_USB_PHY
        select SAMSUNG_DEV_ADC
        select SAMSUNG_DEV_KEYPAD
        select S3C_DEV_USB_HOST
index 610fe28..f9ce1dc 100644 (file)
@@ -43,6 +43,7 @@ obj-$(CONFIG_S3C64XX_SETUP_IDE)               += setup-ide.o
 obj-$(CONFIG_S3C64XX_SETUP_KEYPAD)     += setup-keypad.o
 obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
 obj-$(CONFIG_S3C64XX_SETUP_SPI)                += setup-spi.o
+obj-$(CONFIG_S3C64XX_SETUP_USB_PHY) += setup-usb-phy.o
 
 # Machine support
 
index 8077f65..3b56bd9 100644 (file)
@@ -59,6 +59,7 @@
 #include <plat/sdhci.h>
 #include <plat/gpio-cfg.h>
 #include <plat/s3c64xx-spi.h>
+#include <plat/udc-hs.h>
 
 #include <plat/keypad.h>
 #include <plat/clock.h>
@@ -698,6 +699,8 @@ static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = {
        .cfg_gpio               = crag6410_cfg_sdhci0,
 };
 
+static struct s3c_hsotg_plat crag6410_hsotg_pdata;
+
 static void __init crag6410_machine_init(void)
 {
        /* Open drain IRQs need pullups */
@@ -722,6 +725,7 @@ static void __init crag6410_machine_init(void)
        s3c_i2c0_set_platdata(&i2c0_pdata);
        s3c_i2c1_set_platdata(&i2c1_pdata);
        s3c_fb_set_platdata(&crag6410_lcd_pdata);
+       s3c_hsotg_set_platdata(&crag6410_hsotg_pdata);
 
        i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
        i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
index ce31db1..ce745e1 100644 (file)
@@ -187,6 +187,8 @@ static struct s3c_hwmon_pdata smartq_hwmon_pdata __initdata = {
        },
 };
 
+static struct s3c_hsotg_plat smartq_hsotg_pdata;
+
 static int __init smartq_lcd_setup_gpio(void)
 {
        int ret;
@@ -383,6 +385,7 @@ void __init smartq_map_io(void)
 void __init smartq_machine_init(void)
 {
        s3c_i2c0_set_platdata(NULL);
+       s3c_hsotg_set_platdata(&smartq_hsotg_pdata);
        s3c_hwmon_set_platdata(&smartq_hwmon_pdata);
        s3c_sdhci1_set_platdata(&smartq_internal_hsmmc_pdata);
        s3c_sdhci2_set_platdata(&smartq_internal_hsmmc_pdata);
index ca6fc20..d55bc96 100644 (file)
@@ -72,6 +72,7 @@
 #include <plat/keypad.h>
 #include <plat/backlight.h>
 #include <plat/regs-fb-v4.h>
+#include <plat/udc-hs.h>
 
 #include "common.h"
 
@@ -631,6 +632,8 @@ static struct platform_pwm_backlight_data smdk6410_bl_data = {
        .pwm_id = 1,
 };
 
+static struct s3c_hsotg_plat smdk6410_hsotg_pdata;
+
 static void __init smdk6410_map_io(void)
 {
        u32 tmp;
@@ -659,6 +662,7 @@ static void __init smdk6410_machine_init(void)
        s3c_i2c0_set_platdata(NULL);
        s3c_i2c1_set_platdata(NULL);
        s3c_fb_set_platdata(&smdk6410_lcd_pdata);
+       s3c_hsotg_set_platdata(&smdk6410_hsotg_pdata);
 
        samsung_keypad_set_platdata(&smdk6410_keypad_data);
 
diff --git a/arch/arm/mach-s3c64xx/setup-usb-phy.c b/arch/arm/mach-s3c64xx/setup-usb-phy.c
new file mode 100644 (file)
index 0000000..f6757e0
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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/map.h>
+#include <mach/regs-sys.h>
+#include <plat/cpu.h>
+#include <plat/regs-usb-hsotg-phy.h>
+#include <plat/usb-phy.h>
+
+static int s3c_usb_otgphy_init(struct platform_device *pdev)
+{
+       struct clk *xusbxti;
+       u32 phyclk;
+
+       writel(readl(S3C64XX_OTHERS) | S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS);
+
+       /* set clock frequency for PLL */
+       phyclk = readl(S3C_PHYCLK) & ~S3C_PHYCLK_CLKSEL_MASK;
+
+       xusbxti = clk_get(&pdev->dev, "xusbxti");
+       if (xusbxti && !IS_ERR(xusbxti)) {
+               switch (clk_get_rate(xusbxti)) {
+               case 12 * MHZ:
+                       phyclk |= S3C_PHYCLK_CLKSEL_12M;
+                       break;
+               case 24 * MHZ:
+                       phyclk |= S3C_PHYCLK_CLKSEL_24M;
+                       break;
+               default:
+               case 48 * MHZ:
+                       /* default reference clock */
+                       break;
+               }
+               clk_put(xusbxti);
+       }
+
+       /* TODO: select external clock/oscillator */
+       writel(phyclk | S3C_PHYCLK_CLK_FORCE, S3C_PHYCLK);
+
+       /* set to normal OTG PHY */
+       writel((readl(S3C_PHYPWR) & ~S3C_PHYPWR_NORMAL_MASK), S3C_PHYPWR);
+       mdelay(1);
+
+       /* reset OTG PHY and Link */
+       writel(S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK,
+                       S3C_RSTCON);
+       udelay(20);     /* at-least 10uS */
+       writel(0, S3C_RSTCON);
+
+       return 0;
+}
+
+static int s3c_usb_otgphy_exit(struct platform_device *pdev)
+{
+       writel((readl(S3C_PHYPWR) | S3C_PHYPWR_ANALOG_POWERDOWN |
+                               S3C_PHYPWR_OTG_DISABLE), S3C_PHYPWR);
+
+       writel(readl(S3C64XX_OTHERS) & ~S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS);
+
+       return 0;
+}
+
+int s5p_usb_phy_init(struct platform_device *pdev, int type)
+{
+       if (type == S5P_USB_PHY_DEVICE)
+               return s3c_usb_otgphy_init(pdev);
+
+       return -EINVAL;
+}
+
+int s5p_usb_phy_exit(struct platform_device *pdev, int type)
+{
+       if (type == S5P_USB_PHY_DEVICE)
+               return s3c_usb_otgphy_exit(pdev);
+
+       return -EINVAL;
+}
index 145580a..21168ea 100644 (file)
@@ -57,6 +57,7 @@
 #include <plat/sdhci.h>
 #include <plat/ts.h>
 #include <plat/udc.h>
+#include <plat/udc-hs.h>
 #include <plat/usb-control.h>
 #include <plat/usb-phy.h>
 #include <plat/regs-iic.h>
@@ -1449,6 +1450,19 @@ struct platform_device s3c_device_usb_hsotg = {
                .coherent_dma_mask      = DMA_BIT_MASK(32),
        },
 };
+
+void __init s3c_hsotg_set_platdata(struct s3c_hsotg_plat *pd)
+{
+       struct s3c_hsotg_plat *npd;
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c_hsotg_plat),
+                       &s3c_device_usb_hsotg);
+
+       if (!npd->phy_init)
+               npd->phy_init = s5p_usb_phy_init;
+       if (!npd->phy_exit)
+               npd->phy_exit = s5p_usb_phy_exit;
+}
 #endif /* CONFIG_S3C_DEV_USB_HSOTG */
 
 /* USB High Spped 2.0 Device (Gadget) */
index a111ad8..fcf2796 100644 (file)
@@ -25,8 +25,9 @@
 #define S3C_HSOTG_PHYREG(x)    ((x) + S3C_VA_USB_HSPHY)
 
 #define S3C_PHYPWR                             S3C_HSOTG_PHYREG(0x00)
-#define SRC_PHYPWR_OTG_DISABLE                 (1 << 4)
-#define SRC_PHYPWR_ANALOG_POWERDOWN            (1 << 3)
+#define S3C_PHYPWR_NORMAL_MASK                 (0x19 << 0)
+#define S3C_PHYPWR_OTG_DISABLE                 (1 << 4)
+#define S3C_PHYPWR_ANALOG_POWERDOWN            (1 << 3)
 #define SRC_PHYPWR_FORCE_SUSPEND               (1 << 1)
 
 #define S3C_PHYCLK                             S3C_HSOTG_PHYREG(0x04)
@@ -42,7 +43,7 @@
 
 #define S3C_RSTCON                             S3C_HSOTG_PHYREG(0x08)
 #define S3C_RSTCON_PHYCLK                      (1 << 2)
-#define S3C_RSTCON_HCLK                                (1 << 2)
+#define S3C_RSTCON_HCLK                                (1 << 1)
 #define S3C_RSTCON_PHY                         (1 << 0)
 
 #define S3C_PHYTUNE                            S3C_HSOTG_PHYREG(0x20)
index a22a4f2..c9e3667 100644 (file)
@@ -26,4 +26,9 @@ enum s3c_hsotg_dmamode {
 struct s3c_hsotg_plat {
        enum s3c_hsotg_dmamode  dma;
        unsigned int            is_osc : 1;
+
+       int (*phy_init)(struct platform_device *pdev, int type);
+       int (*phy_exit)(struct platform_device *pdev, int type);
 };
+
+extern void s3c_hsotg_set_platdata(struct s3c_hsotg_plat *pd);