diff options
-rw-r--r-- | arch/arm/mach-exynos/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/mach-exynos/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-exynos/clock.c | 73 | ||||
-rw-r--r-- | arch/arm/mach-exynos/include/mach/irqs.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-exynos/include/mach/map.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-exynos/include/mach/spi-clocks.h | 16 | ||||
-rw-r--r-- | arch/arm/mach-exynos/setup-spi.c | 72 | ||||
-rw-r--r-- | arch/arm/mach-s5p64x0/Kconfig | 24 | ||||
-rw-r--r-- | arch/arm/mach-s5p64x0/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-s5p64x0/clock-s5p6440.c | 72 | ||||
-rw-r--r-- | arch/arm/mach-s5p64x0/clock-s5p6450.c | 72 | ||||
-rw-r--r-- | arch/arm/mach-s5p64x0/cpu.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-s5p64x0/mach-smdk6440.c | 25 | ||||
-rw-r--r-- | arch/arm/mach-s5p64x0/mach-smdk6450.c | 26 | ||||
-rw-r--r-- | arch/arm/mach-s5p64x0/setup-sdhci-gpio.c | 104 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/sdhci.h | 44 |
16 files changed, 463 insertions, 91 deletions
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 0afcc3b0f870..c925fecfa50a 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -148,6 +148,11 @@ config EXYNOS4_SETUP_USB_PHY help Common setup code for USB PHY controller +config EXYNOS4_SETUP_SPI + bool + help + Common setup code for SPI GPIO configurations. + # machine support if ARCH_EXYNOS4 diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 57e529620804..979fdd3d14e6 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_EXYNOS4_SETUP_I2C7) += setup-i2c7.o obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY) += setup-usb-phy.o +obj-$(CONFIG_EXYNOS4_SETUP_SPI) += setup-spi.o diff --git a/arch/arm/mach-exynos/clock.c b/arch/arm/mach-exynos/clock.c index 5d8d4831e244..da50b1af7568 100644 --- a/arch/arm/mach-exynos/clock.c +++ b/arch/arm/mach-exynos/clock.c @@ -1111,36 +1111,6 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 }, }, { .clk = { - .name = "sclk_spi", - .devname = "s3c64xx-spi.0", - .enable = exynos4_clksrc_mask_peril1_ctrl, - .ctrlbit = (1 << 16), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_spi", - .devname = "s3c64xx-spi.1", - .enable = exynos4_clksrc_mask_peril1_ctrl, - .ctrlbit = (1 << 20), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 }, - }, { - .clk = { - .name = "sclk_spi", - .devname = "s3c64xx-spi.2", - .enable = exynos4_clksrc_mask_peril1_ctrl, - .ctrlbit = (1 << 24), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 }, - }, { - .clk = { .name = "sclk_fimg2d", }, .sources = &clkset_mout_g2d, @@ -1257,6 +1227,42 @@ static struct clksrc_clk clk_sclk_mmc3 = { .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 }, }; +static struct clksrc_clk clk_sclk_spi0 = { + .clk = { + .name = "sclk_spi", + .devname = "s3c64xx-spi.0", + .enable = exynos4_clksrc_mask_peril1_ctrl, + .ctrlbit = (1 << 16), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_spi1 = { + .clk = { + .name = "sclk_spi", + .devname = "s3c64xx-spi.1", + .enable = exynos4_clksrc_mask_peril1_ctrl, + .ctrlbit = (1 << 20), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_spi2 = { + .clk = { + .name = "sclk_spi", + .devname = "s3c64xx-spi.2", + .enable = exynos4_clksrc_mask_peril1_ctrl, + .ctrlbit = (1 << 24), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 }, +}; + /* Clock initialization code */ static struct clksrc_clk *sysclks[] = { &clk_mout_apll, @@ -1305,6 +1311,10 @@ static struct clksrc_clk *clksrc_cdev[] = { &clk_sclk_mmc1, &clk_sclk_mmc2, &clk_sclk_mmc3, + &clk_sclk_spi0, + &clk_sclk_spi1, + &clk_sclk_spi2, + }; static struct clk_lookup exynos4_clk_lookup[] = { @@ -1318,6 +1328,9 @@ static struct clk_lookup exynos4_clk_lookup[] = { CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3.clk), CLKDEV_INIT("dma-pl330.0", "apb_pclk", &clk_pdma0), CLKDEV_INIT("dma-pl330.1", "apb_pclk", &clk_pdma1), + CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0", &clk_sclk_spi0.clk), + CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk0", &clk_sclk_spi1.clk), + CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk0", &clk_sclk_spi2.clk), }; static int xtal_rate; diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index 713dd5251c64..f77bce04789a 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h @@ -72,6 +72,9 @@ #define IRQ_IIC5 IRQ_SPI(63) #define IRQ_IIC6 IRQ_SPI(64) #define IRQ_IIC7 IRQ_SPI(65) +#define IRQ_SPI0 IRQ_SPI(66) +#define IRQ_SPI1 IRQ_SPI(67) +#define IRQ_SPI2 IRQ_SPI(68) #define IRQ_USB_HOST IRQ_SPI(70) #define IRQ_USB_HSOTG IRQ_SPI(71) diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 058541d45af0..e6ba01d115f6 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -87,6 +87,10 @@ #define EXYNOS4_PA_SYSMMU_TV 0x12E20000 #define EXYNOS4_PA_SYSMMU_MFC_L 0x13620000 #define EXYNOS4_PA_SYSMMU_MFC_R 0x13630000 +#define EXYNOS4_PA_SPI0 0x13920000 +#define EXYNOS4_PA_SPI1 0x13930000 +#define EXYNOS4_PA_SPI2 0x13940000 + #define EXYNOS4_PA_GPIO1 0x11400000 #define EXYNOS4_PA_GPIO2 0x11000000 @@ -148,6 +152,9 @@ #define S3C_PA_RTC EXYNOS4_PA_RTC #define S3C_PA_WDT EXYNOS4_PA_WATCHDOG #define S3C_PA_UART EXYNOS4_PA_UART +#define S3C_PA_SPI0 EXYNOS4_PA_SPI0 +#define S3C_PA_SPI1 EXYNOS4_PA_SPI1 +#define S3C_PA_SPI2 EXYNOS4_PA_SPI2 #define S5P_PA_CHIPID EXYNOS4_PA_CHIPID #define S5P_PA_EHCI EXYNOS4_PA_EHCI diff --git a/arch/arm/mach-exynos/include/mach/spi-clocks.h b/arch/arm/mach-exynos/include/mach/spi-clocks.h new file mode 100644 index 000000000000..576efdf6d091 --- /dev/null +++ b/arch/arm/mach-exynos/include/mach/spi-clocks.h @@ -0,0 +1,16 @@ +/* linux/arch/arm/mach-exynos4/include/mach/spi-clocks.h + * + * Copyright (C) 2011 Samsung Electronics Co. Ltd. + * + * 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. + */ + +#ifndef __ASM_ARCH_SPI_CLKS_H +#define __ASM_ARCH_SPI_CLKS_H __FILE__ + +/* Must source from SCLK_SPI */ +#define EXYNOS4_SPI_SRCCLK_SCLK 0 + +#endif /* __ASM_ARCH_SPI_CLKS_H */ diff --git a/arch/arm/mach-exynos/setup-spi.c b/arch/arm/mach-exynos/setup-spi.c new file mode 100644 index 000000000000..833ff40ee0e8 --- /dev/null +++ b/arch/arm/mach-exynos/setup-spi.c @@ -0,0 +1,72 @@ +/* linux/arch/arm/mach-exynos4/setup-spi.c + * + * Copyright (C) 2011 Samsung Electronics 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 version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/gpio.h> +#include <linux/platform_device.h> + +#include <plat/gpio-cfg.h> +#include <plat/s3c64xx-spi.h> + +#ifdef CONFIG_S3C64XX_DEV_SPI0 +struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = { + .fifo_lvl_mask = 0x1ff, + .rx_lvl_offset = 15, + .high_speed = 1, + .clk_from_cmu = true, + .tx_st_done = 25, +}; + +int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(EXYNOS4_GPB(0), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(EXYNOS4_GPB(0), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); + return 0; +} +#endif + +#ifdef CONFIG_S3C64XX_DEV_SPI1 +struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = { + .fifo_lvl_mask = 0x7f, + .rx_lvl_offset = 15, + .high_speed = 1, + .clk_from_cmu = true, + .tx_st_done = 25, +}; + +int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(EXYNOS4_GPB(4), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(EXYNOS4_GPB(4), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); + return 0; +} +#endif + +#ifdef CONFIG_S3C64XX_DEV_SPI2 +struct s3c64xx_spi_info s3c64xx_spi2_pdata __initdata = { + .fifo_lvl_mask = 0x7f, + .rx_lvl_offset = 15, + .high_speed = 1, + .clk_from_cmu = true, + .tx_st_done = 25, +}; + +int s3c64xx_spi2_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(EXYNOS4_GPC1(1), S3C_GPIO_SFN(5)); + s3c_gpio_setpull(EXYNOS4_GPC1(1), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(EXYNOS4_GPC1(3), 2, + S3C_GPIO_SFN(5), S3C_GPIO_PULL_UP); + return 0; +} +#endif diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig index dd8c85ef6dab..c87f6108eeb1 100644 --- a/arch/arm/mach-s5p64x0/Kconfig +++ b/arch/arm/mach-s5p64x0/Kconfig @@ -41,6 +41,11 @@ config S5P64X0_SETUP_SPI help Common setup code for SPI GPIO configurations +config S5P64X0_SETUP_SDHCI_GPIO + bool + help + Common setup code for SDHCI gpio. + # machine support config MACH_SMDK6440 @@ -50,12 +55,16 @@ config MACH_SMDK6440 select S3C_DEV_I2C1 select S3C_DEV_RTC select S3C_DEV_WDT + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_HSMMC2 select SAMSUNG_DEV_ADC select SAMSUNG_DEV_BACKLIGHT select SAMSUNG_DEV_PWM select SAMSUNG_DEV_TS select S5P64X0_SETUP_FB_24BPP select S5P64X0_SETUP_I2C1 + select S5P64X0_SETUP_SDHCI_GPIO help Machine support for the Samsung SMDK6440 @@ -66,13 +75,28 @@ config MACH_SMDK6450 select S3C_DEV_I2C1 select S3C_DEV_RTC select S3C_DEV_WDT + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_HSMMC2 select SAMSUNG_DEV_ADC select SAMSUNG_DEV_BACKLIGHT select SAMSUNG_DEV_PWM select SAMSUNG_DEV_TS select S5P64X0_SETUP_FB_24BPP select S5P64X0_SETUP_I2C1 + select S5P64X0_SETUP_SDHCI_GPIO help Machine support for the Samsung SMDK6450 +menu "Use 8-bit SDHCI bus width" + +config S5P64X0_SD_CH1_8BIT + bool "SDHCI Channel 1 (Slot 1)" + depends on MACH_SMDK6450 || MACH_SMDK6440 + help + Support SDHCI Channel 1 8-bit bus. + If selected, Channel 2 is disabled. + +endmenu + endif diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile index a7d7a499d99e..b44cc044b3c3 100644 --- a/arch/arm/mach-s5p64x0/Makefile +++ b/arch/arm/mach-s5p64x0/Makefile @@ -30,3 +30,4 @@ obj-y += dev-audio.o obj-$(CONFIG_S5P64X0_SETUP_I2C1) += setup-i2c1.o obj-$(CONFIG_S5P64X0_SETUP_FB_24BPP) += setup-fb-24bpp.o obj-$(CONFIG_S5P64X0_SETUP_SPI) += setup-spi.o +obj-$(CONFIG_S5P64X0_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c index 73c7cc9ef0dd..c041ad7fbd60 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6440.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c @@ -379,36 +379,6 @@ static struct clksrc_sources clkset_audio = { static struct clksrc_clk clksrcs[] = { { .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.0", - .ctrlbit = (1 << 24), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.1", - .ctrlbit = (1 << 25), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.2", - .ctrlbit = (1 << 26), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 }, - }, { - .clk = { .name = "sclk_post", .ctrlbit = (1 << 10), .enable = s5p64x0_sclk_ctrl, @@ -446,6 +416,42 @@ static struct clksrc_clk clksrcs[] = { }, }; +static struct clksrc_clk clk_sclk_mmc0 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.0", + .ctrlbit = (1 << 24), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_mmc1 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.1", + .ctrlbit = (1 << 25), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_mmc2 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.2", + .ctrlbit = (1 << 26), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 }, +}; + static struct clksrc_clk clk_sclk_uclk = { .clk = { .name = "uclk1", @@ -503,6 +509,9 @@ static struct clksrc_clk *clksrc_cdev[] = { &clk_sclk_uclk, &clk_sclk_spi0, &clk_sclk_spi1, + &clk_sclk_mmc0, + &clk_sclk_mmc1, + &clk_sclk_mmc2 }; static struct clk_lookup s5p6440_clk_lookup[] = { @@ -511,6 +520,9 @@ static struct clk_lookup s5p6440_clk_lookup[] = { CLKDEV_INIT(NULL, "spi_busclk0", &clk_p), CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk), CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk), + CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk), + CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk), + CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk), }; void __init_or_cpufreq s5p6440_setup_clocks(void) diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c index 50f90cbf7798..b5087cb6e818 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6450.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c @@ -413,36 +413,6 @@ static struct clksrc_clk clk_sclk_audio0 = { static struct clksrc_clk clksrcs[] = { { .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.0", - .ctrlbit = (1 << 24), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group2, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.1", - .ctrlbit = (1 << 25), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group2, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.2", - .ctrlbit = (1 << 26), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group2, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 }, - }, { - .clk = { .name = "sclk_fimc", .ctrlbit = (1 << 10), .enable = s5p64x0_sclk_ctrl, @@ -507,6 +477,42 @@ static struct clksrc_clk clksrcs[] = { }, }; +static struct clksrc_clk clk_sclk_mmc0 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.0", + .ctrlbit = (1 << 24), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_mmc1 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.1", + .ctrlbit = (1 << 25), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_mmc2 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.2", + .ctrlbit = (1 << 26), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 }, +}; + static struct clksrc_clk clk_sclk_uclk = { .clk = { .name = "uclk1", @@ -546,6 +552,9 @@ static struct clksrc_clk *clksrc_cdev[] = { &clk_sclk_uclk, &clk_sclk_spi0, &clk_sclk_spi1, + &clk_sclk_mmc0, + &clk_sclk_mmc1, + &clk_sclk_mmc2, }; static struct clk_lookup s5p6450_clk_lookup[] = { @@ -554,6 +563,9 @@ static struct clk_lookup s5p6450_clk_lookup[] = { CLKDEV_INIT(NULL, "spi_busclk0", &clk_p), CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk), CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk), + CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk), + CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk), + CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk), }; /* Clock initialization code */ diff --git a/arch/arm/mach-s5p64x0/cpu.c b/arch/arm/mach-s5p64x0/cpu.c index ecab40cf19ab..f6e24f3ef760 100644 --- a/arch/arm/mach-s5p64x0/cpu.c +++ b/arch/arm/mach-s5p64x0/cpu.c @@ -40,6 +40,7 @@ #include <plat/s5p6450.h> #include <plat/adc-core.h> #include <plat/fb-core.h> +#include <plat/sdhci.h> /* Initial IO mappings */ @@ -112,6 +113,10 @@ void __init s5p6440_map_io(void) s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); + s5p64x0_default_sdhci0(); + s5p64x0_default_sdhci1(); + s5p6440_default_sdhci2(); + iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc)); init_consistent_dma_size(SZ_8M); @@ -123,6 +128,10 @@ void __init s5p6450_map_io(void) s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); + s5p64x0_default_sdhci0(); + s5p64x0_default_sdhci1(); + s5p6450_default_sdhci2(); + iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc)); init_consistent_dma_size(SZ_8M); diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c index 4a1250cd1356..fe168a087531 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6440.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -24,6 +24,7 @@ #include <linux/gpio.h> #include <linux/pwm_backlight.h> #include <linux/fb.h> +#include <linux/mmc/host.h> #include <video/platform_lcd.h> @@ -52,6 +53,7 @@ #include <plat/backlight.h> #include <plat/fb.h> #include <plat/regs-fb.h> +#include <plat/sdhci.h> #define SMDK6440_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ @@ -161,6 +163,25 @@ static struct platform_device *smdk6440_devices[] __initdata = { &s5p6440_device_iis, &s3c_device_fb, &smdk6440_lcd_lte480wv, + &s3c_device_hsmmc0, + &s3c_device_hsmmc1, + &s3c_device_hsmmc2, +}; + +static struct s3c_sdhci_platdata smdk6440_hsmmc0_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_NONE, +}; + +static struct s3c_sdhci_platdata smdk6440_hsmmc1_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_INTERNAL, +#if defined(CONFIG_S5P64X0_SD_CH1_8BIT) + .max_width = 8, + .host_caps = MMC_CAP_8_BIT_DATA, +#endif +}; + +static struct s3c_sdhci_platdata smdk6440_hsmmc2_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_NONE, }; static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = { @@ -234,6 +255,10 @@ static void __init smdk6440_machine_init(void) s5p6440_set_lcd_interface(); s3c_fb_set_platdata(&smdk6440_lcd_pdata); + s3c_sdhci0_set_platdata(&smdk6440_hsmmc0_pdata); + s3c_sdhci1_set_platdata(&smdk6440_hsmmc1_pdata); + s3c_sdhci2_set_platdata(&smdk6440_hsmmc2_pdata); + platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices)); } diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c index 0ab129ecf009..242a415dcf6b 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6450.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -24,6 +24,7 @@ #include <linux/gpio.h> #include <linux/pwm_backlight.h> #include <linux/fb.h> +#include <linux/mmc/host.h> #include <video/platform_lcd.h> @@ -52,6 +53,7 @@ #include <plat/backlight.h> #include <plat/fb.h> #include <plat/regs-fb.h> +#include <plat/sdhci.h> #define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ @@ -179,10 +181,28 @@ static struct platform_device *smdk6450_devices[] __initdata = { &s5p6450_device_iis0, &s3c_device_fb, &smdk6450_lcd_lte480wv, - + &s3c_device_hsmmc0, + &s3c_device_hsmmc1, + &s3c_device_hsmmc2, /* s5p6450_device_spi0 will be added */ }; +static struct s3c_sdhci_platdata smdk6450_hsmmc0_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_NONE, +}; + +static struct s3c_sdhci_platdata smdk6450_hsmmc1_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_NONE, +#if defined(CONFIG_S5P64X0_SD_CH1_8BIT) + .max_width = 8, + .host_caps = MMC_CAP_8_BIT_DATA, +#endif +}; + +static struct s3c_sdhci_platdata smdk6450_hsmmc2_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_NONE, +}; + static struct s3c2410_platform_i2c s5p6450_i2c0_data __initdata = { .flags = 0, .slave_addr = 0x10, @@ -254,6 +274,10 @@ static void __init smdk6450_machine_init(void) s5p6450_set_lcd_interface(); s3c_fb_set_platdata(&smdk6450_lcd_pdata); + s3c_sdhci0_set_platdata(&smdk6450_hsmmc0_pdata); + s3c_sdhci1_set_platdata(&smdk6450_hsmmc1_pdata); + s3c_sdhci2_set_platdata(&smdk6450_hsmmc2_pdata); + platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices)); } diff --git a/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c b/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c new file mode 100644 index 000000000000..8410af0d12bf --- /dev/null +++ b/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c @@ -0,0 +1,104 @@ +/* linux/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5P64X0 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC) + * + * 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/platform_device.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <mach/regs-gpio.h> +#include <mach/regs-clock.h> + +#include <plat/gpio-cfg.h> +#include <plat/sdhci.h> +#include <plat/cpu.h> + +void s5p64x0_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) +{ + struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; + + /* Set all the necessary GPG pins to special-function 2 */ + if (soc_is_s5p6450()) + s3c_gpio_cfgrange_nopull(S5P6450_GPG(0), 2 + width, + S3C_GPIO_SFN(2)); + else + s3c_gpio_cfgrange_nopull(S5P6440_GPG(0), 2 + width, + S3C_GPIO_SFN(2)); + + /* Set GPG[6] pin to special-function 2 - MMC0 CDn */ + if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { + if (soc_is_s5p6450()) { + s3c_gpio_setpull(S5P6450_GPG(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5P6450_GPG(6), S3C_GPIO_SFN(2)); + } else { + s3c_gpio_setpull(S5P6440_GPG(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5P6440_GPG(6), S3C_GPIO_SFN(2)); + } + } +} + +void s5p64x0_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) +{ + struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; + + /* Set GPH[0:1] pins to special-function 2 - CLK and CMD */ + if (soc_is_s5p6450()) + s3c_gpio_cfgrange_nopull(S5P6450_GPH(0), 2, S3C_GPIO_SFN(2)); + else + s3c_gpio_cfgrange_nopull(S5P6440_GPH(0), 2 , S3C_GPIO_SFN(2)); + + switch (width) { + case 8: + /* Set data pins GPH[6:9] special-function 2 */ + if (soc_is_s5p6450()) + s3c_gpio_cfgrange_nopull(S5P6450_GPH(6), 4, + S3C_GPIO_SFN(2)); + else + s3c_gpio_cfgrange_nopull(S5P6440_GPH(6), 4, + S3C_GPIO_SFN(2)); + case 4: + /* set data pins GPH[2:5] special-function 2 */ + if (soc_is_s5p6450()) + s3c_gpio_cfgrange_nopull(S5P6450_GPH(2), 4, + S3C_GPIO_SFN(2)); + else + s3c_gpio_cfgrange_nopull(S5P6440_GPH(2), 4, + S3C_GPIO_SFN(2)); + default: + break; + } + + /* Set GPG[6] pin to special-funtion 3 : MMC1 CDn */ + if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { + if (soc_is_s5p6450()) { + s3c_gpio_setpull(S5P6450_GPG(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5P6450_GPG(6), S3C_GPIO_SFN(3)); + } else { + s3c_gpio_setpull(S5P6440_GPG(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5P6440_GPG(6), S3C_GPIO_SFN(3)); + } + } +} + +void s5p6440_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) +{ + /* Set GPC[4:5] pins to special-function 3 - CLK and CMD */ + s3c_gpio_cfgrange_nopull(S5P6440_GPC(4), 2, S3C_GPIO_SFN(3)); + + /* Set data pins GPH[6:9] pins to special-function 3 */ + s3c_gpio_cfgrange_nopull(S5P6440_GPH(6), 4, S3C_GPIO_SFN(3)); +} + +void s5p6450_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) +{ + /* Set all the necessary GPG pins to special-function 3 */ + s3c_gpio_cfgrange_nopull(S5P6450_GPG(7), 2 + width, S3C_GPIO_SFN(3)); +} diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h index dcff7dd1ae8a..656dc00d30ed 100644 --- a/arch/arm/plat-samsung/include/plat/sdhci.h +++ b/arch/arm/plat-samsung/include/plat/sdhci.h @@ -123,6 +123,10 @@ extern void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *, int w); extern void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *, int w); extern void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *, int w); extern void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *, int w); +extern void s5p64x0_setup_sdhci0_cfg_gpio(struct platform_device *, int w); +extern void s5p64x0_setup_sdhci1_cfg_gpio(struct platform_device *, int w); +extern void s5p6440_setup_sdhci2_cfg_gpio(struct platform_device *, int w); +extern void s5p6450_setup_sdhci2_cfg_gpio(struct platform_device *, int w); /* S3C2416 SDHCI setup */ @@ -146,6 +150,7 @@ static inline void s3c2416_default_sdhci0(void) { } static inline void s3c2416_default_sdhci1(void) { } #endif /* CONFIG_S3C2416_SETUP_SDHCI */ + /* S3C64XX SDHCI setup */ #ifdef CONFIG_S3C64XX_SETUP_SDHCI @@ -201,6 +206,45 @@ static inline void s3c6400_default_sdhci2(void) { } #endif /* CONFIG_S3C64XX_SETUP_SDHCI */ +/* S5P64X0 SDHCI setup */ + +#ifdef CONFIG_S5P64X0_SETUP_SDHCI +static inline void s5p64x0_default_sdhci0(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC + s3c_hsmmc0_def_platdata.cfg_gpio = s5p64x0_setup_sdhci0_cfg_gpio; +#endif +} + +static inline void s5p64x0_default_sdhci1(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC1 + s3c_hsmmc1_def_platdata.cfg_gpio = s5p64x0_setup_sdhci1_cfg_gpio; +#endif +} + +static inline void s5p6440_default_sdhci2(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC2 + s3c_hsmmc2_def_platdata.cfg_gpio = s5p6440_setup_sdhci2_cfg_gpio; +#endif +} + +static inline void s5p6450_default_sdhci2(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC2 + s3c_hsmmc2_def_platdata.cfg_gpio = s5p6450_setup_sdhci2_cfg_gpio; +#endif +} + +#else +static inline void s5p64x0_default_sdhci0(void) { } +static inline void s5p64x0_default_sdhci1(void) { } +static inline void s5p6440_default_sdhci2(void) { } +static inline void s5p6450_default_sdhci2(void) { } + +#endif /* CONFIG_S5P64X0_SETUP_SDHCI */ + /* S5PC100 SDHCI setup */ #ifdef CONFIG_S5PC100_SETUP_SDHCI |