diff options
Diffstat (limited to 'arch/arm/mach-s5p64x0')
35 files changed, 1756 insertions, 1058 deletions
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig index 65c7518dad7f..c87f6108eeb1 100644 --- a/arch/arm/mach-s5p64x0/Kconfig +++ b/arch/arm/mach-s5p64x0/Kconfig @@ -9,53 +9,94 @@ if ARCH_S5P64X0 config CPU_S5P6440 bool - select S3C_PL330_DMA + select SAMSUNG_DMADEV select S5P_HRT + select S5P_SLEEP if PM + select SAMSUNG_WAKEMASK if PM help Enable S5P6440 CPU support config CPU_S5P6450 bool - select S3C_PL330_DMA + select SAMSUNG_DMADEV select S5P_HRT + select S5P_SLEEP if PM + select SAMSUNG_WAKEMASK if PM help Enable S5P6450 CPU support +config S5P64X0_SETUP_FB_24BPP + bool + help + Common setup code for S5P64X0 based boards with a LCD display + through RGB interface. + config S5P64X0_SETUP_I2C1 bool help Common setup code for i2c bus 1. +config S5P64X0_SETUP_SPI + bool + 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 bool "SMDK6440" select CPU_S5P6440 + select S3C_DEV_FB select S3C_DEV_I2C1 select S3C_DEV_RTC select S3C_DEV_WDT - select S3C64XX_DEV_SPI + 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 config MACH_SMDK6450 bool "SMDK6450" select CPU_S5P6450 + select S3C_DEV_FB select S3C_DEV_I2C1 select S3C_DEV_RTC select S3C_DEV_WDT - select S3C64XX_DEV_SPI + 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 5f6afdf067ed..12bb951187a4 100644 --- a/arch/arm/mach-s5p64x0/Makefile +++ b/arch/arm/mach-s5p64x0/Makefile @@ -10,13 +10,16 @@ obj-m := obj-n := obj- := -# Core support for S5P64X0 system +# Core -obj-$(CONFIG_ARCH_S5P64X0) += cpu.o init.o clock.o dma.o gpiolib.o -obj-$(CONFIG_ARCH_S5P64X0) += setup-i2c0.o irq-eint.o +obj-y += common.o clock.o obj-$(CONFIG_CPU_S5P6440) += clock-s5p6440.o obj-$(CONFIG_CPU_S5P6450) += clock-s5p6450.o +obj-$(CONFIG_PM) += pm.o irq-pm.o + +obj-y += dma.o + # machine support obj-$(CONFIG_MACH_SMDK6440) += mach-smdk6440.o @@ -25,6 +28,9 @@ obj-$(CONFIG_MACH_SMDK6450) += mach-smdk6450.o # device support obj-y += dev-audio.o -obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o +obj-y += setup-i2c0.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/Makefile.boot b/arch/arm/mach-s5p64x0/Makefile.boot index ff90aa13bd67..79ece4055b02 100644 --- a/arch/arm/mach-s5p64x0/Makefile.boot +++ b/arch/arm/mach-s5p64x0/Makefile.boot @@ -1,2 +1,2 @@ - zreladdr-y := 0x20008000 + zreladdr-y += 0x20008000 params_phys-y := 0x20000100 diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c index 0e9cd3092dd2..ee1e8e7f5631 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6440.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c @@ -17,7 +17,7 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/clk.h> -#include <linux/sysdev.h> +#include <linux/device.h> #include <linux/io.h> #include <mach/hardware.h> @@ -31,7 +31,8 @@ #include <plat/pll.h> #include <plat/s5p-clock.h> #include <plat/clock-clksrc.h> -#include <plat/s5p6440.h> + +#include "common.h" static u32 epll_div[][5] = { { 36000000, 0, 48, 1, 4 }, @@ -146,7 +147,8 @@ static struct clk init_clocks_off[] = { .enable = s5p64x0_hclk0_ctrl, .ctrlbit = (1 << 8), }, { - .name = "pdma", + .name = "dma", + .devname = "dma-pl330", .parent = &clk_hclk_low.clk, .enable = s5p64x0_hclk0_ctrl, .ctrlbit = (1 << 12), @@ -267,18 +269,6 @@ static struct clk init_clocks_off[] = { .enable = s5p64x0_pclk_ctrl, .ctrlbit = (1 << 31), }, { - .name = "sclk_spi_48", - .devname = "s3c64xx-spi.0", - .parent = &clk_48m, - .enable = s5p64x0_sclk_ctrl, - .ctrlbit = (1 << 22), - }, { - .name = "sclk_spi_48", - .devname = "s3c64xx-spi.1", - .parent = &clk_48m, - .enable = s5p64x0_sclk_ctrl, - .ctrlbit = (1 << 23), - }, { .name = "mmc_48m", .devname = "s3c-sdhci.0", .parent = &clk_48m, @@ -390,65 +380,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 = "uclk1", - .ctrlbit = (1 << 5), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_uart, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 }, - .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 }, - }, { - .clk = { - .name = "sclk_spi", - .devname = "s3c64xx-spi.0", - .ctrlbit = (1 << 20), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_spi", - .devname = "s3c64xx-spi.1", - .ctrlbit = (1 << 21), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 }, - }, { - .clk = { .name = "sclk_post", .ctrlbit = (1 << 10), .enable = s5p64x0_sclk_ctrl, @@ -486,6 +417,77 @@ 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", + .ctrlbit = (1 << 5), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_uart, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_spi0 = { + .clk = { + .name = "sclk_spi", + .devname = "s3c64xx-spi.0", + .ctrlbit = (1 << 20), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_spi1 = { + .clk = { + .name = "sclk_spi", + .devname = "s3c64xx-spi.1", + .ctrlbit = (1 << 21), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 }, +}; + /* Clock initialization code */ static struct clksrc_clk *sysclks[] = { &clk_mout_apll, @@ -499,6 +501,31 @@ static struct clksrc_clk *sysclks[] = { &clk_pclk_low, }; +static struct clk dummy_apb_pclk = { + .name = "apb_pclk", + .id = -1, +}; + +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[] = { + CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk), + CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk), + 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) { struct clk *xtal_clk; @@ -577,9 +604,14 @@ void __init s5p6440_register_clocks(void) s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++) + s3c_register_clksrc(clksrc_cdev[ptr], 1); s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + clkdev_add_table(s5p6440_clk_lookup, ARRAY_SIZE(s5p6440_clk_lookup)); + + s3c24xx_register_clock(&dummy_apb_pclk); s3c_pwmclk_init(); } diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c index d9dc16cde109..dae6a13f43bb 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6450.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c @@ -17,7 +17,7 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/clk.h> -#include <linux/sysdev.h> +#include <linux/device.h> #include <linux/io.h> #include <mach/hardware.h> @@ -31,7 +31,8 @@ #include <plat/pll.h> #include <plat/s5p-clock.h> #include <plat/clock-clksrc.h> -#include <plat/s5p6450.h> + +#include "common.h" static struct clksrc_clk clk_mout_dpll = { .clk = { @@ -179,7 +180,8 @@ static struct clk init_clocks_off[] = { .enable = s5p64x0_hclk0_ctrl, .ctrlbit = (1 << 3), }, { - .name = "pdma", + .name = "dma", + .devname = "dma-pl330", .parent = &clk_hclk_low.clk, .enable = s5p64x0_hclk0_ctrl, .ctrlbit = (1 << 12), @@ -412,65 +414,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 = "uclk1", - .ctrlbit = (1 << 5), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_uart, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 }, - .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 }, - }, { - .clk = { - .name = "sclk_spi", - .devname = "s3c64xx-spi.0", - .ctrlbit = (1 << 20), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group2, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_spi", - .devname = "s3c64xx-spi.1", - .ctrlbit = (1 << 21), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group2, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 }, - }, { - .clk = { .name = "sclk_fimc", .ctrlbit = (1 << 10), .enable = s5p64x0_sclk_ctrl, @@ -535,6 +478,97 @@ 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", + .ctrlbit = (1 << 5), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_uart, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_spi0 = { + .clk = { + .name = "sclk_spi", + .devname = "s3c64xx-spi.0", + .ctrlbit = (1 << 20), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_spi1 = { + .clk = { + .name = "sclk_spi", + .devname = "s3c64xx-spi.1", + .ctrlbit = (1 << 21), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 }, +}; + +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[] = { + CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk), + CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk), + 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 */ static struct clksrc_clk *sysclks[] = { &clk_mout_apll, @@ -553,6 +587,11 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_audio0, }; +static struct clk dummy_apb_pclk = { + .name = "apb_pclk", + .id = -1, +}; + void __init_or_cpufreq s5p6450_setup_clocks(void) { struct clk *xtal_clk; @@ -628,9 +667,14 @@ void __init s5p6450_register_clocks(void) s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++) + s3c_register_clksrc(clksrc_cdev[ptr], 1); s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + clkdev_add_table(s5p6450_clk_lookup, ARRAY_SIZE(s5p6450_clk_lookup)); + + s3c24xx_register_clock(&dummy_apb_pclk); s3c_pwmclk_init(); } diff --git a/arch/arm/mach-s5p64x0/clock.c b/arch/arm/mach-s5p64x0/clock.c index b52c6e2f37a6..241d0e645c85 100644 --- a/arch/arm/mach-s5p64x0/clock.c +++ b/arch/arm/mach-s5p64x0/clock.c @@ -17,7 +17,7 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/clk.h> -#include <linux/sysdev.h> +#include <linux/device.h> #include <linux/io.h> #include <mach/hardware.h> @@ -30,8 +30,8 @@ #include <plat/pll.h> #include <plat/s5p-clock.h> #include <plat/clock-clksrc.h> -#include <plat/s5p6440.h> -#include <plat/s5p6450.h> + +#include "common.h" struct clksrc_clk clk_mout_apll = { .clk = { diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c new file mode 100644 index 000000000000..52b89a376447 --- /dev/null +++ b/arch/arm/mach-s5p64x0/common.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Common Codes for S5P64X0 machines + * + * 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/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/device.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/sched.h> +#include <linux/dma-mapping.h> +#include <linux/gpio.h> +#include <linux/irq.h> + +#include <asm/irq.h> +#include <asm/proc-fns.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/map.h> +#include <mach/hardware.h> +#include <mach/regs-clock.h> +#include <mach/regs-gpio.h> + +#include <plat/cpu.h> +#include <plat/clock.h> +#include <plat/devs.h> +#include <plat/pm.h> +#include <plat/sdhci.h> +#include <plat/adc-core.h> +#include <plat/fb-core.h> +#include <plat/gpio-cfg.h> +#include <plat/regs-irqtype.h> +#include <plat/regs-serial.h> +#include <plat/watchdog-reset.h> + +#include "common.h" + +static const char name_s5p6440[] = "S5P6440"; +static const char name_s5p6450[] = "S5P6450"; + +static struct cpu_table cpu_ids[] __initdata = { + { + .idcode = S5P6440_CPU_ID, + .idmask = S5P64XX_CPU_MASK, + .map_io = s5p6440_map_io, + .init_clocks = s5p6440_init_clocks, + .init_uarts = s5p6440_init_uarts, + .init = s5p64x0_init, + .name = name_s5p6440, + }, { + .idcode = S5P6450_CPU_ID, + .idmask = S5P64XX_CPU_MASK, + .map_io = s5p6450_map_io, + .init_clocks = s5p6450_init_clocks, + .init_uarts = s5p6450_init_uarts, + .init = s5p64x0_init, + .name = name_s5p6450, + }, +}; + +/* Initial IO mappings */ + +static struct map_desc s5p64x0_iodesc[] __initdata = { + { + .virtual = (unsigned long)S5P_VA_CHIPID, + .pfn = __phys_to_pfn(S5P64X0_PA_CHIPID), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_SYS, + .pfn = __phys_to_pfn(S5P64X0_PA_SYSCON), + .length = SZ_64K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_TIMER, + .pfn = __phys_to_pfn(S5P64X0_PA_TIMER), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_WATCHDOG, + .pfn = __phys_to_pfn(S5P64X0_PA_WDT), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_SROMC, + .pfn = __phys_to_pfn(S5P64X0_PA_SROMC), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_GPIO, + .pfn = __phys_to_pfn(S5P64X0_PA_GPIO), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC0, + .pfn = __phys_to_pfn(S5P64X0_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC1, + .pfn = __phys_to_pfn(S5P64X0_PA_VIC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, +}; + +static struct map_desc s5p6440_iodesc[] __initdata = { + { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S5P6440_PA_UART(0)), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +static struct map_desc s5p6450_iodesc[] __initdata = { + { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S5P6450_PA_UART(0)), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_UART + SZ_512K, + .pfn = __phys_to_pfn(S5P6450_PA_UART(5)), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +static void s5p64x0_idle(void) +{ + unsigned long val; + + if (!need_resched()) { + val = __raw_readl(S5P64X0_PWR_CFG); + val &= ~(0x3 << 5); + val |= (0x1 << 5); + __raw_writel(val, S5P64X0_PWR_CFG); + + cpu_do_idle(); + } + local_irq_enable(); +} + +/* + * s5p64x0_map_io + * + * register the standard CPU IO areas + */ + +void __init s5p64x0_init_io(struct map_desc *mach_desc, int size) +{ + /* initialize the io descriptors we need for initialization */ + iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); + if (mach_desc) + iotable_init(mach_desc, size); + + /* detect cpu id and rev. */ + s5p_init_cpu(S5P64X0_SYS_ID); + + s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids)); +} + +void __init s5p6440_map_io(void) +{ + /* initialize any device information early */ + s3c_adc_setname("s3c64xx-adc"); + s3c_fb_setname("s5p64x0-fb"); + + s5p64x0_default_sdhci0(); + s5p64x0_default_sdhci1(); + s5p6440_default_sdhci2(); + + iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc)); + init_consistent_dma_size(SZ_8M); +} + +void __init s5p6450_map_io(void) +{ + /* initialize any device information early */ + s3c_adc_setname("s3c64xx-adc"); + s3c_fb_setname("s5p64x0-fb"); + + s5p64x0_default_sdhci0(); + s5p64x0_default_sdhci1(); + s5p6450_default_sdhci2(); + + iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc)); + init_consistent_dma_size(SZ_8M); +} + +/* + * s5p64x0_init_clocks + * + * register and setup the CPU clocks + */ + +void __init s5p6440_init_clocks(int xtal) +{ + printk(KERN_DEBUG "%s: initializing clocks\n", __func__); + + s3c24xx_register_baseclocks(xtal); + s5p_register_clocks(xtal); + s5p6440_register_clocks(); + s5p6440_setup_clocks(); +} + +void __init s5p6450_init_clocks(int xtal) +{ + printk(KERN_DEBUG "%s: initializing clocks\n", __func__); + + s3c24xx_register_baseclocks(xtal); + s5p_register_clocks(xtal); + s5p6450_register_clocks(); + s5p6450_setup_clocks(); +} + +/* + * s5p64x0_init_irq + * + * register the CPU interrupts + */ + +void __init s5p6440_init_irq(void) +{ + /* S5P6440 supports 2 VIC */ + u32 vic[2]; + + /* + * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)] + * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22] + */ + vic[0] = 0xff800ae7; + vic[1] = 0xffbf23e5; + + s5p_init_irq(vic, ARRAY_SIZE(vic)); +} + +void __init s5p6450_init_irq(void) +{ + /* S5P6450 supports only 2 VIC */ + u32 vic[2]; + + /* + * VIC0 is missing IRQ_VIC0[(13-15), (21-22)] + * VIC1 is missing IRQ VIC1[12, 14, 23] + */ + vic[0] = 0xff9f1fff; + vic[1] = 0xff7fafff; + + s5p_init_irq(vic, ARRAY_SIZE(vic)); +} + +struct bus_type s5p64x0_subsys = { + .name = "s5p64x0-core", + .dev_name = "s5p64x0-core", +}; + +static struct device s5p64x0_dev = { + .bus = &s5p64x0_subsys, +}; + +static int __init s5p64x0_core_init(void) +{ + return subsys_system_register(&s5p64x0_subsys, NULL); +} +core_initcall(s5p64x0_core_init); + +int __init s5p64x0_init(void) +{ + printk(KERN_INFO "S5P64X0(S5P6440/S5P6450): Initializing architecture\n"); + + /* set idle function */ + pm_idle = s5p64x0_idle; + + return device_register(&s5p64x0_dev); +} + +/* uart registration process */ +void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + int uart; + + for (uart = 0; uart < no; uart++) { + s5p_uart_resources[uart].resources->start = S5P6440_PA_UART(uart); + s5p_uart_resources[uart].resources->end = S5P6440_PA_UART(uart) + S5P_SZ_UART; + } + + s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no); +} + +void __init s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no); +} + +#define eint_offset(irq) ((irq) - IRQ_EINT(0)) + +static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type) +{ + int offs = eint_offset(data->irq); + int shift; + u32 ctrl, mask; + u32 newvalue = 0; + + if (offs > 15) + return -EINVAL; + + switch (type) { + case IRQ_TYPE_NONE: + printk(KERN_WARNING "No edge setting!\n"); + break; + case IRQ_TYPE_EDGE_RISING: + newvalue = S3C2410_EXTINT_RISEEDGE; + break; + case IRQ_TYPE_EDGE_FALLING: + newvalue = S3C2410_EXTINT_FALLEDGE; + break; + case IRQ_TYPE_EDGE_BOTH: + newvalue = S3C2410_EXTINT_BOTHEDGE; + break; + case IRQ_TYPE_LEVEL_LOW: + newvalue = S3C2410_EXTINT_LOWLEV; + break; + case IRQ_TYPE_LEVEL_HIGH: + newvalue = S3C2410_EXTINT_HILEV; + break; + default: + printk(KERN_ERR "No such irq type %d", type); + return -EINVAL; + } + + shift = (offs / 2) * 4; + mask = 0x7 << shift; + + ctrl = __raw_readl(S5P64X0_EINT0CON0) & ~mask; + ctrl |= newvalue << shift; + __raw_writel(ctrl, S5P64X0_EINT0CON0); + + /* Configure the GPIO pin for 6450 or 6440 based on CPU ID */ + if (soc_is_s5p6450()) + s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2)); + else + s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2)); + + return 0; +} + +/* + * s5p64x0_irq_demux_eint + * + * This function demuxes the IRQ from the group0 external interrupts, + * from IRQ_EINT(0) to IRQ_EINT(15). It is designed to be inlined into + * the specific handlers s5p64x0_irq_demux_eintX_Y. + */ +static inline void s5p64x0_irq_demux_eint(unsigned int start, unsigned int end) +{ + u32 status = __raw_readl(S5P64X0_EINT0PEND); + u32 mask = __raw_readl(S5P64X0_EINT0MASK); + unsigned int irq; + + status &= ~mask; + status >>= start; + status &= (1 << (end - start + 1)) - 1; + + for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) { + if (status & 1) + generic_handle_irq(irq); + status >>= 1; + } +} + +static void s5p64x0_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc) +{ + s5p64x0_irq_demux_eint(0, 3); +} + +static void s5p64x0_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc) +{ + s5p64x0_irq_demux_eint(4, 11); +} + +static void s5p64x0_irq_demux_eint12_15(unsigned int irq, + struct irq_desc *desc) +{ + s5p64x0_irq_demux_eint(12, 15); +} + +static int s5p64x0_alloc_gc(void) +{ + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + + gc = irq_alloc_generic_chip("s5p64x0-eint", 1, S5P_IRQ_EINT_BASE, + S5P_VA_GPIO, handle_level_irq); + if (!gc) { + printk(KERN_ERR "%s: irq_alloc_generic_chip for group 0" + "external interrupts failed\n", __func__); + return -EINVAL; + } + + ct = gc->chip_types; + ct->chip.irq_ack = irq_gc_ack_set_bit; + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = irq_gc_mask_clr_bit; + ct->chip.irq_set_type = s5p64x0_irq_eint_set_type; + ct->chip.irq_set_wake = s3c_irqext_wake; + ct->regs.ack = EINT0PEND_OFFSET; + ct->regs.mask = EINT0MASK_OFFSET; + irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST | IRQ_NOPROBE, 0); + return 0; +} + +static int __init s5p64x0_init_irq_eint(void) +{ + int ret = s5p64x0_alloc_gc(); + irq_set_chained_handler(IRQ_EINT0_3, s5p64x0_irq_demux_eint0_3); + irq_set_chained_handler(IRQ_EINT4_11, s5p64x0_irq_demux_eint4_11); + irq_set_chained_handler(IRQ_EINT12_15, s5p64x0_irq_demux_eint12_15); + + return ret; +} +arch_initcall(s5p64x0_init_irq_eint); + +void s5p64x0_restart(char mode, const char *cmd) +{ + if (mode != 's') + arch_wdt_reset(); + + soft_restart(0); +} diff --git a/arch/arm/mach-s5p64x0/common.h b/arch/arm/mach-s5p64x0/common.h new file mode 100644 index 000000000000..f8a60fdc5884 --- /dev/null +++ b/arch/arm/mach-s5p64x0/common.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Common Header for S5P64X0 machines + * + * 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 __ARCH_ARM_MACH_S5P64X0_COMMON_H +#define __ARCH_ARM_MACH_S5P64X0_COMMON_H + +void s5p6440_init_irq(void); +void s5p6450_init_irq(void); +void s5p64x0_init_io(struct map_desc *mach_desc, int size); + +void s5p6440_register_clocks(void); +void s5p6440_setup_clocks(void); + +void s5p6450_register_clocks(void); +void s5p6450_setup_clocks(void); + +void s5p64x0_restart(char mode, const char *cmd); + +#ifdef CONFIG_CPU_S5P6440 + +extern int s5p64x0_init(void); +extern void s5p6440_map_io(void); +extern void s5p6440_init_clocks(int xtal); + +extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +#else +#define s5p6440_init_clocks NULL +#define s5p6440_init_uarts NULL +#define s5p6440_map_io NULL +#define s5p64x0_init NULL +#endif + +#ifdef CONFIG_CPU_S5P6450 + +extern int s5p64x0_init(void); +extern void s5p6450_map_io(void); +extern void s5p6450_init_clocks(int xtal); + +extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +#else +#define s5p6450_init_clocks NULL +#define s5p6450_init_uarts NULL +#define s5p6450_map_io NULL +#define s5p64x0_init NULL +#endif + +#endif /* __ARCH_ARM_MACH_S5P64X0_COMMON_H */ diff --git a/arch/arm/mach-s5p64x0/cpu.c b/arch/arm/mach-s5p64x0/cpu.c deleted file mode 100644 index a5c00952ea35..000000000000 --- a/arch/arm/mach-s5p64x0/cpu.c +++ /dev/null @@ -1,209 +0,0 @@ -/* linux/arch/arm/mach-s5p64x0/cpu.c - * - * Copyright (c) 2009-2010 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 version 2 as - * published by the Free Software Foundation. -*/ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/init.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/sysdev.h> -#include <linux/serial_core.h> -#include <linux/platform_device.h> -#include <linux/sched.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/irq.h> -#include <asm/proc-fns.h> -#include <asm/irq.h> - -#include <mach/hardware.h> -#include <mach/map.h> -#include <mach/regs-clock.h> - -#include <plat/regs-serial.h> -#include <plat/cpu.h> -#include <plat/devs.h> -#include <plat/clock.h> -#include <plat/s5p6440.h> -#include <plat/s5p6450.h> -#include <plat/adc-core.h> - -/* Initial IO mappings */ - -static struct map_desc s5p64x0_iodesc[] __initdata = { - { - .virtual = (unsigned long)S5P_VA_GPIO, - .pfn = __phys_to_pfn(S5P64X0_PA_GPIO), - .length = SZ_4K, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)VA_VIC0, - .pfn = __phys_to_pfn(S5P64X0_PA_VIC0), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)VA_VIC1, - .pfn = __phys_to_pfn(S5P64X0_PA_VIC1), - .length = SZ_16K, - .type = MT_DEVICE, - }, -}; - -static struct map_desc s5p6440_iodesc[] __initdata = { - { - .virtual = (unsigned long)S3C_VA_UART, - .pfn = __phys_to_pfn(S5P6440_PA_UART(0)), - .length = SZ_4K, - .type = MT_DEVICE, - }, -}; - -static struct map_desc s5p6450_iodesc[] __initdata = { - { - .virtual = (unsigned long)S3C_VA_UART, - .pfn = __phys_to_pfn(S5P6450_PA_UART(0)), - .length = SZ_512K, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)S3C_VA_UART + SZ_512K, - .pfn = __phys_to_pfn(S5P6450_PA_UART(5)), - .length = SZ_4K, - .type = MT_DEVICE, - }, -}; - -static void s5p64x0_idle(void) -{ - unsigned long val; - - if (!need_resched()) { - val = __raw_readl(S5P64X0_PWR_CFG); - val &= ~(0x3 << 5); - val |= (0x1 << 5); - __raw_writel(val, S5P64X0_PWR_CFG); - - cpu_do_idle(); - } - local_irq_enable(); -} - -/* - * s5p64x0_map_io - * - * register the standard CPU IO areas - */ - -void __init s5p6440_map_io(void) -{ - /* initialize any device information early */ - s3c_adc_setname("s3c64xx-adc"); - - iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); - iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc)); -} - -void __init s5p6450_map_io(void) -{ - /* initialize any device information early */ - s3c_adc_setname("s3c64xx-adc"); - - iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); - iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc)); -} - -/* - * s5p64x0_init_clocks - * - * register and setup the CPU clocks - */ - -void __init s5p6440_init_clocks(int xtal) -{ - printk(KERN_DEBUG "%s: initializing clocks\n", __func__); - - s3c24xx_register_baseclocks(xtal); - s5p_register_clocks(xtal); - s5p6440_register_clocks(); - s5p6440_setup_clocks(); -} - -void __init s5p6450_init_clocks(int xtal) -{ - printk(KERN_DEBUG "%s: initializing clocks\n", __func__); - - s3c24xx_register_baseclocks(xtal); - s5p_register_clocks(xtal); - s5p6450_register_clocks(); - s5p6450_setup_clocks(); -} - -/* - * s5p64x0_init_irq - * - * register the CPU interrupts - */ - -void __init s5p6440_init_irq(void) -{ - /* S5P6440 supports 2 VIC */ - u32 vic[2]; - - /* - * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)] - * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22] - */ - vic[0] = 0xff800ae7; - vic[1] = 0xffbf23e5; - - s5p_init_irq(vic, ARRAY_SIZE(vic)); -} - -void __init s5p6450_init_irq(void) -{ - /* S5P6450 supports only 2 VIC */ - u32 vic[2]; - - /* - * VIC0 is missing IRQ_VIC0[(13-15), (21-22)] - * VIC1 is missing IRQ VIC1[12, 14, 23] - */ - vic[0] = 0xff9f1fff; - vic[1] = 0xff7fafff; - - s5p_init_irq(vic, ARRAY_SIZE(vic)); -} - -struct sysdev_class s5p64x0_sysclass = { - .name = "s5p64x0-core", -}; - -static struct sys_device s5p64x0_sysdev = { - .cls = &s5p64x0_sysclass, -}; - -static int __init s5p64x0_core_init(void) -{ - return sysdev_class_register(&s5p64x0_sysclass); -} -core_initcall(s5p64x0_core_init); - -int __init s5p64x0_init(void) -{ - printk(KERN_INFO "S5P64X0(S5P6440/S5P6450): Initializing architecture\n"); - - /* set idle function */ - pm_idle = s5p64x0_idle; - - return sysdev_register(&s5p64x0_sysdev); -} diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c deleted file mode 100644 index ac825e826326..000000000000 --- a/arch/arm/mach-s5p64x0/dev-spi.c +++ /dev/null @@ -1,226 +0,0 @@ -/* linux/arch/arm/mach-s5p64x0/dev-spi.c - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Copyright (C) 2010 Samsung Electronics Co. Ltd. - * Jaswinder Singh <jassi.brar@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/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/gpio.h> - -#include <mach/dma.h> -#include <mach/map.h> -#include <mach/irqs.h> -#include <mach/regs-clock.h> -#include <mach/spi-clocks.h> - -#include <plat/s3c64xx-spi.h> -#include <plat/gpio-cfg.h> - -static char *s5p64x0_spi_src_clks[] = { - [S5P64X0_SPI_SRCCLK_PCLK] = "pclk", - [S5P64X0_SPI_SRCCLK_SCLK] = "sclk_spi", -}; - -/* SPI Controller platform_devices */ - -/* Since we emulate multi-cs capability, we do not touch the CS. - * The emulated CS is toggled by board specific mechanism, as it can - * be either some immediate GPIO or some signal out of some other - * chip in between ... or some yet another way. - * We simply do not assume anything about CS. - */ -static int s5p6440_spi_cfg_gpio(struct platform_device *pdev) -{ - unsigned int base; - - switch (pdev->id) { - case 0: - base = S5P6440_GPC(0); - break; - - case 1: - base = S5P6440_GPC(4); - break; - - default: - dev_err(&pdev->dev, "Invalid SPI Controller number!"); - return -EINVAL; - } - - s3c_gpio_cfgall_range(base, 3, - S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); - - return 0; -} - -static int s5p6450_spi_cfg_gpio(struct platform_device *pdev) -{ - unsigned int base; - - switch (pdev->id) { - case 0: - base = S5P6450_GPC(0); - break; - - case 1: - base = S5P6450_GPC(4); - break; - - default: - dev_err(&pdev->dev, "Invalid SPI Controller number!"); - return -EINVAL; - } - - s3c_gpio_cfgall_range(base, 3, - S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); - - return 0; -} - -static struct resource s5p64x0_spi0_resource[] = { - [0] = { - .start = S5P64X0_PA_SPI0, - .end = S5P64X0_PA_SPI0 + 0x100 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = DMACH_SPI0_TX, - .end = DMACH_SPI0_TX, - .flags = IORESOURCE_DMA, - }, - [2] = { - .start = DMACH_SPI0_RX, - .end = DMACH_SPI0_RX, - .flags = IORESOURCE_DMA, - }, - [3] = { - .start = IRQ_SPI0, - .end = IRQ_SPI0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct s3c64xx_spi_info s5p6440_spi0_pdata = { - .cfg_gpio = s5p6440_spi_cfg_gpio, - .fifo_lvl_mask = 0x1ff, - .rx_lvl_offset = 15, - .tx_st_done = 25, -}; - -static struct s3c64xx_spi_info s5p6450_spi0_pdata = { - .cfg_gpio = s5p6450_spi_cfg_gpio, - .fifo_lvl_mask = 0x1ff, - .rx_lvl_offset = 15, - .tx_st_done = 25, -}; - -static u64 spi_dmamask = DMA_BIT_MASK(32); - -struct platform_device s5p64x0_device_spi0 = { - .name = "s3c64xx-spi", - .id = 0, - .num_resources = ARRAY_SIZE(s5p64x0_spi0_resource), - .resource = s5p64x0_spi0_resource, - .dev = { - .dma_mask = &spi_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -static struct resource s5p64x0_spi1_resource[] = { - [0] = { - .start = S5P64X0_PA_SPI1, - .end = S5P64X0_PA_SPI1 + 0x100 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = DMACH_SPI1_TX, - .end = DMACH_SPI1_TX, - .flags = IORESOURCE_DMA, - }, - [2] = { - .start = DMACH_SPI1_RX, - .end = DMACH_SPI1_RX, - .flags = IORESOURCE_DMA, - }, - [3] = { - .start = IRQ_SPI1, - .end = IRQ_SPI1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct s3c64xx_spi_info s5p6440_spi1_pdata = { - .cfg_gpio = s5p6440_spi_cfg_gpio, - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 15, - .tx_st_done = 25, -}; - -static struct s3c64xx_spi_info s5p6450_spi1_pdata = { - .cfg_gpio = s5p6450_spi_cfg_gpio, - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 15, - .tx_st_done = 25, -}; - -struct platform_device s5p64x0_device_spi1 = { - .name = "s3c64xx-spi", - .id = 1, - .num_resources = ARRAY_SIZE(s5p64x0_spi1_resource), - .resource = s5p64x0_spi1_resource, - .dev = { - .dma_mask = &spi_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) -{ - unsigned int id; - struct s3c64xx_spi_info *pd; - - id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000; - - /* Reject invalid configuration */ - if (!num_cs || src_clk_nr < 0 - || src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) { - printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__); - return; - } - - switch (cntrlr) { - case 0: - if (id == 0x50000) - pd = &s5p6450_spi0_pdata; - else - pd = &s5p6440_spi0_pdata; - - s5p64x0_device_spi0.dev.platform_data = pd; - break; - case 1: - if (id == 0x50000) - pd = &s5p6450_spi1_pdata; - else - pd = &s5p6440_spi1_pdata; - - s5p64x0_device_spi1.dev.platform_data = pd; - break; - default: - printk(KERN_ERR "%s: Invalid SPI controller(%d)\n", - __func__, cntrlr); - return; - } - - pd->num_cs = num_cs; - pd->src_clk_nr = src_clk_nr; - pd->src_clk_name = s5p64x0_spi_src_clks[src_clk_nr]; -} diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c index d7ad944b3475..f820c0744405 100644 --- a/arch/arm/mach-s5p64x0/dma.c +++ b/arch/arm/mach-s5p64x0/dma.c @@ -21,128 +21,121 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/amba/bus.h> +#include <linux/amba/pl330.h> + +#include <asm/irq.h> #include <mach/map.h> #include <mach/irqs.h> #include <mach/regs-clock.h> +#include <mach/dma.h> +#include <plat/cpu.h> #include <plat/devs.h> -#include <plat/s3c-pl330-pdata.h> +#include <plat/irqs.h> static u64 dma_dmamask = DMA_BIT_MASK(32); -static struct resource s5p64x0_pdma_resource[] = { - [0] = { - .start = S5P64X0_PA_PDMA, - .end = S5P64X0_PA_PDMA + SZ_4K, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_DMA0, - .end = IRQ_DMA0, - .flags = IORESOURCE_IRQ, - }, +u8 s5p6440_pdma_peri[] = { + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_MAX, + DMACH_MAX, + DMACH_PCM0_TX, + DMACH_PCM0_RX, + DMACH_I2S0_TX, + DMACH_I2S0_RX, + DMACH_SPI0_TX, + DMACH_SPI0_RX, + DMACH_MAX, + DMACH_MAX, + DMACH_MAX, + DMACH_MAX, + DMACH_SPI1_TX, + DMACH_SPI1_RX, }; -static struct s3c_pl330_platdata s5p6440_pdma_pdata = { - .peri = { - [0] = DMACH_UART0_RX, - [1] = DMACH_UART0_TX, - [2] = DMACH_UART1_RX, - [3] = DMACH_UART1_TX, - [4] = DMACH_UART2_RX, - [5] = DMACH_UART2_TX, - [6] = DMACH_UART3_RX, - [7] = DMACH_UART3_TX, - [8] = DMACH_MAX, - [9] = DMACH_MAX, - [10] = DMACH_PCM0_TX, - [11] = DMACH_PCM0_RX, - [12] = DMACH_I2S0_TX, - [13] = DMACH_I2S0_RX, - [14] = DMACH_SPI0_TX, - [15] = DMACH_SPI0_RX, - [16] = DMACH_MAX, - [17] = DMACH_MAX, - [18] = DMACH_MAX, - [19] = DMACH_MAX, - [20] = DMACH_SPI1_TX, - [21] = DMACH_SPI1_RX, - [22] = DMACH_MAX, - [23] = DMACH_MAX, - [24] = DMACH_MAX, - [25] = DMACH_MAX, - [26] = DMACH_MAX, - [27] = DMACH_MAX, - [28] = DMACH_MAX, - [29] = DMACH_PWM, - [30] = DMACH_MAX, - [31] = DMACH_MAX, - }, +struct dma_pl330_platdata s5p6440_pdma_pdata = { + .nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri), + .peri_id = s5p6440_pdma_peri, }; -static struct s3c_pl330_platdata s5p6450_pdma_pdata = { - .peri = { - [0] = DMACH_UART0_RX, - [1] = DMACH_UART0_TX, - [2] = DMACH_UART1_RX, - [3] = DMACH_UART1_TX, - [4] = DMACH_UART2_RX, - [5] = DMACH_UART2_TX, - [6] = DMACH_UART3_RX, - [7] = DMACH_UART3_TX, - [8] = DMACH_UART4_RX, - [9] = DMACH_UART4_TX, - [10] = DMACH_PCM0_TX, - [11] = DMACH_PCM0_RX, - [12] = DMACH_I2S0_TX, - [13] = DMACH_I2S0_RX, - [14] = DMACH_SPI0_TX, - [15] = DMACH_SPI0_RX, - [16] = DMACH_PCM1_TX, - [17] = DMACH_PCM1_RX, - [18] = DMACH_PCM2_TX, - [19] = DMACH_PCM2_RX, - [20] = DMACH_SPI1_TX, - [21] = DMACH_SPI1_RX, - [22] = DMACH_USI_TX, - [23] = DMACH_USI_RX, - [24] = DMACH_MAX, - [25] = DMACH_I2S1_TX, - [26] = DMACH_I2S1_RX, - [27] = DMACH_I2S2_TX, - [28] = DMACH_I2S2_RX, - [29] = DMACH_PWM, - [30] = DMACH_UART5_RX, - [31] = DMACH_UART5_TX, - }, +u8 s5p6450_pdma_peri[] = { + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_UART4_RX, + DMACH_UART4_TX, + DMACH_PCM0_TX, + DMACH_PCM0_RX, + DMACH_I2S0_TX, + DMACH_I2S0_RX, + DMACH_SPI0_TX, + DMACH_SPI0_RX, + DMACH_PCM1_TX, + DMACH_PCM1_RX, + DMACH_PCM2_TX, + DMACH_PCM2_RX, + DMACH_SPI1_TX, + DMACH_SPI1_RX, + DMACH_USI_TX, + DMACH_USI_RX, + DMACH_MAX, + DMACH_I2S1_TX, + DMACH_I2S1_RX, + DMACH_I2S2_TX, + DMACH_I2S2_RX, + DMACH_PWM, + DMACH_UART5_RX, + DMACH_UART5_TX, }; -static struct platform_device s5p64x0_device_pdma = { - .name = "s3c-pl330", - .id = -1, - .num_resources = ARRAY_SIZE(s5p64x0_pdma_resource), - .resource = s5p64x0_pdma_resource, - .dev = { +struct dma_pl330_platdata s5p6450_pdma_pdata = { + .nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri), + .peri_id = s5p6450_pdma_peri, +}; + +struct amba_device s5p64x0_device_pdma = { + .dev = { + .init_name = "dma-pl330", .dma_mask = &dma_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), }, + .res = { + .start = S5P64X0_PA_PDMA, + .end = S5P64X0_PA_PDMA + SZ_4K, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_DMA0, NO_IRQ}, + .periphid = 0x00041330, }; static int __init s5p64x0_dma_init(void) { - unsigned int id; - - id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000; - - if (id == 0x50000) + if (soc_is_s5p6450()) { + dma_cap_set(DMA_SLAVE, s5p6450_pdma_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, s5p6450_pdma_pdata.cap_mask); s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata; - else + } else { + dma_cap_set(DMA_SLAVE, s5p6440_pdma_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, s5p6440_pdma_pdata.cap_mask); s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata; + } - platform_device_register(&s5p64x0_device_pdma); + amba_device_register(&s5p64x0_device_pdma, &iomem_resource); return 0; } diff --git a/arch/arm/mach-s5p64x0/gpiolib.c b/arch/arm/mach-s5p64x0/gpiolib.c index e7fb3b004e77..700dac6c43f3 100644 --- a/arch/arm/mach-s5p64x0/gpiolib.c +++ b/arch/arm/mach-s5p64x0/gpiolib.c @@ -19,6 +19,7 @@ #include <mach/regs-gpio.h> #include <mach/regs-clock.h> +#include <plat/cpu.h> #include <plat/gpio-core.h> #include <plat/gpio-cfg.h> #include <plat/gpio-cfg-helpers.h> @@ -473,14 +474,10 @@ static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip, static int __init s5p64x0_gpiolib_init(void) { - unsigned int chipid; - - chipid = __raw_readl(S5P64X0_SYS_ID); - s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs, ARRAY_SIZE(s5p64x0_gpio_cfgs)); - if ((chipid & 0xff000) == 0x50000) { + if (soc_is_s5p6450()) { samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit, ARRAY_SIZE(s5p6450_gpio_2bit)); diff --git a/arch/arm/mach-s5p64x0/include/mach/clkdev.h b/arch/arm/mach-s5p64x0/include/mach/clkdev.h deleted file mode 100644 index 7dffa83d23ff..000000000000 --- a/arch/arm/mach-s5p64x0/include/mach/clkdev.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __MACH_CLKDEV_H__ -#define __MACH_CLKDEV_H__ - -#define __clk_get(clk) ({ 1; }) -#define __clk_put(clk) do {} while (0) - -#endif diff --git a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S index 79b04e6a6f8e..e80ba3c69814 100644 --- a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S +++ b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S @@ -15,7 +15,7 @@ #include <plat/regs-serial.h> - .macro addruart, rp, rv + .macro addruart, rp, rv, tmp mov \rp, #0xE0000000 orr \rp, \rp, #0x00100000 ldr \rp, [\rp, #0x118 ] diff --git a/arch/arm/mach-s5p64x0/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h index 81209eb1409b..5a622af461d7 100644 --- a/arch/arm/mach-s5p64x0/include/mach/dma.h +++ b/arch/arm/mach-s5p64x0/include/mach/dma.h @@ -20,7 +20,7 @@ #ifndef __MACH_DMA_H #define __MACH_DMA_H -/* This platform uses the common S3C DMA API driver for PL330 */ -#include <plat/s3c-dma-pl330.h> +/* This platform uses the common common DMA API driver for PL330 */ +#include <plat/dma-pl330.h> #endif /* __MACH_DMA_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/entry-macro.S b/arch/arm/mach-s5p64x0/include/mach/entry-macro.S index 10b62b4f8211..fbb246d0a3df 100644 --- a/arch/arm/mach-s5p64x0/include/mach/entry-macro.S +++ b/arch/arm/mach-s5p64x0/include/mach/entry-macro.S @@ -10,7 +10,8 @@ * published by the Free Software Foundation. */ -#include <mach/map.h> -#include <plat/irqs.h> + .macro disable_fiq + .endm -#include <asm/entry-macro-vic2.S> + .macro arch_ret_to_user, tmp1, tmp2 + .endm diff --git a/arch/arm/mach-s5p64x0/include/mach/gpio.h b/arch/arm/mach-s5p64x0/include/mach/gpio.h index adb5f298ead8..06cd3c9b16ac 100644 --- a/arch/arm/mach-s5p64x0/include/mach/gpio.h +++ b/arch/arm/mach-s5p64x0/include/mach/gpio.h @@ -13,11 +13,6 @@ #ifndef __ASM_ARCH_GPIO_H #define __ASM_ARCH_GPIO_H __FILE__ -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep -#define gpio_to_irq __gpio_to_irq - /* GPIO bank sizes */ #define S5P6440_GPIO_A_NR (6) @@ -134,6 +129,4 @@ enum s5p6450_gpio_number { #define ARCH_NR_GPIOS (S5P64X0_GPIO_END + CONFIG_SAMSUNG_GPIO_EXTRA) -#include <asm-generic/gpio.h> - #endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h index 5837a36ece8d..5b845e849b30 100644 --- a/arch/arm/mach-s5p64x0/include/mach/irqs.h +++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h @@ -87,6 +87,10 @@ #define IRQ_I2S0 IRQ_I2SV40 +#define IRQ_LCD_FIFO IRQ_DISPCON0 +#define IRQ_LCD_VSYNC IRQ_DISPCON1 +#define IRQ_LCD_SYSTEM IRQ_DISPCON2 + /* S5P6450 EINT feature will be added */ /* @@ -137,6 +141,8 @@ #define IRQ_EINT_GROUP(grp, x) (IRQ_EINT_GROUP##grp##_BASE + (x)) +#define IRQ_TIMER_BASE (11) + /* Set the default NR_IRQS */ #define NR_IRQS (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1) diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h index 95c91257c7ca..0c0175dbfa34 100644 --- a/arch/arm/mach-s5p64x0/include/mach/map.h +++ b/arch/arm/mach-s5p64x0/include/mach/map.h @@ -47,6 +47,8 @@ #define S5P64X0_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000)) +#define S5P64X0_PA_FB 0xEE000000 + #define S5P64X0_PA_I2S 0xF2000000 #define S5P6450_PA_I2S1 0xF2800000 #define S5P6450_PA_I2S2 0xF2900000 @@ -64,6 +66,9 @@ #define S3C_PA_IIC1 S5P6440_PA_IIC1 #define S3C_PA_RTC S5P64X0_PA_RTC #define S3C_PA_WDT S5P64X0_PA_WDT +#define S3C_PA_FB S5P64X0_PA_FB +#define S3C_PA_SPI0 S5P64X0_PA_SPI0 +#define S3C_PA_SPI1 S5P64X0_PA_SPI1 #define S5P_PA_CHIPID S5P64X0_PA_CHIPID #define S5P_PA_SROMC S5P64X0_PA_SROMC @@ -85,5 +90,6 @@ #define S5P_PA_UART5 S5P6450_PA_UART(5) #define S5P_SZ_UART SZ_256 +#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/memory.h b/arch/arm/mach-s5p64x0/include/mach/memory.h deleted file mode 100644 index 365a6eb4b88f..000000000000 --- a/arch/arm/mach-s5p64x0/include/mach/memory.h +++ /dev/null @@ -1,19 +0,0 @@ -/* linux/arch/arm/mach-s5p64x0/include/mach/memory.h - * - * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * S5P64X0 - Memory definitions - * - * 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_MEMORY_H -#define __ASM_ARCH_MEMORY_H __FILE__ - -#define PLAT_PHYS_OFFSET UL(0x20000000) -#define CONSISTENT_DMA_SIZE SZ_8M - -#endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/pm-core.h b/arch/arm/mach-s5p64x0/include/mach/pm-core.h new file mode 100644 index 000000000000..e52f7545d3aa --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/pm-core.h @@ -0,0 +1,117 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/pm-core.h + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - PM core support for arch/arm/plat-samsung/pm.c + * + * Based on PM core support for S3C64XX by Ben Dooks + * + * 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 <mach/regs-gpio.h> + +static inline void s3c_pm_debug_init_uart(void) +{ + u32 tmp = __raw_readl(S5P64X0_CLK_GATE_PCLK); + + /* + * As a note, since the S5P64X0 UARTs generally have multiple + * clock sources, we simply enable PCLK at the moment and hope + * that the resume settings for the UART are suitable for the + * use with PCLK. + */ + tmp |= S5P64X0_CLK_GATE_PCLK_UART0; + tmp |= S5P64X0_CLK_GATE_PCLK_UART1; + tmp |= S5P64X0_CLK_GATE_PCLK_UART2; + tmp |= S5P64X0_CLK_GATE_PCLK_UART3; + + __raw_writel(tmp, S5P64X0_CLK_GATE_PCLK); + udelay(10); +} + +static inline void s3c_pm_arch_prepare_irqs(void) +{ + /* VIC should have already been taken care of */ + + /* clear any pending EINT0 interrupts */ + __raw_writel(__raw_readl(S5P64X0_EINT0PEND), S5P64X0_EINT0PEND); +} + +static inline void s3c_pm_arch_stop_clocks(void) { } +static inline void s3c_pm_arch_show_resume_irqs(void) { } + +/* + * make these defines, we currently do not have any need to change + * the IRQ wake controls depending on the CPU we are running on + */ +#define s3c_irqwake_eintallow ((1 << 16) - 1) +#define s3c_irqwake_intallow (~0) + +static inline void s3c_pm_arch_update_uart(void __iomem *regs, + struct pm_uart_save *save) +{ + u32 ucon = __raw_readl(regs + S3C2410_UCON); + u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK; + u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK; + u32 new_ucon; + u32 delta; + + /* + * S5P64X0 UART blocks only support level interrupts, so ensure that + * when we restore unused UART blocks we force the level interrupt + * settings. + */ + save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL; + + /* + * We have a constraint on changing the clock type of the UART + * between UCLKx and PCLK, so ensure that when we restore UCON + * that the CLK field is correctly modified if the bootloader + * has changed anything. + */ + if (ucon_clk != save_clk) { + new_ucon = save->ucon; + delta = ucon_clk ^ save_clk; + + /* + * change from UCLKx => wrong PCLK, + * either UCLK can be tested for by a bit-test + * with UCLK0 + */ + if (ucon_clk & S3C6400_UCON_UCLK0 && + !(save_clk & S3C6400_UCON_UCLK0) && + delta & S3C6400_UCON_PCLK2) { + new_ucon &= ~S3C6400_UCON_UCLK0; + } else if (delta == S3C6400_UCON_PCLK2) { + /* + * as a precaution, don't change from + * PCLK2 => PCLK or vice-versa + */ + new_ucon ^= S3C6400_UCON_PCLK2; + } + + S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n", + ucon, new_ucon, save->ucon); + save->ucon = new_ucon; + } +} + +static inline void s3c_pm_restored_gpios(void) +{ + /* ensure sleep mode has been cleared from the system */ + __raw_writel(0, S5P64X0_SLPEN); +} + +static inline void samsung_pm_saved_gpios(void) +{ + /* + * turn on the sleep mode and keep it there, as it seems that during + * suspend the xCON registers get re-set and thus you can end up with + * problems between going to sleep and resuming. + */ + __raw_writel(S5P64X0_SLPEN_USE_xSLP, S5P64X0_SLPEN); +} diff --git a/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h b/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h deleted file mode 100644 index 19fff8b701c0..000000000000 --- a/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h +++ /dev/null @@ -1,68 +0,0 @@ -/* linux/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h - * - * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * http://armlinux.simtec.co.uk/ - * - * S5P64X0 - pwm clock and timer 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. -*/ - -#ifndef __ASM_ARCH_PWMCLK_H -#define __ASM_ARCH_PWMCLK_H __FILE__ - -/** - * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk - * @tcfg: The timer TCFG1 register bits shifted down to 0. - * - * Return true if the given configuration from TCFG1 is a TCLK instead - * any of the TDIV clocks. - */ -static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) -{ - return 0; -} - -/** - * tcfg_to_divisor() - convert tcfg1 setting to a divisor - * @tcfg1: The tcfg1 setting, shifted down. - * - * Get the divisor value for the given tcfg1 setting. We assume the - * caller has already checked to see if this is not a TCLK source. - */ -static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) -{ - return 1 << tcfg1; -} - -/** - * pwm_tdiv_has_div1() - does the tdiv setting have a /1 - * - * Return true if we have a /1 in the tdiv setting. - */ -static inline unsigned int pwm_tdiv_has_div1(void) -{ - return 1; -} - -/** - * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. - * @div: The divisor to calculate the bit information for. - * - * Turn a divisor into the necessary bit field for TCFG1. - */ -static inline unsigned long pwm_tdiv_div_bits(unsigned int div) -{ - return ilog2(div); -} - -#define S3C_TCFG1_MUX_TCLK 0 - -#endif /* __ASM_ARCH_PWMCLK_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h index a133f22fa155..bd91112c813c 100644 --- a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h +++ b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h @@ -41,17 +41,50 @@ #define S5P6450_DPLL_CON S5P_CLKREG(0x50) #define S5P6450_DPLL_CON_K S5P_CLKREG(0x54) +#define S5P64X0_AHB_CON0 S5P_CLKREG(0x100) #define S5P64X0_CLK_SRC1 S5P_CLKREG(0x10C) #define S5P64X0_SYS_ID S5P_CLKREG(0x118) #define S5P64X0_SYS_OTHERS S5P_CLKREG(0x11C) #define S5P64X0_PWR_CFG S5P_CLKREG(0x804) +#define S5P64X0_EINT_WAKEUP_MASK S5P_CLKREG(0x808) +#define S5P64X0_SLEEP_CFG S5P_CLKREG(0x818) +#define S5P64X0_PWR_STABLE S5P_CLKREG(0x828) + #define S5P64X0_OTHERS S5P_CLKREG(0x900) +#define S5P64X0_WAKEUP_STAT S5P_CLKREG(0x908) + +#define S5P64X0_INFORM0 S5P_CLKREG(0xA00) #define S5P64X0_CLKDIV0_HCLK_SHIFT (8) #define S5P64X0_CLKDIV0_HCLK_MASK (0xF << S5P64X0_CLKDIV0_HCLK_SHIFT) +/* HCLK GATE Registers */ +#define S5P64X0_CLK_GATE_HCLK1_FIMGVG (1 << 2) +#define S5P64X0_CLK_GATE_SCLK1_FIMGVG (1 << 2) + +/* PCLK GATE Registers */ +#define S5P64X0_CLK_GATE_PCLK_UART3 (1 << 4) +#define S5P64X0_CLK_GATE_PCLK_UART2 (1 << 3) +#define S5P64X0_CLK_GATE_PCLK_UART1 (1 << 2) +#define S5P64X0_CLK_GATE_PCLK_UART0 (1 << 1) + +#define S5P64X0_PWR_CFG_MMC1_DISABLE (1 << 15) +#define S5P64X0_PWR_CFG_MMC0_DISABLE (1 << 14) +#define S5P64X0_PWR_CFG_RTC_TICK_DISABLE (1 << 11) +#define S5P64X0_PWR_CFG_RTC_ALRM_DISABLE (1 << 10) +#define S5P64X0_PWR_CFG_WFI_MASK (3 << 5) +#define S5P64X0_PWR_CFG_WFI_SLEEP (3 << 5) + +#define S5P64X0_SLEEP_CFG_OSC_EN (1 << 0) + +#define S5P64X0_PWR_STABLE_PWR_CNT_VAL4 (4 << 0) + +#define S5P6450_OTHERS_DISABLE_INT (1 << 31) +#define S5P64X0_OTHERS_RET_UART (1 << 26) +#define S5P64X0_OTHERS_RET_MMC1 (1 << 25) +#define S5P64X0_OTHERS_RET_MMC0 (1 << 24) #define S5P64X0_OTHERS_USB_SIG_MASK (1 << 16) /* Compatibility defines */ diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h index 6ce254729f3b..cfdfa4fdadf2 100644 --- a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h +++ b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h @@ -34,14 +34,35 @@ #define S5P6450_GPQ_BASE (S5P_VA_GPIO + 0x0180) #define S5P6450_GPS_BASE (S5P_VA_GPIO + 0x0300) +#define S5P64X0_SPCON0 (S5P_VA_GPIO + 0x1A0) +#define S5P64X0_SPCON0_LCD_SEL_MASK (0x3 << 0) +#define S5P64X0_SPCON0_LCD_SEL_RGB (0x1 << 0) +#define S5P64X0_SPCON1 (S5P_VA_GPIO + 0x2B0) + +#define S5P64X0_MEM0CONSLP0 (S5P_VA_GPIO + 0x1C0) +#define S5P64X0_MEM0CONSLP1 (S5P_VA_GPIO + 0x1C4) +#define S5P64X0_MEM0DRVCON (S5P_VA_GPIO + 0x1D0) +#define S5P64X0_MEM1DRVCON (S5P_VA_GPIO + 0x1D4) + +#define S5P64X0_EINT12CON (S5P_VA_GPIO + 0x200) +#define S5P64X0_EINT12FLTCON (S5P_VA_GPIO + 0x220) +#define S5P64X0_EINT12MASK (S5P_VA_GPIO + 0x240) + /* External interrupt control registers for group0 */ #define EINT0CON0_OFFSET (0x900) +#define EINT0FLTCON0_OFFSET (0x910) +#define EINT0FLTCON1_OFFSET (0x914) #define EINT0MASK_OFFSET (0x920) #define EINT0PEND_OFFSET (0x924) #define S5P64X0_EINT0CON0 (S5P_VA_GPIO + EINT0CON0_OFFSET) +#define S5P64X0_EINT0FLTCON0 (S5P_VA_GPIO + EINT0FLTCON0_OFFSET) +#define S5P64X0_EINT0FLTCON1 (S5P_VA_GPIO + EINT0FLTCON1_OFFSET) #define S5P64X0_EINT0MASK (S5P_VA_GPIO + EINT0MASK_OFFSET) #define S5P64X0_EINT0PEND (S5P_VA_GPIO + EINT0PEND_OFFSET) +#define S5P64X0_SLPEN (S5P_VA_GPIO + 0x930) +#define S5P64X0_SLPEN_USE_xSLP (1 << 0) + #endif /* __ASM_ARCH_REGS_GPIO_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/system.h b/arch/arm/mach-s5p64x0/include/mach/system.h index 60f57532c970..cf26e0954a2f 100644 --- a/arch/arm/mach-s5p64x0/include/mach/system.h +++ b/arch/arm/mach-s5p64x0/include/mach/system.h @@ -13,8 +13,6 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H __FILE__ -#include <plat/system-reset.h> - static void arch_idle(void) { /* nothing here yet */ diff --git a/arch/arm/mach-s5p64x0/include/mach/vmalloc.h b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h deleted file mode 100644 index 38dcc71a03cc..000000000000 --- a/arch/arm/mach-s5p64x0/include/mach/vmalloc.h +++ /dev/null @@ -1,20 +0,0 @@ -/* linux/arch/arm/mach-s5p64x0/include/mach/vmalloc.h - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Copyright 2010 Ben Dooks <ben-linux@fluff.org> - * - * 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. - * - * S3C6400 vmalloc definition -*/ - -#ifndef __ASM_ARCH_VMALLOC_H -#define __ASM_ARCH_VMALLOC_H - -#define VMALLOC_END 0xF6000000UL - -#endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/mach-s5p64x0/init.c b/arch/arm/mach-s5p64x0/init.c deleted file mode 100644 index 79833caf8165..000000000000 --- a/arch/arm/mach-s5p64x0/init.c +++ /dev/null @@ -1,73 +0,0 @@ -/* linux/arch/arm/mach-s5p64x0/init.c - * - * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * S5P64X0 - Init 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/kernel.h> -#include <linux/types.h> -#include <linux/init.h> -#include <linux/serial_core.h> - -#include <mach/map.h> - -#include <plat/cpu.h> -#include <plat/devs.h> -#include <plat/s5p6440.h> -#include <plat/s5p6450.h> -#include <plat/regs-serial.h> - -static struct s3c24xx_uart_clksrc s5p64x0_serial_clocks[] = { - [0] = { - .name = "pclk_low", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, - [1] = { - .name = "uclk1", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, -}; - -/* uart registration process */ - -void __init s5p64x0_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) -{ - struct s3c2410_uartcfg *tcfg = cfg; - u32 ucnt; - - for (ucnt = 0; ucnt < no; ucnt++, tcfg++) { - if (!tcfg->clocks) { - tcfg->clocks = s5p64x0_serial_clocks; - tcfg->clocks_size = ARRAY_SIZE(s5p64x0_serial_clocks); - } - } -} - -void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no) -{ - int uart; - - for (uart = 0; uart < no; uart++) { - s5p_uart_resources[uart].resources->start = S5P6440_PA_UART(uart); - s5p_uart_resources[uart].resources->end = S5P6440_PA_UART(uart) + S5P_SZ_UART; - } - - s5p64x0_common_init_uarts(cfg, no); - s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no); -} - -void __init s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no) -{ - s5p64x0_common_init_uarts(cfg, no); - s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no); -} diff --git a/arch/arm/mach-s5p64x0/irq-eint.c b/arch/arm/mach-s5p64x0/irq-eint.c deleted file mode 100644 index 69ed4545112b..000000000000 --- a/arch/arm/mach-s5p64x0/irq-eint.c +++ /dev/null @@ -1,152 +0,0 @@ -/* arch/arm/mach-s5p64x0/irq-eint.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd - * http://www.samsung.com/ - * - * Based on linux/arch/arm/mach-s3c64xx/irq-eint.c - * - * S5P64X0 - Interrupt handling for External Interrupts. - * - * 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/kernel.h> -#include <linux/gpio.h> -#include <linux/irq.h> -#include <linux/io.h> - -#include <plat/regs-irqtype.h> -#include <plat/gpio-cfg.h> - -#include <mach/regs-gpio.h> -#include <mach/regs-clock.h> - -#define eint_offset(irq) ((irq) - IRQ_EINT(0)) - -static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type) -{ - int offs = eint_offset(data->irq); - int shift; - u32 ctrl, mask; - u32 newvalue = 0; - - if (offs > 15) - return -EINVAL; - - switch (type) { - case IRQ_TYPE_NONE: - printk(KERN_WARNING "No edge setting!\n"); - break; - case IRQ_TYPE_EDGE_RISING: - newvalue = S3C2410_EXTINT_RISEEDGE; - break; - case IRQ_TYPE_EDGE_FALLING: - newvalue = S3C2410_EXTINT_FALLEDGE; - break; - case IRQ_TYPE_EDGE_BOTH: - newvalue = S3C2410_EXTINT_BOTHEDGE; - break; - case IRQ_TYPE_LEVEL_LOW: - newvalue = S3C2410_EXTINT_LOWLEV; - break; - case IRQ_TYPE_LEVEL_HIGH: - newvalue = S3C2410_EXTINT_HILEV; - break; - default: - printk(KERN_ERR "No such irq type %d", type); - return -EINVAL; - } - - shift = (offs / 2) * 4; - mask = 0x7 << shift; - - ctrl = __raw_readl(S5P64X0_EINT0CON0) & ~mask; - ctrl |= newvalue << shift; - __raw_writel(ctrl, S5P64X0_EINT0CON0); - - /* Configure the GPIO pin for 6450 or 6440 based on CPU ID */ - if (0x50000 == (__raw_readl(S5P64X0_SYS_ID) & 0xFF000)) - s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2)); - else - s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2)); - - return 0; -} - -/* - * s5p64x0_irq_demux_eint - * - * This function demuxes the IRQ from the group0 external interrupts, - * from IRQ_EINT(0) to IRQ_EINT(15). It is designed to be inlined into - * the specific handlers s5p64x0_irq_demux_eintX_Y. - */ -static inline void s5p64x0_irq_demux_eint(unsigned int start, unsigned int end) -{ - u32 status = __raw_readl(S5P64X0_EINT0PEND); - u32 mask = __raw_readl(S5P64X0_EINT0MASK); - unsigned int irq; - - status &= ~mask; - status >>= start; - status &= (1 << (end - start + 1)) - 1; - - for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) { - if (status & 1) - generic_handle_irq(irq); - status >>= 1; - } -} - -static void s5p64x0_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc) -{ - s5p64x0_irq_demux_eint(0, 3); -} - -static void s5p64x0_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc) -{ - s5p64x0_irq_demux_eint(4, 11); -} - -static void s5p64x0_irq_demux_eint12_15(unsigned int irq, - struct irq_desc *desc) -{ - s5p64x0_irq_demux_eint(12, 15); -} - -static int s5p64x0_alloc_gc(void) -{ - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - - gc = irq_alloc_generic_chip("s5p64x0-eint", 1, S5P_IRQ_EINT_BASE, - S5P_VA_GPIO, handle_level_irq); - if (!gc) { - printk(KERN_ERR "%s: irq_alloc_generic_chip for group 0" - "external interrupts failed\n", __func__); - return -EINVAL; - } - - ct = gc->chip_types; - ct->chip.irq_ack = irq_gc_ack; - ct->chip.irq_mask = irq_gc_mask_set_bit; - ct->chip.irq_unmask = irq_gc_mask_clr_bit; - ct->chip.irq_set_type = s5p64x0_irq_eint_set_type; - ct->regs.ack = EINT0PEND_OFFSET; - ct->regs.mask = EINT0MASK_OFFSET; - irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE, - IRQ_NOREQUEST | IRQ_NOPROBE, 0); - return 0; -} - -static int __init s5p64x0_init_irq_eint(void) -{ - int ret = s5p64x0_alloc_gc(); - irq_set_chained_handler(IRQ_EINT0_3, s5p64x0_irq_demux_eint0_3); - irq_set_chained_handler(IRQ_EINT4_11, s5p64x0_irq_demux_eint4_11); - irq_set_chained_handler(IRQ_EINT12_15, s5p64x0_irq_demux_eint12_15); - - return ret; -} -arch_initcall(s5p64x0_init_irq_eint); diff --git a/arch/arm/mach-s5p64x0/irq-pm.c b/arch/arm/mach-s5p64x0/irq-pm.c new file mode 100644 index 000000000000..3e6f2456ee9d --- /dev/null +++ b/arch/arm/mach-s5p64x0/irq-pm.c @@ -0,0 +1,92 @@ +/* linux/arch/arm/mach-s5p64x0/irq-pm.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - Interrupt handling Power Management + * + * Based on arch/arm/mach-s3c64xx/irq-pm.c by Ben Dooks + * + * 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/syscore_ops.h> +#include <linux/serial_core.h> +#include <linux/io.h> + +#include <plat/regs-serial.h> +#include <plat/pm.h> + +#include <mach/regs-gpio.h> + +static struct sleep_save irq_save[] = { + SAVE_ITEM(S5P64X0_EINT0CON0), + SAVE_ITEM(S5P64X0_EINT0FLTCON0), + SAVE_ITEM(S5P64X0_EINT0FLTCON1), + SAVE_ITEM(S5P64X0_EINT0MASK), +}; + +static struct irq_grp_save { + u32 con; + u32 fltcon; + u32 mask; +} eint_grp_save[4]; + +static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS]; + +static int s5p64x0_irq_pm_suspend(void) +{ + struct irq_grp_save *grp = eint_grp_save; + int i; + + S3C_PMDBG("%s: suspending IRQs\n", __func__); + + s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); + + for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++) + irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM); + + for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) { + grp->con = __raw_readl(S5P64X0_EINT12CON + (i * 4)); + grp->mask = __raw_readl(S5P64X0_EINT12MASK + (i * 4)); + grp->fltcon = __raw_readl(S5P64X0_EINT12FLTCON + (i * 4)); + } + + return 0; +} + +static void s5p64x0_irq_pm_resume(void) +{ + struct irq_grp_save *grp = eint_grp_save; + int i; + + S3C_PMDBG("%s: resuming IRQs\n", __func__); + + s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); + + for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++) + __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM); + + for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) { + __raw_writel(grp->con, S5P64X0_EINT12CON + (i * 4)); + __raw_writel(grp->mask, S5P64X0_EINT12MASK + (i * 4)); + __raw_writel(grp->fltcon, S5P64X0_EINT12FLTCON + (i * 4)); + } + + S3C_PMDBG("%s: IRQ configuration restored\n", __func__); +} + +static struct syscore_ops s5p64x0_irq_syscore_ops = { + .suspend = s5p64x0_irq_pm_suspend, + .resume = s5p64x0_irq_pm_resume, +}; + +static int __init s5p64x0_syscore_init(void) +{ + register_syscore_ops(&s5p64x0_irq_syscore_ops); + + return 0; +} +core_initcall(s5p64x0_syscore_init); diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c index 346f8dfa6f35..a40e325d62c8 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6440.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -23,7 +23,12 @@ #include <linux/clk.h> #include <linux/gpio.h> #include <linux/pwm_backlight.h> +#include <linux/fb.h> +#include <linux/mmc/host.h> +#include <video/platform_lcd.h> + +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/irq.h> @@ -37,7 +42,6 @@ #include <plat/regs-serial.h> #include <plat/gpio-cfg.h> -#include <plat/s5p6440.h> #include <plat/clock.h> #include <plat/devs.h> #include <plat/cpu.h> @@ -47,6 +51,11 @@ #include <plat/ts.h> #include <plat/s5p-time.h> #include <plat/backlight.h> +#include <plat/fb.h> +#include <plat/regs-fb.h> +#include <plat/sdhci.h> + +#include "common.h" #define SMDK6440_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ @@ -92,6 +101,59 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = { }, }; +/* Frame Buffer */ +static struct s3c_fb_pd_win smdk6440_fb_win0 = { + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 24, +}; + +static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = { + .win[0] = &smdk6440_fb_win0, + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, +}; + +/* LCD power controller */ +static void smdk6440_lte480_reset_power(struct plat_lcd_data *pd, + unsigned int power) +{ + int err; + + if (power) { + err = gpio_request(S5P6440_GPN(5), "GPN"); + if (err) { + printk(KERN_ERR "failed to request GPN for lcd reset\n"); + return; + } + + gpio_direction_output(S5P6440_GPN(5), 1); + gpio_set_value(S5P6440_GPN(5), 0); + gpio_set_value(S5P6440_GPN(5), 1); + gpio_free(S5P6440_GPN(5)); + } +} + +static struct plat_lcd_data smdk6440_lcd_power_data = { + .set_power = smdk6440_lte480_reset_power, +}; + +static struct platform_device smdk6440_lcd_lte480wv = { + .name = "platform-lcd", + .dev.parent = &s3c_device_fb.dev, + .dev.platform_data = &smdk6440_lcd_power_data, +}; + static struct platform_device *smdk6440_devices[] __initdata = { &s3c_device_adc, &s3c_device_rtc, @@ -101,6 +163,27 @@ static struct platform_device *smdk6440_devices[] __initdata = { &s3c_device_wdt, &samsung_asoc_dma, &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 = { @@ -129,12 +212,6 @@ static struct i2c_board_info smdk6440_i2c_devs1[] __initdata = { /* To be populated */ }; -static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { - .delay = 10000, - .presc = 49, - .oversampling_shift = 2, -}; - /* LCD Backlight data */ static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = { .no = S5P6440_GPF(15), @@ -147,15 +224,26 @@ static struct platform_pwm_backlight_data smdk6440_bl_data = { static void __init smdk6440_map_io(void) { - s5p_init_io(NULL, 0, S5P64X0_SYS_ID); + s5p64x0_init_io(NULL, 0); s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs)); s5p_set_timer_source(S5P_PWM3, S5P_PWM4); } +static void s5p6440_set_lcd_interface(void) +{ + unsigned int cfg; + + /* select TFT LCD type (RGB I/F) */ + cfg = __raw_readl(S5P64X0_SPCON0); + cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK; + cfg |= S5P64X0_SPCON0_LCD_SEL_RGB; + __raw_writel(cfg, S5P64X0_SPCON0); +} + static void __init smdk6440_machine_init(void) { - s3c24xx_ts_set_platdata(&s3c_ts_platform); + s3c24xx_ts_set_platdata(NULL); s3c_i2c0_set_platdata(&s5p6440_i2c0_data); s3c_i2c1_set_platdata(&s5p6440_i2c1_data); @@ -166,15 +254,24 @@ static void __init smdk6440_machine_init(void) samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data); + 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)); } MACHINE_START(SMDK6440, "SMDK6440") /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ - .boot_params = S5P64X0_PA_SDRAM + 0x100, + .atag_offset = 0x100, .init_irq = s5p6440_init_irq, + .handle_irq = vic_handle_irq, .map_io = smdk6440_map_io, .init_machine = smdk6440_machine_init, .timer = &s5p_timer, + .restart = s5p64x0_restart, MACHINE_END diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c index 33f2adf8f3fe..efb69e2f2afe 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6450.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -23,7 +23,12 @@ #include <linux/clk.h> #include <linux/gpio.h> #include <linux/pwm_backlight.h> +#include <linux/fb.h> +#include <linux/mmc/host.h> +#include <video/platform_lcd.h> + +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/irq.h> @@ -37,7 +42,6 @@ #include <plat/regs-serial.h> #include <plat/gpio-cfg.h> -#include <plat/s5p6450.h> #include <plat/clock.h> #include <plat/devs.h> #include <plat/cpu.h> @@ -47,6 +51,11 @@ #include <plat/ts.h> #include <plat/s5p-time.h> #include <plat/backlight.h> +#include <plat/fb.h> +#include <plat/regs-fb.h> +#include <plat/sdhci.h> + +#include "common.h" #define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ @@ -110,6 +119,59 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = { #endif }; +/* Frame Buffer */ +static struct s3c_fb_pd_win smdk6450_fb_win0 = { + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 24, +}; + +static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = { + .win[0] = &smdk6450_fb_win0, + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, +}; + +/* LCD power controller */ +static void smdk6450_lte480_reset_power(struct plat_lcd_data *pd, + unsigned int power) +{ + int err; + + if (power) { + err = gpio_request(S5P6450_GPN(5), "GPN"); + if (err) { + printk(KERN_ERR "failed to request GPN for lcd reset\n"); + return; + } + + gpio_direction_output(S5P6450_GPN(5), 1); + gpio_set_value(S5P6450_GPN(5), 0); + gpio_set_value(S5P6450_GPN(5), 1); + gpio_free(S5P6450_GPN(5)); + } +} + +static struct plat_lcd_data smdk6450_lcd_power_data = { + .set_power = smdk6450_lte480_reset_power, +}; + +static struct platform_device smdk6450_lcd_lte480wv = { + .name = "platform-lcd", + .dev.parent = &s3c_device_fb.dev, + .dev.platform_data = &smdk6450_lcd_power_data, +}; + static struct platform_device *smdk6450_devices[] __initdata = { &s3c_device_adc, &s3c_device_rtc, @@ -119,9 +181,30 @@ static struct platform_device *smdk6450_devices[] __initdata = { &s3c_device_wdt, &samsung_asoc_dma, &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, @@ -148,12 +231,6 @@ static struct i2c_board_info smdk6450_i2c_devs1[] __initdata = { { I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */ }; -static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { - .delay = 10000, - .presc = 49, - .oversampling_shift = 2, -}; - /* LCD Backlight data */ static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = { .no = S5P6450_GPF(15), @@ -166,15 +243,26 @@ static struct platform_pwm_backlight_data smdk6450_bl_data = { static void __init smdk6450_map_io(void) { - s5p_init_io(NULL, 0, S5P64X0_SYS_ID); + s5p64x0_init_io(NULL, 0); s3c24xx_init_clocks(19200000); s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs)); s5p_set_timer_source(S5P_PWM3, S5P_PWM4); } +static void s5p6450_set_lcd_interface(void) +{ + unsigned int cfg; + + /* select TFT LCD type (RGB I/F) */ + cfg = __raw_readl(S5P64X0_SPCON0); + cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK; + cfg |= S5P64X0_SPCON0_LCD_SEL_RGB; + __raw_writel(cfg, S5P64X0_SPCON0); +} + static void __init smdk6450_machine_init(void) { - s3c24xx_ts_set_platdata(&s3c_ts_platform); + s3c24xx_ts_set_platdata(NULL); s3c_i2c0_set_platdata(&s5p6450_i2c0_data); s3c_i2c1_set_platdata(&s5p6450_i2c1_data); @@ -185,15 +273,24 @@ static void __init smdk6450_machine_init(void) samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data); + 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)); } MACHINE_START(SMDK6450, "SMDK6450") /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ - .boot_params = S5P64X0_PA_SDRAM + 0x100, + .atag_offset = 0x100, .init_irq = s5p6450_init_irq, + .handle_irq = vic_handle_irq, .map_io = smdk6450_map_io, .init_machine = smdk6450_machine_init, .timer = &s5p_timer, + .restart = s5p64x0_restart, MACHINE_END diff --git a/arch/arm/mach-s5p64x0/pm.c b/arch/arm/mach-s5p64x0/pm.c new file mode 100644 index 000000000000..23f9b22439c9 --- /dev/null +++ b/arch/arm/mach-s5p64x0/pm.c @@ -0,0 +1,206 @@ +/* linux/arch/arm/mach-s5p64x0/pm.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 Power Management Support + * + * Based on arch/arm/mach-s3c64xx/pm.c by Ben Dooks + * + * 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/suspend.h> +#include <linux/syscore_ops.h> +#include <linux/io.h> + +#include <plat/cpu.h> +#include <plat/pm.h> +#include <plat/regs-timer.h> +#include <plat/wakeup-mask.h> + +#include <mach/regs-clock.h> +#include <mach/regs-gpio.h> + +static struct sleep_save s5p64x0_core_save[] = { + SAVE_ITEM(S5P64X0_APLL_CON), + SAVE_ITEM(S5P64X0_MPLL_CON), + SAVE_ITEM(S5P64X0_EPLL_CON), + SAVE_ITEM(S5P64X0_EPLL_CON_K), + SAVE_ITEM(S5P64X0_CLK_SRC0), + SAVE_ITEM(S5P64X0_CLK_SRC1), + SAVE_ITEM(S5P64X0_CLK_DIV0), + SAVE_ITEM(S5P64X0_CLK_DIV1), + SAVE_ITEM(S5P64X0_CLK_DIV2), + SAVE_ITEM(S5P64X0_CLK_DIV3), + SAVE_ITEM(S5P64X0_CLK_GATE_MEM0), + SAVE_ITEM(S5P64X0_CLK_GATE_HCLK1), + SAVE_ITEM(S5P64X0_CLK_GATE_SCLK1), +}; + +static struct sleep_save s5p64x0_misc_save[] = { + SAVE_ITEM(S5P64X0_AHB_CON0), + SAVE_ITEM(S5P64X0_SPCON0), + SAVE_ITEM(S5P64X0_SPCON1), + SAVE_ITEM(S5P64X0_MEM0CONSLP0), + SAVE_ITEM(S5P64X0_MEM0CONSLP1), + SAVE_ITEM(S5P64X0_MEM0DRVCON), + SAVE_ITEM(S5P64X0_MEM1DRVCON), + + SAVE_ITEM(S3C64XX_TINT_CSTAT), +}; + +/* DPLL is present only in S5P6450 */ +static struct sleep_save s5p6450_core_save[] = { + SAVE_ITEM(S5P6450_DPLL_CON), + SAVE_ITEM(S5P6450_DPLL_CON_K), +}; + +void s3c_pm_configure_extint(void) +{ + __raw_writel(s3c_irqwake_eintmask, S5P64X0_EINT_WAKEUP_MASK); +} + +void s3c_pm_restore_core(void) +{ + __raw_writel(0, S5P64X0_EINT_WAKEUP_MASK); + + s3c_pm_do_restore_core(s5p64x0_core_save, + ARRAY_SIZE(s5p64x0_core_save)); + + if (soc_is_s5p6450()) + s3c_pm_do_restore_core(s5p6450_core_save, + ARRAY_SIZE(s5p6450_core_save)); + + s3c_pm_do_restore(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save)); +} + +void s3c_pm_save_core(void) +{ + s3c_pm_do_save(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save)); + + if (soc_is_s5p6450()) + s3c_pm_do_save(s5p6450_core_save, + ARRAY_SIZE(s5p6450_core_save)); + + s3c_pm_do_save(s5p64x0_core_save, ARRAY_SIZE(s5p64x0_core_save)); +} + +static int s5p64x0_cpu_suspend(unsigned long arg) +{ + unsigned long tmp = 0; + + /* + * Issue the standby signal into the pm unit. Note, we + * issue a write-buffer drain just in case. + */ + asm("b 1f\n\t" + ".align 5\n\t" + "1:\n\t" + "mcr p15, 0, %0, c7, c10, 5\n\t" + "mcr p15, 0, %0, c7, c10, 4\n\t" + "mcr p15, 0, %0, c7, c0, 4" : : "r" (tmp)); + + /* we should never get past here */ + panic("sleep resumed to originator?"); +} + +/* mapping of interrupts to parts of the wakeup mask */ +static struct samsung_wakeup_mask s5p64x0_wake_irqs[] = { + { .irq = IRQ_RTC_ALARM, .bit = S5P64X0_PWR_CFG_RTC_ALRM_DISABLE, }, + { .irq = IRQ_RTC_TIC, .bit = S5P64X0_PWR_CFG_RTC_TICK_DISABLE, }, + { .irq = IRQ_HSMMC0, .bit = S5P64X0_PWR_CFG_MMC0_DISABLE, }, + { .irq = IRQ_HSMMC1, .bit = S5P64X0_PWR_CFG_MMC1_DISABLE, }, +}; + +static void s5p64x0_pm_prepare(void) +{ + u32 tmp; + + samsung_sync_wakemask(S5P64X0_PWR_CFG, + s5p64x0_wake_irqs, ARRAY_SIZE(s5p64x0_wake_irqs)); + + /* store the resume address in INFORM0 register */ + __raw_writel(virt_to_phys(s3c_cpu_resume), S5P64X0_INFORM0); + + /* setup clock gating for FIMGVG block */ + __raw_writel((__raw_readl(S5P64X0_CLK_GATE_HCLK1) | \ + (S5P64X0_CLK_GATE_HCLK1_FIMGVG)), S5P64X0_CLK_GATE_HCLK1); + __raw_writel((__raw_readl(S5P64X0_CLK_GATE_SCLK1) | \ + (S5P64X0_CLK_GATE_SCLK1_FIMGVG)), S5P64X0_CLK_GATE_SCLK1); + + /* Configure the stabilization counter with wait time required */ + __raw_writel(S5P64X0_PWR_STABLE_PWR_CNT_VAL4, S5P64X0_PWR_STABLE); + + /* set WFI to SLEEP mode configuration */ + tmp = __raw_readl(S5P64X0_SLEEP_CFG); + tmp &= ~(S5P64X0_SLEEP_CFG_OSC_EN); + __raw_writel(tmp, S5P64X0_SLEEP_CFG); + + tmp = __raw_readl(S5P64X0_PWR_CFG); + tmp &= ~(S5P64X0_PWR_CFG_WFI_MASK); + tmp |= S5P64X0_PWR_CFG_WFI_SLEEP; + __raw_writel(tmp, S5P64X0_PWR_CFG); + + /* + * set OTHERS register to disable interrupt before going to + * sleep. This bit is present only in S5P6450, it is reserved + * in S5P6440. + */ + if (soc_is_s5p6450()) { + tmp = __raw_readl(S5P64X0_OTHERS); + tmp |= S5P6450_OTHERS_DISABLE_INT; + __raw_writel(tmp, S5P64X0_OTHERS); + } + + /* ensure previous wakeup state is cleared before sleeping */ + __raw_writel(__raw_readl(S5P64X0_WAKEUP_STAT), S5P64X0_WAKEUP_STAT); + +} + +static int s5p64x0_pm_add(struct device *dev) +{ + pm_cpu_prep = s5p64x0_pm_prepare; + pm_cpu_sleep = s5p64x0_cpu_suspend; + pm_uart_udivslot = 1; + + return 0; +} + +static struct subsys_interface s5p64x0_pm_interface = { + .name = "s5p64x0_pm", + .subsys = &s5p64x0_subsys, + .add_dev = s5p64x0_pm_add, +}; + +static __init int s5p64x0_pm_drvinit(void) +{ + s3c_pm_init(); + + return subsys_interface_register(&s5p64x0_pm_interface); +} +arch_initcall(s5p64x0_pm_drvinit); + +static void s5p64x0_pm_resume(void) +{ + u32 tmp; + + tmp = __raw_readl(S5P64X0_OTHERS); + tmp |= (S5P64X0_OTHERS_RET_MMC0 | S5P64X0_OTHERS_RET_MMC1 | \ + S5P64X0_OTHERS_RET_UART); + __raw_writel(tmp , S5P64X0_OTHERS); +} + +static struct syscore_ops s5p64x0_pm_syscore_ops = { + .resume = s5p64x0_pm_resume, +}; + +static __init int s5p64x0_pm_syscore_init(void) +{ + register_syscore_ops(&s5p64x0_pm_syscore_ops); + + return 0; +} +arch_initcall(s5p64x0_pm_syscore_init); diff --git a/arch/arm/mach-s5p64x0/setup-fb-24bpp.c b/arch/arm/mach-s5p64x0/setup-fb-24bpp.c new file mode 100644 index 000000000000..f346ee4af54d --- /dev/null +++ b/arch/arm/mach-s5p64x0/setup-fb-24bpp.c @@ -0,0 +1,29 @@ +/* linux/arch/arm/mach-s5p64x0/setup-fb-24bpp.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Base S5P64X0 GPIO setup information for LCD framebuffer + * + * 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/fb.h> +#include <linux/gpio.h> + +#include <plat/cpu.h> +#include <plat/fb.h> +#include <plat/gpio-cfg.h> + +void s5p64x0_fb_gpio_setup_24bpp(void) +{ + if (soc_is_s5p6440()) { + s3c_gpio_cfgrange_nopull(S5P6440_GPI(0), 16, S3C_GPIO_SFN(2)); + s3c_gpio_cfgrange_nopull(S5P6440_GPJ(0), 12, S3C_GPIO_SFN(2)); + } else if (soc_is_s5p6450()) { + s3c_gpio_cfgrange_nopull(S5P6450_GPI(0), 16, S3C_GPIO_SFN(2)); + s3c_gpio_cfgrange_nopull(S5P6450_GPJ(0), 12, S3C_GPIO_SFN(2)); + } +} 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/mach-s5p64x0/setup-spi.c b/arch/arm/mach-s5p64x0/setup-spi.c new file mode 100644 index 000000000000..e9b841240352 --- /dev/null +++ b/arch/arm/mach-s5p64x0/setup-spi.c @@ -0,0 +1,55 @@ +/* linux/arch/arm/mach-s5p64x0/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 <linux/io.h> + +#include <plat/gpio-cfg.h> +#include <plat/cpu.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, + .tx_st_done = 25, +}; + +int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) +{ + if (soc_is_s5p6450()) + s3c_gpio_cfgall_range(S5P6450_GPC(0), 3, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); + else + s3c_gpio_cfgall_range(S5P6440_GPC(0), 3, + 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, + .tx_st_done = 25, +}; + +int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) +{ + if (soc_is_s5p6450()) + s3c_gpio_cfgall_range(S5P6450_GPC(4), 3, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); + else + s3c_gpio_cfgall_range(S5P6440_GPC(4), 3, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); + return 0; +} +#endif |