diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig index dd20c66cd700..326ea3a98725 100644 --- a/arch/arm/mach-s3c64xx/Kconfig +++ b/arch/arm/mach-s3c64xx/Kconfig @@ -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 diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile index 610fe2807ed7..f9ce1dc28ce4 100644 --- a/arch/arm/mach-s3c64xx/Makefile +++ b/arch/arm/mach-s3c64xx/Makefile @@ -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 diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index 8077f650eb0e..3b56bd9cb880 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include @@ -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)); diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c index ce31db136231..ce745e19aa27 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq.c +++ b/arch/arm/mach-s3c64xx/mach-smartq.c @@ -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); diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index ca6fc204f0ea..d55bc96d9582 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -72,6 +72,7 @@ #include #include #include +#include #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 index 000000000000..f6757e02d7db --- /dev/null +++ b/arch/arm/mach-s3c64xx/setup-usb-phy.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2011 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 145580a4a62c..21168eaad356 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -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) */ diff --git a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h index a111ad871833..fcf279662067 100644 --- a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h +++ b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h @@ -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) diff --git a/arch/arm/plat-samsung/include/plat/udc-hs.h b/arch/arm/plat-samsung/include/plat/udc-hs.h index a22a4f2eea94..c9e3667cb2b1 100644 --- a/arch/arm/plat-samsung/include/plat/udc-hs.h +++ b/arch/arm/plat-samsung/include/plat/udc-hs.h @@ -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);