diff options
180 files changed, 8951 insertions, 3271 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9c26ba7244fb..27564682d222 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -678,8 +678,8 @@ config ARCH_S3C64XX help Samsung S3C64XX series based systems -config ARCH_S5P6440 - bool "Samsung S5P6440" +config ARCH_S5P64X0 + bool "Samsung S5P6440 S5P6450" select CPU_V6 select GENERIC_GPIO select HAVE_CLK @@ -688,7 +688,8 @@ config ARCH_S5P6440 select HAVE_S3C2410_I2C select HAVE_S3C_RTC help - Samsung S5P6440 CPU based systems + Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440, + SMDK6450. config ARCH_S5P6442 bool "Samsung S5P6442" @@ -716,9 +717,11 @@ config ARCH_S5PC100 config ARCH_S5PV210 bool "Samsung S5PV210/S5PC110" select CPU_V7 + select ARCH_SPARSEMEM_ENABLE select GENERIC_GPIO select HAVE_CLK select ARM_L1_CACHE_SHIFT_6 + select ARCH_HAS_CPUFREQ select ARCH_USES_GETTIMEOFFSET select HAVE_S3C2410_I2C select HAVE_S3C_RTC @@ -729,9 +732,13 @@ config ARCH_S5PV210 config ARCH_S5PV310 bool "Samsung S5PV310/S5PC210" select CPU_V7 + select ARCH_SPARSEMEM_ENABLE select GENERIC_GPIO select HAVE_CLK select GENERIC_CLOCKEVENTS + select HAVE_S3C_RTC + select HAVE_S3C2410_I2C + select HAVE_S3C2410_WATCHDOG help Samsung S5PV310 series based systems @@ -928,7 +935,7 @@ if ARCH_S3C64XX source "arch/arm/mach-s3c64xx/Kconfig" endif -source "arch/arm/mach-s5p6440/Kconfig" +source "arch/arm/mach-s5p64x0/Kconfig" source "arch/arm/mach-s5p6442/Kconfig" @@ -1271,7 +1278,7 @@ source kernel/Kconfig.preempt config HZ int - default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || \ + default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P64X0 || \ ARCH_S5P6442 || ARCH_S5PV210 || ARCH_S5PV310 default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER default AT91_TIMER_HZ if ARCH_AT91 diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 59c1ce858fc8..8420f21571da 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -173,7 +173,7 @@ machine-$(CONFIG_ARCH_RPC) := rpc machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443 machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0 machine-$(CONFIG_ARCH_S3C64XX) := s3c64xx -machine-$(CONFIG_ARCH_S5P6440) := s5p6440 +machine-$(CONFIG_ARCH_S5P64X0) := s5p64x0 machine-$(CONFIG_ARCH_S5P6442) := s5p6442 machine-$(CONFIG_ARCH_S5PC100) := s5pc100 machine-$(CONFIG_ARCH_S5PV210) := s5pv210 diff --git a/arch/arm/configs/s5p6440_defconfig b/arch/arm/configs/s5p64x0_defconfig index 0b0266c6d326..2993ecd35145 100644 --- a/arch/arm/configs/s5p6440_defconfig +++ b/arch/arm/configs/s5p64x0_defconfig @@ -5,10 +5,11 @@ CONFIG_KALLSYMS_ALL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set -CONFIG_ARCH_S5P6440=y +CONFIG_ARCH_S5P64X0=y CONFIG_S3C_BOOT_ERROR_RESET=y CONFIG_S3C_LOWLEVEL_UART_PORT=1 CONFIG_MACH_SMDK6440=y +CONFIG_MACH_SMDK6450=y CONFIG_CPU_32v6K=y CONFIG_AEABI=y CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc" diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c index 9648fbc36eec..4a5c682a3727 100644 --- a/arch/arm/mach-s3c64xx/dev-audio.c +++ b/arch/arm/mach-s3c64xx/dev-audio.c @@ -22,44 +22,33 @@ #include <plat/audio.h> #include <plat/gpio-cfg.h> -#include <mach/gpio-bank-c.h> -#include <mach/gpio-bank-d.h> -#include <mach/gpio-bank-e.h> -#include <mach/gpio-bank-h.h> - static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev) { + unsigned int base; + switch (pdev->id) { case 0: - s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); - s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); - s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK); - s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI); - s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0); + base = S3C64XX_GPD(0); break; case 1: - s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK); - s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK); - s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK); - s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI); - s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0); + base = S3C64XX_GPE(0); + break; default: printk(KERN_DEBUG "Invalid I2S Controller number!"); return -EINVAL; } + s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(3)); + return 0; } static int s3c64xx_i2sv4_cfg_gpio(struct platform_device *pdev) { - s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0); - s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1); - s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2); - s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK); - s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK); - s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK); - s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI); + s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin_range(S3C64XX_GPH(6), 4, S3C_GPIO_SFN(5)); return 0; } @@ -168,26 +157,21 @@ EXPORT_SYMBOL(s3c64xx_device_iisv4); static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev) { + unsigned int base; + switch (pdev->id) { case 0: - s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_PCM0_SCLK); - s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_PCM0_EXTCLK); - s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_PCM0_FSYNC); - s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_PCM0_SIN); - s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_PCM0_SOUT); + base = S3C64XX_GPD(0); break; case 1: - s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_PCM1_SCLK); - s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_PCM1_EXTCLK); - s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_PCM1_FSYNC); - s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_PCM1_SIN); - s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT); + base = S3C64XX_GPE(0); break; default: printk(KERN_DEBUG "Invalid PCM Controller number!"); return -EINVAL; } + s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(2)); return 0; } @@ -261,24 +245,12 @@ EXPORT_SYMBOL(s3c64xx_device_pcm1); static int s3c64xx_ac97_cfg_gpd(struct platform_device *pdev) { - s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_AC97_BITCLK); - s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_AC97_nRESET); - s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_AC97_SYNC); - s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_AC97_SDI); - s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_AC97_SDO); - - return 0; + return s3c_gpio_cfgpin_range(S3C64XX_GPD(0), 5, S3C_GPIO_SFN(4)); } static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev) { - s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_AC97_BITCLK); - s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_AC97_nRESET); - s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_AC97_SYNC); - s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_AC97_SDI); - s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_AC97_SDO); - - return 0; + return s3c_gpio_cfgpin_range(S3C64XX_GPE(0), 5, S3C_GPIO_SFN(4)); } static struct resource s3c64xx_ac97_resource[] = { diff --git a/arch/arm/mach-s3c64xx/gpiolib.c b/arch/arm/mach-s3c64xx/gpiolib.c index 300dee4a667b..fd99a82e82c4 100644 --- a/arch/arm/mach-s3c64xx/gpiolib.c +++ b/arch/arm/mach-s3c64xx/gpiolib.c @@ -195,11 +195,6 @@ static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = { .get_pull = s3c_gpio_getpull_updown, }; -int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin) -{ - return IRQ_EINT(0) + pin; -} - static struct s3c_gpio_chip gpio_2bit[] = { { .base = S3C64XX_GPF_BASE, @@ -227,12 +222,13 @@ static struct s3c_gpio_chip gpio_2bit[] = { }, }, { .base = S3C64XX_GPN_BASE, + .irq_base = IRQ_EINT(0), .config = &gpio_2bit_cfg_eint10, .chip = { .base = S3C64XX_GPN(0), .ngpio = S3C64XX_GPIO_N_NR, .label = "GPN", - .to_irq = s3c64xx_gpio2int_gpn, + .to_irq = samsung_gpiolib_to_irq, }, }, { .base = S3C64XX_GPO_BASE, diff --git a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c index 000736877df2..8f3091182f9c 100644 --- a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c +++ b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c @@ -23,15 +23,6 @@ extern void s3c64xx_fb_gpio_setup_24bpp(void) { - unsigned int gpio; - - for (gpio = S3C64XX_GPI(0); gpio <= S3C64XX_GPI(15); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } - - for (gpio = S3C64XX_GPJ(0); gpio <= S3C64XX_GPJ(11); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S3C64XX_GPI(0), 16, S3C_GPIO_SFN(2)); + s3c_gpio_cfgrange_nopull(S3C64XX_GPJ(0), 12, S3C_GPIO_SFN(2)); } diff --git a/arch/arm/mach-s3c64xx/setup-ide.c b/arch/arm/mach-s3c64xx/setup-ide.c index c12c315f33bc..41b425602d88 100644 --- a/arch/arm/mach-s3c64xx/setup-ide.c +++ b/arch/arm/mach-s3c64xx/setup-ide.c @@ -17,11 +17,11 @@ #include <mach/map.h> #include <mach/regs-clock.h> #include <plat/gpio-cfg.h> +#include <plat/ata.h> void s3c64xx_ide_setup_gpio(void) { u32 reg; - u32 gpio = 0; reg = readl(S3C_MEM_SYS_CFG) & (~0x3f); @@ -32,15 +32,12 @@ void s3c64xx_ide_setup_gpio(void) s3c_gpio_cfgpin(S3C64XX_GPB(4), S3C_GPIO_SFN(4)); /* Set XhiDATA[15:0] pins as CF Data[15:0] */ - for (gpio = S3C64XX_GPK(0); gpio <= S3C64XX_GPK(15); gpio++) - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin_range(S3C64XX_GPK(0), 16, S3C_GPIO_SFN(5)); /* Set XhiADDR[2:0] pins as CF ADDR[2:0] */ - for (gpio = S3C64XX_GPL(0); gpio <= S3C64XX_GPL(2); gpio++) - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6)); + s3c_gpio_cfgpin_range(S3C64XX_GPL(0), 3, S3C_GPIO_SFN(6)); /* Set Xhi ctrl pins as CF ctrl pins(IORDY, IOWR, IORD, CE[0:1]) */ s3c_gpio_cfgpin(S3C64XX_GPM(5), S3C_GPIO_SFN(1)); - for (gpio = S3C64XX_GPM(0); gpio <= S3C64XX_GPM(4); gpio++) - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6)); + s3c_gpio_cfgpin_range(S3C64XX_GPM(0), 5, S3C_GPIO_SFN(6)); } diff --git a/arch/arm/mach-s3c64xx/setup-keypad.c b/arch/arm/mach-s3c64xx/setup-keypad.c index abc34e4e1a93..f8ed0d22db70 100644 --- a/arch/arm/mach-s3c64xx/setup-keypad.c +++ b/arch/arm/mach-s3c64xx/setup-keypad.c @@ -12,23 +12,13 @@ #include <linux/gpio.h> #include <plat/gpio-cfg.h> +#include <plat/keypad.h> void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) { - unsigned int gpio; - unsigned int end; - /* Set all the necessary GPK pins to special-function 3: KP_ROW[x] */ - end = S3C64XX_GPK(8 + rows); - for (gpio = S3C64XX_GPK(8); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S3C64XX_GPK(8), 8 + rows, S3C_GPIO_SFN(3)); /* Set all the necessary GPL pins to special-function 3: KP_COL[x] */ - end = S3C64XX_GPL(0 + cols); - for (gpio = S3C64XX_GPL(0); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S3C64XX_GPL(0), cols, S3C_GPIO_SFN(3)); } diff --git a/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c b/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c index 322359591374..6eac071afae2 100644 --- a/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c +++ b/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c @@ -24,16 +24,9 @@ void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) { struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; - unsigned int gpio; - unsigned int end; - end = S3C64XX_GPG(2 + width); - - /* Set all the necessary GPG pins to special-function 0 */ - for (gpio = S3C64XX_GPG(0); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + /* Set all the necessary GPG pins to special-function 2 */ + s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2)); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); @@ -44,16 +37,9 @@ void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) { struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; - unsigned int gpio; - unsigned int end; - end = S3C64XX_GPH(2 + width); - - /* Set all the necessary GPG pins to special-function 0 */ - for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + /* Set all the necessary GPH pins to special-function 2 */ + s3c_gpio_cfgrange_nopull(S3C64XX_GPH(0), 2 + width, S3C_GPIO_SFN(2)); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); @@ -63,20 +49,9 @@ void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) { - unsigned int gpio; - unsigned int end; + /* Set all the necessary GPH pins to special-function 3 */ + s3c_gpio_cfgrange_nopull(S3C64XX_GPH(6), width, S3C_GPIO_SFN(3)); - end = S3C64XX_GPH(6 + width); - - /* Set all the necessary GPH pins to special-function 1 */ - for (gpio = S3C64XX_GPH(6); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } - - /* Set all the necessary GPC pins to special-function 1 */ - for (gpio = S3C64XX_GPC(4); gpio < S3C64XX_GPC(6); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + /* Set all the necessary GPC pins to special-function 3 */ + s3c_gpio_cfgrange_nopull(S3C64XX_GPC(4), 2, S3C_GPIO_SFN(3)); } diff --git a/arch/arm/mach-s5p6440/Kconfig b/arch/arm/mach-s5p6440/Kconfig deleted file mode 100644 index 6a4af7f57584..000000000000 --- a/arch/arm/mach-s5p6440/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -# arch/arm/mach-s5p6440/Kconfig -# -# Copyright (c) 2009 Samsung Electronics Co., Ltd. -# http://www.samsung.com/ -# -# Licensed under GPLv2 - -if ARCH_S5P6440 - -config CPU_S5P6440 - bool - select S3C_PL330_DMA - help - Enable S5P6440 CPU support - -config S5P6440_SETUP_I2C1 - bool - help - Common setup code for i2c bus 1. - -config MACH_SMDK6440 - bool "SMDK6440" - select CPU_S5P6440 - select S3C_DEV_I2C1 - select S3C_DEV_RTC - select S3C_DEV_WDT - select SAMSUNG_DEV_ADC - select SAMSUNG_DEV_TS - select S5P6440_SETUP_I2C1 - help - Machine support for the Samsung SMDK6440 - -endif diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile deleted file mode 100644 index c3fe4d3662a9..000000000000 --- a/arch/arm/mach-s5p6440/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# arch/arm/mach-s5p6440/Makefile -# -# Copyright (c) 2009 Samsung Electronics Co., Ltd. -# http://www.samsung.com/ -# -# Licensed under GPLv2 - -obj-y := -obj-m := -obj-n := -obj- := - -# Core support for S5P6440 system - -obj-$(CONFIG_CPU_S5P6440) += cpu.o init.o clock.o gpio.o dma.o -obj-$(CONFIG_CPU_S5P6440) += setup-i2c0.o - -# machine support - -obj-$(CONFIG_MACH_SMDK6440) += mach-smdk6440.o - -# device support -obj-y += dev-audio.o -obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o -obj-$(CONFIG_S5P6440_SETUP_I2C1) += setup-i2c1.o diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c deleted file mode 100644 index ca6e48dce777..000000000000 --- a/arch/arm/mach-s5p6440/clock.c +++ /dev/null @@ -1,846 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/clock.c - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - Clock 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/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/sysdev.h> -#include <linux/io.h> - -#include <mach/hardware.h> -#include <mach/map.h> - -#include <plat/cpu-freq.h> -#include <mach/regs-clock.h> -#include <plat/clock.h> -#include <plat/cpu.h> -#include <plat/clock-clksrc.h> -#include <plat/s5p-clock.h> -#include <plat/pll.h> -#include <plat/s5p6440.h> - -/* APLL Mux output clock */ -static struct clksrc_clk clk_mout_apll = { - .clk = { - .name = "mout_apll", - .id = -1, - }, - .sources = &clk_src_apll, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 }, -}; - -static int s5p6440_epll_enable(struct clk *clk, int enable) -{ - unsigned int ctrlbit = clk->ctrlbit; - unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit; - - if (enable) - __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON); - else - __raw_writel(epll_con, S5P_EPLL_CON); - - return 0; -} - -static unsigned long s5p6440_epll_get_rate(struct clk *clk) -{ - return clk->rate; -} - -static u32 epll_div[][5] = { - { 36000000, 0, 48, 1, 4 }, - { 48000000, 0, 32, 1, 3 }, - { 60000000, 0, 40, 1, 3 }, - { 72000000, 0, 48, 1, 3 }, - { 84000000, 0, 28, 1, 2 }, - { 96000000, 0, 32, 1, 2 }, - { 32768000, 45264, 43, 1, 4 }, - { 45158000, 6903, 30, 1, 3 }, - { 49152000, 50332, 32, 1, 3 }, - { 67738000, 10398, 45, 1, 3 }, - { 73728000, 9961, 49, 1, 3 } -}; - -static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate) -{ - unsigned int epll_con, epll_con_k; - unsigned int i; - - if (clk->rate == rate) /* Return if nothing changed */ - return 0; - - epll_con = __raw_readl(S5P_EPLL_CON); - epll_con_k = __raw_readl(S5P_EPLL_CON_K); - - epll_con_k &= ~(PLL90XX_KDIV_MASK); - epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK); - - for (i = 0; i < ARRAY_SIZE(epll_div); i++) { - if (epll_div[i][0] == rate) { - epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT); - epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) | - (epll_div[i][3] << PLL90XX_PDIV_SHIFT) | - (epll_div[i][4] << PLL90XX_SDIV_SHIFT); - break; - } - } - - if (i == ARRAY_SIZE(epll_div)) { - printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__); - return -EINVAL; - } - - __raw_writel(epll_con, S5P_EPLL_CON); - __raw_writel(epll_con_k, S5P_EPLL_CON_K); - - clk->rate = rate; - - return 0; -} - -static struct clk_ops s5p6440_epll_ops = { - .get_rate = s5p6440_epll_get_rate, - .set_rate = s5p6440_epll_set_rate, -}; - -static struct clksrc_clk clk_mout_epll = { - .clk = { - .name = "mout_epll", - .id = -1, - }, - .sources = &clk_src_epll, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 2, .size = 1 }, -}; - -static struct clksrc_clk clk_mout_mpll = { - .clk = { - .name = "mout_mpll", - .id = -1, - }, - .sources = &clk_src_mpll, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 }, -}; - -enum perf_level { - L0 = 532*1000, - L1 = 266*1000, - L2 = 133*1000, -}; - -static const u32 clock_table[][3] = { - /*{ARM_CLK, DIVarm, DIVhclk}*/ - {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P_CLKDIV0_HCLK_SHIFT)}, - {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P_CLKDIV0_HCLK_SHIFT)}, - {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P_CLKDIV0_HCLK_SHIFT)}, -}; - -static unsigned long s5p6440_armclk_get_rate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - u32 clkdiv; - - /* divisor mask starts at bit0, so no need to shift */ - clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK; - - return rate / (clkdiv + 1); -} - -static unsigned long s5p6440_armclk_round_rate(struct clk *clk, - unsigned long rate) -{ - u32 iter; - - for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) { - if (rate > clock_table[iter][0]) - return clock_table[iter-1][0]; - } - - return clock_table[ARRAY_SIZE(clock_table) - 1][0]; -} - -static int s5p6440_armclk_set_rate(struct clk *clk, unsigned long rate) -{ - u32 round_tmp; - u32 iter; - u32 clk_div0_tmp; - u32 cur_rate = clk->ops->get_rate(clk); - unsigned long flags; - - round_tmp = clk->ops->round_rate(clk, rate); - if (round_tmp == cur_rate) - return 0; - - - for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) { - if (round_tmp == clock_table[iter][0]) - break; - } - - if (iter >= ARRAY_SIZE(clock_table)) - iter = ARRAY_SIZE(clock_table) - 1; - - local_irq_save(flags); - if (cur_rate > round_tmp) { - /* Frequency Down */ - clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK); - clk_div0_tmp |= clock_table[iter][1]; - __raw_writel(clk_div0_tmp, ARM_CLK_DIV); - - clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & - ~(S5P_CLKDIV0_HCLK_MASK); - clk_div0_tmp |= clock_table[iter][2]; - __raw_writel(clk_div0_tmp, ARM_CLK_DIV); - - - } else { - /* Frequency Up */ - clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & - ~(S5P_CLKDIV0_HCLK_MASK); - clk_div0_tmp |= clock_table[iter][2]; - __raw_writel(clk_div0_tmp, ARM_CLK_DIV); - - clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK); - clk_div0_tmp |= clock_table[iter][1]; - __raw_writel(clk_div0_tmp, ARM_CLK_DIV); - } - local_irq_restore(flags); - - clk->rate = clock_table[iter][0]; - - return 0; -} - -static struct clk_ops s5p6440_clkarm_ops = { - .get_rate = s5p6440_armclk_get_rate, - .set_rate = s5p6440_armclk_set_rate, - .round_rate = s5p6440_armclk_round_rate, -}; - -static struct clksrc_clk clk_armclk = { - .clk = { - .name = "armclk", - .id = 1, - .parent = &clk_mout_apll.clk, - .ops = &s5p6440_clkarm_ops, - }, - .reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 4 }, -}; - -static struct clksrc_clk clk_dout_mpll = { - .clk = { - .name = "dout_mpll", - .id = -1, - .parent = &clk_mout_mpll.clk, - }, - .reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 }, -}; - -static struct clksrc_clk clk_hclk = { - .clk = { - .name = "clk_hclk", - .id = -1, - .parent = &clk_armclk.clk, - }, - .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 }, -}; - -static struct clksrc_clk clk_pclk = { - .clk = { - .name = "clk_pclk", - .id = -1, - .parent = &clk_hclk.clk, - }, - .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 4 }, -}; - -static struct clk *clkset_hclklow_list[] = { - &clk_mout_apll.clk, - &clk_mout_mpll.clk, -}; - -static struct clksrc_sources clkset_hclklow = { - .sources = clkset_hclklow_list, - .nr_sources = ARRAY_SIZE(clkset_hclklow_list), -}; - -static struct clksrc_clk clk_hclk_low = { - .clk = { - .name = "hclk_low", - .id = -1, - }, - .sources = &clkset_hclklow, - .reg_src = { .reg = S5P_SYS_OTHERS, .shift = 6, .size = 1 }, - .reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 }, -}; - -static struct clksrc_clk clk_pclk_low = { - .clk = { - .name = "pclk_low", - .id = -1, - .parent = &clk_hclk_low.clk, - }, - .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 }, -}; - -int s5p6440_clk48m_ctrl(struct clk *clk, int enable) -{ - unsigned long flags; - u32 val; - - /* can't rely on clock lock, this register has other usages */ - local_irq_save(flags); - - val = __raw_readl(S5P_OTHERS); - if (enable) - val |= S5P_OTHERS_USB_SIG_MASK; - else - val &= ~S5P_OTHERS_USB_SIG_MASK; - - __raw_writel(val, S5P_OTHERS); - - local_irq_restore(flags); - - return 0; -} - -static int s5p6440_pclk_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_PCLK, clk, enable); -} - -static int s5p6440_hclk0_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_HCLK0, clk, enable); -} - -static int s5p6440_hclk1_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_HCLK1, clk, enable); -} - -static int s5p6440_sclk_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable); -} - -static int s5p6440_sclk1_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_SCLK1, clk, enable); -} - -static int s5p6440_mem_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable); -} - -/* - * The following clocks will be disabled during clock initialization. It is - * recommended to keep the following clocks disabled until the driver requests - * for enabling the clock. - */ -static struct clk init_clocks_disable[] = { - { - .name = "nand", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_mem_ctrl, - .ctrlbit = S5P_CLKCON_MEM0_HCLK_NFCON, - }, { - .name = "adc", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_TSADC, - }, { - .name = "i2c", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_IIC0, - }, { - .name = "i2s_v40", - .id = 0, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_IIS2, - }, { - .name = "spi", - .id = 0, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_SPI0, - }, { - .name = "spi", - .id = 1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_SPI1, - }, { - .name = "sclk_spi_48", - .id = 0, - .parent = &clk_48m, - .enable = s5p6440_sclk_ctrl, - .ctrlbit = S5P_CLKCON_SCLK0_SPI0_48, - }, { - .name = "sclk_spi_48", - .id = 1, - .parent = &clk_48m, - .enable = s5p6440_sclk_ctrl, - .ctrlbit = S5P_CLKCON_SCLK0_SPI1_48, - }, { - .name = "mmc_48m", - .id = 0, - .parent = &clk_48m, - .enable = s5p6440_sclk_ctrl, - .ctrlbit = S5P_CLKCON_SCLK0_MMC0_48, - }, { - .name = "mmc_48m", - .id = 1, - .parent = &clk_48m, - .enable = s5p6440_sclk_ctrl, - .ctrlbit = S5P_CLKCON_SCLK0_MMC1_48, - }, { - .name = "mmc_48m", - .id = 2, - .parent = &clk_48m, - .enable = s5p6440_sclk_ctrl, - .ctrlbit = S5P_CLKCON_SCLK0_MMC2_48, - }, { - .name = "otg", - .id = -1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = S5P_CLKCON_HCLK0_USB - }, { - .name = "post", - .id = -1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = S5P_CLKCON_HCLK0_POST0 - }, { - .name = "lcd", - .id = -1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk1_ctrl, - .ctrlbit = S5P_CLKCON_HCLK1_DISPCON, - }, { - .name = "hsmmc", - .id = 0, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = S5P_CLKCON_HCLK0_HSMMC0, - }, { - .name = "hsmmc", - .id = 1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = S5P_CLKCON_HCLK0_HSMMC1, - }, { - .name = "hsmmc", - .id = 2, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = S5P_CLKCON_HCLK0_HSMMC2, - }, { - .name = "rtc", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_RTC, - }, { - .name = "watchdog", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_WDT, - }, { - .name = "timers", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_PWM, - }, { - .name = "hclk_fimgvg", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_hclk1_ctrl, - .ctrlbit = (1 << 2), - }, { - .name = "tsi", - .id = -1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk1_ctrl, - .ctrlbit = (1 << 0), - }, { - .name = "pclk_fimgvg", - .id = -1, - .parent = &clk_pclk.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 31), - }, { - .name = "dmc0", - .id = -1, - .parent = &clk_pclk.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 30), - }, { - .name = "etm", - .id = -1, - .parent = &clk_pclk.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 29), - }, { - .name = "dsim", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 28), - }, { - .name = "gps", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 25), - }, { - .name = "pcm", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 8), - }, { - .name = "irom", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = (1 << 25), - }, { - .name = "dma", - .id = -1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = (1 << 12), - }, { - .name = "2d", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = (1 << 8), - }, -}; - -/* - * The following clocks will be enabled during clock initialization. - */ -static struct clk init_clocks[] = { - { - .name = "gpio", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_GPIO, - }, { - .name = "uart", - .id = 0, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_UART0, - }, { - .name = "uart", - .id = 1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_UART1, - }, { - .name = "uart", - .id = 2, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_UART2, - }, { - .name = "uart", - .id = 3, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_UART3, - }, { - .name = "mem", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = (1 << 21), - }, { - .name = "intc", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = (1 << 1), - }, -}; - -static struct clk clk_iis_cd_v40 = { - .name = "iis_cdclk_v40", - .id = -1, -}; - -static struct clk clk_pcm_cd = { - .name = "pcm_cdclk", - .id = -1, -}; - -static struct clk *clkset_group1_list[] = { - &clk_mout_epll.clk, - &clk_dout_mpll.clk, - &clk_fin_epll, -}; - -static struct clksrc_sources clkset_group1 = { - .sources = clkset_group1_list, - .nr_sources = ARRAY_SIZE(clkset_group1_list), -}; - -static struct clk *clkset_uart_list[] = { - &clk_mout_epll.clk, - &clk_dout_mpll.clk, -}; - -static struct clksrc_sources clkset_uart = { - .sources = clkset_uart_list, - .nr_sources = ARRAY_SIZE(clkset_uart_list), -}; - -static struct clk *clkset_audio_list[] = { - &clk_mout_epll.clk, - &clk_dout_mpll.clk, - &clk_fin_epll, - &clk_iis_cd_v40, - &clk_pcm_cd, -}; - -static struct clksrc_sources clkset_audio = { - .sources = clkset_audio_list, - .nr_sources = ARRAY_SIZE(clkset_audio_list), -}; - -static struct clksrc_clk clksrcs[] = { - { - .clk = { - .name = "mmc_bus", - .id = 0, - .ctrlbit = S5P_CLKCON_SCLK0_MMC0, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "mmc_bus", - .id = 1, - .ctrlbit = S5P_CLKCON_SCLK0_MMC1, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "mmc_bus", - .id = 2, - .ctrlbit = S5P_CLKCON_SCLK0_MMC2, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 }, - }, { - .clk = { - .name = "uclk1", - .id = -1, - .ctrlbit = S5P_CLKCON_SCLK0_UART, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_uart, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 13, .size = 1 }, - .reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 }, - }, { - .clk = { - .name = "spi_epll", - .id = 0, - .ctrlbit = S5P_CLKCON_SCLK0_SPI0, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "spi_epll", - .id = 1, - .ctrlbit = S5P_CLKCON_SCLK0_SPI1, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "sclk_post", - .id = -1, - .ctrlbit = (1 << 10), - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 26, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 }, - }, { - .clk = { - .name = "sclk_dispcon", - .id = -1, - .ctrlbit = (1 << 1), - .enable = s5p6440_sclk1_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_fimgvg", - .id = -1, - .ctrlbit = (1 << 2), - .enable = s5p6440_sclk1_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "sclk_audio2", - .id = -1, - .ctrlbit = (1 << 11), - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_audio, - .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 3 }, - .reg_div = { .reg = S5P_CLK_DIV2, .shift = 24, .size = 4 }, - }, -}; - -/* Clock initialisation code */ -static struct clksrc_clk *sysclks[] = { - &clk_mout_apll, - &clk_mout_epll, - &clk_mout_mpll, - &clk_dout_mpll, - &clk_armclk, - &clk_hclk, - &clk_pclk, - &clk_hclk_low, - &clk_pclk_low, -}; - -void __init_or_cpufreq s5p6440_setup_clocks(void) -{ - struct clk *xtal_clk; - unsigned long xtal; - unsigned long fclk; - unsigned long hclk; - unsigned long hclk_low; - unsigned long pclk; - unsigned long pclk_low; - unsigned long epll; - unsigned long apll; - unsigned long mpll; - unsigned int ptr; - - /* Set S5P6440 functions for clk_fout_epll */ - clk_fout_epll.enable = s5p6440_epll_enable; - clk_fout_epll.ops = &s5p6440_epll_ops; - - clk_48m.enable = s5p6440_clk48m_ctrl; - - xtal_clk = clk_get(NULL, "ext_xtal"); - BUG_ON(IS_ERR(xtal_clk)); - - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON), - __raw_readl(S5P_EPLL_CON_K)); - mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); - apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502); - - clk_fout_mpll.rate = mpll; - clk_fout_epll.rate = epll; - clk_fout_apll.rate = apll; - - printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \ - " E=%ld.%ldMHz\n", - print_mhz(apll), print_mhz(mpll), print_mhz(epll)); - - fclk = clk_get_rate(&clk_armclk.clk); - hclk = clk_get_rate(&clk_hclk.clk); - pclk = clk_get_rate(&clk_pclk.clk); - hclk_low = clk_get_rate(&clk_hclk_low.clk); - pclk_low = clk_get_rate(&clk_pclk_low.clk); - - printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \ - " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n", - print_mhz(hclk), print_mhz(hclk_low), - print_mhz(pclk), print_mhz(pclk_low)); - - clk_f.rate = fclk; - clk_h.rate = hclk; - clk_p.rate = pclk; - - for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) - s3c_set_clksrc(&clksrcs[ptr], true); -} - -static struct clk *clks[] __initdata = { - &clk_ext, - &clk_iis_cd_v40, - &clk_pcm_cd, -}; - -void __init s5p6440_register_clocks(void) -{ - struct clk *clkp; - int ret; - int ptr; - - ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); - if (ret > 0) - printk(KERN_ERR "Failed to register %u clocks\n", ret); - - for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) - s3c_register_clksrc(sysclks[ptr], 1); - - s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); - s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); - - clkp = init_clocks_disable; - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - (clkp->enable)(clkp, 0); - } - - s3c_pwmclk_init(); -} diff --git a/arch/arm/mach-s5p6440/cpu.c b/arch/arm/mach-s5p6440/cpu.c deleted file mode 100644 index ec592e866054..000000000000 --- a/arch/arm/mach-s5p6440/cpu.c +++ /dev/null @@ -1,117 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/cpu.c - * - * Copyright (c) 2009 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 <mach/hardware.h> -#include <mach/map.h> -#include <asm/irq.h> - -#include <plat/regs-serial.h> -#include <mach/regs-clock.h> - -#include <plat/cpu.h> -#include <plat/devs.h> -#include <plat/clock.h> -#include <plat/s5p6440.h> -#include <plat/adc-core.h> - -static void s5p6440_idle(void) -{ - unsigned long val; - - if (!need_resched()) { - val = __raw_readl(S5P_PWR_CFG); - val &= ~(0x3<<5); - val |= (0x1<<5); - __raw_writel(val, S5P_PWR_CFG); - - cpu_do_idle(); - } - local_irq_enable(); -} - -/* s5p6440_map_io - * - * register the standard cpu IO areas -*/ - -void __init s5p6440_map_io(void) -{ - /* initialize any device information early */ - s3c_adc_setname("s3c64xx-adc"); -} - -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 s5p6440_init_irq(void) -{ - /* S5P6440 supports only 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)); -} - -struct sysdev_class s5p6440_sysclass = { - .name = "s5p6440-core", -}; - -static struct sys_device s5p6440_sysdev = { - .cls = &s5p6440_sysclass, -}; - -static int __init s5p6440_core_init(void) -{ - return sysdev_class_register(&s5p6440_sysclass); -} - -core_initcall(s5p6440_core_init); - -int __init s5p6440_init(void) -{ - printk(KERN_INFO "S5P6440: Initializing architecture\n"); - - /* set idle function */ - pm_idle = s5p6440_idle; - - return sysdev_register(&s5p6440_sysdev); -} diff --git a/arch/arm/mach-s5p6440/dev-audio.c b/arch/arm/mach-s5p6440/dev-audio.c deleted file mode 100644 index 3ca0d2b8275d..000000000000 --- a/arch/arm/mach-s5p6440/dev-audio.c +++ /dev/null @@ -1,127 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/dev-audio.c - * - * 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 <plat/gpio-cfg.h> -#include <plat/audio.h> - -#include <mach/map.h> -#include <mach/dma.h> -#include <mach/irqs.h> - -static int s5p6440_cfg_i2s(struct platform_device *pdev) -{ - /* configure GPIO for i2s port */ - switch (pdev->id) { - case -1: - s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5)); - break; - - default: - printk(KERN_ERR "Invalid Device %d\n", pdev->id); - return -EINVAL; - } - - return 0; -} - -static struct s3c_audio_pdata s3c_i2s_pdata = { - .cfg_gpio = s5p6440_cfg_i2s, -}; - -static struct resource s5p6440_iis0_resource[] = { - [0] = { - .start = S5P6440_PA_I2S, - .end = S5P6440_PA_I2S + 0x100 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = DMACH_I2S0_TX, - .end = DMACH_I2S0_TX, - .flags = IORESOURCE_DMA, - }, - [2] = { - .start = DMACH_I2S0_RX, - .end = DMACH_I2S0_RX, - .flags = IORESOURCE_DMA, - }, -}; - -struct platform_device s5p6440_device_iis = { - .name = "s3c64xx-iis-v4", - .id = -1, - .num_resources = ARRAY_SIZE(s5p6440_iis0_resource), - .resource = s5p6440_iis0_resource, - .dev = { - .platform_data = &s3c_i2s_pdata, - }, -}; - -/* PCM Controller platform_devices */ - -static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev) -{ - switch (pdev->id) { - case 0: - s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2)); - break; - - default: - printk(KERN_DEBUG "Invalid PCM Controller number!"); - return -EINVAL; - } - - return 0; -} - -static struct s3c_audio_pdata s3c_pcm_pdata = { - .cfg_gpio = s5p6440_pcm_cfg_gpio, -}; - -static struct resource s5p6440_pcm0_resource[] = { - [0] = { - .start = S5P6440_PA_PCM, - .end = S5P6440_PA_PCM + 0x100 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = DMACH_PCM0_TX, - .end = DMACH_PCM0_TX, - .flags = IORESOURCE_DMA, - }, - [2] = { - .start = DMACH_PCM0_RX, - .end = DMACH_PCM0_RX, - .flags = IORESOURCE_DMA, - }, -}; - -struct platform_device s5p6440_device_pcm = { - .name = "samsung-pcm", - .id = 0, - .num_resources = ARRAY_SIZE(s5p6440_pcm0_resource), - .resource = s5p6440_pcm0_resource, - .dev = { - .platform_data = &s3c_pcm_pdata, - }, -}; diff --git a/arch/arm/mach-s5p6440/dev-spi.c b/arch/arm/mach-s5p6440/dev-spi.c deleted file mode 100644 index 510af44d180c..000000000000 --- a/arch/arm/mach-s5p6440/dev-spi.c +++ /dev/null @@ -1,176 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/dev-spi.c - * - * 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/spi-clocks.h> - -#include <plat/s3c64xx-spi.h> -#include <plat/gpio-cfg.h> - -static char *spi_src_clks[] = { - [S5P6440_SPI_SRCCLK_PCLK] = "pclk", - [S5P6440_SPI_SRCCLK_SCLK] = "spi_epll", -}; - -/* 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) -{ - switch (pdev->id) { - case 0: - s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP); - break; - - case 1: - s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP); - break; - - default: - dev_err(&pdev->dev, "Invalid SPI Controller number!"); - return -EINVAL; - } - - return 0; -} - -static struct resource s5p6440_spi0_resource[] = { - [0] = { - .start = S5P6440_PA_SPI0, - .end = S5P6440_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, -}; - -static u64 spi_dmamask = DMA_BIT_MASK(32); - -struct platform_device s5p6440_device_spi0 = { - .name = "s3c64xx-spi", - .id = 0, - .num_resources = ARRAY_SIZE(s5p6440_spi0_resource), - .resource = s5p6440_spi0_resource, - .dev = { - .dma_mask = &spi_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &s5p6440_spi0_pdata, - }, -}; - -static struct resource s5p6440_spi1_resource[] = { - [0] = { - .start = S5P6440_PA_SPI1, - .end = S5P6440_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, -}; - -struct platform_device s5p6440_device_spi1 = { - .name = "s3c64xx-spi", - .id = 1, - .num_resources = ARRAY_SIZE(s5p6440_spi1_resource), - .resource = s5p6440_spi1_resource, - .dev = { - .dma_mask = &spi_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &s5p6440_spi1_pdata, - }, -}; - -void __init s5p6440_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) -{ - struct s3c64xx_spi_info *pd; - - /* Reject invalid configuration */ - if (!num_cs || src_clk_nr < 0 - || src_clk_nr > S5P6440_SPI_SRCCLK_SCLK) { - printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__); - return; - } - - switch (cntrlr) { - case 0: - pd = &s5p6440_spi0_pdata; - break; - case 1: - pd = &s5p6440_spi1_pdata; - 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 = spi_src_clks[src_clk_nr]; -} diff --git a/arch/arm/mach-s5p6440/include/mach/debug-macro.S b/arch/arm/mach-s5p6440/include/mach/debug-macro.S deleted file mode 100644 index 1347d7f99079..000000000000 --- a/arch/arm/mach-s5p6440/include/mach/debug-macro.S +++ /dev/null @@ -1,37 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/debug-macro.S - * - * Copyright (c) 2009 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. -*/ - -/* pull in the relevant register and map files. */ - -#include <mach/map.h> -#include <plat/regs-serial.h> - - /* note, for the boot process to work we have to keep the UART - * virtual address aligned to an 1MiB boundary for the L1 - * mapping the head code makes. We keep the UART virtual address - * aligned and add in the offset when we load the value here. - */ - - .macro addruart, rx, rtmp - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 - ldreq \rx, = S3C_PA_UART - ldrne \rx, = S3C_VA_UART -#if CONFIG_DEBUG_S3C_UART != 0 - add \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART) -#endif - .endm - -/* include the reset of the code which will do the work, we're only - * compiling for a single cpu processor type so the default of s3c2440 - * will be fine with us. - */ - -#include <plat/debug-macro.S> diff --git a/arch/arm/mach-s5p6440/include/mach/gpio.h b/arch/arm/mach-s5p6440/include/mach/gpio.h deleted file mode 100644 index 21783834f2a2..000000000000 --- a/arch/arm/mach-s5p6440/include/mach/gpio.h +++ /dev/null @@ -1,80 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/gpio.h - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - GPIO lib 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_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) -#define S5P6440_GPIO_B_NR (7) -#define S5P6440_GPIO_C_NR (8) -#define S5P6440_GPIO_F_NR (2) -#define S5P6440_GPIO_G_NR (7) -#define S5P6440_GPIO_H_NR (10) -#define S5P6440_GPIO_I_NR (16) -#define S5P6440_GPIO_J_NR (12) -#define S5P6440_GPIO_N_NR (16) -#define S5P6440_GPIO_P_NR (8) -#define S5P6440_GPIO_R_NR (15) - -/* GPIO bank numbers */ - -/* CONFIG_S3C_GPIO_SPACE allows the user to select extra - * space for debugging purposes so that any accidental - * change from one gpio bank to another can be caught. -*/ -#define S5P6440_GPIO_NEXT(__gpio) \ - ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1) - -enum s5p_gpio_number { - S5P6440_GPIO_A_START = 0, - S5P6440_GPIO_B_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_A), - S5P6440_GPIO_C_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_B), - S5P6440_GPIO_F_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_C), - S5P6440_GPIO_G_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_F), - S5P6440_GPIO_H_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_G), - S5P6440_GPIO_I_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_H), - S5P6440_GPIO_J_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_I), - S5P6440_GPIO_N_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_J), - S5P6440_GPIO_P_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_N), - S5P6440_GPIO_R_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_P), -}; - -/* S5P6440 GPIO number definitions. */ -#define S5P6440_GPA(_nr) (S5P6440_GPIO_A_START + (_nr)) -#define S5P6440_GPB(_nr) (S5P6440_GPIO_B_START + (_nr)) -#define S5P6440_GPC(_nr) (S5P6440_GPIO_C_START + (_nr)) -#define S5P6440_GPF(_nr) (S5P6440_GPIO_F_START + (_nr)) -#define S5P6440_GPG(_nr) (S5P6440_GPIO_G_START + (_nr)) -#define S5P6440_GPH(_nr) (S5P6440_GPIO_H_START + (_nr)) -#define S5P6440_GPI(_nr) (S5P6440_GPIO_I_START + (_nr)) -#define S5P6440_GPJ(_nr) (S5P6440_GPIO_J_START + (_nr)) -#define S5P6440_GPN(_nr) (S5P6440_GPIO_N_START + (_nr)) -#define S5P6440_GPP(_nr) (S5P6440_GPIO_P_START + (_nr)) -#define S5P6440_GPR(_nr) (S5P6440_GPIO_R_START + (_nr)) - -/* the end of the S5P6440 specific gpios */ -#define S5P6440_GPIO_END (S5P6440_GPR(S5P6440_GPIO_R_NR) + 1) -#define S3C_GPIO_END S5P6440_GPIO_END - -/* define the number of gpios we need to the one after the GPR() range */ -#define ARCH_NR_GPIOS (S5P6440_GPR(S5P6440_GPIO_R_NR) + \ - CONFIG_SAMSUNG_GPIO_EXTRA + 1) - -#include <asm-generic/gpio.h> - -#endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/io.h b/arch/arm/mach-s5p6440/include/mach/io.h deleted file mode 100644 index fa2d69cb1ad7..000000000000 --- a/arch/arm/mach-s5p6440/include/mach/io.h +++ /dev/null @@ -1,18 +0,0 @@ -/* arch/arm/mach-s5p6440/include/mach/io.h - * - * Copyright 2008 Simtec Electronics - * Ben Dooks <ben-linux@fluff.org> - * - * Default IO routines for S3C64XX based - */ - -#ifndef __ASM_ARM_ARCH_IO_H -#define __ASM_ARM_ARCH_IO_H - -/* No current ISA/PCI bus support. */ -#define __io(a) __typesafe_io(a) -#define __mem_pci(a) (a) - -#define IO_SPACE_LIMIT (0xFFFFFFFF) - -#endif diff --git a/arch/arm/mach-s5p6440/include/mach/map.h b/arch/arm/mach-s5p6440/include/mach/map.h deleted file mode 100644 index 6cc5cbc88ffb..000000000000 --- a/arch/arm/mach-s5p6440/include/mach/map.h +++ /dev/null @@ -1,86 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/map.h - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - Memory map 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_MAP_H -#define __ASM_ARCH_MAP_H __FILE__ - -#include <plat/map-base.h> -#include <plat/map-s5p.h> - -#define S5P6440_PA_CHIPID (0xE0000000) -#define S5P_PA_CHIPID S5P6440_PA_CHIPID - -#define S5P6440_PA_SYSCON (0xE0100000) -#define S5P6440_PA_CLK (S5P6440_PA_SYSCON + 0x0) -#define S5P_PA_SYSCON S5P6440_PA_SYSCON - -#define S5P6440_PA_GPIO (0xE0308000) -#define S5P_PA_GPIO S5P6440_PA_GPIO - -#define S5P6440_PA_VIC0 (0xE4000000) -#define S5P_PA_VIC0 S5P6440_PA_VIC0 - -#define S5P6440_PA_PDMA 0xE9000000 - -#define S5P6440_PA_VIC1 (0xE4100000) -#define S5P_PA_VIC1 S5P6440_PA_VIC1 - -#define S5P6440_PA_TIMER (0xEA000000) -#define S5P_PA_TIMER S5P6440_PA_TIMER - -#define S5P6440_PA_RTC (0xEA100000) - -#define S5P6440_PA_WDT (0xEA200000) -#define S5P_PA_WDT S5P6440_PA_WDT - -#define S5P6440_PA_UART (0xEC000000) - -#define S5P_PA_UART0 (S5P6440_PA_UART + 0x0) -#define S5P_PA_UART1 (S5P6440_PA_UART + 0x400) -#define S5P_PA_UART2 (S5P6440_PA_UART + 0x800) -#define S5P_PA_UART3 (S5P6440_PA_UART + 0xC00) - -#define S5P_SZ_UART SZ_256 - -#define S5P6440_PA_IIC0 (0xEC104000) -#define S5P6440_PA_IIC1 (0xEC20F000) - -#define S5P6440_PA_SPI0 0xEC400000 -#define S5P6440_PA_SPI1 0xEC500000 - -#define S5P6440_PA_HSOTG (0xED100000) - -#define S5P6440_PA_HSMMC0 (0xED800000) -#define S5P6440_PA_HSMMC1 (0xED900000) -#define S5P6440_PA_HSMMC2 (0xEDA00000) - -#define S5P6440_PA_SDRAM (0x20000000) -#define S5P_PA_SDRAM S5P6440_PA_SDRAM - -/* I2S */ -#define S5P6440_PA_I2S 0xF2000000 - -/* PCM */ -#define S5P6440_PA_PCM 0xF2100000 - -#define S5P6440_PA_ADC (0xF3000000) - -/* compatibiltiy defines. */ -#define S3C_PA_UART S5P6440_PA_UART -#define S3C_PA_IIC S5P6440_PA_IIC0 -#define S3C_PA_RTC S5P6440_PA_RTC -#define S3C_PA_IIC1 S5P6440_PA_IIC1 -#define S3C_PA_WDT S5P6440_PA_WDT - -#define SAMSUNG_PA_ADC S5P6440_PA_ADC - -#endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/regs-clock.h b/arch/arm/mach-s5p6440/include/mach/regs-clock.h deleted file mode 100644 index c783ecc9f193..000000000000 --- a/arch/arm/mach-s5p6440/include/mach/regs-clock.h +++ /dev/null @@ -1,130 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/regs-clock.h - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - Clock register 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_REGS_CLOCK_H -#define __ASM_ARCH_REGS_CLOCK_H __FILE__ - -#include <mach/map.h> - -#define S5P_CLKREG(x) (S3C_VA_SYS + (x)) - -#define S5P_APLL_LOCK S5P_CLKREG(0x00) -#define S5P_MPLL_LOCK S5P_CLKREG(0x04) -#define S5P_EPLL_LOCK S5P_CLKREG(0x08) -#define S5P_APLL_CON S5P_CLKREG(0x0C) -#define S5P_MPLL_CON S5P_CLKREG(0x10) -#define S5P_EPLL_CON S5P_CLKREG(0x14) -#define S5P_EPLL_CON_K S5P_CLKREG(0x18) -#define S5P_CLK_SRC0 S5P_CLKREG(0x1C) -#define S5P_CLK_DIV0 S5P_CLKREG(0x20) -#define S5P_CLK_DIV1 S5P_CLKREG(0x24) -#define S5P_CLK_DIV2 S5P_CLKREG(0x28) -#define S5P_CLK_OUT S5P_CLKREG(0x2C) -#define S5P_CLK_GATE_HCLK0 S5P_CLKREG(0x30) -#define S5P_CLK_GATE_PCLK S5P_CLKREG(0x34) -#define S5P_CLK_GATE_SCLK0 S5P_CLKREG(0x38) -#define S5P_CLK_GATE_MEM0 S5P_CLKREG(0x3C) -#define S5P_CLK_DIV3 S5P_CLKREG(0x40) -#define S5P_CLK_GATE_HCLK1 S5P_CLKREG(0x44) -#define S5P_CLK_GATE_SCLK1 S5P_CLKREG(0x48) -#define S5P_AHB_CON0 S5P_CLKREG(0x100) -#define S5P_CLK_SRC1 S5P_CLKREG(0x10C) -#define S5P_SWRESET S5P_CLKREG(0x114) -#define S5P_SYS_ID S5P_CLKREG(0x118) -#define S5P_SYS_OTHERS S5P_CLKREG(0x11C) -#define S5P_MEM_CFG_STAT S5P_CLKREG(0x12C) -#define S5P_PWR_CFG S5P_CLKREG(0x804) -#define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0x808) -#define S5P_NORMAL_CFG S5P_CLKREG(0x810) -#define S5P_STOP_CFG S5P_CLKREG(0x814) -#define S5P_SLEEP_CFG S5P_CLKREG(0x818) -#define S5P_OSC_FREQ S5P_CLKREG(0x820) -#define S5P_OSC_STABLE S5P_CLKREG(0x824) -#define S5P_PWR_STABLE S5P_CLKREG(0x828) -#define S5P_MTC_STABLE S5P_CLKREG(0x830) -#define S5P_OTHERS S5P_CLKREG(0x900) -#define S5P_RST_STAT S5P_CLKREG(0x904) -#define S5P_WAKEUP_STAT S5P_CLKREG(0x908) -#define S5P_SLPEN S5P_CLKREG(0x930) -#define S5P_INFORM0 S5P_CLKREG(0xA00) -#define S5P_INFORM1 S5P_CLKREG(0xA04) -#define S5P_INFORM2 S5P_CLKREG(0xA08) -#define S5P_INFORM3 S5P_CLKREG(0xA0C) - -/* CLKDIV0 */ -#define S5P_CLKDIV0_PCLK_MASK (0xf << 12) -#define S5P_CLKDIV0_PCLK_SHIFT (12) -#define S5P_CLKDIV0_HCLK_MASK (0xf << 8) -#define S5P_CLKDIV0_HCLK_SHIFT (8) -#define S5P_CLKDIV0_MPLL_MASK (0x1 << 4) -#define S5P_CLKDIV0_ARM_MASK (0xf << 0) -#define S5P_CLKDIV0_ARM_SHIFT (0) - -/* CLKDIV3 */ -#define S5P_CLKDIV3_PCLK_LOW_MASK (0xf << 12) -#define S5P_CLKDIV3_PCLK_LOW_SHIFT (12) -#define S5P_CLKDIV3_HCLK_LOW_MASK (0xf << 8) -#define S5P_CLKDIV3_HCLK_LOW_SHIFT (8) - -/* HCLK0 GATE Registers */ -#define S5P_CLKCON_HCLK0_USB (1<<20) -#define S5P_CLKCON_HCLK0_HSMMC2 (1<<19) -#define S5P_CLKCON_HCLK0_HSMMC1 (1<<18) -#define S5P_CLKCON_HCLK0_HSMMC0 (1<<17) -#define S5P_CLKCON_HCLK0_POST0 (1<<5) - -/* HCLK1 GATE Registers */ -#define S5P_CLKCON_HCLK1_DISPCON (1<<1) - -/* PCLK GATE Registers */ -#define S5P_CLKCON_PCLK_IIS2 (1<<26) -#define S5P_CLKCON_PCLK_SPI1 (1<<22) -#define S5P_CLKCON_PCLK_SPI0 (1<<21) -#define S5P_CLKCON_PCLK_GPIO (1<<18) -#define S5P_CLKCON_PCLK_IIC0 (1<<17) -#define S5P_CLKCON_PCLK_TSADC (1<<12) -#define S5P_CLKCON_PCLK_PWM (1<<7) -#define S5P_CLKCON_PCLK_RTC (1<<6) -#define S5P_CLKCON_PCLK_WDT (1<<5) -#define S5P_CLKCON_PCLK_UART3 (1<<4) -#define S5P_CLKCON_PCLK_UART2 (1<<3) -#define S5P_CLKCON_PCLK_UART1 (1<<2) -#define S5P_CLKCON_PCLK_UART0 (1<<1) - -/* SCLK0 GATE Registers */ -#define S5P_CLKCON_SCLK0_MMC2_48 (1<<29) -#define S5P_CLKCON_SCLK0_MMC1_48 (1<<28) -#define S5P_CLKCON_SCLK0_MMC0_48 (1<<27) -#define S5P_CLKCON_SCLK0_MMC2 (1<<26) -#define S5P_CLKCON_SCLK0_MMC1 (1<<25) -#define S5P_CLKCON_SCLK0_MMC0 (1<<24) -#define S5P_CLKCON_SCLK0_SPI1_48 (1<<23) -#define S5P_CLKCON_SCLK0_SPI0_48 (1<<22) -#define S5P_CLKCON_SCLK0_SPI1 (1<<21) -#define S5P_CLKCON_SCLK0_SPI0 (1<<20) -#define S5P_CLKCON_SCLK0_UART (1<<5) - -/* SCLK1 GATE Registers */ - -/* MEM0 GATE Registers */ -#define S5P_CLKCON_MEM0_HCLK_NFCON (1<<2) - -/*OTHERS Resgister */ -#define S5P_OTHERS_USB_SIG_MASK (1<<16) -#define S5P_OTHERS_HCLK_LOW_SEL_MPLL (1<<6) - -/* Compatibility defines */ -#define ARM_CLK_DIV S5P_CLK_DIV0 -#define ARM_DIV_RATIO_SHIFT 0 -#define ARM_DIV_MASK (0xf << ARM_DIV_RATIO_SHIFT) - -#endif /* __ASM_ARCH_REGS_CLOCK_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/spi-clocks.h b/arch/arm/mach-s5p6440/include/mach/spi-clocks.h deleted file mode 100644 index 5fbca50d1cfb..000000000000 --- a/arch/arm/mach-s5p6440/include/mach/spi-clocks.h +++ /dev/null @@ -1,17 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/spi-clocks.h - * - * 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. - */ - -#ifndef __S5P6440_PLAT_SPI_CLKS_H -#define __S5P6440_PLAT_SPI_CLKS_H __FILE__ - -#define S5P6440_SPI_SRCCLK_PCLK 0 -#define S5P6440_SPI_SRCCLK_SCLK 1 - -#endif /* __S5P6440_PLAT_SPI_CLKS_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/uncompress.h b/arch/arm/mach-s5p6440/include/mach/uncompress.h deleted file mode 100644 index 7c1f600d65c0..000000000000 --- a/arch/arm/mach-s5p6440/include/mach/uncompress.h +++ /dev/null @@ -1,24 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/uncompress.h - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - uncompress code - * - * 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_UNCOMPRESS_H -#define __ASM_ARCH_UNCOMPRESS_H - -#include <mach/map.h> -#include <plat/uncompress.h> - -static void arch_detect_cpu(void) -{ - /* we do not need to do any cpu detection here at the moment. */ -} - -#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-s5p6440/init.c b/arch/arm/mach-s5p6440/init.c deleted file mode 100644 index a1f3727e4021..000000000000 --- a/arch/arm/mach-s5p6440/init.c +++ /dev/null @@ -1,52 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/init.c - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - 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 <plat/cpu.h> -#include <plat/devs.h> -#include <plat/s5p6440.h> -#include <plat/regs-serial.h> - -static struct s3c24xx_uart_clksrc s5p6440_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 s5p6440_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 = s5p6440_serial_clocks; - tcfg->clocks_size = ARRAY_SIZE(s5p6440_serial_clocks); - } - } - - s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no); -} diff --git a/arch/arm/mach-s5p6440/setup-i2c0.c b/arch/arm/mach-s5p6440/setup-i2c0.c deleted file mode 100644 index 2c99d14f7ac7..000000000000 --- a/arch/arm/mach-s5p6440/setup-i2c0.c +++ /dev/null @@ -1,30 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/setup-i2c0.c - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * I2C0 GPIO configuration. - * - * Based on plat-s3c64xx/setup-i2c0.c - * - * 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> - -struct platform_device; /* don't need the contents */ - -#include <linux/gpio.h> -#include <plat/gpio-cfg.h> -#include <plat/iic.h> - -void s3c_i2c0_cfg_gpio(struct platform_device *dev) -{ - s3c_gpio_cfgpin(S5P6440_GPB(5), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5P6440_GPB(5), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5P6440_GPB(6), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5P6440_GPB(6), S3C_GPIO_PULL_UP); -} diff --git a/arch/arm/mach-s5p6440/setup-i2c1.c b/arch/arm/mach-s5p6440/setup-i2c1.c deleted file mode 100644 index 9a1537f786e0..000000000000 --- a/arch/arm/mach-s5p6440/setup-i2c1.c +++ /dev/null @@ -1,30 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/setup-i2c1.c - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * I2C1 GPIO configuration. - * - * Based on plat-s3c64xx/setup-i2c0.c - * - * 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/gpio.h> - -struct platform_device; /* don't need the contents */ - -#include <plat/gpio-cfg.h> -#include <plat/iic.h> - -void s3c_i2c1_cfg_gpio(struct platform_device *dev) -{ - s3c_gpio_cfgpin(S5P6440_GPR(9), S3C_GPIO_SFN(6)); - s3c_gpio_setpull(S5P6440_GPR(9), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5P6440_GPR(10), S3C_GPIO_SFN(6)); - s3c_gpio_setpull(S5P6440_GPR(10), S3C_GPIO_PULL_UP); -} diff --git a/arch/arm/mach-s5p6442/Kconfig b/arch/arm/mach-s5p6442/Kconfig index 0fda0a5df968..33569e4007c4 100644 --- a/arch/arm/mach-s5p6442/Kconfig +++ b/arch/arm/mach-s5p6442/Kconfig @@ -11,7 +11,6 @@ if ARCH_S5P6442 config CPU_S5P6442 bool - select PLAT_S5P select S3C_PL330_DMA help Enable S5P6442 CPU support diff --git a/arch/arm/mach-s5p6442/cpu.c b/arch/arm/mach-s5p6442/cpu.c index 70ac681af72b..842af86bda6d 100644 --- a/arch/arm/mach-s5p6442/cpu.c +++ b/arch/arm/mach-s5p6442/cpu.c @@ -1,7 +1,7 @@ /* linux/arch/arm/mach-s5p6442/cpu.c * * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * 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 @@ -48,10 +48,30 @@ static struct map_desc s5p6442_iodesc[] __initdata = { .length = SZ_16K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S5P_VA_GPIO, + .pfn = __phys_to_pfn(S5P6442_PA_GPIO), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC0, + .pfn = __phys_to_pfn(S5P6442_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC1, + .pfn = __phys_to_pfn(S5P6442_PA_VIC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)VA_VIC2, .pfn = __phys_to_pfn(S5P6442_PA_VIC2), .length = SZ_16K, .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_512K, + .type = MT_DEVICE, } }; @@ -63,10 +83,11 @@ static void s5p6442_idle(void) local_irq_enable(); } -/* s5p6442_map_io +/* + * s5p6442_map_io * * register the standard cpu IO areas -*/ + */ void __init s5p6442_map_io(void) { diff --git a/arch/arm/mach-s5p6442/dev-audio.c b/arch/arm/mach-s5p6442/dev-audio.c index 7a4e34720b7b..3462197ff352 100644 --- a/arch/arm/mach-s5p6442/dev-audio.c +++ b/arch/arm/mach-s5p6442/dev-audio.c @@ -21,22 +21,16 @@ static int s5p6442_cfg_i2s(struct platform_device *pdev) { + unsigned int base; + /* configure GPIO for i2s port */ switch (pdev->id) { case 1: - s3c_gpio_cfgpin(S5P6442_GPC1(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6442_GPC1(1), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6442_GPC1(2), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6442_GPC1(3), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6442_GPC1(4), S3C_GPIO_SFN(2)); + base = S5P6442_GPC1(0); break; case -1: - s3c_gpio_cfgpin(S5P6442_GPC0(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6442_GPC0(1), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6442_GPC0(2), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6442_GPC0(3), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6442_GPC0(4), S3C_GPIO_SFN(2)); + base = S5P6442_GPC0(0); break; default: @@ -44,6 +38,7 @@ static int s5p6442_cfg_i2s(struct platform_device *pdev) return -EINVAL; } + s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(2)); return 0; } @@ -111,21 +106,15 @@ struct platform_device s5p6442_device_iis1 = { static int s5p6442_pcm_cfg_gpio(struct platform_device *pdev) { + unsigned int base; + switch (pdev->id) { case 0: - s3c_gpio_cfgpin(S5P6442_GPC0(0), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5P6442_GPC0(1), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5P6442_GPC0(2), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5P6442_GPC0(3), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5P6442_GPC0(4), S3C_GPIO_SFN(3)); + base = S5P6442_GPC0(0); break; case 1: - s3c_gpio_cfgpin(S5P6442_GPC1(0), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5P6442_GPC1(1), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5P6442_GPC1(2), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5P6442_GPC1(3), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5P6442_GPC1(4), S3C_GPIO_SFN(3)); + base = S5P6442_GPC1(0); break; default: @@ -133,6 +122,7 @@ static int s5p6442_pcm_cfg_gpio(struct platform_device *pdev) return -EINVAL; } + s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(3)); return 0; } diff --git a/arch/arm/mach-s5p6442/dev-spi.c b/arch/arm/mach-s5p6442/dev-spi.c index e894651a88bd..cce8c2470709 100644 --- a/arch/arm/mach-s5p6442/dev-spi.c +++ b/arch/arm/mach-s5p6442/dev-spi.c @@ -38,11 +38,9 @@ static int s5p6442_spi_cfg_gpio(struct platform_device *pdev) switch (pdev->id) { case 0: s3c_gpio_cfgpin(S5P6442_GPB(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6442_GPB(2), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6442_GPB(3), S3C_GPIO_SFN(2)); s3c_gpio_setpull(S5P6442_GPB(0), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5P6442_GPB(2), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5P6442_GPB(3), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5P6442_GPB(2), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); break; default: diff --git a/arch/arm/mach-s5p6442/include/mach/map.h b/arch/arm/mach-s5p6442/include/mach/map.h index 281d256faafb..31fb2e68d527 100644 --- a/arch/arm/mach-s5p6442/include/mach/map.h +++ b/arch/arm/mach-s5p6442/include/mach/map.h @@ -23,16 +23,10 @@ #define S5P_PA_SYSCON S5P6442_PA_SYSCON #define S5P6442_PA_GPIO (0xE0200000) -#define S5P_PA_GPIO S5P6442_PA_GPIO #define S5P6442_PA_VIC0 (0xE4000000) -#define S5P_PA_VIC0 S5P6442_PA_VIC0 - #define S5P6442_PA_VIC1 (0xE4100000) -#define S5P_PA_VIC1 S5P6442_PA_VIC1 - #define S5P6442_PA_VIC2 (0xE4200000) -#define S5P_PA_VIC2 S5P6442_PA_VIC2 #define S5P6442_PA_MDMA 0xE8000000 #define S5P6442_PA_PDMA 0xE9000000 diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig new file mode 100644 index 000000000000..164d2783d381 --- /dev/null +++ b/arch/arm/mach-s5p64x0/Kconfig @@ -0,0 +1,55 @@ +# arch/arm/mach-s5p64x0/Kconfig +# +# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. +# http://www.samsung.com/ +# +# Licensed under GPLv2 + +if ARCH_S5P64X0 + +config CPU_S5P6440 + bool + select S3C_PL330_DMA + help + Enable S5P6440 CPU support + +config CPU_S5P6450 + bool + select S3C_PL330_DMA + help + Enable S5P6450 CPU support + +config S5P64X0_SETUP_I2C1 + bool + help + Common setup code for i2c bus 1. + +# machine support + +config MACH_SMDK6440 + bool "SMDK6440" + select CPU_S5P6440 + select S3C_DEV_I2C1 + select S3C_DEV_RTC + select S3C_DEV_WDT + select S3C64XX_DEV_SPI + select SAMSUNG_DEV_ADC + select SAMSUNG_DEV_TS + select S5P64X0_SETUP_I2C1 + help + Machine support for the Samsung SMDK6440 + +config MACH_SMDK6450 + bool "SMDK6450" + select CPU_S5P6450 + select S3C_DEV_I2C1 + select S3C_DEV_RTC + select S3C_DEV_WDT + select S3C64XX_DEV_SPI + select SAMSUNG_DEV_ADC + select SAMSUNG_DEV_TS + select S5P64X0_SETUP_I2C1 + help + Machine support for the Samsung SMDK6450 + +endif diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile new file mode 100644 index 000000000000..2655829e6bf8 --- /dev/null +++ b/arch/arm/mach-s5p64x0/Makefile @@ -0,0 +1,30 @@ +# arch/arm/mach-s5p64x0/Makefile +# +# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. +# http://www.samsung.com +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := +obj- := + +# Core support for S5P64X0 system + +obj-$(CONFIG_ARCH_S5P64X0) += cpu.o init.o clock.o dma.o +obj-$(CONFIG_ARCH_S5P64X0) += setup-i2c0.o +obj-$(CONFIG_CPU_S5P6440) += clock-s5p6440.o gpio.o +obj-$(CONFIG_CPU_S5P6450) += clock-s5p6450.o + +# machine support + +obj-$(CONFIG_MACH_SMDK6440) += mach-smdk6440.o +obj-$(CONFIG_MACH_SMDK6450) += mach-smdk6450.o + +# device support + +obj-y += dev-audio.o +obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o + +obj-$(CONFIG_S5P64X0_SETUP_I2C1) += setup-i2c1.o diff --git a/arch/arm/mach-s5p6440/Makefile.boot b/arch/arm/mach-s5p64x0/Makefile.boot index ff90aa13bd67..ff90aa13bd67 100644 --- a/arch/arm/mach-s5p6440/Makefile.boot +++ b/arch/arm/mach-s5p64x0/Makefile.boot diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c new file mode 100644 index 000000000000..0d728d3383b4 --- /dev/null +++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c @@ -0,0 +1,629 @@ +/* linux/arch/arm/mach-s5p64x0/clock-s5p6440.c + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P6440 - Clock 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/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> +#include <mach/regs-clock.h> +#include <mach/s5p64x0-clock.h> + +#include <plat/cpu-freq.h> +#include <plat/clock.h> +#include <plat/cpu.h> +#include <plat/pll.h> +#include <plat/s5p-clock.h> +#include <plat/clock-clksrc.h> +#include <plat/s5p6440.h> + +static u32 epll_div[][5] = { + { 36000000, 0, 48, 1, 4 }, + { 48000000, 0, 32, 1, 3 }, + { 60000000, 0, 40, 1, 3 }, + { 72000000, 0, 48, 1, 3 }, + { 84000000, 0, 28, 1, 2 }, + { 96000000, 0, 32, 1, 2 }, + { 32768000, 45264, 43, 1, 4 }, + { 45158000, 6903, 30, 1, 3 }, + { 49152000, 50332, 32, 1, 3 }, + { 67738000, 10398, 45, 1, 3 }, + { 73728000, 9961, 49, 1, 3 } +}; + +static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int epll_con, epll_con_k; + unsigned int i; + + if (clk->rate == rate) /* Return if nothing changed */ + return 0; + + epll_con = __raw_readl(S5P64X0_EPLL_CON); + epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K); + + epll_con_k &= ~(PLL90XX_KDIV_MASK); + epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK); + + for (i = 0; i < ARRAY_SIZE(epll_div); i++) { + if (epll_div[i][0] == rate) { + epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT); + epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) | + (epll_div[i][3] << PLL90XX_PDIV_SHIFT) | + (epll_div[i][4] << PLL90XX_SDIV_SHIFT); + break; + } + } + + if (i == ARRAY_SIZE(epll_div)) { + printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__); + return -EINVAL; + } + + __raw_writel(epll_con, S5P64X0_EPLL_CON); + __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K); + + printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n", + clk->rate, rate); + + clk->rate = rate; + + return 0; +} + +static struct clk_ops s5p6440_epll_ops = { + .get_rate = s5p_epll_get_rate, + .set_rate = s5p6440_epll_set_rate, +}; + +static struct clksrc_clk clk_hclk = { + .clk = { + .name = "clk_hclk", + .id = -1, + .parent = &clk_armclk.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk clk_pclk = { + .clk = { + .name = "clk_pclk", + .id = -1, + .parent = &clk_hclk.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 }, +}; +static struct clksrc_clk clk_hclk_low = { + .clk = { + .name = "clk_hclk_low", + .id = -1, + }, + .sources = &clkset_hclk_low, + .reg_src = { .reg = S5P64X0_SYS_OTHERS, .shift = 6, .size = 1 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk clk_pclk_low = { + .clk = { + .name = "clk_pclk_low", + .id = -1, + .parent = &clk_hclk_low.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 }, +}; + +/* + * The following clocks will be disabled during clock initialization. It is + * recommended to keep the following clocks disabled until the driver requests + * for enabling the clock. + */ +static struct clk init_clocks_disable[] = { + { + .name = "nand", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_mem_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "post", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 5) + }, { + .name = "2d", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 17), + }, { + .name = "hsmmc", + .id = 1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 18), + }, { + .name = "hsmmc", + .id = 2, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 19), + }, { + .name = "otg", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 20) + }, { + .name = "irom", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 25), + }, { + .name = "lcd", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk1_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "hclk_fimgvg", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk1_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "tsi", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk1_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "rtc", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "timers", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "pcm", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "adc", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "i2c", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 17), + }, { + .name = "spi", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 21), + }, { + .name = "spi", + .id = 1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 22), + }, { + .name = "gps", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 25), + }, { + .name = "i2s_v40", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 26), + }, { + .name = "dsim", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 28), + }, { + .name = "etm", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 29), + }, { + .name = "dmc0", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 30), + }, { + .name = "pclk_fimgvg", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 31), + }, { + .name = "sclk_spi_48", + .id = 0, + .parent = &clk_48m, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 22), + }, { + .name = "sclk_spi_48", + .id = 1, + .parent = &clk_48m, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 23), + }, { + .name = "mmc_48m", + .id = 0, + .parent = &clk_48m, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 27), + }, { + .name = "mmc_48m", + .id = 1, + .parent = &clk_48m, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 28), + }, { + .name = "mmc_48m", + .id = 2, + .parent = &clk_48m, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 29), + }, +}; + +/* + * The following clocks will be enabled during clock initialization. + */ +static struct clk init_clocks[] = { + { + .name = "intc", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "mem", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 21), + }, { + .name = "dma", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "uart", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "uart", + .id = 1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "uart", + .id = 2, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "uart", + .id = 3, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "gpio", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 18), + }, +}; + +static struct clk clk_iis_cd_v40 = { + .name = "iis_cdclk_v40", + .id = -1, +}; + +static struct clk clk_pcm_cd = { + .name = "pcm_cdclk", + .id = -1, +}; + +static struct clk *clkset_group1_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll.clk, + &clk_fin_epll, +}; + +static struct clksrc_sources clkset_group1 = { + .sources = clkset_group1_list, + .nr_sources = ARRAY_SIZE(clkset_group1_list), +}; + +static struct clk *clkset_uart_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll.clk, +}; + +static struct clksrc_sources clkset_uart = { + .sources = clkset_uart_list, + .nr_sources = ARRAY_SIZE(clkset_uart_list), +}; + +static struct clk *clkset_audio_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll.clk, + &clk_fin_epll, + &clk_iis_cd_v40, + &clk_pcm_cd, +}; + +static struct clksrc_sources clkset_audio = { + .sources = clkset_audio_list, + .nr_sources = ARRAY_SIZE(clkset_audio_list), +}; + +static struct clksrc_clk clksrcs[] = { + { + .clk = { + .name = "mmc_bus", + .id = 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 = "mmc_bus", + .id = 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 = "mmc_bus", + .id = 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", + .id = -1, + .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", + .id = 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", + .id = 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", + .id = -1, + .ctrlbit = (1 << 10), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "sclk_dispcon", + .id = -1, + .ctrlbit = (1 << 1), + .enable = s5p64x0_sclk1_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimgvg", + .id = -1, + .ctrlbit = (1 << 2), + .enable = s5p64x0_sclk1_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_audio2", + .id = -1, + .ctrlbit = (1 << 11), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_audio, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 }, + }, +}; + +/* Clock initialization code */ +static struct clksrc_clk *sysclks[] = { + &clk_mout_apll, + &clk_mout_epll, + &clk_mout_mpll, + &clk_dout_mpll, + &clk_armclk, + &clk_hclk, + &clk_pclk, + &clk_hclk_low, + &clk_pclk_low, +}; + +void __init_or_cpufreq s5p6440_setup_clocks(void) +{ + struct clk *xtal_clk; + + unsigned long xtal; + unsigned long fclk; + unsigned long hclk; + unsigned long hclk_low; + unsigned long pclk; + unsigned long pclk_low; + + unsigned long apll; + unsigned long mpll; + unsigned long epll; + unsigned int ptr; + + /* Set S5P6440 functions for clk_fout_epll */ + + clk_fout_epll.enable = s5p_epll_enable; + clk_fout_epll.ops = &s5p6440_epll_ops; + + clk_48m.enable = s5p64x0_clk48m_ctrl; + + xtal_clk = clk_get(NULL, "ext_xtal"); + BUG_ON(IS_ERR(xtal_clk)); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502); + mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502); + epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON), + __raw_readl(S5P64X0_EPLL_CON_K)); + + clk_fout_apll.rate = apll; + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + + printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \ + " E=%ld.%ldMHz\n", + print_mhz(apll), print_mhz(mpll), print_mhz(epll)); + + fclk = clk_get_rate(&clk_armclk.clk); + hclk = clk_get_rate(&clk_hclk.clk); + pclk = clk_get_rate(&clk_pclk.clk); + hclk_low = clk_get_rate(&clk_hclk_low.clk); + pclk_low = clk_get_rate(&clk_pclk_low.clk); + + printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \ + " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n", + print_mhz(hclk), print_mhz(hclk_low), + print_mhz(pclk), print_mhz(pclk_low)); + + clk_f.rate = fclk; + clk_h.rate = hclk; + clk_p.rate = pclk; + + for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) + s3c_set_clksrc(&clksrcs[ptr], true); +} + +static struct clk *clks[] __initdata = { + &clk_ext, + &clk_iis_cd_v40, + &clk_pcm_cd, +}; + +void __init s5p6440_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); + + for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) + s3c_register_clksrc(sysclks[ptr], 1); + + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); + s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + (clkp->enable)(clkp, 0); + } + + s3c_pwmclk_init(); +} diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c new file mode 100644 index 000000000000..1b9b0f92d178 --- /dev/null +++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c @@ -0,0 +1,658 @@ +/* linux/arch/arm/mach-s5p64x0/clock-s5p6450.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P6450 - Clock 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/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> +#include <mach/regs-clock.h> +#include <mach/s5p64x0-clock.h> + +#include <plat/cpu-freq.h> +#include <plat/clock.h> +#include <plat/cpu.h> +#include <plat/pll.h> +#include <plat/s5p-clock.h> +#include <plat/clock-clksrc.h> +#include <plat/s5p6450.h> + +static struct clksrc_clk clk_mout_dpll = { + .clk = { + .name = "mout_dpll", + .id = -1, + }, + .sources = &clk_src_dpll, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 5, .size = 1 }, +}; + +static u32 epll_div[][5] = { + { 133000000, 27307, 55, 2, 2 }, + { 100000000, 43691, 41, 2, 2 }, + { 480000000, 0, 80, 2, 0 }, +}; + +static int s5p6450_epll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int epll_con, epll_con_k; + unsigned int i; + + if (clk->rate == rate) /* Return if nothing changed */ + return 0; + + epll_con = __raw_readl(S5P64X0_EPLL_CON); + epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K); + + epll_con_k &= ~(PLL90XX_KDIV_MASK); + epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK); + + for (i = 0; i < ARRAY_SIZE(epll_div); i++) { + if (epll_div[i][0] == rate) { + epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT); + epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) | + (epll_div[i][3] << PLL90XX_PDIV_SHIFT) | + (epll_div[i][4] << PLL90XX_SDIV_SHIFT); + break; + } + } + + if (i == ARRAY_SIZE(epll_div)) { + printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__); + return -EINVAL; + } + + __raw_writel(epll_con, S5P64X0_EPLL_CON); + __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K); + + printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n", + clk->rate, rate); + + clk->rate = rate; + + return 0; +} + +static struct clk_ops s5p6450_epll_ops = { + .get_rate = s5p_epll_get_rate, + .set_rate = s5p6450_epll_set_rate, +}; + +static struct clksrc_clk clk_dout_epll = { + .clk = { + .name = "dout_epll", + .id = -1, + .parent = &clk_mout_epll.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 24, .size = 4 }, +}; + +static struct clksrc_clk clk_mout_hclk_sel = { + .clk = { + .name = "mout_hclk_sel", + .id = -1, + }, + .sources = &clkset_hclk_low, + .reg_src = { .reg = S5P64X0_OTHERS, .shift = 15, .size = 1 }, +}; + +static struct clk *clkset_hclk_list[] = { + &clk_mout_hclk_sel.clk, + &clk_armclk.clk, +}; + +static struct clksrc_sources clkset_hclk = { + .sources = clkset_hclk_list, + .nr_sources = ARRAY_SIZE(clkset_hclk_list), +}; + +static struct clksrc_clk clk_hclk = { + .clk = { + .name = "clk_hclk", + .id = -1, + }, + .sources = &clkset_hclk, + .reg_src = { .reg = S5P64X0_OTHERS, .shift = 14, .size = 1 }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk clk_pclk = { + .clk = { + .name = "clk_pclk", + .id = -1, + .parent = &clk_hclk.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 }, +}; +static struct clksrc_clk clk_dout_pwm_ratio0 = { + .clk = { + .name = "clk_dout_pwm_ratio0", + .id = -1, + .parent = &clk_mout_hclk_sel.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 16, .size = 4 }, +}; + +static struct clksrc_clk clk_pclk_to_wdt_pwm = { + .clk = { + .name = "clk_pclk_to_wdt_pwm", + .id = -1, + .parent = &clk_dout_pwm_ratio0.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 20, .size = 4 }, +}; + +static struct clksrc_clk clk_hclk_low = { + .clk = { + .name = "clk_hclk_low", + .id = -1, + }, + .sources = &clkset_hclk_low, + .reg_src = { .reg = S5P64X0_OTHERS, .shift = 6, .size = 1 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk clk_pclk_low = { + .clk = { + .name = "clk_pclk_low", + .id = -1, + .parent = &clk_hclk_low.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 }, +}; + +/* + * The following clocks will be disabled during clock initialization. It is + * recommended to keep the following clocks disabled until the driver requests + * for enabling the clock. + */ +static struct clk init_clocks_disable[] = { + { + .name = "usbhost", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 17), + }, { + .name = "hsmmc", + .id = 1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 18), + }, { + .name = "hsmmc", + .id = 2, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 19), + }, { + .name = "usbotg", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 20), + }, { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s5p64x0_hclk1_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "adc", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "i2c", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 17), + }, { + .name = "spi", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 21), + }, { + .name = "spi", + .id = 1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 22), + }, { + .name = "iis", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 26), + }, { + .name = "i2c", + .id = 1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 27), + }, { + .name = "dmc0", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 30), + } +}; + +/* + * The following clocks will be enabled during clock initialization. + */ +static struct clk init_clocks[] = { + { + .name = "intc", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "mem", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 21), + }, { + .name = "dma", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "uart", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "uart", + .id = 1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "uart", + .id = 2, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "uart", + .id = 3, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "timers", + .id = -1, + .parent = &clk_pclk_to_wdt_pwm.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "gpio", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 18), + }, +}; + +static struct clk *clkset_uart_list[] = { + &clk_dout_epll.clk, + &clk_dout_mpll.clk, +}; + +static struct clksrc_sources clkset_uart = { + .sources = clkset_uart_list, + .nr_sources = ARRAY_SIZE(clkset_uart_list), +}; + +static struct clk *clkset_mali_list[] = { + &clk_mout_epll.clk, + &clk_mout_apll.clk, + &clk_mout_mpll.clk, +}; + +static struct clksrc_sources clkset_mali = { + .sources = clkset_mali_list, + .nr_sources = ARRAY_SIZE(clkset_mali_list), +}; + +static struct clk *clkset_group2_list[] = { + &clk_dout_epll.clk, + &clk_dout_mpll.clk, + &clk_ext_xtal_mux, +}; + +static struct clksrc_sources clkset_group2 = { + .sources = clkset_group2_list, + .nr_sources = ARRAY_SIZE(clkset_group2_list), +}; + +static struct clk *clkset_dispcon_list[] = { + &clk_dout_epll.clk, + &clk_dout_mpll.clk, + &clk_ext_xtal_mux, + &clk_mout_dpll.clk, +}; + +static struct clksrc_sources clkset_dispcon = { + .sources = clkset_dispcon_list, + .nr_sources = ARRAY_SIZE(clkset_dispcon_list), +}; + +static struct clk *clkset_hsmmc44_list[] = { + &clk_dout_epll.clk, + &clk_dout_mpll.clk, + &clk_ext_xtal_mux, + &s5p_clk_27m, + &clk_48m, +}; + +static struct clksrc_sources clkset_hsmmc44 = { + .sources = clkset_hsmmc44_list, + .nr_sources = ARRAY_SIZE(clkset_hsmmc44_list), +}; + +static struct clk *clkset_sclk_audio0_list[] = { + [0] = &clk_dout_epll.clk, + [1] = &clk_dout_mpll.clk, + [2] = &clk_ext_xtal_mux, + [3] = NULL, + [4] = NULL, +}; + +static struct clksrc_sources clkset_sclk_audio0 = { + .sources = clkset_sclk_audio0_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_audio0_list), +}; + +static struct clksrc_clk clk_sclk_audio0 = { + .clk = { + .name = "audio-bus", + .id = -1, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 8), + .parent = &clk_dout_epll.clk, + }, + .sources = &clkset_sclk_audio0, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 10, .size = 3 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk clksrcs[] = { + { + .clk = { + .name = "sclk_mmc", + .id = 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", + .id = 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", + .id = 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", + .id = -1, + .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", + .id = 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", + .id = 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", + .id = -1, + .ctrlbit = (1 << 10), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "aclk_mali", + .id = -1, + .ctrlbit = (1 << 2), + .enable = s5p64x0_sclk1_ctrl, + }, + .sources = &clkset_mali, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_2d", + .id = -1, + .ctrlbit = (1 << 12), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_mali, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 30, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_usi", + .id = -1, + .ctrlbit = (1 << 7), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 10, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_camif", + .id = -1, + .ctrlbit = (1 << 6), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 28, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_dispcon", + .id = -1, + .ctrlbit = (1 << 1), + .enable = s5p64x0_sclk1_ctrl, + }, + .sources = &clkset_dispcon, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_hsmmc44", + .id = -1, + .ctrlbit = (1 << 30), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_hsmmc44, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 6, .size = 3 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 28, .size = 4 }, + }, +}; + +/* Clock initialization code */ +static struct clksrc_clk *sysclks[] = { + &clk_mout_apll, + &clk_mout_epll, + &clk_dout_epll, + &clk_mout_mpll, + &clk_dout_mpll, + &clk_armclk, + &clk_mout_hclk_sel, + &clk_dout_pwm_ratio0, + &clk_pclk_to_wdt_pwm, + &clk_hclk, + &clk_pclk, + &clk_hclk_low, + &clk_pclk_low, + &clk_sclk_audio0, +}; + +void __init_or_cpufreq s5p6450_setup_clocks(void) +{ + struct clk *xtal_clk; + + unsigned long xtal; + unsigned long fclk; + unsigned long hclk; + unsigned long hclk_low; + unsigned long pclk; + unsigned long pclk_low; + + unsigned long apll; + unsigned long mpll; + unsigned long epll; + unsigned long dpll; + unsigned int ptr; + + /* Set S5P6450 functions for clk_fout_epll */ + + clk_fout_epll.enable = s5p_epll_enable; + clk_fout_epll.ops = &s5p6450_epll_ops; + + clk_48m.enable = s5p64x0_clk48m_ctrl; + + xtal_clk = clk_get(NULL, "ext_xtal"); + BUG_ON(IS_ERR(xtal_clk)); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502); + mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502); + epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON), + __raw_readl(S5P64X0_EPLL_CON_K)); + dpll = s5p_get_pll46xx(xtal, __raw_readl(S5P6450_DPLL_CON), + __raw_readl(S5P6450_DPLL_CON_K), pll_4650c); + + clk_fout_apll.rate = apll; + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + clk_fout_dpll.rate = dpll; + + printk(KERN_INFO "S5P6450: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \ + " E=%ld.%ldMHz, D=%ld.%ldMHz\n", + print_mhz(apll), print_mhz(mpll), print_mhz(epll), + print_mhz(dpll)); + + fclk = clk_get_rate(&clk_armclk.clk); + hclk = clk_get_rate(&clk_hclk.clk); + pclk = clk_get_rate(&clk_pclk.clk); + hclk_low = clk_get_rate(&clk_hclk_low.clk); + pclk_low = clk_get_rate(&clk_pclk_low.clk); + + printk(KERN_INFO "S5P6450: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \ + " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n", + print_mhz(hclk), print_mhz(hclk_low), + print_mhz(pclk), print_mhz(pclk_low)); + + clk_f.rate = fclk; + clk_h.rate = hclk; + clk_p.rate = pclk; + + for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) + s3c_set_clksrc(&clksrcs[ptr], true); +} + +void __init s5p6450_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) + s3c_register_clksrc(sysclks[ptr], 1); + + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); + s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + (clkp->enable)(clkp, 0); + } + + s3c_pwmclk_init(); +} diff --git a/arch/arm/mach-s5p64x0/clock.c b/arch/arm/mach-s5p64x0/clock.c new file mode 100644 index 000000000000..b52c6e2f37a6 --- /dev/null +++ b/arch/arm/mach-s5p64x0/clock.c @@ -0,0 +1,235 @@ +/* linux/arch/arm/mach-s5p64x0/clock.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - Clock 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/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> +#include <mach/regs-clock.h> + +#include <plat/cpu-freq.h> +#include <plat/clock.h> +#include <plat/cpu.h> +#include <plat/pll.h> +#include <plat/s5p-clock.h> +#include <plat/clock-clksrc.h> +#include <plat/s5p6440.h> +#include <plat/s5p6450.h> + +struct clksrc_clk clk_mout_apll = { + .clk = { + .name = "mout_apll", + .id = -1, + }, + .sources = &clk_src_apll, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 0, .size = 1 }, +}; + +struct clksrc_clk clk_mout_mpll = { + .clk = { + .name = "mout_mpll", + .id = -1, + }, + .sources = &clk_src_mpll, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 1, .size = 1 }, +}; + +struct clksrc_clk clk_mout_epll = { + .clk = { + .name = "mout_epll", + .id = -1, + }, + .sources = &clk_src_epll, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 2, .size = 1 }, +}; + +enum perf_level { + L0 = 532*1000, + L1 = 266*1000, + L2 = 133*1000, +}; + +static const u32 clock_table[][3] = { + /*{ARM_CLK, DIVarm, DIVhclk}*/ + {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P64X0_CLKDIV0_HCLK_SHIFT)}, + {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P64X0_CLKDIV0_HCLK_SHIFT)}, + {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)}, +}; + +unsigned long s5p64x0_armclk_get_rate(struct clk *clk) +{ + unsigned long rate = clk_get_rate(clk->parent); + u32 clkdiv; + + /* divisor mask starts at bit0, so no need to shift */ + clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK; + + return rate / (clkdiv + 1); +} + +unsigned long s5p64x0_armclk_round_rate(struct clk *clk, unsigned long rate) +{ + u32 iter; + + for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) { + if (rate > clock_table[iter][0]) + return clock_table[iter-1][0]; + } + + return clock_table[ARRAY_SIZE(clock_table) - 1][0]; +} + +int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate) +{ + u32 round_tmp; + u32 iter; + u32 clk_div0_tmp; + u32 cur_rate = clk->ops->get_rate(clk); + unsigned long flags; + + round_tmp = clk->ops->round_rate(clk, rate); + if (round_tmp == cur_rate) + return 0; + + + for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) { + if (round_tmp == clock_table[iter][0]) + break; + } + + if (iter >= ARRAY_SIZE(clock_table)) + iter = ARRAY_SIZE(clock_table) - 1; + + local_irq_save(flags); + if (cur_rate > round_tmp) { + /* Frequency Down */ + clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK); + clk_div0_tmp |= clock_table[iter][1]; + __raw_writel(clk_div0_tmp, ARM_CLK_DIV); + + clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & + ~(S5P64X0_CLKDIV0_HCLK_MASK); + clk_div0_tmp |= clock_table[iter][2]; + __raw_writel(clk_div0_tmp, ARM_CLK_DIV); + + + } else { + /* Frequency Up */ + clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & + ~(S5P64X0_CLKDIV0_HCLK_MASK); + clk_div0_tmp |= clock_table[iter][2]; + __raw_writel(clk_div0_tmp, ARM_CLK_DIV); + + clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK); + clk_div0_tmp |= clock_table[iter][1]; + __raw_writel(clk_div0_tmp, ARM_CLK_DIV); + } + local_irq_restore(flags); + + clk->rate = clock_table[iter][0]; + + return 0; +} + +struct clk_ops s5p64x0_clkarm_ops = { + .get_rate = s5p64x0_armclk_get_rate, + .set_rate = s5p64x0_armclk_set_rate, + .round_rate = s5p64x0_armclk_round_rate, +}; + +struct clksrc_clk clk_armclk = { + .clk = { + .name = "armclk", + .id = 1, + .parent = &clk_mout_apll.clk, + .ops = &s5p64x0_clkarm_ops, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 0, .size = 4 }, +}; + +struct clksrc_clk clk_dout_mpll = { + .clk = { + .name = "dout_mpll", + .id = -1, + .parent = &clk_mout_mpll.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 4, .size = 1 }, +}; + +struct clk *clkset_hclk_low_list[] = { + &clk_mout_apll.clk, + &clk_mout_mpll.clk, +}; + +struct clksrc_sources clkset_hclk_low = { + .sources = clkset_hclk_low_list, + .nr_sources = ARRAY_SIZE(clkset_hclk_low_list), +}; + +int s5p64x0_pclk_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_PCLK, clk, enable); +} + +int s5p64x0_hclk0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK0, clk, enable); +} + +int s5p64x0_hclk1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK1, clk, enable); +} + +int s5p64x0_sclk_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK0, clk, enable); +} + +int s5p64x0_sclk1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK1, clk, enable); +} + +int s5p64x0_mem_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_MEM0, clk, enable); +} + +int s5p64x0_clk48m_ctrl(struct clk *clk, int enable) +{ + unsigned long flags; + u32 val; + + /* can't rely on clock lock, this register has other usages */ + local_irq_save(flags); + + val = __raw_readl(S5P64X0_OTHERS); + if (enable) + val |= S5P64X0_OTHERS_USB_SIG_MASK; + else + val &= ~S5P64X0_OTHERS_USB_SIG_MASK; + + __raw_writel(val, S5P64X0_OTHERS); + + local_irq_restore(flags); + + return 0; +} diff --git a/arch/arm/mach-s5p64x0/cpu.c b/arch/arm/mach-s5p64x0/cpu.c new file mode 100644 index 000000000000..b8d02eb4cf30 --- /dev/null +++ b/arch/arm/mach-s5p64x0/cpu.c @@ -0,0 +1,209 @@ +/* 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(s5p6440_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-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c new file mode 100644 index 000000000000..396bacc0a39a --- /dev/null +++ b/arch/arm/mach-s5p64x0/dev-audio.c @@ -0,0 +1,152 @@ +/* linux/arch/arm/mach-s5p64x0/dev-audio.c + * + * 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 <plat/gpio-cfg.h> +#include <plat/audio.h> + +#include <mach/map.h> +#include <mach/dma.h> +#include <mach/irqs.h> + +static int s5p6440_cfg_i2s(struct platform_device *pdev) +{ + /* configure GPIO for i2s port */ + switch (pdev->id) { + case -1: + s3c_gpio_cfgpin_range(S5P6440_GPR(4), 5, S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin_range(S5P6440_GPR(13), 2, S3C_GPIO_SFN(5)); + break; + + default: + printk(KERN_ERR "Invalid Device %d\n", pdev->id); + return -EINVAL; + } + + return 0; +} + +static int s5p6450_cfg_i2s(struct platform_device *pdev) +{ + /* configure GPIO for i2s port */ + switch (pdev->id) { + case -1: + s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin_range(S5P6450_GPR(4), 5, S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin_range(S5P6450_GPR(13), 2, S3C_GPIO_SFN(5)); + + break; + + default: + printk(KERN_ERR "Invalid Device %d\n", pdev->id); + return -EINVAL; + } + + return 0; +} + +static struct s3c_audio_pdata s5p6440_i2s_pdata = { + .cfg_gpio = s5p6440_cfg_i2s, +}; + +static struct s3c_audio_pdata s5p6450_i2s_pdata = { + .cfg_gpio = s5p6450_cfg_i2s, +}; + +static struct resource s5p64x0_iis0_resource[] = { + [0] = { + .start = S5P64X0_PA_I2S, + .end = S5P64X0_PA_I2S + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_I2S0_TX, + .end = DMACH_I2S0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_I2S0_RX, + .end = DMACH_I2S0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5p6440_device_iis = { + .name = "s3c64xx-iis-v4", + .id = -1, + .num_resources = ARRAY_SIZE(s5p64x0_iis0_resource), + .resource = s5p64x0_iis0_resource, + .dev = { + .platform_data = &s5p6440_i2s_pdata, + }, +}; + +struct platform_device s5p6450_device_iis0 = { + .name = "s3c64xx-iis-v4", + .id = -1, + .num_resources = ARRAY_SIZE(s5p64x0_iis0_resource), + .resource = s5p64x0_iis0_resource, + .dev = { + .platform_data = &s5p6450_i2s_pdata, + }, +}; + +/* PCM Controller platform_devices */ + +static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev) +{ + switch (pdev->id) { + case 0: + s3c_gpio_cfgpin_range(S5P6440_GPR(6), 3, S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin_range(S5P6440_GPR(13), 2, S3C_GPIO_SFN(2)); + break; + + default: + printk(KERN_DEBUG "Invalid PCM Controller number!"); + return -EINVAL; + } + + return 0; +} + +static struct s3c_audio_pdata s5p6440_pcm_pdata = { + .cfg_gpio = s5p6440_pcm_cfg_gpio, +}; + +static struct resource s5p6440_pcm0_resource[] = { + [0] = { + .start = S5P64X0_PA_PCM, + .end = S5P64X0_PA_PCM + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_PCM0_TX, + .end = DMACH_PCM0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_PCM0_RX, + .end = DMACH_PCM0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5p6440_device_pcm = { + .name = "samsung-pcm", + .id = 0, + .num_resources = ARRAY_SIZE(s5p6440_pcm0_resource), + .resource = s5p6440_pcm0_resource, + .dev = { + .platform_data = &s5p6440_pcm_pdata, + }, +}; diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c new file mode 100644 index 000000000000..e78ee18c76e3 --- /dev/null +++ b/arch/arm/mach-s5p64x0/dev-spi.c @@ -0,0 +1,222 @@ +/* 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, +}; + +static struct s3c64xx_spi_info s5p6450_spi0_pdata = { + .cfg_gpio = s5p6450_spi_cfg_gpio, + .fifo_lvl_mask = 0x1ff, + .rx_lvl_offset = 15, +}; + +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, +}; + +static struct s3c64xx_spi_info s5p6450_spi1_pdata = { + .cfg_gpio = s5p6450_spi_cfg_gpio, + .fifo_lvl_mask = 0x7f, + .rx_lvl_offset = 15, +}; + +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-s5p6440/dma.c b/arch/arm/mach-s5p64x0/dma.c index 07606ad57519..29a8c2410049 100644 --- a/arch/arm/mach-s5p6440/dma.c +++ b/arch/arm/mach-s5p64x0/dma.c @@ -1,4 +1,8 @@ -/* +/* linux/arch/arm/mach-s5p64x0/dma.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> * @@ -15,26 +19,25 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ +*/ #include <linux/platform_device.h> #include <linux/dma-mapping.h> -#include <plat/devs.h> -#include <plat/irqs.h> - #include <mach/map.h> #include <mach/irqs.h> +#include <mach/regs-clock.h> +#include <plat/devs.h> #include <plat/s3c-pl330-pdata.h> static u64 dma_dmamask = DMA_BIT_MASK(32); -static struct resource s5p6440_pdma_resource[] = { +static struct resource s5p64x0_pdma_resource[] = { [0] = { - .start = S5P6440_PA_PDMA, - .end = S5P6440_PA_PDMA + SZ_4K, - .flags = IORESOURCE_MEM, + .start = S5P64X0_PA_PDMA, + .end = S5P64X0_PA_PDMA + SZ_4K, + .flags = IORESOURCE_MEM, }, [1] = { .start = IRQ_DMA0, @@ -80,26 +83,67 @@ static struct s3c_pl330_platdata s5p6440_pdma_pdata = { }, }; -static struct platform_device s5p6440_device_pdma = { +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, + }, +}; + +static struct platform_device s5p64x0_device_pdma = { .name = "s3c-pl330", - .id = 1, - .num_resources = ARRAY_SIZE(s5p6440_pdma_resource), - .resource = s5p6440_pdma_resource, + .id = 0, + .num_resources = ARRAY_SIZE(s5p64x0_pdma_resource), + .resource = s5p64x0_pdma_resource, .dev = { .dma_mask = &dma_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &s5p6440_pdma_pdata, }, }; -static struct platform_device *s5p6440_dmacs[] __initdata = { - &s5p6440_device_pdma, -}; - -static int __init s5p6440_dma_init(void) +static int __init s5p64x0_dma_init(void) { - platform_add_devices(s5p6440_dmacs, ARRAY_SIZE(s5p6440_dmacs)); + unsigned int id; + + id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000; + + if (id == 0x50000) + s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata; + else + s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata; + + platform_device_register(&s5p64x0_device_pdma); return 0; } -arch_initcall(s5p6440_dma_init); +arch_initcall(s5p64x0_dma_init); diff --git a/arch/arm/mach-s5p6440/gpio.c b/arch/arm/mach-s5p64x0/gpio.c index 8bf6e0ce51c9..39159dd5a29a 100644 --- a/arch/arm/mach-s5p6440/gpio.c +++ b/arch/arm/mach-s5p64x0/gpio.c @@ -1,14 +1,14 @@ -/* arch/arm/mach-s5p6440/gpio.c +/* linux/arch/arm/mach-s5p64x0/gpio.c * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - GPIOlib support + * S5P64X0 - GPIOlib 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/irq.h> @@ -22,26 +22,29 @@ #include <plat/gpio-cfg.h> #include <plat/gpio-cfg-helpers.h> -/* GPIO bank summary: -* -* Bank GPIOs Style SlpCon ExtInt Group -* A 6 4Bit Yes 1 -* B 7 4Bit Yes 1 -* C 8 4Bit Yes 2 -* F 2 2Bit Yes 4 [1] -* G 7 4Bit Yes 5 -* H 10 4Bit[2] Yes 6 -* I 16 2Bit Yes None -* J 12 2Bit Yes None -* N 16 2Bit No IRQ_EINT -* P 8 2Bit Yes 8 -* R 15 4Bit[2] Yes 8 -* -* [1] BANKF pins 14,15 do not form part of the external interrupt sources -* [2] BANK has two control registers, GPxCON0 and GPxCON1 -*/ +/* To be implemented S5P6450 GPIO */ + +/* + * S5P6440 GPIO bank summary: + * + * Bank GPIOs Style SlpCon ExtInt Group + * A 6 4Bit Yes 1 + * B 7 4Bit Yes 1 + * C 8 4Bit Yes 2 + * F 2 2Bit Yes 4 [1] + * G 7 4Bit Yes 5 + * H 10 4Bit[2] Yes 6 + * I 16 2Bit Yes None + * J 12 2Bit Yes None + * N 16 2Bit No IRQ_EINT + * P 8 2Bit Yes 8 + * R 15 4Bit[2] Yes 8 + * + * [1] BANKF pins 14,15 do not form part of the external interrupt sources + * [2] BANK has two control registers, GPxCON0 and GPxCON1 + */ -static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip, +static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip *chip, unsigned int offset) { struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); @@ -77,7 +80,7 @@ static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip, return 0; } -static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip, +static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip *chip, unsigned int offset, int value) { struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); @@ -124,12 +127,11 @@ static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip, return 0; } -int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip, +int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip, unsigned int off, unsigned int cfg) { void __iomem *reg = chip->base; unsigned int shift; - unsigned long flags; u32 con; switch (off) { @@ -155,26 +157,22 @@ int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip, cfg <<= shift; } - s3c_gpio_lock(chip, flags); - con = __raw_readl(reg); con &= ~(0xf << shift); con |= cfg; __raw_writel(con, reg); - s3c_gpio_unlock(chip, flags); - return 0; } -static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = { +static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = { { .cfg_eint = 0, }, { .cfg_eint = 7, }, { .cfg_eint = 3, - .set_config = s5p6440_gpio_setcfg_4bit_rbank, + .set_config = s5p64x0_gpio_setcfg_4bit_rbank, }, { .cfg_eint = 0, .set_config = s3c_gpio_setcfg_s3c24xx, @@ -193,7 +191,7 @@ static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = { static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { { .base = S5P6440_GPA_BASE, - .config = &s5p6440_gpio_cfgs[1], + .config = &s5p64x0_gpio_cfgs[1], .chip = { .base = S5P6440_GPA(0), .ngpio = S5P6440_GPIO_A_NR, @@ -201,7 +199,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { }, }, { .base = S5P6440_GPB_BASE, - .config = &s5p6440_gpio_cfgs[1], + .config = &s5p64x0_gpio_cfgs[1], .chip = { .base = S5P6440_GPB(0), .ngpio = S5P6440_GPIO_B_NR, @@ -209,7 +207,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { }, }, { .base = S5P6440_GPC_BASE, - .config = &s5p6440_gpio_cfgs[1], + .config = &s5p64x0_gpio_cfgs[1], .chip = { .base = S5P6440_GPC(0), .ngpio = S5P6440_GPIO_C_NR, @@ -217,7 +215,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { }, }, { .base = S5P6440_GPG_BASE, - .config = &s5p6440_gpio_cfgs[1], + .config = &s5p64x0_gpio_cfgs[1], .chip = { .base = S5P6440_GPG(0), .ngpio = S5P6440_GPIO_G_NR, @@ -229,7 +227,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = { { .base = S5P6440_GPH_BASE + 0x4, - .config = &s5p6440_gpio_cfgs[1], + .config = &s5p64x0_gpio_cfgs[1], .chip = { .base = S5P6440_GPH(0), .ngpio = S5P6440_GPIO_H_NR, @@ -238,10 +236,10 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = { }, }; -static struct s3c_gpio_chip gpio_rbank_4bit2[] = { +static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = { { .base = S5P6440_GPR_BASE + 0x4, - .config = &s5p6440_gpio_cfgs[2], + .config = &s5p64x0_gpio_cfgs[2], .chip = { .base = S5P6440_GPR(0), .ngpio = S5P6440_GPIO_R_NR, @@ -253,7 +251,7 @@ static struct s3c_gpio_chip gpio_rbank_4bit2[] = { static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { { .base = S5P6440_GPF_BASE, - .config = &s5p6440_gpio_cfgs[5], + .config = &s5p64x0_gpio_cfgs[5], .chip = { .base = S5P6440_GPF(0), .ngpio = S5P6440_GPIO_F_NR, @@ -261,7 +259,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { }, }, { .base = S5P6440_GPI_BASE, - .config = &s5p6440_gpio_cfgs[3], + .config = &s5p64x0_gpio_cfgs[3], .chip = { .base = S5P6440_GPI(0), .ngpio = S5P6440_GPIO_I_NR, @@ -269,7 +267,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { }, }, { .base = S5P6440_GPJ_BASE, - .config = &s5p6440_gpio_cfgs[3], + .config = &s5p64x0_gpio_cfgs[3], .chip = { .base = S5P6440_GPJ(0), .ngpio = S5P6440_GPIO_J_NR, @@ -277,7 +275,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { }, }, { .base = S5P6440_GPN_BASE, - .config = &s5p6440_gpio_cfgs[4], + .config = &s5p64x0_gpio_cfgs[4], .chip = { .base = S5P6440_GPN(0), .ngpio = S5P6440_GPIO_N_NR, @@ -285,7 +283,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { }, }, { .base = S5P6440_GPP_BASE, - .config = &s5p6440_gpio_cfgs[5], + .config = &s5p64x0_gpio_cfgs[5], .chip = { .base = S5P6440_GPP(0), .ngpio = S5P6440_GPIO_P_NR, @@ -294,7 +292,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { }, }; -void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips) +void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips) { for (; nr_chips > 0; nr_chips--, chipcfg++) { if (!chipcfg->set_config) @@ -308,13 +306,13 @@ void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips) } } -static void __init s5p6440_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip, +static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip, int nr_chips) { for (; nr_chips > 0; nr_chips--, chip++) { - chip->chip.direction_input = s5p6440_gpiolib_rbank_4bit2_input; + chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input; chip->chip.direction_output = - s5p6440_gpiolib_rbank_4bit2_output; + s5p64x0_gpiolib_rbank_4bit2_output; s3c_gpiolib_add(chip); } } @@ -324,8 +322,8 @@ static int __init s5p6440_gpiolib_init(void) struct s3c_gpio_chip *chips = s5p6440_gpio_2bit; int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit); - s5p6440_gpiolib_set_cfg(s5p6440_gpio_cfgs, - ARRAY_SIZE(s5p6440_gpio_cfgs)); + s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs, + ARRAY_SIZE(s5p64x0_gpio_cfgs)); for (; nr_chips > 0; nr_chips--, chips++) s3c_gpiolib_add(chips); @@ -336,8 +334,8 @@ static int __init s5p6440_gpiolib_init(void) samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2, ARRAY_SIZE(s5p6440_gpio_4bit2)); - s5p6440_gpio_add_rbank_4bit2(gpio_rbank_4bit2, - ARRAY_SIZE(gpio_rbank_4bit2)); + s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2, + ARRAY_SIZE(s5p6440_gpio_rbank_4bit2)); return 0; } diff --git a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S new file mode 100644 index 000000000000..79b04e6a6f8e --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S @@ -0,0 +1,33 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/debug-macro.S + * + * 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. +*/ + +/* pull in the relevant register and map files. */ + +#include <plat/map-base.h> +#include <plat/map-s5p.h> + +#include <plat/regs-serial.h> + + .macro addruart, rp, rv + mov \rp, #0xE0000000 + orr \rp, \rp, #0x00100000 + ldr \rp, [\rp, #0x118 ] + and \rp, \rp, #0xff000 + teq \rp, #0x50000 @@ S5P6450 + ldreq \rp, =0xEC800000 + movne \rp, #0xEC000000 @@ S5P6440 + ldrne \rv, = S3C_VA_UART +#if CONFIG_DEBUG_S3C_UART != 0 + add \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART) + add \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART) +#endif + .endm + +#include <plat/debug-macro.S> diff --git a/arch/arm/mach-s5p6440/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h index 81209eb1409b..81209eb1409b 100644 --- a/arch/arm/mach-s5p6440/include/mach/dma.h +++ b/arch/arm/mach-s5p64x0/include/mach/dma.h diff --git a/arch/arm/mach-s5p6440/include/mach/entry-macro.S b/arch/arm/mach-s5p64x0/include/mach/entry-macro.S index e65f1b967262..10b62b4f8211 100644 --- a/arch/arm/mach-s5p6440/include/mach/entry-macro.S +++ b/arch/arm/mach-s5p64x0/include/mach/entry-macro.S @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/entry-macro.S +/* linux/arch/arm/mach-s5p64x0/include/mach/entry-macro.S * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * Low-level IRQ helper macros for the Samsung S5P6440 + * Low-level IRQ helper macros for the Samsung S5P64X0 * * 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 diff --git a/arch/arm/mach-s5p64x0/include/mach/gpio.h b/arch/arm/mach-s5p64x0/include/mach/gpio.h new file mode 100644 index 000000000000..5486c8f01f1d --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/gpio.h @@ -0,0 +1,139 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/gpio.h + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - GPIO lib 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_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) +#define S5P6440_GPIO_B_NR (7) +#define S5P6440_GPIO_C_NR (8) +#define S5P6440_GPIO_F_NR (2) +#define S5P6440_GPIO_G_NR (7) +#define S5P6440_GPIO_H_NR (10) +#define S5P6440_GPIO_I_NR (16) +#define S5P6440_GPIO_J_NR (12) +#define S5P6440_GPIO_N_NR (16) +#define S5P6440_GPIO_P_NR (8) +#define S5P6440_GPIO_R_NR (15) + +#define S5P6450_GPIO_A_NR (6) +#define S5P6450_GPIO_B_NR (7) +#define S5P6450_GPIO_C_NR (8) +#define S5P6450_GPIO_D_NR (8) +#define S5P6450_GPIO_F_NR (2) +#define S5P6450_GPIO_G_NR (14) +#define S5P6450_GPIO_H_NR (10) +#define S5P6450_GPIO_I_NR (16) +#define S5P6450_GPIO_J_NR (12) +#define S5P6450_GPIO_K_NR (5) +#define S5P6450_GPIO_N_NR (16) +#define S5P6450_GPIO_P_NR (11) +#define S5P6450_GPIO_Q_NR (14) +#define S5P6450_GPIO_R_NR (15) +#define S5P6450_GPIO_S_NR (8) + +/* GPIO bank numbers */ + +/* CONFIG_S3C_GPIO_SPACE allows the user to select extra + * space for debugging purposes so that any accidental + * change from one gpio bank to another can be caught. +*/ + +#define S5P64X0_GPIO_NEXT(__gpio) \ + ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1) + +enum s5p6440_gpio_number { + S5P6440_GPIO_A_START = 0, + S5P6440_GPIO_B_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_A), + S5P6440_GPIO_C_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_B), + S5P6440_GPIO_F_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_C), + S5P6440_GPIO_G_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_F), + S5P6440_GPIO_H_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_G), + S5P6440_GPIO_I_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_H), + S5P6440_GPIO_J_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_I), + S5P6440_GPIO_N_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_J), + S5P6440_GPIO_P_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_N), + S5P6440_GPIO_R_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_P), +}; + +enum s5p6450_gpio_number { + S5P6450_GPIO_A_START = 0, + S5P6450_GPIO_B_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_A), + S5P6450_GPIO_C_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_B), + S5P6450_GPIO_D_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_C), + S5P6450_GPIO_F_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_D), + S5P6450_GPIO_G_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_F), + S5P6450_GPIO_H_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_G), + S5P6450_GPIO_I_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_H), + S5P6450_GPIO_J_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_I), + S5P6450_GPIO_K_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_J), + S5P6450_GPIO_N_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_K), + S5P6450_GPIO_P_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_N), + S5P6450_GPIO_Q_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_P), + S5P6450_GPIO_R_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_Q), + S5P6450_GPIO_S_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_R), +}; + +/* GPIO number definitions */ + +#define S5P6440_GPA(_nr) (S5P6440_GPIO_A_START + (_nr)) +#define S5P6440_GPB(_nr) (S5P6440_GPIO_B_START + (_nr)) +#define S5P6440_GPC(_nr) (S5P6440_GPIO_C_START + (_nr)) +#define S5P6440_GPF(_nr) (S5P6440_GPIO_F_START + (_nr)) +#define S5P6440_GPG(_nr) (S5P6440_GPIO_G_START + (_nr)) +#define S5P6440_GPH(_nr) (S5P6440_GPIO_H_START + (_nr)) +#define S5P6440_GPI(_nr) (S5P6440_GPIO_I_START + (_nr)) +#define S5P6440_GPJ(_nr) (S5P6440_GPIO_J_START + (_nr)) +#define S5P6440_GPN(_nr) (S5P6440_GPIO_N_START + (_nr)) +#define S5P6440_GPP(_nr) (S5P6440_GPIO_P_START + (_nr)) +#define S5P6440_GPR(_nr) (S5P6440_GPIO_R_START + (_nr)) + +#define S5P6450_GPA(_nr) (S5P6450_GPIO_A_START + (_nr)) +#define S5P6450_GPB(_nr) (S5P6450_GPIO_B_START + (_nr)) +#define S5P6450_GPC(_nr) (S5P6450_GPIO_C_START + (_nr)) +#define S5P6450_GPD(_nr) (S5P6450_GPIO_D_START + (_nr)) +#define S5P6450_GPF(_nr) (S5P6450_GPIO_F_START + (_nr)) +#define S5P6450_GPG(_nr) (S5P6450_GPIO_G_START + (_nr)) +#define S5P6450_GPH(_nr) (S5P6450_GPIO_H_START + (_nr)) +#define S5P6450_GPI(_nr) (S5P6450_GPIO_I_START + (_nr)) +#define S5P6450_GPJ(_nr) (S5P6450_GPIO_J_START + (_nr)) +#define S5P6450_GPK(_nr) (S5P6450_GPIO_K_START + (_nr)) +#define S5P6450_GPN(_nr) (S5P6450_GPIO_N_START + (_nr)) +#define S5P6450_GPP(_nr) (S5P6450_GPIO_P_START + (_nr)) +#define S5P6450_GPQ(_nr) (S5P6450_GPIO_Q_START + (_nr)) +#define S5P6450_GPR(_nr) (S5P6450_GPIO_R_START + (_nr)) +#define S5P6450_GPS(_nr) (S5P6450_GPIO_S_START + (_nr)) + +/* the end of the S5P64X0 specific gpios */ + +#define S5P6440_GPIO_END (S5P6440_GPR(S5P6440_GPIO_R_NR) + 1) +#define S5P6450_GPIO_END (S5P6450_GPS(S5P6450_GPIO_S_NR) + 1) + +#define S5P64X0_GPIO_END (S5P6440_GPIO_END > S5P6450_GPIO_END ? \ + S5P6440_GPIO_END : S5P6450_GPIO_END) + +#define S3C_GPIO_END S5P64X0_GPIO_END + +/* define the number of gpios we need to the one after the last GPIO range */ + +#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-s5p6440/include/mach/hardware.h b/arch/arm/mach-s5p64x0/include/mach/hardware.h index be8b26e875db..d3e87996dd9a 100644 --- a/arch/arm/mach-s5p6440/include/mach/hardware.h +++ b/arch/arm/mach-s5p64x0/include/mach/hardware.h @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/hardware.h +/* linux/arch/arm/mach-s5p64x0/include/mach/hardware.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - Hardware support + * S5P64X0 - Hardware 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 diff --git a/arch/arm/mach-s5p64x0/include/mach/i2c.h b/arch/arm/mach-s5p64x0/include/mach/i2c.h new file mode 100644 index 000000000000..887d25209e8e --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/i2c.h @@ -0,0 +1,17 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/i2c.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 I2C configuration + * + * 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. +*/ + +extern void s5p6440_i2c0_cfg_gpio(struct platform_device *dev); +extern void s5p6440_i2c1_cfg_gpio(struct platform_device *dev); + +extern void s5p6450_i2c0_cfg_gpio(struct platform_device *dev); +extern void s5p6450_i2c1_cfg_gpio(struct platform_device *dev); diff --git a/arch/arm/mach-s5p64x0/include/mach/io.h b/arch/arm/mach-s5p64x0/include/mach/io.h new file mode 100644 index 000000000000..a3e095c02fb5 --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/io.h @@ -0,0 +1,25 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/io.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben-linux@fluff.org> + * + * Default IO routines for S5P64X0 based + * + * 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_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +/* No current ISA/PCI bus support. */ +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#define IO_SPACE_LIMIT (0xFFFFFFFF) + +#endif diff --git a/arch/arm/mach-s5p6440/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h index 16a761270de1..513abffc7604 100644 --- a/arch/arm/mach-s5p6440/include/mach/irqs.h +++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h @@ -1,17 +1,17 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/irqs.h +/* linux/arch/arm/mach-s5p64x0/include/mach/irqs.h * - * Copyright 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - IRQ definitions + * S5P64X0 - IRQ 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_S5P_IRQS_H -#define __ASM_ARCH_S5P_IRQS_H __FILE__ +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H __FILE__ #include <plat/irqs.h> @@ -20,10 +20,12 @@ #define IRQ_EINT0_3 S5P_IRQ_VIC0(0) #define IRQ_EINT4_11 S5P_IRQ_VIC0(1) #define IRQ_RTC_TIC S5P_IRQ_VIC0(2) +#define IRQ_IIS1 S5P_IRQ_VIC0(3) /* for only S5P6450 */ +#define IRQ_IIS2 S5P_IRQ_VIC0(4) /* for only S5P6450 */ #define IRQ_IIC1 S5P_IRQ_VIC0(5) #define IRQ_I2SV40 S5P_IRQ_VIC0(6) -#define IRQ_GPS S5P_IRQ_VIC0(7) -#define IRQ_POST0 S5P_IRQ_VIC0(9) +#define IRQ_GPS S5P_IRQ_VIC0(7) /* for only S5P6450 */ + #define IRQ_2D S5P_IRQ_VIC0(11) #define IRQ_TIMER0_VIC S5P_IRQ_VIC0(23) #define IRQ_TIMER1_VIC S5P_IRQ_VIC0(24) @@ -39,22 +41,26 @@ #define IRQ_EINT12_15 S5P_IRQ_VIC1(0) #define IRQ_PCM0 S5P_IRQ_VIC1(2) +#define IRQ_PCM1 S5P_IRQ_VIC1(3) /* for only S5P6450 */ +#define IRQ_PCM2 S5P_IRQ_VIC1(4) /* for only S5P6450 */ #define IRQ_UART0 S5P_IRQ_VIC1(5) #define IRQ_UART1 S5P_IRQ_VIC1(6) #define IRQ_UART2 S5P_IRQ_VIC1(7) #define IRQ_UART3 S5P_IRQ_VIC1(8) #define IRQ_DMA0 S5P_IRQ_VIC1(9) +#define IRQ_UART4 S5P_IRQ_VIC1(10) /* S5P6450 */ +#define IRQ_UART5 S5P_IRQ_VIC1(11) /* S5P6450 */ #define IRQ_NFC S5P_IRQ_VIC1(13) +#define IRQ_USI S5P_IRQ_VIC1(15) /* S5P6450 */ #define IRQ_SPI0 S5P_IRQ_VIC1(16) #define IRQ_SPI1 S5P_IRQ_VIC1(17) +#define IRQ_HSMMC2 S5P_IRQ_VIC1(17) /* Shared */ #define IRQ_IIC S5P_IRQ_VIC1(18) #define IRQ_DISPCON3 S5P_IRQ_VIC1(19) -#define IRQ_FIMGVG S5P_IRQ_VIC1(20) #define IRQ_EINT_GROUPS S5P_IRQ_VIC1(21) -#define IRQ_PMU S5P_IRQ_VIC1(23) +#define IRQ_PMU S5P_IRQ_VIC1(23) /* S5P6440 */ #define IRQ_HSMMC0 S5P_IRQ_VIC1(24) #define IRQ_HSMMC1 S5P_IRQ_VIC1(25) -#define IRQ_HSMMC2 IRQ_SPI1 /* shared with SPI1 */ #define IRQ_OTG S5P_IRQ_VIC1(26) #define IRQ_DSI S5P_IRQ_VIC1(27) #define IRQ_RTC_ALARM S5P_IRQ_VIC1(28) @@ -63,6 +69,24 @@ #define IRQ_TC IRQ_PENDN #define IRQ_ADC S5P_IRQ_VIC1(31) +/* UART interrupts, S5P6450 has 5 UARTs */ +#define IRQ_S5P_UART_BASE4 (96) +#define IRQ_S5P_UART_BASE5 (100) + +#define IRQ_S5P_UART_RX4 (IRQ_S5P_UART_BASE4 + UART_IRQ_RXD) +#define IRQ_S5P_UART_TX4 (IRQ_S5P_UART_BASE4 + UART_IRQ_TXD) +#define IRQ_S5P_UART_ERR4 (IRQ_S5P_UART_BASE4 + UART_IRQ_ERR) + +#define IRQ_S5P_UART_RX5 (IRQ_S5P_UART_BASE5 + UART_IRQ_RXD) +#define IRQ_S5P_UART_TX5 (IRQ_S5P_UART_BASE5 + UART_IRQ_TXD) +#define IRQ_S5P_UART_ERR5 (IRQ_S5P_UART_BASE5 + UART_IRQ_ERR) + +/* S3C compatibilty defines */ +#define IRQ_S3CUART_RX4 IRQ_S5P_UART_RX4 +#define IRQ_S3CUART_RX5 IRQ_S5P_UART_RX5 + +/* S5P6450 EINT feature will be added */ + /* * Since the IRQ_EINT(x) are a linear mapping on s5p6440 we just defined * them as an IRQ_EINT(x) macro from S5P_IRQ_EINT_BASE which we place @@ -115,4 +139,4 @@ #define NR_IRQS (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1) -#endif /* __ASM_ARCH_S5P_IRQS_H */ +#endif /* __ASM_ARCH_IRQS_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h new file mode 100644 index 000000000000..31e534156e06 --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/map.h @@ -0,0 +1,83 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/map.h + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - Memory map 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_MAP_H +#define __ASM_ARCH_MAP_H __FILE__ + +#include <plat/map-base.h> +#include <plat/map-s5p.h> + +#define S5P64X0_PA_SDRAM (0x20000000) + +#define S5P64X0_PA_CHIPID (0xE0000000) +#define S5P_PA_CHIPID S5P64X0_PA_CHIPID + +#define S5P64X0_PA_SYSCON (0xE0100000) +#define S5P_PA_SYSCON S5P64X0_PA_SYSCON + +#define S5P64X0_PA_GPIO (0xE0308000) + +#define S5P64X0_PA_VIC0 (0xE4000000) +#define S5P64X0_PA_VIC1 (0xE4100000) + +#define S5P64X0_PA_PDMA (0xE9000000) + +#define S5P64X0_PA_TIMER (0xEA000000) +#define S5P_PA_TIMER S5P64X0_PA_TIMER + +#define S5P64X0_PA_RTC (0xEA100000) + +#define S5P64X0_PA_WDT (0xEA200000) + +#define S5P6440_PA_UART(x) (0xEC000000 + ((x) * S3C_UART_OFFSET)) +#define S5P6450_PA_UART(x) ((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000)) + +#define S5P_PA_UART0 S5P6450_PA_UART(0) +#define S5P_PA_UART1 S5P6450_PA_UART(1) +#define S5P_PA_UART2 S5P6450_PA_UART(2) +#define S5P_PA_UART3 S5P6450_PA_UART(3) +#define S5P_PA_UART4 S5P6450_PA_UART(4) +#define S5P_PA_UART5 S5P6450_PA_UART(5) + +#define S5P_SZ_UART SZ_256 + +#define S5P6440_PA_IIC0 (0xEC104000) +#define S5P6440_PA_IIC1 (0xEC20F000) +#define S5P6450_PA_IIC0 (0xEC100000) +#define S5P6450_PA_IIC1 (0xEC200000) + +#define S5P64X0_PA_SPI0 (0xEC400000) +#define S5P64X0_PA_SPI1 (0xEC500000) + +#define S5P64X0_PA_HSOTG (0xED100000) + +#define S5P64X0_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000)) + +#define S5P64X0_PA_I2S (0xF2000000) + +#define S5P64X0_PA_PCM (0xF2100000) + +#define S5P64X0_PA_ADC (0xF3000000) + +/* compatibiltiy defines. */ + +#define S3C_PA_HSMMC0 S5P64X0_PA_HSMMC(0) +#define S3C_PA_HSMMC1 S5P64X0_PA_HSMMC(1) +#define S3C_PA_HSMMC2 S5P64X0_PA_HSMMC(2) +#define S3C_PA_IIC S5P6440_PA_IIC0 +#define S3C_PA_IIC1 S5P6440_PA_IIC1 +#define S3C_PA_RTC S5P64X0_PA_RTC +#define S3C_PA_WDT S5P64X0_PA_WDT + +#define SAMSUNG_PA_ADC S5P64X0_PA_ADC + +#endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/memory.h b/arch/arm/mach-s5p64x0/include/mach/memory.h index d62910c71b56..1b036b0a24ce 100644 --- a/arch/arm/mach-s5p6440/include/mach/memory.h +++ b/arch/arm/mach-s5p64x0/include/mach/memory.h @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/memory.h +/* linux/arch/arm/mach-s5p64x0/include/mach/memory.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - Memory definitions + * 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 @@ -11,9 +11,9 @@ */ #ifndef __ASM_ARCH_MEMORY_H -#define __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H __FILE__ -#define PHYS_OFFSET UL(0x20000000) +#define PHYS_OFFSET UL(0x20000000) #define CONSISTENT_DMA_SIZE SZ_8M #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h b/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h index 6a2a02fdf12a..19fff8b701c0 100644 --- a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h +++ b/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h @@ -1,16 +1,14 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/pwm-clock.h +/* linux/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * 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/ * - * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h - * - * S5P6440 - pwm clock and timer support + * 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 diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h new file mode 100644 index 000000000000..a133f22fa155 --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h @@ -0,0 +1,65 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/regs-clock.h + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - Clock register 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_REGS_CLOCK_H +#define __ASM_ARCH_REGS_CLOCK_H __FILE__ + +#include <mach/map.h> + +#define S5P_CLKREG(x) (S3C_VA_SYS + (x)) + +#define S5P64X0_APLL_CON S5P_CLKREG(0x0C) +#define S5P64X0_MPLL_CON S5P_CLKREG(0x10) +#define S5P64X0_EPLL_CON S5P_CLKREG(0x14) +#define S5P64X0_EPLL_CON_K S5P_CLKREG(0x18) + +#define S5P64X0_CLK_SRC0 S5P_CLKREG(0x1C) + +#define S5P64X0_CLK_DIV0 S5P_CLKREG(0x20) +#define S5P64X0_CLK_DIV1 S5P_CLKREG(0x24) +#define S5P64X0_CLK_DIV2 S5P_CLKREG(0x28) + +#define S5P64X0_CLK_GATE_HCLK0 S5P_CLKREG(0x30) +#define S5P64X0_CLK_GATE_PCLK S5P_CLKREG(0x34) +#define S5P64X0_CLK_GATE_SCLK0 S5P_CLKREG(0x38) +#define S5P64X0_CLK_GATE_MEM0 S5P_CLKREG(0x3C) + +#define S5P64X0_CLK_DIV3 S5P_CLKREG(0x40) + +#define S5P64X0_CLK_GATE_HCLK1 S5P_CLKREG(0x44) +#define S5P64X0_CLK_GATE_SCLK1 S5P_CLKREG(0x48) + +#define S5P6450_DPLL_CON S5P_CLKREG(0x50) +#define S5P6450_DPLL_CON_K S5P_CLKREG(0x54) + +#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_OTHERS S5P_CLKREG(0x900) + +#define S5P64X0_CLKDIV0_HCLK_SHIFT (8) +#define S5P64X0_CLKDIV0_HCLK_MASK (0xF << S5P64X0_CLKDIV0_HCLK_SHIFT) + +#define S5P64X0_OTHERS_USB_SIG_MASK (1 << 16) + +/* Compatibility defines */ + +#define ARM_CLK_DIV S5P64X0_CLK_DIV0 +#define ARM_DIV_RATIO_SHIFT 0 +#define ARM_DIV_MASK (0xF << ARM_DIV_RATIO_SHIFT) + +#define S5P_EPLL_CON S5P64X0_EPLL_CON + +#endif /* __ASM_ARCH_REGS_CLOCK_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/regs-gpio.h b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h index 82ff753913da..85f448e20a8b 100644 --- a/arch/arm/mach-s5p6440/include/mach/regs-gpio.h +++ b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h @@ -1,21 +1,24 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/regs-gpio.h +/* linux/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - GPIO register definitions + * S5P64X0 - GPIO register 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_REGS_GPIO_H #define __ASM_ARCH_REGS_GPIO_H __FILE__ #include <mach/map.h> +/* Will be implemented S5P6442 GPIOlib */ + /* Base addresses for each of the banks */ + #define S5P6440_GPA_BASE (S5P_VA_GPIO + 0x0000) #define S5P6440_GPB_BASE (S5P_VA_GPIO + 0x0020) #define S5P6440_GPC_BASE (S5P_VA_GPIO + 0x0040) @@ -27,6 +30,7 @@ #define S5P6440_GPN_BASE (S5P_VA_GPIO + 0x0830) #define S5P6440_GPP_BASE (S5P_VA_GPIO + 0x0160) #define S5P6440_GPR_BASE (S5P_VA_GPIO + 0x0290) + #define S5P6440_EINT0CON0 (S5P_VA_GPIO + 0x900) #define S5P6440_EINT0FLTCON0 (S5P_VA_GPIO + 0x910) #define S5P6440_EINT0FLTCON1 (S5P_VA_GPIO + 0x914) @@ -34,19 +38,23 @@ #define S5P6440_EINT0PEND (S5P_VA_GPIO + 0x924) /* for LCD */ + #define S5P6440_SPCON_LCD_SEL_RGB (1 << 0) #define S5P6440_SPCON_LCD_SEL_MASK (3 << 0) -/* These set of macros are not really useful for the - * GPF/GPI/GPJ/GPN/GPP, - * useful for others set of GPIO's (4 bit) +/* + * These set of macros are not really useful for the + * GPF/GPI/GPJ/GPN/GPP, useful for others set of GPIO's (4 bit) */ + #define S5P6440_GPIO_CONMASK(__gpio) (0xf << ((__gpio) * 4)) #define S5P6440_GPIO_INPUT(__gpio) (0x0 << ((__gpio) * 4)) #define S5P6440_GPIO_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) -/* Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit) - * */ +/* + * Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit) + */ + #define S5P6440_GPIO2_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) #define S5P6440_GPIO2_INPUT(__gpio) (0x0 << ((__gpio) * 2)) #define S5P6440_GPIO2_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) diff --git a/arch/arm/mach-s5p6440/include/mach/regs-irq.h b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h index a961f4beeb0c..4aaebdace55f 100644 --- a/arch/arm/mach-s5p6440/include/mach/regs-irq.h +++ b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/regs-irq.h +/* linux/arch/arm/mach-s5p64x0/include/mach/regs-irq.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - IRQ register definitions + * S5P64X0 - IRQ register 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 diff --git a/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h b/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h new file mode 100644 index 000000000000..ff85b4b6e8d9 --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h @@ -0,0 +1,46 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Header file for s5p64x0 clock 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_CLOCK_H +#define __ASM_ARCH_CLOCK_H __FILE__ + +#include <linux/clk.h> + +extern struct clksrc_clk clk_mout_apll; +extern struct clksrc_clk clk_mout_mpll; +extern struct clksrc_clk clk_mout_epll; + +extern int s5p64x0_epll_enable(struct clk *clk, int enable); +extern unsigned long s5p64x0_epll_get_rate(struct clk *clk); + +extern unsigned long s5p64x0_armclk_get_rate(struct clk *clk); +extern unsigned long s5p64x0_armclk_round_rate(struct clk *clk, unsigned long rate); +extern int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate); + +extern struct clk_ops s5p64x0_clkarm_ops; + +extern struct clksrc_clk clk_armclk; +extern struct clksrc_clk clk_dout_mpll; + +extern struct clk *clkset_hclk_low_list[]; +extern struct clksrc_sources clkset_hclk_low; + +extern int s5p64x0_pclk_ctrl(struct clk *clk, int enable); +extern int s5p64x0_hclk0_ctrl(struct clk *clk, int enable); +extern int s5p64x0_hclk1_ctrl(struct clk *clk, int enable); +extern int s5p64x0_sclk_ctrl(struct clk *clk, int enable); +extern int s5p64x0_sclk1_ctrl(struct clk *clk, int enable); +extern int s5p64x0_mem_ctrl(struct clk *clk, int enable); + +extern int s5p64x0_clk48m_ctrl(struct clk *clk, int enable); + +#endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h new file mode 100644 index 000000000000..170a20a9643a --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h @@ -0,0 +1,20 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h + * + * 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. +*/ + +#ifndef __ASM_ARCH_SPI_CLKS_H +#define __ASM_ARCH_SPI_CLKS_H __FILE__ + +#define S5P64X0_SPI_SRCCLK_PCLK 0 +#define S5P64X0_SPI_SRCCLK_SCLK 1 + +#endif /* __ASM_ARCH_SPI_CLKS_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/system.h b/arch/arm/mach-s5p64x0/include/mach/system.h index a359ee3fa510..60f57532c970 100644 --- a/arch/arm/mach-s5p6440/include/mach/system.h +++ b/arch/arm/mach-s5p64x0/include/mach/system.h @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/system.h +/* linux/arch/arm/mach-s5p64x0/include/mach/system.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - system support header + * S5P64X0 - system support header * * 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 diff --git a/arch/arm/mach-s5p6440/include/mach/tick.h b/arch/arm/mach-s5p64x0/include/mach/tick.h index 2f25c7f07970..00aa7f1d8e51 100644 --- a/arch/arm/mach-s5p6440/include/mach/tick.h +++ b/arch/arm/mach-s5p64x0/include/mach/tick.h @@ -1,9 +1,14 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/tick.h +/* linux/arch/arm/mach-s5p64x0/include/mach/tick.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - Timer tick support definitions + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S5P64X0 - Timer tick support 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 diff --git a/arch/arm/mach-s5p6440/include/mach/timex.h b/arch/arm/mach-s5p64x0/include/mach/timex.h index fb2e8cd40829..4b91faa195a8 100644 --- a/arch/arm/mach-s5p6440/include/mach/timex.h +++ b/arch/arm/mach-s5p64x0/include/mach/timex.h @@ -1,9 +1,12 @@ -/* arch/arm/mach-s3c64xx/include/mach/timex.h +/* linux/arch/arm/mach-s5p64x0/include/mach/timex.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * Copyright (c) 2003-2005 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * - * S3C6400 - time parameters + * S5P64X0 - time parameters * * 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 diff --git a/arch/arm/mach-s5p64x0/include/mach/uncompress.h b/arch/arm/mach-s5p64x0/include/mach/uncompress.h new file mode 100644 index 000000000000..c65b229aab23 --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/uncompress.h @@ -0,0 +1,212 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/uncompress.h + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - uncompress code + * + * 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_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +#include <mach/map.h> + +/* + * cannot use commonly <plat/uncompress.h> + * because uart base of S5P6440 and S5P6450 is different + */ + +typedef unsigned int upf_t; /* cannot include linux/serial_core.h */ + +/* uart setup */ + +static unsigned int fifo_mask; +static unsigned int fifo_max; + +/* forward declerations */ + +static void arch_detect_cpu(void); + +/* defines for UART registers */ + +#include <plat/regs-serial.h> +#include <plat/regs-watchdog.h> + +/* working in physical space... */ +#undef S3C2410_WDOGREG +#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x))) + +/* how many bytes we allow into the FIFO at a time in FIFO mode */ +#define FIFO_MAX (14) + +static unsigned long uart_base; + +static __inline__ void get_uart_base(void) +{ + unsigned int chipid; + + chipid = *(const volatile unsigned int __force *) 0xE0100118; + + uart_base = S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT; + + if ((chipid & 0xff000) == 0x50000) + uart_base += 0xEC800000; + else + uart_base += 0xEC000000; +} + +static __inline__ void uart_wr(unsigned int reg, unsigned int val) +{ + volatile unsigned int *ptr; + + get_uart_base(); + ptr = (volatile unsigned int *)(reg + uart_base); + *ptr = val; +} + +static __inline__ unsigned int uart_rd(unsigned int reg) +{ + volatile unsigned int *ptr; + + get_uart_base(); + ptr = (volatile unsigned int *)(reg + uart_base); + return *ptr; +} + +/* + * we can deal with the case the UARTs are being run + * in FIFO mode, so that we don't hold up our execution + * waiting for tx to happen... + */ + +static void putc(int ch) +{ + if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) { + int level; + + while (1) { + level = uart_rd(S3C2410_UFSTAT); + level &= fifo_mask; + + if (level < fifo_max) + break; + } + + } else { + /* not using fifos */ + + while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE) + barrier(); + } + + /* write byte to transmission register */ + uart_wr(S3C2410_UTXH, ch); +} + +static inline void flush(void) +{ +} + +#define __raw_writel(d, ad) \ + do { \ + *((volatile unsigned int __force *)(ad)) = (d); \ + } while (0) + +/* + * CONFIG_S3C_BOOT_WATCHDOG + * + * Simple boot-time watchdog setup, to reboot the system if there is + * any problem with the boot process + */ + +#ifdef CONFIG_S3C_BOOT_WATCHDOG + +#define WDOG_COUNT (0xff00) + +static inline void arch_decomp_wdog(void) +{ + __raw_writel(WDOG_COUNT, S3C2410_WTCNT); +} + +static void arch_decomp_wdog_start(void) +{ + __raw_writel(WDOG_COUNT, S3C2410_WTDAT); + __raw_writel(WDOG_COUNT, S3C2410_WTCNT); + __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON); +} + +#else +#define arch_decomp_wdog_start() +#define arch_decomp_wdog() +#endif + +#ifdef CONFIG_S3C_BOOT_ERROR_RESET + +static void arch_decomp_error(const char *x) +{ + putstr("\n\n"); + putstr(x); + putstr("\n\n -- System resetting\n"); + + __raw_writel(0x4000, S3C2410_WTDAT); + __raw_writel(0x4000, S3C2410_WTCNT); + __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON); + + while(1); +} + +#define arch_error arch_decomp_error +#endif + +#ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO +static inline void arch_enable_uart_fifo(void) +{ + u32 fifocon = uart_rd(S3C2410_UFCON); + + if (!(fifocon & S3C2410_UFCON_FIFOMODE)) { + fifocon |= S3C2410_UFCON_RESETBOTH; + uart_wr(S3C2410_UFCON, fifocon); + + /* wait for fifo reset to complete */ + while (1) { + fifocon = uart_rd(S3C2410_UFCON); + if (!(fifocon & S3C2410_UFCON_RESETBOTH)) + break; + } + } +} +#else +#define arch_enable_uart_fifo() do { } while(0) +#endif + +static void arch_decomp_setup(void) +{ + /* + * we may need to setup the uart(s) here if we are not running + * on an BAST... the BAST will have left the uarts configured + * after calling linux. + */ + + arch_detect_cpu(); + arch_decomp_wdog_start(); + + /* + * Enable the UART FIFOs if they where not enabled and our + * configuration says we should turn them on. + */ + + arch_enable_uart_fifo(); +} + + + +static void arch_detect_cpu(void) +{ + /* we do not need to do any cpu detection here at the moment. */ +} + +#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/vmalloc.h b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h index e3f0eebf5205..97a9df38f1cf 100644 --- a/arch/arm/mach-s5p6440/include/mach/vmalloc.h +++ b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h @@ -1,4 +1,7 @@ -/* arch/arm/mach-s5p6440/include/mach/vmalloc.h +/* 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> * diff --git a/arch/arm/mach-s5p64x0/init.c b/arch/arm/mach-s5p64x0/init.c new file mode 100644 index 000000000000..79833caf8165 --- /dev/null +++ b/arch/arm/mach-s5p64x0/init.c @@ -0,0 +1,73 @@ +/* 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-s5p6440/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c index 9202aaac3b56..28de0a57208c 100644 --- a/arch/arm/mach-s5p6440/mach-smdk6440.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -1,7 +1,7 @@ -/* linux/arch/arm/mach-s5p6440/mach-smdk6440.c +/* linux/arch/arm/mach-s5p64x0/mach-smdk6440.c * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * 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 @@ -21,21 +21,22 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/clk.h> +#include <linux/gpio.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> +#include <asm/irq.h> +#include <asm/mach-types.h> #include <mach/hardware.h> #include <mach/map.h> - -#include <asm/irq.h> -#include <asm/mach-types.h> +#include <mach/regs-clock.h> +#include <mach/i2c.h> #include <plat/regs-serial.h> - +#include <plat/gpio-cfg.h> #include <plat/s5p6440.h> #include <plat/clock.h> -#include <mach/regs-clock.h> #include <plat/devs.h> #include <plat/cpu.h> #include <plat/iic.h> @@ -58,43 +59,60 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = { [0] = { - .hwport = 0, - .flags = 0, - .ucon = SMDK6440_UCON_DEFAULT, - .ulcon = SMDK6440_ULCON_DEFAULT, - .ufcon = SMDK6440_UFCON_DEFAULT, + .hwport = 0, + .flags = 0, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, [1] = { - .hwport = 1, - .flags = 0, - .ucon = SMDK6440_UCON_DEFAULT, - .ulcon = SMDK6440_ULCON_DEFAULT, - .ufcon = SMDK6440_UFCON_DEFAULT, + .hwport = 1, + .flags = 0, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, [2] = { - .hwport = 2, - .flags = 0, - .ucon = SMDK6440_UCON_DEFAULT, - .ulcon = SMDK6440_ULCON_DEFAULT, - .ufcon = SMDK6440_UFCON_DEFAULT, + .hwport = 2, + .flags = 0, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, [3] = { - .hwport = 3, - .flags = 0, - .ucon = SMDK6440_UCON_DEFAULT, - .ulcon = SMDK6440_ULCON_DEFAULT, - .ufcon = SMDK6440_UFCON_DEFAULT, + .hwport = 3, + .flags = 0, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, }; static struct platform_device *smdk6440_devices[] __initdata = { - &s5p6440_device_iis, &s3c_device_adc, &s3c_device_rtc, &s3c_device_i2c0, &s3c_device_i2c1, &s3c_device_ts, &s3c_device_wdt, + &s5p6440_device_iis, +}; + +static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = { + .flags = 0, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, + .cfg_gpio = s5p6440_i2c0_cfg_gpio, +}; + +static struct s3c2410_platform_i2c s5p6440_i2c1_data __initdata = { + .flags = 0, + .bus_num = 1, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, + .cfg_gpio = s5p6440_i2c1_cfg_gpio, }; static struct i2c_board_info smdk6440_i2c_devs0[] __initdata = { @@ -113,7 +131,7 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { static void __init smdk6440_map_io(void) { - s5p_init_io(NULL, 0, S5P_SYS_ID); + s5p_init_io(NULL, 0, S5P64X0_SYS_ID); s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs)); } @@ -122,9 +140,8 @@ static void __init smdk6440_machine_init(void) { s3c24xx_ts_set_platdata(&s3c_ts_platform); - /* I2C */ - s3c_i2c0_set_platdata(NULL); - s3c_i2c1_set_platdata(NULL); + s3c_i2c0_set_platdata(&s5p6440_i2c0_data); + s3c_i2c1_set_platdata(&s5p6440_i2c1_data); i2c_register_board_info(0, smdk6440_i2c_devs0, ARRAY_SIZE(smdk6440_i2c_devs0)); i2c_register_board_info(1, smdk6440_i2c_devs1, @@ -135,9 +152,9 @@ static void __init smdk6440_machine_init(void) MACHINE_START(SMDK6440, "SMDK6440") /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ - .phys_io = S3C_PA_UART & 0xfff00000, + .phys_io = S5P6440_PA_UART(0) & 0xfff00000, .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, - .boot_params = S5P_PA_SDRAM + 0x100, + .boot_params = S5P64X0_PA_SDRAM + 0x100, .init_irq = s5p6440_init_irq, .map_io = smdk6440_map_io, diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c new file mode 100644 index 000000000000..8e982171418b --- /dev/null +++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -0,0 +1,182 @@ +/* linux/arch/arm/mach-s5p64x0/mach-smdk6450.c + * + * Copyright (c) 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/delay.h> +#include <linux/init.h> +#include <linux/i2c.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/gpio.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/irq.h> +#include <asm/mach-types.h> + +#include <mach/hardware.h> +#include <mach/map.h> +#include <mach/regs-clock.h> +#include <mach/i2c.h> + +#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> +#include <plat/iic.h> +#include <plat/pll.h> +#include <plat/adc.h> +#include <plat/ts.h> + +#define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ + S3C2410_UCON_RXILEVEL | \ + S3C2410_UCON_TXIRQMODE | \ + S3C2410_UCON_RXIRQMODE | \ + S3C2410_UCON_RXFIFO_TOI | \ + S3C2443_UCON_RXERR_IRQEN) + +#define SMDK6450_ULCON_DEFAULT S3C2410_LCON_CS8 + +#define SMDK6450_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ + S3C2440_UFCON_TXTRIG16 | \ + S3C2410_UFCON_RXTRIG8) + +static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, + [3] = { + .hwport = 3, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, +#if CONFIG_SERIAL_SAMSUNG_UARTS > 4 + [4] = { + .hwport = 4, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, +#endif +#if CONFIG_SERIAL_SAMSUNG_UARTS > 5 + [5] = { + .hwport = 5, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, +#endif +}; + +static struct platform_device *smdk6450_devices[] __initdata = { + &s3c_device_adc, + &s3c_device_rtc, + &s3c_device_i2c0, + &s3c_device_i2c1, + &s3c_device_ts, + &s3c_device_wdt, + &s5p6450_device_iis0, + /* s5p6450_device_spi0 will be added */ +}; + +static struct s3c2410_platform_i2c s5p6450_i2c0_data __initdata = { + .flags = 0, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, + .cfg_gpio = s5p6450_i2c0_cfg_gpio, +}; + +static struct s3c2410_platform_i2c s5p6450_i2c1_data __initdata = { + .flags = 0, + .bus_num = 1, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, + .cfg_gpio = s5p6450_i2c1_cfg_gpio, +}; + +static struct i2c_board_info smdk6450_i2c_devs0[] __initdata = { + { I2C_BOARD_INFO("24c08", 0x50), }, /* Samsung KS24C080C EEPROM */ +}; + +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, +}; + +static void __init smdk6450_map_io(void) +{ + s5p_init_io(NULL, 0, S5P64X0_SYS_ID); + s3c24xx_init_clocks(19200000); + s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs)); +} + +static void __init smdk6450_machine_init(void) +{ + s3c24xx_ts_set_platdata(&s3c_ts_platform); + + s3c_i2c0_set_platdata(&s5p6450_i2c0_data); + s3c_i2c1_set_platdata(&s5p6450_i2c1_data); + i2c_register_board_info(0, smdk6450_i2c_devs0, + ARRAY_SIZE(smdk6450_i2c_devs0)); + i2c_register_board_info(1, smdk6450_i2c_devs1, + ARRAY_SIZE(smdk6450_i2c_devs1)); + + platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices)); +} + +MACHINE_START(SMDK6450, "SMDK6450") + /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ + .phys_io = S5P6450_PA_UART(0) & 0xfff00000, + .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, + .boot_params = S5P64X0_PA_SDRAM + 0x100, + + .init_irq = s5p6450_init_irq, + .map_io = smdk6450_map_io, + .init_machine = smdk6450_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END diff --git a/arch/arm/mach-s5p64x0/setup-i2c0.c b/arch/arm/mach-s5p64x0/setup-i2c0.c new file mode 100644 index 000000000000..46b463917c54 --- /dev/null +++ b/arch/arm/mach-s5p64x0/setup-i2c0.c @@ -0,0 +1,38 @@ +/* linux/arch/arm/mach-s5p64x0/setup-i2c0.c + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * I2C0 GPIO configuration. + * + * Based on plat-s3c64x0/setup-i2c0.c + * + * 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/gpio.h> + +struct platform_device; /* don't need the contents */ + +#include <plat/gpio-cfg.h> +#include <plat/iic.h> + +#include <mach/i2c.h> + +void s5p6440_i2c0_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgall_range(S5P6440_GPB(5), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); +} + +void s5p6450_i2c0_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgall_range(S5P6450_GPB(5), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); +} + +void s3c_i2c0_cfg_gpio(struct platform_device *dev) { } diff --git a/arch/arm/mach-s5p64x0/setup-i2c1.c b/arch/arm/mach-s5p64x0/setup-i2c1.c new file mode 100644 index 000000000000..6ad3b986021c --- /dev/null +++ b/arch/arm/mach-s5p64x0/setup-i2c1.c @@ -0,0 +1,38 @@ +/* linux/arch/arm/mach-s5p64xx/setup-i2c1.c + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * I2C1 GPIO configuration. + * + * Based on plat-s3c64xx/setup-i2c0.c + * + * 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/gpio.h> + +struct platform_device; /* don't need the contents */ + +#include <plat/gpio-cfg.h> +#include <plat/iic.h> + +#include <mach/i2c.h> + +void s5p6440_i2c1_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgall_range(S5P6440_GPR(9), 2, + S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP); +} + +void s5p6450_i2c1_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgall_range(S5P6450_GPR(9), 2, + S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP); +} + +void s3c_i2c1_cfg_gpio(struct platform_device *dev) { } diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig index 77ae4bfb74ba..b8fbf2fcba6f 100644 --- a/arch/arm/mach-s5pc100/Kconfig +++ b/arch/arm/mach-s5pc100/Kconfig @@ -9,7 +9,6 @@ if ARCH_S5PC100 config CPU_S5PC100 bool - select PLAT_S5P select S5P_EXT_INT select S3C_PL330_DMA help diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile index a021ed1fb4b6..eecab57d2e5d 100644 --- a/arch/arm/mach-s5pc100/Makefile +++ b/arch/arm/mach-s5pc100/Makefile @@ -11,7 +11,7 @@ obj- := # Core support for S5PC100 system -obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o irq-gpio.o +obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o obj-$(CONFIG_CPU_S5PC100) += dma.o diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c index 084abd13b0a5..2d4a761a5163 100644 --- a/arch/arm/mach-s5pc100/clock.c +++ b/arch/arm/mach-s5pc100/clock.c @@ -273,24 +273,6 @@ static struct clksrc_clk clk_div_hdmi = { .reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 }, }; -static int s5pc100_epll_enable(struct clk *clk, int enable) -{ - unsigned int ctrlbit = clk->ctrlbit; - unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit; - - if (enable) - __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON); - else - __raw_writel(epll_con, S5P_EPLL_CON); - - return 0; -} - -static unsigned long s5pc100_epll_get_rate(struct clk *clk) -{ - return clk->rate; -} - static u32 epll_div[][4] = { { 32750000, 131, 3, 4 }, { 32768000, 131, 3, 4 }, @@ -341,13 +323,16 @@ static int s5pc100_epll_set_rate(struct clk *clk, unsigned long rate) __raw_writel(epll_con, S5P_EPLL_CON); + printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n", + clk->rate, rate); + clk->rate = rate; return 0; } static struct clk_ops s5pc100_epll_ops = { - .get_rate = s5pc100_epll_get_rate, + .get_rate = s5p_epll_get_rate, .set_rate = s5pc100_epll_set_rate, }; @@ -691,55 +676,55 @@ static struct clk init_clocks_disable[] = { }, { .name = "iis", .id = 0, - .parent = &clk_div_d1_bus.clk, + .parent = &clk_div_pclkd1.clk, .enable = s5pc100_d1_5_ctrl, .ctrlbit = (1 << 0), }, { .name = "iis", .id = 1, - .parent = &clk_div_d1_bus.clk, + .parent = &clk_div_pclkd1.clk, .enable = s5pc100_d1_5_ctrl, .ctrlbit = (1 << 1), }, { .name = "iis", .id = 2, - .parent = &clk_div_d1_bus.clk, + .parent = &clk_div_pclkd1.clk, .enable = s5pc100_d1_5_ctrl, .ctrlbit = (1 << 2), }, { .name = "ac97", .id = -1, - .parent = &clk_div_d1_bus.clk, + .parent = &clk_div_pclkd1.clk, .enable = s5pc100_d1_5_ctrl, .ctrlbit = (1 << 3), }, { .name = "pcm", .id = 0, - .parent = &clk_div_d1_bus.clk, + .parent = &clk_div_pclkd1.clk, .enable = s5pc100_d1_5_ctrl, .ctrlbit = (1 << 4), }, { .name = "pcm", .id = 1, - .parent = &clk_div_d1_bus.clk, + .parent = &clk_div_pclkd1.clk, .enable = s5pc100_d1_5_ctrl, .ctrlbit = (1 << 5), }, { .name = "spdif", .id = -1, - .parent = &clk_div_d1_bus.clk, + .parent = &clk_div_pclkd1.clk, .enable = s5pc100_d1_5_ctrl, .ctrlbit = (1 << 6), }, { .name = "adc", .id = -1, - .parent = &clk_div_d1_bus.clk, + .parent = &clk_div_pclkd1.clk, .enable = s5pc100_d1_5_ctrl, .ctrlbit = (1 << 7), }, { .name = "keypad", .id = -1, - .parent = &clk_div_d1_bus.clk, + .parent = &clk_div_pclkd1.clk, .enable = s5pc100_d1_5_ctrl, .ctrlbit = (1 << 8), }, { @@ -848,6 +833,18 @@ struct clksrc_sources clk_src_group3 = { .nr_sources = ARRAY_SIZE(clk_src_group3_list), }; +static struct clksrc_clk clk_sclk_audio0 = { + .clk = { + .name = "sclk_audio", + .id = 0, + .ctrlbit = (1 << 8), + .enable = s5pc100_sclk1_ctrl, + }, + .sources = &clk_src_group3, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 }, +}; + static struct clk *clk_src_group4_list[] = { [0] = &clk_mout_epll.clk, [1] = &clk_div_mpll.clk, @@ -862,6 +859,18 @@ struct clksrc_sources clk_src_group4 = { .nr_sources = ARRAY_SIZE(clk_src_group4_list), }; +static struct clksrc_clk clk_sclk_audio1 = { + .clk = { + .name = "sclk_audio", + .id = 1, + .ctrlbit = (1 << 9), + .enable = s5pc100_sclk1_ctrl, + }, + .sources = &clk_src_group4, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 }, +}; + static struct clk *clk_src_group5_list[] = { [0] = &clk_mout_epll.clk, [1] = &clk_div_mpll.clk, @@ -875,6 +884,18 @@ struct clksrc_sources clk_src_group5 = { .nr_sources = ARRAY_SIZE(clk_src_group5_list), }; +static struct clksrc_clk clk_sclk_audio2 = { + .clk = { + .name = "sclk_audio", + .id = 2, + .ctrlbit = (1 << 10), + .enable = s5pc100_sclk1_ctrl, + }, + .sources = &clk_src_group5, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 }, +}; + static struct clk *clk_src_group6_list[] = { [0] = &s5p_clk_27m, [1] = &clk_vclk54m, @@ -944,6 +965,64 @@ struct clksrc_sources clk_src_pwi = { .nr_sources = ARRAY_SIZE(clk_src_pwi_list), }; +static struct clk *clk_sclk_spdif_list[] = { + [0] = &clk_sclk_audio0.clk, + [1] = &clk_sclk_audio1.clk, + [2] = &clk_sclk_audio2.clk, +}; + +struct clksrc_sources clk_src_sclk_spdif = { + .sources = clk_sclk_spdif_list, + .nr_sources = ARRAY_SIZE(clk_sclk_spdif_list), +}; + +static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *pclk; + int ret; + + pclk = clk_get_parent(clk); + if (IS_ERR(pclk)) + return -EINVAL; + + ret = pclk->ops->set_rate(pclk, rate); + clk_put(pclk); + + return ret; +} + +static unsigned long s5pc100_spdif_get_rate(struct clk *clk) +{ + struct clk *pclk; + int rate; + + pclk = clk_get_parent(clk); + if (IS_ERR(pclk)) + return -EINVAL; + + rate = pclk->ops->get_rate(clk); + clk_put(pclk); + + return rate; +} + +static struct clk_ops s5pc100_sclk_spdif_ops = { + .set_rate = s5pc100_spdif_set_rate, + .get_rate = s5pc100_spdif_get_rate, +}; + +static struct clksrc_clk clk_sclk_spdif = { + .clk = { + .name = "sclk_spdif", + .id = -1, + .ctrlbit = (1 << 11), + .enable = s5pc100_sclk1_ctrl, + .ops = &s5pc100_sclk_spdif_ops, + }, + .sources = &clk_src_sclk_spdif, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 24, .size = 2 }, +}; + static struct clksrc_clk clksrcs[] = { { .clk = { @@ -1001,39 +1080,6 @@ static struct clksrc_clk clksrcs[] = { .reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 }, }, { .clk = { - .name = "sclk_audio", - .id = 0, - .ctrlbit = (1 << 8), - .enable = s5pc100_sclk1_ctrl, - - }, - .sources = &clk_src_group3, - .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 }, - .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 }, - }, { - .clk = { - .name = "sclk_audio", - .id = 1, - .ctrlbit = (1 << 9), - .enable = s5pc100_sclk1_ctrl, - - }, - .sources = &clk_src_group4, - .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 }, - .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 }, - }, { - .clk = { - .name = "sclk_audio", - .id = 2, - .ctrlbit = (1 << 10), - .enable = s5pc100_sclk1_ctrl, - - }, - .sources = &clk_src_group5, - .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 }, - .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 }, - }, { - .clk = { .name = "sclk_lcd", .id = -1, .ctrlbit = (1 << 0), @@ -1179,6 +1225,10 @@ static struct clksrc_clk *sysclks[] = { &clk_div_pclkd1, &clk_div_cam, &clk_div_hdmi, + &clk_sclk_audio0, + &clk_sclk_audio1, + &clk_sclk_audio2, + &clk_sclk_spdif, }; void __init_or_cpufreq s5pc100_setup_clocks(void) @@ -1196,7 +1246,7 @@ void __init_or_cpufreq s5pc100_setup_clocks(void) unsigned int ptr; /* Set S5PC100 functions for clk_fout_epll */ - clk_fout_epll.enable = s5pc100_epll_enable; + clk_fout_epll.enable = s5p_epll_enable; clk_fout_epll.ops = &s5pc100_epll_ops; printk(KERN_DEBUG "%s: registering clocks\n", __func__); diff --git a/arch/arm/mach-s5pc100/cpu.c b/arch/arm/mach-s5pc100/cpu.c index cd1afbce83e2..fd2708e7d8a9 100644 --- a/arch/arm/mach-s5pc100/cpu.c +++ b/arch/arm/mach-s5pc100/cpu.c @@ -1,5 +1,8 @@ /* linux/arch/arm/mach-s5pc100/cpu.c * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * * Copyright 2009 Samsung Electronics Co. * Byungho Min <bhmin@samsung.com> * @@ -57,11 +60,31 @@ static struct map_desc s5pc100_iodesc[] __initdata = { .length = SZ_16K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S5P_VA_GPIO, + .pfn = __phys_to_pfn(S5PC100_PA_GPIO), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC0, + .pfn = __phys_to_pfn(S5PC100_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC1, + .pfn = __phys_to_pfn(S5PC100_PA_VIC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)VA_VIC2, - .pfn = __phys_to_pfn(S5P_PA_VIC2), + .pfn = __phys_to_pfn(S5PC100_PA_VIC2), .length = SZ_16K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_512K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)S5PC100_VA_OTHERS, .pfn = __phys_to_pfn(S5PC100_PA_OTHERS), .length = SZ_4K, diff --git a/arch/arm/mach-s5pc100/dev-audio.c b/arch/arm/mach-s5pc100/dev-audio.c index a699ed6acc23..564e195ec493 100644 --- a/arch/arm/mach-s5pc100/dev-audio.c +++ b/arch/arm/mach-s5pc100/dev-audio.c @@ -24,19 +24,11 @@ static int s5pc100_cfg_i2s(struct platform_device *pdev) /* configure GPIO for i2s port */ switch (pdev->id) { case 1: - s3c_gpio_cfgpin(S5PC100_GPC(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PC100_GPC(1), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PC100_GPC(2), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PC100_GPC(3), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PC100_GPC(4), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(2)); break; case 2: - s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PC100_GPG3(1), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PC100_GPG3(2), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PC100_GPG3(3), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PC100_GPG3(4), S3C_GPIO_SFN(4)); + s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(4)); break; case -1: /* Dedicated pins */ @@ -144,19 +136,11 @@ static int s5pc100_pcm_cfg_gpio(struct platform_device *pdev) { switch (pdev->id) { case 0: - s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5PC100_GPG3(1), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5PC100_GPG3(2), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5PC100_GPG3(3), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5PC100_GPG3(4), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(5)); break; case 1: - s3c_gpio_cfgpin(S5PC100_GPC(0), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PC100_GPC(1), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PC100_GPC(2), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PC100_GPC(3), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PC100_GPC(4), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(3)); break; default: @@ -231,13 +215,7 @@ struct platform_device s5pc100_device_pcm1 = { static int s5pc100_ac97_cfg_gpio(struct platform_device *pdev) { - s3c_gpio_cfgpin(S5PC100_GPC(0), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PC100_GPC(1), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PC100_GPC(2), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PC100_GPC(3), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PC100_GPC(4), S3C_GPIO_SFN(4)); - - return 0; + return s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(4)); } static struct resource s5pc100_ac97_resource[] = { @@ -285,3 +263,57 @@ struct platform_device s5pc100_device_ac97 = { .coherent_dma_mask = DMA_BIT_MASK(32), }, }; + +/* S/PDIF Controller platform_device */ +static int s5pc100_spdif_cfg_gpd(struct platform_device *pdev) +{ + s3c_gpio_cfgpin_range(S5PC100_GPD(5), 2, S3C_GPIO_SFN(3)); + + return 0; +} + +static int s5pc100_spdif_cfg_gpg3(struct platform_device *pdev) +{ + s3c_gpio_cfgpin_range(S5PC100_GPG3(5), 2, S3C_GPIO_SFN(3)); + + return 0; +} + +static struct resource s5pc100_spdif_resource[] = { + [0] = { + .start = S5PC100_PA_SPDIF, + .end = S5PC100_PA_SPDIF + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_SPDIF, + .end = DMACH_SPDIF, + .flags = IORESOURCE_DMA, + }, +}; + +static struct s3c_audio_pdata s5p_spdif_pdata = { + .cfg_gpio = s5pc100_spdif_cfg_gpd, +}; + +static u64 s5pc100_spdif_dmamask = DMA_BIT_MASK(32); + +struct platform_device s5pc100_device_spdif = { + .name = "samsung-spdif", + .id = -1, + .num_resources = ARRAY_SIZE(s5pc100_spdif_resource), + .resource = s5pc100_spdif_resource, + .dev = { + .platform_data = &s5p_spdif_pdata, + .dma_mask = &s5pc100_spdif_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +void __init s5pc100_spdif_setup_gpio(int gpio) +{ + if (gpio == S5PC100_SPDIF_GPD) + s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpd; + else + s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpg3; +} diff --git a/arch/arm/mach-s5pc100/dev-spi.c b/arch/arm/mach-s5pc100/dev-spi.c index a0ef7c302c16..57b19794d9bb 100644 --- a/arch/arm/mach-s5pc100/dev-spi.c +++ b/arch/arm/mach-s5pc100/dev-spi.c @@ -38,30 +38,20 @@ static int s5pc100_spi_cfg_gpio(struct platform_device *pdev) { switch (pdev->id) { case 0: - s3c_gpio_cfgpin(S5PC100_GPB(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PC100_GPB(1), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PC100_GPB(2), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PC100_GPB(0), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5PC100_GPB(1), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5PC100_GPB(2), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PC100_GPB(0), 3, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); break; case 1: - s3c_gpio_cfgpin(S5PC100_GPB(4), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PC100_GPB(5), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PC100_GPB(6), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PC100_GPB(4), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5PC100_GPB(5), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5PC100_GPB(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PC100_GPB(4), 3, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); break; case 2: s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PC100_GPG3(2), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PC100_GPG3(3), S3C_GPIO_SFN(3)); s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5PC100_GPG3(2), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5PC100_GPG3(3), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PC100_GPB(2), 2, + S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); break; default: diff --git a/arch/arm/mach-s5pc100/gpiolib.c b/arch/arm/mach-s5pc100/gpiolib.c index 0fab7f2cd8bf..20856eb7dd51 100644 --- a/arch/arm/mach-s5pc100/gpiolib.c +++ b/arch/arm/mach-s5pc100/gpiolib.c @@ -1,5 +1,7 @@ -/* - * arch/arm/plat-s5pc100/gpiolib.c +/* linux/arch/arm/mach-s5pc100/gpiolib.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * Copyright 2009 Samsung Electronics Co * Kyungmin Park <kyungmin.park@samsung.com> @@ -61,30 +63,6 @@ * L3 8 4Bit None */ -static int s5pc100_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) -{ - return S3C_IRQ_GPIO(chip->base + offset); -} - -static int s5pc100_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset) -{ - int base; - - base = chip->base - S5PC100_GPH0(0); - if (base == 0) - return IRQ_EINT(offset); - base = chip->base - S5PC100_GPH1(0); - if (base == 0) - return IRQ_EINT(8 + offset); - base = chip->base - S5PC100_GPH2(0); - if (base == 0) - return IRQ_EINT(16 + offset); - base = chip->base - S5PC100_GPH3(0); - if (base == 0) - return IRQ_EINT(24 + offset); - return -EINVAL; -} - static struct s3c_gpio_cfg gpio_cfg = { .set_config = s3c_gpio_setcfg_s3c64xx_4bit, .set_pull = s3c_gpio_setpull_updown, @@ -104,209 +82,150 @@ static struct s3c_gpio_cfg gpio_cfg_noint = { .get_pull = s3c_gpio_getpull_updown, }; +/* + * GPIO bank's base address given the index of the bank in the + * list of all gpio banks. + */ +#define S5PC100_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20)) + +/* + * Following are the gpio banks in S5PC100. + * + * The 'config' member when left to NULL, is initialized to the default + * structure gpio_cfg in the init function below. + * + * The 'base' member is also initialized in the init function below. + * Note: The initialization of 'base' member of s3c_gpio_chip structure + * uses the above macro and depends on the banks being listed in order here. + */ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { { - .base = S5PC100_GPA0_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPA0(0), .ngpio = S5PC100_GPIO_A0_NR, .label = "GPA0", }, }, { - .base = S5PC100_GPA1_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPA1(0), .ngpio = S5PC100_GPIO_A1_NR, .label = "GPA1", }, }, { - .base = S5PC100_GPB_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPB(0), .ngpio = S5PC100_GPIO_B_NR, .label = "GPB", }, }, { - .base = S5PC100_GPC_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPC(0), .ngpio = S5PC100_GPIO_C_NR, .label = "GPC", }, }, { - .base = S5PC100_GPD_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPD(0), .ngpio = S5PC100_GPIO_D_NR, .label = "GPD", }, }, { - .base = S5PC100_GPE0_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPE0(0), .ngpio = S5PC100_GPIO_E0_NR, .label = "GPE0", }, }, { - .base = S5PC100_GPE1_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPE1(0), .ngpio = S5PC100_GPIO_E1_NR, .label = "GPE1", }, }, { - .base = S5PC100_GPF0_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPF0(0), .ngpio = S5PC100_GPIO_F0_NR, .label = "GPF0", }, }, { - .base = S5PC100_GPF1_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPF1(0), .ngpio = S5PC100_GPIO_F1_NR, .label = "GPF1", }, }, { - .base = S5PC100_GPF2_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPF2(0), .ngpio = S5PC100_GPIO_F2_NR, .label = "GPF2", }, }, { - .base = S5PC100_GPF3_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPF3(0), .ngpio = S5PC100_GPIO_F3_NR, .label = "GPF3", }, }, { - .base = S5PC100_GPG0_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPG0(0), .ngpio = S5PC100_GPIO_G0_NR, .label = "GPG0", }, }, { - .base = S5PC100_GPG1_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPG1(0), .ngpio = S5PC100_GPIO_G1_NR, .label = "GPG1", }, }, { - .base = S5PC100_GPG2_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPG2(0), .ngpio = S5PC100_GPIO_G2_NR, .label = "GPG2", }, }, { - .base = S5PC100_GPG3_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPG3(0), .ngpio = S5PC100_GPIO_G3_NR, .label = "GPG3", }, }, { - .base = S5PC100_GPH0_BASE, - .config = &gpio_cfg_eint, - .chip = { - .base = S5PC100_GPH0(0), - .ngpio = S5PC100_GPIO_H0_NR, - .label = "GPH0", - }, - }, { - .base = S5PC100_GPH1_BASE, - .config = &gpio_cfg_eint, - .chip = { - .base = S5PC100_GPH1(0), - .ngpio = S5PC100_GPIO_H1_NR, - .label = "GPH1", - }, - }, { - .base = S5PC100_GPH2_BASE, - .config = &gpio_cfg_eint, - .chip = { - .base = S5PC100_GPH2(0), - .ngpio = S5PC100_GPIO_H2_NR, - .label = "GPH2", - }, - }, { - .base = S5PC100_GPH3_BASE, - .config = &gpio_cfg_eint, - .chip = { - .base = S5PC100_GPH3(0), - .ngpio = S5PC100_GPIO_H3_NR, - .label = "GPH3", - }, - }, { - .base = S5PC100_GPI_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPI(0), .ngpio = S5PC100_GPIO_I_NR, .label = "GPI", }, }, { - .base = S5PC100_GPJ0_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPJ0(0), .ngpio = S5PC100_GPIO_J0_NR, .label = "GPJ0", }, }, { - .base = S5PC100_GPJ1_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPJ1(0), .ngpio = S5PC100_GPIO_J1_NR, .label = "GPJ1", }, }, { - .base = S5PC100_GPJ2_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPJ2(0), .ngpio = S5PC100_GPIO_J2_NR, .label = "GPJ2", }, }, { - .base = S5PC100_GPJ3_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPJ3(0), .ngpio = S5PC100_GPIO_J3_NR, .label = "GPJ3", }, }, { - .base = S5PC100_GPJ4_BASE, - .config = &gpio_cfg, .chip = { .base = S5PC100_GPJ4(0), .ngpio = S5PC100_GPIO_J4_NR, .label = "GPJ4", }, }, { - .base = S5PC100_GPK0_BASE, .config = &gpio_cfg_noint, .chip = { .base = S5PC100_GPK0(0), @@ -314,7 +233,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { .label = "GPK0", }, }, { - .base = S5PC100_GPK1_BASE, .config = &gpio_cfg_noint, .chip = { .base = S5PC100_GPK1(0), @@ -322,7 +240,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { .label = "GPK1", }, }, { - .base = S5PC100_GPK2_BASE, .config = &gpio_cfg_noint, .chip = { .base = S5PC100_GPK2(0), @@ -330,7 +247,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { .label = "GPK2", }, }, { - .base = S5PC100_GPK3_BASE, .config = &gpio_cfg_noint, .chip = { .base = S5PC100_GPK3(0), @@ -338,7 +254,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { .label = "GPK3", }, }, { - .base = S5PC100_GPL0_BASE, .config = &gpio_cfg_noint, .chip = { .base = S5PC100_GPL0(0), @@ -346,7 +261,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { .label = "GPL0", }, }, { - .base = S5PC100_GPL1_BASE, .config = &gpio_cfg_noint, .chip = { .base = S5PC100_GPL1(0), @@ -354,7 +268,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { .label = "GPL1", }, }, { - .base = S5PC100_GPL2_BASE, .config = &gpio_cfg_noint, .chip = { .base = S5PC100_GPL2(0), @@ -362,7 +275,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { .label = "GPL2", }, }, { - .base = S5PC100_GPL3_BASE, .config = &gpio_cfg_noint, .chip = { .base = S5PC100_GPL3(0), @@ -370,56 +282,72 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { .label = "GPL3", }, }, { - .base = S5PC100_GPL4_BASE, .config = &gpio_cfg_noint, .chip = { .base = S5PC100_GPL4(0), .ngpio = S5PC100_GPIO_L4_NR, .label = "GPL4", }, + }, { + .base = (S5P_VA_GPIO + 0xC00), + .config = &gpio_cfg_eint, + .irq_base = IRQ_EINT(0), + .chip = { + .base = S5PC100_GPH0(0), + .ngpio = S5PC100_GPIO_H0_NR, + .label = "GPH0", + .to_irq = samsung_gpiolib_to_irq, + }, + }, { + .base = (S5P_VA_GPIO + 0xC20), + .config = &gpio_cfg_eint, + .irq_base = IRQ_EINT(8), + .chip = { + .base = S5PC100_GPH1(0), + .ngpio = S5PC100_GPIO_H1_NR, + .label = "GPH1", + .to_irq = samsung_gpiolib_to_irq, + }, + }, { + .base = (S5P_VA_GPIO + 0xC40), + .config = &gpio_cfg_eint, + .irq_base = IRQ_EINT(16), + .chip = { + .base = S5PC100_GPH2(0), + .ngpio = S5PC100_GPIO_H2_NR, + .label = "GPH2", + .to_irq = samsung_gpiolib_to_irq, + }, + }, { + .base = (S5P_VA_GPIO + 0xC60), + .config = &gpio_cfg_eint, + .irq_base = IRQ_EINT(24), + .chip = { + .base = S5PC100_GPH3(0), + .ngpio = S5PC100_GPIO_H3_NR, + .label = "GPH3", + .to_irq = samsung_gpiolib_to_irq, + }, }, }; -/* FIXME move from irq-gpio.c */ -extern struct irq_chip s5pc100_gpioint; -extern void s5pc100_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc); - -static __init void s5pc100_gpiolib_link(struct s3c_gpio_chip *chip) +static __init int s5pc100_gpiolib_init(void) { - /* Interrupt */ - if (chip->config == &gpio_cfg) { - int i, irq; - - chip->chip.to_irq = s5pc100_gpiolib_to_irq; + struct s3c_gpio_chip *chip = s5pc100_gpio_chips; + int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips); + int gpioint_group = 0; + int i; - for (i = 0; i < chip->chip.ngpio; i++) { - irq = S3C_IRQ_GPIO_BASE + chip->chip.base + i; - set_irq_chip(irq, &s5pc100_gpioint); - set_irq_data(irq, &chip->chip); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, IRQF_VALID); + for (i = 0; i < nr_chips; i++, chip++) { + if (chip->config == NULL) { + chip->config = &gpio_cfg; + chip->group = gpioint_group++; } - } else if (chip->config == &gpio_cfg_eint) { - chip->chip.to_irq = s5pc100_gpiolib_to_eint; + if (chip->base == NULL) + chip->base = S5PC100_BANK_BASE(i); } -} - -static __init int s5pc100_gpiolib_init(void) -{ - struct s3c_gpio_chip *chip; - int nr_chips; - - chip = s5pc100_gpio_chips; - nr_chips = ARRAY_SIZE(s5pc100_gpio_chips); - - for (; nr_chips > 0; nr_chips--, chip++) - s5pc100_gpiolib_link(chip); - - samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, - ARRAY_SIZE(s5pc100_gpio_chips)); - /* Interrupt */ - set_irq_chained_handler(IRQ_GPIOINT, s5pc100_irq_gpioint_handler); + samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips); return 0; } diff --git a/arch/arm/mach-s5pc100/include/mach/gpio.h b/arch/arm/mach-s5pc100/include/mach/gpio.h index 71ae1f52df1d..29a8a12d9b4f 100644 --- a/arch/arm/mach-s5pc100/include/mach/gpio.h +++ b/arch/arm/mach-s5pc100/include/mach/gpio.h @@ -146,13 +146,6 @@ enum s5p_gpio_number { /* define the number of gpios we need to the one after the MP04() range */ #define ARCH_NR_GPIOS (S5PC100_GPIO_END + 1) -#define EINT_MODE S3C_GPIO_SFN(0x2) - -#define EINT_GPIO_0(x) S5PC100_GPH0(x) -#define EINT_GPIO_1(x) S5PC100_GPH1(x) -#define EINT_GPIO_2(x) S5PC100_GPH2(x) -#define EINT_GPIO_3(x) S5PC100_GPH3(x) - #include <asm-generic/gpio.h> #endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h index 06513e647242..d2eb4757381f 100644 --- a/arch/arm/mach-s5pc100/include/mach/irqs.h +++ b/arch/arm/mach-s5pc100/include/mach/irqs.h @@ -48,8 +48,8 @@ #define IRQ_SPI1 S5P_IRQ_VIC1(16) #define IRQ_SPI2 S5P_IRQ_VIC1(17) #define IRQ_IRDA S5P_IRQ_VIC1(18) -#define IRQ_CAN0 S5P_IRQ_VIC1(19) -#define IRQ_CAN1 S5P_IRQ_VIC1(20) +#define IRQ_IIC2 S5P_IRQ_VIC1(19) +#define IRQ_IIC3 S5P_IRQ_VIC1(20) #define IRQ_HSIRX S5P_IRQ_VIC1(21) #define IRQ_HSITX S5P_IRQ_VIC1(22) #define IRQ_UHOST S5P_IRQ_VIC1(23) @@ -100,11 +100,12 @@ #define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) #define S5P_EINT_BASE2 (IRQ_VIC_END + 1) -#define S3C_IRQ_GPIO_BASE (IRQ_EINT(31) + 1) -#define S3C_IRQ_GPIO(x) (S3C_IRQ_GPIO_BASE + (x)) +/* GPIO interrupt */ +#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1) +#define S5P_GPIOINT_GROUP_MAXNR 21 -/* Until MP04 Groups -> 40 (exactly 39) Groups * 8 ~= 320 GPIOs */ -#define NR_IRQS (S3C_IRQ_GPIO(320) + 1) +/* Set the default NR_IRQS */ +#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1) /* Compatibility */ #define IRQ_LCD_FIFO IRQ_LCD0 diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h index 01b9134feff0..32e9cab5c864 100644 --- a/arch/arm/mach-s5pc100/include/mach/map.h +++ b/arch/arm/mach-s5pc100/include/mach/map.h @@ -44,19 +44,16 @@ #define S5PC100_PA_OTHERS (0xE0200000) #define S5PC100_VA_OTHERS (S3C_VA_SYS + 0x10000) -#define S5P_PA_GPIO (0xE0300000) +#define S5PC100_PA_GPIO (0xE0300000) #define S5PC1XX_VA_GPIO S3C_ADDR(0x00500000) /* Interrupt */ -#define S5PC100_PA_VIC (0xE4000000) +#define S5PC100_PA_VIC0 (0xE4000000) +#define S5PC100_PA_VIC1 (0xE4100000) +#define S5PC100_PA_VIC2 (0xE4200000) #define S5PC100_VA_VIC S3C_VA_IRQ -#define S5PC100_PA_VIC_OFFSET 0x100000 #define S5PC100_VA_VIC_OFFSET 0x10000 -#define S5PC1XX_PA_VIC(x) (S5PC100_PA_VIC + ((x) * S5PC100_PA_VIC_OFFSET)) #define S5PC1XX_VA_VIC(x) (S5PC100_VA_VIC + ((x) * S5PC100_VA_VIC_OFFSET)) -#define S5P_PA_VIC0 S5PC1XX_PA_VIC(0) -#define S5P_PA_VIC1 S5PC1XX_PA_VIC(1) -#define S5P_PA_VIC2 S5PC1XX_PA_VIC(2) #define S5PC100_PA_ONENAND (0xE7100000) @@ -113,6 +110,8 @@ #define S5PC100_PA_PCM0 0xF2400000 #define S5PC100_PA_PCM1 0xF2500000 +#define S5PC100_PA_SPDIF 0xF2600000 + #define S5PC100_PA_TSADC (0xF3000000) /* KEYPAD */ diff --git a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h index dd6295e1251d..0bf73209ec7b 100644 --- a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h +++ b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h @@ -11,43 +11,6 @@ #include <mach/map.h> -/* S5PC100 */ -#define S5PC100_GPIO_BASE S5P_VA_GPIO -#define S5PC100_GPA0_BASE (S5PC100_GPIO_BASE + 0x0000) -#define S5PC100_GPA1_BASE (S5PC100_GPIO_BASE + 0x0020) -#define S5PC100_GPB_BASE (S5PC100_GPIO_BASE + 0x0040) -#define S5PC100_GPC_BASE (S5PC100_GPIO_BASE + 0x0060) -#define S5PC100_GPD_BASE (S5PC100_GPIO_BASE + 0x0080) -#define S5PC100_GPE0_BASE (S5PC100_GPIO_BASE + 0x00A0) -#define S5PC100_GPE1_BASE (S5PC100_GPIO_BASE + 0x00C0) -#define S5PC100_GPF0_BASE (S5PC100_GPIO_BASE + 0x00E0) -#define S5PC100_GPF1_BASE (S5PC100_GPIO_BASE + 0x0100) -#define S5PC100_GPF2_BASE (S5PC100_GPIO_BASE + 0x0120) -#define S5PC100_GPF3_BASE (S5PC100_GPIO_BASE + 0x0140) -#define S5PC100_GPG0_BASE (S5PC100_GPIO_BASE + 0x0160) -#define S5PC100_GPG1_BASE (S5PC100_GPIO_BASE + 0x0180) -#define S5PC100_GPG2_BASE (S5PC100_GPIO_BASE + 0x01A0) -#define S5PC100_GPG3_BASE (S5PC100_GPIO_BASE + 0x01C0) -#define S5PC100_GPH0_BASE (S5PC100_GPIO_BASE + 0x0C00) -#define S5PC100_GPH1_BASE (S5PC100_GPIO_BASE + 0x0C20) -#define S5PC100_GPH2_BASE (S5PC100_GPIO_BASE + 0x0C40) -#define S5PC100_GPH3_BASE (S5PC100_GPIO_BASE + 0x0C60) -#define S5PC100_GPI_BASE (S5PC100_GPIO_BASE + 0x01E0) -#define S5PC100_GPJ0_BASE (S5PC100_GPIO_BASE + 0x0200) -#define S5PC100_GPJ1_BASE (S5PC100_GPIO_BASE + 0x0220) -#define S5PC100_GPJ2_BASE (S5PC100_GPIO_BASE + 0x0240) -#define S5PC100_GPJ3_BASE (S5PC100_GPIO_BASE + 0x0260) -#define S5PC100_GPJ4_BASE (S5PC100_GPIO_BASE + 0x0280) -#define S5PC100_GPK0_BASE (S5PC100_GPIO_BASE + 0x02A0) -#define S5PC100_GPK1_BASE (S5PC100_GPIO_BASE + 0x02C0) -#define S5PC100_GPK2_BASE (S5PC100_GPIO_BASE + 0x02E0) -#define S5PC100_GPK3_BASE (S5PC100_GPIO_BASE + 0x0300) -#define S5PC100_GPL0_BASE (S5PC100_GPIO_BASE + 0x0320) -#define S5PC100_GPL1_BASE (S5PC100_GPIO_BASE + 0x0340) -#define S5PC100_GPL2_BASE (S5PC100_GPIO_BASE + 0x0360) -#define S5PC100_GPL3_BASE (S5PC100_GPIO_BASE + 0x0380) -#define S5PC100_GPL4_BASE (S5PC100_GPIO_BASE + 0x03A0) - #define S5PC100EINT30CON (S5P_VA_GPIO + 0xE00) #define S5P_EINT_CON(x) (S5PC100EINT30CON + ((x) * 0x4)) @@ -64,12 +27,12 @@ #define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7)) -/* values for S5P_EXTINT0 */ -#define S5P_EXTINT_LOWLEV (0x00) -#define S5P_EXTINT_HILEV (0x01) -#define S5P_EXTINT_FALLEDGE (0x02) -#define S5P_EXTINT_RISEEDGE (0x03) -#define S5P_EXTINT_BOTHEDGE (0x04) +#define EINT_MODE S3C_GPIO_SFN(0x2) + +#define EINT_GPIO_0(x) S5PC100_GPH0(x) +#define EINT_GPIO_1(x) S5PC100_GPH1(x) +#define EINT_GPIO_2(x) S5PC100_GPH2(x) +#define EINT_GPIO_3(x) S5PC100_GPH3(x) #endif /* __ASM_MACH_S5PC100_REGS_GPIO_H */ diff --git a/arch/arm/mach-s5pc100/irq-gpio.c b/arch/arm/mach-s5pc100/irq-gpio.c deleted file mode 100644 index 2bf86c18bc73..000000000000 --- a/arch/arm/mach-s5pc100/irq-gpio.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * arch/arm/mach-s5pc100/irq-gpio.c - * - * Copyright (C) 2009 Samsung Electronics - * - * S5PC100 - Interrupt handling for IRQ_GPIO${group}(x) - * - * 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/interrupt.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/gpio.h> - -#include <mach/map.h> -#include <plat/gpio-cfg.h> - -#define S5P_GPIOREG(x) (S5P_VA_GPIO + (x)) - -#define CON_OFFSET 0x700 -#define MASK_OFFSET 0x900 -#define PEND_OFFSET 0xA00 -#define CON_OFFSET_2 0xE00 -#define MASK_OFFSET_2 0xF00 -#define PEND_OFFSET_2 0xF40 - -#define GPIOINT_LEVEL_LOW 0x0 -#define GPIOINT_LEVEL_HIGH 0x1 -#define GPIOINT_EDGE_FALLING 0x2 -#define GPIOINT_EDGE_RISING 0x3 -#define GPIOINT_EDGE_BOTH 0x4 - -static int group_to_con_offset(int group) -{ - return group << 2; -} - -static int group_to_mask_offset(int group) -{ - return group << 2; -} - -static int group_to_pend_offset(int group) -{ - return group << 2; -} - -static int s5pc100_get_start(unsigned int group) -{ - switch (group) { - case 0: return S5PC100_GPIO_A0_START; - case 1: return S5PC100_GPIO_A1_START; - case 2: return S5PC100_GPIO_B_START; - case 3: return S5PC100_GPIO_C_START; - case 4: return S5PC100_GPIO_D_START; - case 5: return S5PC100_GPIO_E0_START; - case 6: return S5PC100_GPIO_E1_START; - case 7: return S5PC100_GPIO_F0_START; - case 8: return S5PC100_GPIO_F1_START; - case 9: return S5PC100_GPIO_F2_START; - case 10: return S5PC100_GPIO_F3_START; - case 11: return S5PC100_GPIO_G0_START; - case 12: return S5PC100_GPIO_G1_START; - case 13: return S5PC100_GPIO_G2_START; - case 14: return S5PC100_GPIO_G3_START; - case 15: return S5PC100_GPIO_I_START; - case 16: return S5PC100_GPIO_J0_START; - case 17: return S5PC100_GPIO_J1_START; - case 18: return S5PC100_GPIO_J2_START; - case 19: return S5PC100_GPIO_J3_START; - case 20: return S5PC100_GPIO_J4_START; - default: - BUG(); - } - - return -EINVAL; -} - -static int s5pc100_get_group(unsigned int irq) -{ - irq -= S3C_IRQ_GPIO(0); - - switch (irq) { - case S5PC100_GPIO_A0_START ... S5PC100_GPIO_A1_START - 1: - return 0; - case S5PC100_GPIO_A1_START ... S5PC100_GPIO_B_START - 1: - return 1; - case S5PC100_GPIO_B_START ... S5PC100_GPIO_C_START - 1: - return 2; - case S5PC100_GPIO_C_START ... S5PC100_GPIO_D_START - 1: - return 3; - case S5PC100_GPIO_D_START ... S5PC100_GPIO_E0_START - 1: - return 4; - case S5PC100_GPIO_E0_START ... S5PC100_GPIO_E1_START - 1: - return 5; - case S5PC100_GPIO_E1_START ... S5PC100_GPIO_F0_START - 1: - return 6; - case S5PC100_GPIO_F0_START ... S5PC100_GPIO_F1_START - 1: - return 7; - case S5PC100_GPIO_F1_START ... S5PC100_GPIO_F2_START - 1: - return 8; - case S5PC100_GPIO_F2_START ... S5PC100_GPIO_F3_START - 1: - return 9; - case S5PC100_GPIO_F3_START ... S5PC100_GPIO_G0_START - 1: - return 10; - case S5PC100_GPIO_G0_START ... S5PC100_GPIO_G1_START - 1: - return 11; - case S5PC100_GPIO_G1_START ... S5PC100_GPIO_G2_START - 1: - return 12; - case S5PC100_GPIO_G2_START ... S5PC100_GPIO_G3_START - 1: - return 13; - case S5PC100_GPIO_G3_START ... S5PC100_GPIO_H0_START - 1: - return 14; - case S5PC100_GPIO_I_START ... S5PC100_GPIO_J0_START - 1: - return 15; - case S5PC100_GPIO_J0_START ... S5PC100_GPIO_J1_START - 1: - return 16; - case S5PC100_GPIO_J1_START ... S5PC100_GPIO_J2_START - 1: - return 17; - case S5PC100_GPIO_J2_START ... S5PC100_GPIO_J3_START - 1: - return 18; - case S5PC100_GPIO_J3_START ... S5PC100_GPIO_J4_START - 1: - return 19; - case S5PC100_GPIO_J4_START ... S5PC100_GPIO_K0_START - 1: - return 20; - default: - BUG(); - } - - return -EINVAL; -} - -static int s5pc100_get_offset(unsigned int irq) -{ - struct gpio_chip *chip = get_irq_data(irq); - return irq - S3C_IRQ_GPIO(chip->base); -} - -static void s5pc100_gpioint_ack(unsigned int irq) -{ - int group, offset, pend_offset; - unsigned int value; - - group = s5pc100_get_group(irq); - offset = s5pc100_get_offset(irq); - pend_offset = group_to_pend_offset(group); - - value = __raw_readl(S5P_GPIOREG(PEND_OFFSET) + pend_offset); - value |= 1 << offset; - __raw_writel(value, S5P_GPIOREG(PEND_OFFSET) + pend_offset); -} - -static void s5pc100_gpioint_mask(unsigned int irq) -{ - int group, offset, mask_offset; - unsigned int value; - - group = s5pc100_get_group(irq); - offset = s5pc100_get_offset(irq); - mask_offset = group_to_mask_offset(group); - - value = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset); - value |= 1 << offset; - __raw_writel(value, S5P_GPIOREG(MASK_OFFSET) + mask_offset); -} - -static void s5pc100_gpioint_unmask(unsigned int irq) -{ - int group, offset, mask_offset; - unsigned int value; - - group = s5pc100_get_group(irq); - offset = s5pc100_get_offset(irq); - mask_offset = group_to_mask_offset(group); - - value = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset); - value &= ~(1 << offset); - __raw_writel(value, S5P_GPIOREG(MASK_OFFSET) + mask_offset); -} - -static void s5pc100_gpioint_mask_ack(unsigned int irq) -{ - s5pc100_gpioint_mask(irq); - s5pc100_gpioint_ack(irq); -} - -static int s5pc100_gpioint_set_type(unsigned int irq, unsigned int type) -{ - int group, offset, con_offset; - unsigned int value; - - group = s5pc100_get_group(irq); - offset = s5pc100_get_offset(irq); - con_offset = group_to_con_offset(group); - - switch (type) { - case IRQ_TYPE_NONE: - printk(KERN_WARNING "No irq type\n"); - return -EINVAL; - case IRQ_TYPE_EDGE_RISING: - type = GPIOINT_EDGE_RISING; - break; - case IRQ_TYPE_EDGE_FALLING: - type = GPIOINT_EDGE_FALLING; - break; - case IRQ_TYPE_EDGE_BOTH: - type = GPIOINT_EDGE_BOTH; - break; - case IRQ_TYPE_LEVEL_HIGH: - type = GPIOINT_LEVEL_HIGH; - break; - case IRQ_TYPE_LEVEL_LOW: - type = GPIOINT_LEVEL_LOW; - break; - default: - BUG(); - } - - - value = __raw_readl(S5P_GPIOREG(CON_OFFSET) + con_offset); - value &= ~(0xf << (offset * 0x4)); - value |= (type << (offset * 0x4)); - __raw_writel(value, S5P_GPIOREG(CON_OFFSET) + con_offset); - - return 0; -} - -struct irq_chip s5pc100_gpioint = { - .name = "GPIO", - .ack = s5pc100_gpioint_ack, - .mask = s5pc100_gpioint_mask, - .mask_ack = s5pc100_gpioint_mask_ack, - .unmask = s5pc100_gpioint_unmask, - .set_type = s5pc100_gpioint_set_type, -}; - -void s5pc100_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc) -{ - int group, offset, pend_offset, mask_offset; - int real_irq, group_end; - unsigned int pend, mask; - - group_end = 21; - - for (group = 0; group < group_end; group++) { - pend_offset = group_to_pend_offset(group); - pend = __raw_readl(S5P_GPIOREG(PEND_OFFSET) + pend_offset); - if (!pend) - continue; - - mask_offset = group_to_mask_offset(group); - mask = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset); - pend &= ~mask; - - for (offset = 0; offset < 8; offset++) { - if (pend & (1 << offset)) { - real_irq = s5pc100_get_start(group) + offset; - generic_handle_irq(S3C_IRQ_GPIO(real_irq)); - } - } - } -} diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c index 020c3f98f81f..994a1e152732 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -47,6 +47,7 @@ #include <plat/adc.h> #include <plat/keypad.h> #include <plat/ts.h> +#include <plat/audio.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ #define SMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ @@ -196,6 +197,7 @@ static struct platform_device *smdkc100_devices[] __initdata = { &s5p_device_fimc0, &s5p_device_fimc1, &s5p_device_fimc2, + &s5pc100_device_spdif, }; static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { @@ -226,6 +228,8 @@ static void __init smdkc100_machine_init(void) samsung_keypad_set_platdata(&smdkc100_keypad_data); + s5pc100_spdif_setup_gpio(S5PC100_SPDIF_GPD); + /* LCD init */ gpio_request(S5PC100_GPD(0), "GPD"); gpio_request(S5PC100_GPH0(6), "GPH0"); diff --git a/arch/arm/mach-s5pc100/setup-fb-24bpp.c b/arch/arm/mach-s5pc100/setup-fb-24bpp.c index 6eba6cb8e2f4..d31c0f3fe222 100644 --- a/arch/arm/mach-s5pc100/setup-fb-24bpp.c +++ b/arch/arm/mach-s5pc100/setup-fb-24bpp.c @@ -22,27 +22,15 @@ #define DISR_OFFSET 0x7008 -void s5pc100_fb_gpio_setup_24bpp(void) +static void s5pc100_fb_setgpios(unsigned int base, unsigned int nr) { - unsigned int gpio = 0; - - for (gpio = S5PC100_GPF0(0); gpio <= S5PC100_GPF0(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } - - for (gpio = S5PC100_GPF1(0); gpio <= S5PC100_GPF1(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } - - for (gpio = S5PC100_GPF2(0); gpio <= S5PC100_GPF2(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2)); +} - for (gpio = S5PC100_GPF3(0); gpio <= S5PC100_GPF3(3); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } +void s5pc100_fb_gpio_setup_24bpp(void) +{ + s5pc100_fb_setgpios(S5PC100_GPF0(0), 8); + s5pc100_fb_setgpios(S5PC100_GPF1(0), 8); + s5pc100_fb_setgpios(S5PC100_GPF2(0), 8); + s5pc100_fb_setgpios(S5PC100_GPF3(0), 4); } diff --git a/arch/arm/mach-s5pc100/setup-i2c0.c b/arch/arm/mach-s5pc100/setup-i2c0.c index dd3174e6ecc5..eaef7a3bda49 100644 --- a/arch/arm/mach-s5pc100/setup-i2c0.c +++ b/arch/arm/mach-s5pc100/setup-i2c0.c @@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */ void s3c_i2c0_cfg_gpio(struct platform_device *dev) { - s3c_gpio_cfgpin(S5PC100_GPD(3), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PC100_GPD(3), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5PC100_GPD(4), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PC100_GPD(4), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PC100_GPD(3), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); } diff --git a/arch/arm/mach-s5pc100/setup-i2c1.c b/arch/arm/mach-s5pc100/setup-i2c1.c index d1fec26b69ee..aaff74a90dee 100644 --- a/arch/arm/mach-s5pc100/setup-i2c1.c +++ b/arch/arm/mach-s5pc100/setup-i2c1.c @@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */ void s3c_i2c1_cfg_gpio(struct platform_device *dev) { - s3c_gpio_cfgpin(S5PC100_GPD(5), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PC100_GPD(5), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5PC100_GPD(6), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PC100_GPD(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PC100_GPD(5), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); } diff --git a/arch/arm/mach-s5pc100/setup-ide.c b/arch/arm/mach-s5pc100/setup-ide.c index 83575671fb59..223aae044466 100644 --- a/arch/arm/mach-s5pc100/setup-ide.c +++ b/arch/arm/mach-s5pc100/setup-ide.c @@ -17,52 +17,39 @@ #include <mach/regs-clock.h> #include <plat/gpio-cfg.h> +static void s5pc100_ide_cfg_gpios(unsigned int base, unsigned int nr) +{ + s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4)); + + for (; nr > 0; nr--, base++) + s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4); +} + void s5pc100_ide_setup_gpio(void) { u32 reg; - u32 gpio = 0; /* Independent CF interface, CF chip select configuration */ reg = readl(S5PC100_MEM_SYS_CFG) & (~0x3f); writel(reg | MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S5PC100_MEM_SYS_CFG); /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */ - for (gpio = S5PC100_GPJ0(0); gpio <= S5PC100_GPJ0(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } + s5pc100_ide_cfg_gpios(S5PC100_GPJ0(0), 8); /*CF_Data[0 - 7] */ - for (gpio = S5PC100_GPJ2(0); gpio <= S5PC100_GPJ2(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } + s5pc100_ide_cfg_gpios(S5PC100_GPJ2(0), 8); /* CF_Data[8 - 15] */ - for (gpio = S5PC100_GPJ3(0); gpio <= S5PC100_GPJ3(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } + s5pc100_ide_cfg_gpios(S5PC100_GPJ3(0), 8); /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */ - for (gpio = S5PC100_GPJ4(0); gpio <= S5PC100_GPJ4(3); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } + s5pc100_ide_cfg_gpios(S5PC100_GPJ4(0), 4); /* EBI_OE, EBI_WE */ - for (gpio = S5PC100_GPK0(6); gpio <= S5PC100_GPK0(7); gpio++) - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0)); + s3c_gpio_cfgpin_range(S5PC100_GPK0(6), 2, S3C_GPIO_SFN(0)); /* CF_OE, CF_WE */ - for (gpio = S5PC100_GPK1(6); gpio <= S5PC100_GPK1(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PC100_GPK1(6), 8, S3C_GPIO_SFN(2)); /* CF_CD */ s3c_gpio_cfgpin(S5PC100_GPK3(5), S3C_GPIO_SFN(2)); diff --git a/arch/arm/mach-s5pc100/setup-keypad.c b/arch/arm/mach-s5pc100/setup-keypad.c index d0837a72a58e..ada377f0c206 100644 --- a/arch/arm/mach-s5pc100/setup-keypad.c +++ b/arch/arm/mach-s5pc100/setup-keypad.c @@ -15,20 +15,9 @@ void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) { - unsigned int gpio; - unsigned int end; - /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */ - end = S5PC100_GPH3(rows); - for (gpio = S5PC100_GPH3(0); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PC100_GPH3(0), rows, S3C_GPIO_SFN(3)); /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */ - end = S5PC100_GPH2(cols); - for (gpio = S5PC100_GPH2(0); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PC100_GPH2(0), cols, S3C_GPIO_SFN(3)); } diff --git a/arch/arm/mach-s5pc100/setup-sdhci-gpio.c b/arch/arm/mach-s5pc100/setup-sdhci-gpio.c index dc7208c639ea..03c02d04c68c 100644 --- a/arch/arm/mach-s5pc100/setup-sdhci-gpio.c +++ b/arch/arm/mach-s5pc100/setup-sdhci-gpio.c @@ -25,8 +25,6 @@ void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) { struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; - unsigned int gpio; - unsigned int end; unsigned int num; num = width; @@ -34,20 +32,11 @@ void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) if (width == 8) num = width - 2; - end = S5PC100_GPG0(2 + num); - /* Set all the necessary GPG0/GPG1 pins to special-function 0 */ - for (gpio = S5PC100_GPG0(0); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PC100_GPG0(0), 2 + num, S3C_GPIO_SFN(2)); - if (width == 8) { - for (gpio = S5PC100_GPG1(0); gpio <= S5PC100_GPG1(1); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } - } + if (width == 8) + s3c_gpio_cfgrange_nopull(S5PC100_GPG1(0), 2, S3C_GPIO_SFN(2)); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP); @@ -58,16 +47,9 @@ void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) { struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; - unsigned int gpio; - unsigned int end; - - end = S5PC100_GPG2(2 + width); /* Set all the necessary GPG2 pins to special-function 2 */ - for (gpio = S5PC100_GPG2(0); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PC100_GPG2(0), 2 + width, S3C_GPIO_SFN(2)); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP); @@ -78,16 +60,9 @@ void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) { struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; - unsigned int gpio; - unsigned int end; - - end = S5PC100_GPG3(2 + width); /* Set all the necessary GPG3 pins to special-function 2 */ - for (gpio = S5PC100_GPG3(0); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PC100_GPG3(0), 2 + width, S3C_GPIO_SFN(2)); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP); diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig index d3a38955c741..862f239a0fdb 100644 --- a/arch/arm/mach-s5pv210/Kconfig +++ b/arch/arm/mach-s5pv210/Kconfig @@ -11,9 +11,9 @@ if ARCH_S5PV210 config CPU_S5PV210 bool - select PLAT_S5P select S3C_PL330_DMA select S5P_EXT_INT + select S5PV210_PM if PM help Enable S5PV210 CPU support @@ -53,17 +53,11 @@ config S5PV210_SETUP_SDHCI_GPIO help Common setup code for SDHCI gpio. -config S5PC110_DEV_ONENAND - bool - help - Compile in platform device definition for OneNAND1 controller - menu "S5PC110 Machines" config MACH_AQUILA bool "Aquila" select CPU_S5PV210 - select ARCH_SPARSEMEM_ENABLE select S3C_DEV_FB select S5P_DEV_FIMC0 select S5P_DEV_FIMC1 @@ -71,7 +65,7 @@ config MACH_AQUILA select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 select S3C_DEV_HSMMC2 - select S5PC110_DEV_ONENAND + select S5P_DEV_ONENAND select S5PV210_SETUP_FB_24BPP select S5PV210_SETUP_SDHCI help @@ -80,7 +74,7 @@ config MACH_AQUILA config MACH_GONI bool "GONI" select CPU_S5PV210 - select ARCH_SPARSEMEM_ENABLE + select S5P_GPIO_INT select S3C_DEV_FB select S5P_DEV_FIMC0 select S5P_DEV_FIMC1 @@ -88,8 +82,15 @@ config MACH_GONI select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 select S3C_DEV_HSMMC2 - select S5PC110_DEV_ONENAND + select S3C_DEV_I2C1 + select S3C_DEV_I2C2 + select S3C_DEV_USB_HSOTG + select S5P_DEV_ONENAND + select SAMSUNG_DEV_KEYPAD select S5PV210_SETUP_FB_24BPP + select S5PV210_SETUP_I2C1 + select S5PV210_SETUP_I2C2 + select S5PV210_SETUP_KEYPAD select S5PV210_SETUP_SDHCI help Machine support for Samsung GONI board @@ -98,7 +99,6 @@ config MACH_GONI config MACH_SMDKC110 bool "SMDKC110" select CPU_S5PV210 - select ARCH_SPARSEMEM_ENABLE select S3C_DEV_I2C1 select S3C_DEV_I2C2 select S3C_DEV_RTC @@ -118,7 +118,6 @@ menu "S5PV210 Machines" config MACH_SMDKV210 bool "SMDKV210" select CPU_S5PV210 - select ARCH_SPARSEMEM_ENABLE select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 select S3C_DEV_HSMMC2 @@ -139,6 +138,29 @@ config MACH_SMDKV210 help Machine support for Samsung SMDKV210 +config MACH_TORBRECK + bool "Torbreck" + select CPU_S5PV210 + select ARCH_SPARSEMEM_ENABLE + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_HSMMC2 + select S3C_DEV_HSMMC3 + select S3C_DEV_I2C1 + select S3C_DEV_I2C2 + select S3C_DEV_RTC + select S3C_DEV_WDT + select S5PV210_SETUP_I2C1 + select S5PV210_SETUP_I2C2 + select S5PV210_SETUP_SDHCI + help + Machine support for aESOP Torbreck + endmenu +config S5PV210_PM + bool + help + Power Management code common to S5PV210 + endif diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile index 05048c5aa4c6..ff1a0db57a2f 100644 --- a/arch/arm/mach-s5pv210/Makefile +++ b/arch/arm/mach-s5pv210/Makefile @@ -14,6 +14,8 @@ obj- := obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o gpiolib.o obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o +obj-$(CONFIG_S5PV210_PM) += pm.o sleep.o +obj-$(CONFIG_CPU_FREQ) += cpufreq.o # machine support @@ -21,12 +23,12 @@ obj-$(CONFIG_MACH_AQUILA) += mach-aquila.o obj-$(CONFIG_MACH_SMDKV210) += mach-smdkv210.o obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o obj-$(CONFIG_MACH_GONI) += mach-goni.o +obj-$(CONFIG_MACH_TORBRECK) += mach-torbreck.o # device support obj-y += dev-audio.o obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o -obj-$(CONFIG_S5PC110_DEV_ONENAND) += dev-onenand.o obj-$(CONFIG_S5PV210_SETUP_FB_24BPP) += setup-fb-24bpp.o obj-$(CONFIG_S5PV210_SETUP_I2C1) += setup-i2c1.o diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index d562670e1b0b..38ad7e55ab12 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -31,6 +31,8 @@ #include <plat/clock-clksrc.h> #include <plat/s5pv210.h> +static unsigned long xtal; + static struct clksrc_clk clk_mout_apll = { .clk = { .name = "mout_apll", @@ -259,6 +261,36 @@ static struct clksrc_clk clk_sclk_vpll = { .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 }, }; +static struct clk *clkset_moutdmc0src_list[] = { + [0] = &clk_sclk_a2m.clk, + [1] = &clk_mout_mpll.clk, + [2] = NULL, + [3] = NULL, +}; + +static struct clksrc_sources clkset_moutdmc0src = { + .sources = clkset_moutdmc0src_list, + .nr_sources = ARRAY_SIZE(clkset_moutdmc0src_list), +}; + +static struct clksrc_clk clk_mout_dmc0 = { + .clk = { + .name = "mout_dmc0", + .id = -1, + }, + .sources = &clkset_moutdmc0src, + .reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 }, +}; + +static struct clksrc_clk clk_sclk_dmc0 = { + .clk = { + .name = "sclk_dmc0", + .id = -1, + .parent = &clk_mout_dmc0.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 }, +}; + static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk) { return clk_get_rate(clk->parent) / 2; @@ -268,6 +300,15 @@ static struct clk_ops clk_hclk_imem_ops = { .get_rate = s5pv210_clk_imem_get_rate, }; +static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk *clk) +{ + return s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); +} + +static struct clk_ops clk_fout_apll_ops = { + .get_rate = s5pv210_clk_fout_apll_get_rate, +}; + static struct clk init_clocks_disable[] = { { .name = "rot", @@ -431,6 +472,12 @@ static struct clk init_clocks_disable[] = { .parent = &clk_p, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1 << 6), + }, { + .name = "spdif", + .id = -1, + .parent = &clk_p, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 0), }, }; @@ -660,6 +707,53 @@ static struct clksrc_sources clkset_sclk_spdif = { .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), }; +static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *pclk; + int ret; + + pclk = clk_get_parent(clk); + if (IS_ERR(pclk)) + return -EINVAL; + + ret = pclk->ops->set_rate(pclk, rate); + clk_put(pclk); + + return ret; +} + +static unsigned long s5pv210_spdif_get_rate(struct clk *clk) +{ + struct clk *pclk; + int rate; + + pclk = clk_get_parent(clk); + if (IS_ERR(pclk)) + return -EINVAL; + + rate = pclk->ops->get_rate(clk); + clk_put(pclk); + + return rate; +} + +static struct clk_ops s5pv210_sclk_spdif_ops = { + .set_rate = s5pv210_spdif_set_rate, + .get_rate = s5pv210_spdif_get_rate, +}; + +static struct clksrc_clk clk_sclk_spdif = { + .clk = { + .name = "sclk_spdif", + .id = -1, + .enable = s5pv210_clk_mask0_ctrl, + .ctrlbit = (1 << 27), + .ops = &s5pv210_sclk_spdif_ops, + }, + .sources = &clkset_sclk_spdif, + .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 }, +}; + static struct clk *clkset_group2_list[] = { [0] = &clk_ext_xtal_mux, [1] = &clk_xusbxti, @@ -744,15 +838,6 @@ static struct clksrc_clk clksrcs[] = { .sources = &clkset_sclk_mixer, .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, }, { - .clk = { - .name = "sclk_spdif", - .id = -1, - .enable = s5pv210_clk_mask0_ctrl, - .ctrlbit = (1 << 27), - }, - .sources = &clkset_sclk_spdif, - .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 }, - }, { .clk = { .name = "sclk_fimc", .id = 0, @@ -953,12 +1038,93 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_dac, &clk_sclk_pixel, &clk_sclk_hdmi, + &clk_mout_dmc0, + &clk_sclk_dmc0, + &clk_sclk_audio0, + &clk_sclk_audio1, + &clk_sclk_audio2, + &clk_sclk_spdif, +}; + +static u32 epll_div[][6] = { + { 48000000, 0, 48, 3, 3, 0 }, + { 96000000, 0, 48, 3, 2, 0 }, + { 144000000, 1, 72, 3, 2, 0 }, + { 192000000, 0, 48, 3, 1, 0 }, + { 288000000, 1, 72, 3, 1, 0 }, + { 32750000, 1, 65, 3, 4, 35127 }, + { 32768000, 1, 65, 3, 4, 35127 }, + { 45158400, 0, 45, 3, 3, 10355 }, + { 45000000, 0, 45, 3, 3, 10355 }, + { 45158000, 0, 45, 3, 3, 10355 }, + { 49125000, 0, 49, 3, 3, 9961 }, + { 49152000, 0, 49, 3, 3, 9961 }, + { 67737600, 1, 67, 3, 3, 48366 }, + { 67738000, 1, 67, 3, 3, 48366 }, + { 73800000, 1, 73, 3, 3, 47710 }, + { 73728000, 1, 73, 3, 3, 47710 }, + { 36000000, 1, 32, 3, 4, 0 }, + { 60000000, 1, 60, 3, 3, 0 }, + { 72000000, 1, 72, 3, 3, 0 }, + { 80000000, 1, 80, 3, 3, 0 }, + { 84000000, 0, 42, 3, 2, 0 }, + { 50000000, 0, 50, 3, 3, 0 }, +}; + +static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int epll_con, epll_con_k; + unsigned int i; + + /* Return if nothing changed */ + if (clk->rate == rate) + return 0; + + epll_con = __raw_readl(S5P_EPLL_CON); + epll_con_k = __raw_readl(S5P_EPLL_CON1); + + epll_con_k &= ~PLL46XX_KDIV_MASK; + epll_con &= ~(1 << 27 | + PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | + PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | + PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT); + + for (i = 0; i < ARRAY_SIZE(epll_div); i++) { + if (epll_div[i][0] == rate) { + epll_con_k |= epll_div[i][5] << 0; + epll_con |= (epll_div[i][1] << 27 | + epll_div[i][2] << PLL46XX_MDIV_SHIFT | + epll_div[i][3] << PLL46XX_PDIV_SHIFT | + epll_div[i][4] << PLL46XX_SDIV_SHIFT); + break; + } + } + + if (i == ARRAY_SIZE(epll_div)) { + printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", + __func__); + return -EINVAL; + } + + __raw_writel(epll_con, S5P_EPLL_CON); + __raw_writel(epll_con_k, S5P_EPLL_CON1); + + printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n", + clk->rate, rate); + + clk->rate = rate; + + return 0; +} + +static struct clk_ops s5pv210_epll_ops = { + .set_rate = s5pv210_epll_set_rate, + .get_rate = s5p_epll_get_rate, }; void __init_or_cpufreq s5pv210_setup_clocks(void) { struct clk *xtal_clk; - unsigned long xtal; unsigned long vpllsrc; unsigned long armclk; unsigned long hclk_msys; @@ -974,6 +1140,10 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) unsigned int ptr; u32 clkdiv0, clkdiv1; + /* Set functions for clk_fout_epll */ + clk_fout_epll.enable = s5p_epll_enable; + clk_fout_epll.ops = &s5pv210_epll_ops; + printk(KERN_DEBUG "%s: registering clocks\n", __func__); clkdiv0 = __raw_readl(S5P_CLK_DIV0); @@ -992,11 +1162,12 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); - epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500); + epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON), + __raw_readl(S5P_EPLL_CON1), pll_4600); vpllsrc = clk_get_rate(&clk_vpllsrc.clk); vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502); - clk_fout_apll.rate = apll; + clk_fout_apll.ops = &clk_fout_apll_ops; clk_fout_mpll.rate = mpll; clk_fout_epll.rate = epll; clk_fout_vpll.rate = vpll; diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c index 245b82b53df4..8eb480e201b0 100644 --- a/arch/arm/mach-s5pv210/cpu.c +++ b/arch/arm/mach-s5pv210/cpu.c @@ -1,7 +1,7 @@ /* linux/arch/arm/mach-s5pv210/cpu.c * * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * 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 @@ -51,6 +51,21 @@ static struct map_desc s5pv210_iodesc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S5P_VA_GPIO, + .pfn = __phys_to_pfn(S5PV210_PA_GPIO), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC0, + .pfn = __phys_to_pfn(S5PV210_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC1, + .pfn = __phys_to_pfn(S5PV210_PA_VIC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)VA_VIC2, .pfn = __phys_to_pfn(S5PV210_PA_VIC2), .length = SZ_16K, @@ -61,10 +76,30 @@ static struct map_desc s5pv210_iodesc[] __initdata = { .length = SZ_16K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_512K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)S5P_VA_SROMC, .pfn = __phys_to_pfn(S5PV210_PA_SROMC), .length = SZ_4K, .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_DMC0, + .pfn = __phys_to_pfn(S5PV210_PA_DMC0), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_DMC1, + .pfn = __phys_to_pfn(S5PV210_PA_DMC1), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_USB_HSPHY, + .pfn =__phys_to_pfn(S5PV210_PA_HSPHY), + .length = SZ_4K, + .type = MT_DEVICE, } }; diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c new file mode 100644 index 000000000000..a6f22920a2c2 --- /dev/null +++ b/arch/arm/mach-s5pv210/cpufreq.c @@ -0,0 +1,484 @@ +/* linux/arch/arm/mach-s5pv210/cpufreq.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * CPU frequency scaling for S5PC110/S5PV210 + * + * 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/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/cpufreq.h> + +#include <mach/map.h> +#include <mach/regs-clock.h> + +static struct clk *cpu_clk; +static struct clk *dmc0_clk; +static struct clk *dmc1_clk; +static struct cpufreq_freqs freqs; + +/* APLL M,P,S values for 1G/800Mhz */ +#define APLL_VAL_1000 ((1 << 31) | (125 << 16) | (3 << 8) | 1) +#define APLL_VAL_800 ((1 << 31) | (100 << 16) | (3 << 8) | 1) + +/* + * DRAM configurations to calculate refresh counter for changing + * frequency of memory. + */ +struct dram_conf { + unsigned long freq; /* HZ */ + unsigned long refresh; /* DRAM refresh counter * 1000 */ +}; + +/* DRAM configuration (DMC0 and DMC1) */ +static struct dram_conf s5pv210_dram_conf[2]; + +enum perf_level { + L0, L1, L2, L3, L4, +}; + +enum s5pv210_mem_type { + LPDDR = 0x1, + LPDDR2 = 0x2, + DDR2 = 0x4, +}; + +enum s5pv210_dmc_port { + DMC0 = 0, + DMC1, +}; + +static struct cpufreq_frequency_table s5pv210_freq_table[] = { + {L0, 1000*1000}, + {L1, 800*1000}, + {L2, 400*1000}, + {L3, 200*1000}, + {L4, 100*1000}, + {0, CPUFREQ_TABLE_END}, +}; + +static u32 clkdiv_val[5][11] = { + /* + * Clock divider value for following + * { APLL, A2M, HCLK_MSYS, PCLK_MSYS, + * HCLK_DSYS, PCLK_DSYS, HCLK_PSYS, PCLK_PSYS, + * ONEDRAM, MFC, G3D } + */ + + /* L0 : [1000/200/100][166/83][133/66][200/200] */ + {0, 4, 4, 1, 3, 1, 4, 1, 3, 0, 0}, + + /* L1 : [800/200/100][166/83][133/66][200/200] */ + {0, 3, 3, 1, 3, 1, 4, 1, 3, 0, 0}, + + /* L2 : [400/200/100][166/83][133/66][200/200] */ + {1, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0}, + + /* L3 : [200/200/100][166/83][133/66][200/200] */ + {3, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0}, + + /* L4 : [100/100/100][83/83][66/66][100/100] */ + {7, 7, 0, 0, 7, 0, 9, 0, 7, 0, 0}, +}; + +/* + * This function set DRAM refresh counter + * accoriding to operating frequency of DRAM + * ch: DMC port number 0 or 1 + * freq: Operating frequency of DRAM(KHz) + */ +static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq) +{ + unsigned long tmp, tmp1; + void __iomem *reg = NULL; + + if (ch == DMC0) + reg = (S5P_VA_DMC0 + 0x30); + else if (ch == DMC1) + reg = (S5P_VA_DMC1 + 0x30); + else + printk(KERN_ERR "Cannot find DMC port\n"); + + /* Find current DRAM frequency */ + tmp = s5pv210_dram_conf[ch].freq; + + do_div(tmp, freq); + + tmp1 = s5pv210_dram_conf[ch].refresh; + + do_div(tmp1, tmp); + + __raw_writel(tmp1, reg); +} + +int s5pv210_verify_speed(struct cpufreq_policy *policy) +{ + if (policy->cpu) + return -EINVAL; + + return cpufreq_frequency_table_verify(policy, s5pv210_freq_table); +} + +unsigned int s5pv210_getspeed(unsigned int cpu) +{ + if (cpu) + return 0; + + return clk_get_rate(cpu_clk) / 1000; +} + +static int s5pv210_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned long reg; + unsigned int index, priv_index; + unsigned int pll_changing = 0; + unsigned int bus_speed_changing = 0; + + freqs.old = s5pv210_getspeed(0); + + if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, + target_freq, relation, &index)) + return -EINVAL; + + freqs.new = s5pv210_freq_table[index].frequency; + freqs.cpu = 0; + + if (freqs.new == freqs.old) + return 0; + + /* Finding current running level index */ + if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, + freqs.old, relation, &priv_index)) + return -EINVAL; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + if (freqs.new > freqs.old) { + /* Voltage up: will be implemented */ + } + + /* Check if there need to change PLL */ + if ((index == L0) || (priv_index == L0)) + pll_changing = 1; + + /* Check if there need to change System bus clock */ + if ((index == L4) || (priv_index == L4)) + bus_speed_changing = 1; + + if (bus_speed_changing) { + /* + * Reconfigure DRAM refresh counter value for minimum + * temporary clock while changing divider. + * expected clock is 83Mhz : 7.8usec/(1/83Mhz) = 0x287 + */ + if (pll_changing) + s5pv210_set_refresh(DMC1, 83000); + else + s5pv210_set_refresh(DMC1, 100000); + + s5pv210_set_refresh(DMC0, 83000); + } + + /* + * APLL should be changed in this level + * APLL -> MPLL(for stable transition) -> APLL + * Some clock source's clock API are not prepared. + * Do not use clock API in below code. + */ + if (pll_changing) { + /* + * 1. Temporary Change divider for MFC and G3D + * SCLKA2M(200/1=200)->(200/4=50)Mhz + */ + reg = __raw_readl(S5P_CLK_DIV2); + reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK); + reg |= (3 << S5P_CLKDIV2_G3D_SHIFT) | + (3 << S5P_CLKDIV2_MFC_SHIFT); + __raw_writel(reg, S5P_CLK_DIV2); + + /* For MFC, G3D dividing */ + do { + reg = __raw_readl(S5P_CLKDIV_STAT0); + } while (reg & ((1 << 16) | (1 << 17))); + + /* + * 2. Change SCLKA2M(200Mhz)to SCLKMPLL in MFC_MUX, G3D MUX + * (200/4=50)->(667/4=166)Mhz + */ + reg = __raw_readl(S5P_CLK_SRC2); + reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK); + reg |= (1 << S5P_CLKSRC2_G3D_SHIFT) | + (1 << S5P_CLKSRC2_MFC_SHIFT); + __raw_writel(reg, S5P_CLK_SRC2); + + do { + reg = __raw_readl(S5P_CLKMUX_STAT1); + } while (reg & ((1 << 7) | (1 << 3))); + + /* + * 3. DMC1 refresh count for 133Mhz if (index == L4) is + * true refresh counter is already programed in upper + * code. 0x287@83Mhz + */ + if (!bus_speed_changing) + s5pv210_set_refresh(DMC1, 133000); + + /* 4. SCLKAPLL -> SCLKMPLL */ + reg = __raw_readl(S5P_CLK_SRC0); + reg &= ~(S5P_CLKSRC0_MUX200_MASK); + reg |= (0x1 << S5P_CLKSRC0_MUX200_SHIFT); + __raw_writel(reg, S5P_CLK_SRC0); + + do { + reg = __raw_readl(S5P_CLKMUX_STAT0); + } while (reg & (0x1 << 18)); + + } + + /* Change divider */ + reg = __raw_readl(S5P_CLK_DIV0); + + reg &= ~(S5P_CLKDIV0_APLL_MASK | S5P_CLKDIV0_A2M_MASK | + S5P_CLKDIV0_HCLK200_MASK | S5P_CLKDIV0_PCLK100_MASK | + S5P_CLKDIV0_HCLK166_MASK | S5P_CLKDIV0_PCLK83_MASK | + S5P_CLKDIV0_HCLK133_MASK | S5P_CLKDIV0_PCLK66_MASK); + + reg |= ((clkdiv_val[index][0] << S5P_CLKDIV0_APLL_SHIFT) | + (clkdiv_val[index][1] << S5P_CLKDIV0_A2M_SHIFT) | + (clkdiv_val[index][2] << S5P_CLKDIV0_HCLK200_SHIFT) | + (clkdiv_val[index][3] << S5P_CLKDIV0_PCLK100_SHIFT) | + (clkdiv_val[index][4] << S5P_CLKDIV0_HCLK166_SHIFT) | + (clkdiv_val[index][5] << S5P_CLKDIV0_PCLK83_SHIFT) | + (clkdiv_val[index][6] << S5P_CLKDIV0_HCLK133_SHIFT) | + (clkdiv_val[index][7] << S5P_CLKDIV0_PCLK66_SHIFT)); + + __raw_writel(reg, S5P_CLK_DIV0); + + do { + reg = __raw_readl(S5P_CLKDIV_STAT0); + } while (reg & 0xff); + + /* ARM MCS value changed */ + reg = __raw_readl(S5P_ARM_MCS_CON); + reg &= ~0x3; + if (index >= L3) + reg |= 0x3; + else + reg |= 0x1; + + __raw_writel(reg, S5P_ARM_MCS_CON); + + if (pll_changing) { + /* 5. Set Lock time = 30us*24Mhz = 0x2cf */ + __raw_writel(0x2cf, S5P_APLL_LOCK); + + /* + * 6. Turn on APLL + * 6-1. Set PMS values + * 6-2. Wait untile the PLL is locked + */ + if (index == L0) + __raw_writel(APLL_VAL_1000, S5P_APLL_CON); + else + __raw_writel(APLL_VAL_800, S5P_APLL_CON); + + do { + reg = __raw_readl(S5P_APLL_CON); + } while (!(reg & (0x1 << 29))); + + /* + * 7. Change souce clock from SCLKMPLL(667Mhz) + * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX + * (667/4=166)->(200/4=50)Mhz + */ + reg = __raw_readl(S5P_CLK_SRC2); + reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK); + reg |= (0 << S5P_CLKSRC2_G3D_SHIFT) | + (0 << S5P_CLKSRC2_MFC_SHIFT); + __raw_writel(reg, S5P_CLK_SRC2); + + do { + reg = __raw_readl(S5P_CLKMUX_STAT1); + } while (reg & ((1 << 7) | (1 << 3))); + + /* + * 8. Change divider for MFC and G3D + * (200/4=50)->(200/1=200)Mhz + */ + reg = __raw_readl(S5P_CLK_DIV2); + reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK); + reg |= (clkdiv_val[index][10] << S5P_CLKDIV2_G3D_SHIFT) | + (clkdiv_val[index][9] << S5P_CLKDIV2_MFC_SHIFT); + __raw_writel(reg, S5P_CLK_DIV2); + + /* For MFC, G3D dividing */ + do { + reg = __raw_readl(S5P_CLKDIV_STAT0); + } while (reg & ((1 << 16) | (1 << 17))); + + /* 9. Change MPLL to APLL in MSYS_MUX */ + reg = __raw_readl(S5P_CLK_SRC0); + reg &= ~(S5P_CLKSRC0_MUX200_MASK); + reg |= (0x0 << S5P_CLKSRC0_MUX200_SHIFT); + __raw_writel(reg, S5P_CLK_SRC0); + + do { + reg = __raw_readl(S5P_CLKMUX_STAT0); + } while (reg & (0x1 << 18)); + + /* + * 10. DMC1 refresh counter + * L4 : DMC1 = 100Mhz 7.8us/(1/100) = 0x30c + * Others : DMC1 = 200Mhz 7.8us/(1/200) = 0x618 + */ + if (!bus_speed_changing) + s5pv210_set_refresh(DMC1, 200000); + } + + /* + * L4 level need to change memory bus speed, hence onedram clock divier + * and memory refresh parameter should be changed + */ + if (bus_speed_changing) { + reg = __raw_readl(S5P_CLK_DIV6); + reg &= ~S5P_CLKDIV6_ONEDRAM_MASK; + reg |= (clkdiv_val[index][8] << S5P_CLKDIV6_ONEDRAM_SHIFT); + __raw_writel(reg, S5P_CLK_DIV6); + + do { + reg = __raw_readl(S5P_CLKDIV_STAT1); + } while (reg & (1 << 15)); + + /* Reconfigure DRAM refresh counter value */ + if (index != L4) { + /* + * DMC0 : 166Mhz + * DMC1 : 200Mhz + */ + s5pv210_set_refresh(DMC0, 166000); + s5pv210_set_refresh(DMC1, 200000); + } else { + /* + * DMC0 : 83Mhz + * DMC1 : 100Mhz + */ + s5pv210_set_refresh(DMC0, 83000); + s5pv210_set_refresh(DMC1, 100000); + } + } + + if (freqs.new < freqs.old) { + /* Voltage down: will be implemented */ + } + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + printk(KERN_DEBUG "Perf changed[L%d]\n", index); + + return 0; +} + +#ifdef CONFIG_PM +static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy, + pm_message_t pmsg) +{ + return 0; +} + +static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy) +{ + return 0; +} +#endif + +static int check_mem_type(void __iomem *dmc_reg) +{ + unsigned long val; + + val = __raw_readl(dmc_reg + 0x4); + val = (val & (0xf << 8)); + + return val >> 8; +} + +static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) +{ + unsigned long mem_type; + + cpu_clk = clk_get(NULL, "armclk"); + if (IS_ERR(cpu_clk)) + return PTR_ERR(cpu_clk); + + dmc0_clk = clk_get(NULL, "sclk_dmc0"); + if (IS_ERR(dmc0_clk)) { + clk_put(cpu_clk); + return PTR_ERR(dmc0_clk); + } + + dmc1_clk = clk_get(NULL, "hclk_msys"); + if (IS_ERR(dmc1_clk)) { + clk_put(dmc0_clk); + clk_put(cpu_clk); + return PTR_ERR(dmc1_clk); + } + + if (policy->cpu != 0) + return -EINVAL; + + /* + * check_mem_type : This driver only support LPDDR & LPDDR2. + * other memory type is not supported. + */ + mem_type = check_mem_type(S5P_VA_DMC0); + + if ((mem_type != LPDDR) && (mem_type != LPDDR2)) { + printk(KERN_ERR "CPUFreq doesn't support this memory type\n"); + return -EINVAL; + } + + /* Find current refresh counter and frequency each DMC */ + s5pv210_dram_conf[0].refresh = (__raw_readl(S5P_VA_DMC0 + 0x30) * 1000); + s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk); + + s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000); + s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk); + + policy->cur = policy->min = policy->max = s5pv210_getspeed(0); + + cpufreq_frequency_table_get_attr(s5pv210_freq_table, policy->cpu); + + policy->cpuinfo.transition_latency = 40000; + + return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table); +} + +static struct cpufreq_driver s5pv210_driver = { + .flags = CPUFREQ_STICKY, + .verify = s5pv210_verify_speed, + .target = s5pv210_target, + .get = s5pv210_getspeed, + .init = s5pv210_cpu_init, + .name = "s5pv210", +#ifdef CONFIG_PM + .suspend = s5pv210_cpufreq_suspend, + .resume = s5pv210_cpufreq_resume, +#endif +}; + +static int __init s5pv210_cpufreq_init(void) +{ + return cpufreq_register_driver(&s5pv210_driver); +} + +late_initcall(s5pv210_cpufreq_init); diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c index 21dc6cf955c3..1303fcb12b51 100644 --- a/arch/arm/mach-s5pv210/dev-audio.c +++ b/arch/arm/mach-s5pv210/dev-audio.c @@ -24,29 +24,15 @@ static int s5pv210_cfg_i2s(struct platform_device *pdev) /* configure GPIO for i2s port */ switch (pdev->id) { case 1: - s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(2)); break; case 2: - s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(4)); + s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(4)); break; case -1: - s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPI(5), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPI(6), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin_range(S5PV210_GPI(0), 7, S3C_GPIO_SFN(2)); break; default: @@ -151,25 +137,13 @@ static int s5pv210_pcm_cfg_gpio(struct platform_device *pdev) { switch (pdev->id) { case 0: - s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin_range(S5PV210_GPI(0), 5, S3C_GPIO_SFN(3)); break; case 1: - s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(3)); - s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(3)); break; case 2: - s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(2)); break; default: printk(KERN_DEBUG "Invalid PCM Controller number!"); @@ -271,13 +245,7 @@ struct platform_device s5pv210_device_pcm2 = { static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev) { - s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(4)); - s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(4)); - - return 0; + return s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(4)); } static struct resource s5pv210_ac97_resource[] = { @@ -325,3 +293,43 @@ struct platform_device s5pv210_device_ac97 = { .coherent_dma_mask = DMA_BIT_MASK(32), }, }; + +/* S/PDIF Controller platform_device */ + +static int s5pv210_spdif_cfg_gpio(struct platform_device *pdev) +{ + s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 2, S3C_GPIO_SFN(3)); + + return 0; +} + +static struct resource s5pv210_spdif_resource[] = { + [0] = { + .start = S5PV210_PA_SPDIF, + .end = S5PV210_PA_SPDIF + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_SPDIF, + .end = DMACH_SPDIF, + .flags = IORESOURCE_DMA, + }, +}; + +static struct s3c_audio_pdata samsung_spdif_pdata = { + .cfg_gpio = s5pv210_spdif_cfg_gpio, +}; + +static u64 s5pv210_spdif_dmamask = DMA_BIT_MASK(32); + +struct platform_device s5pv210_device_spdif = { + .name = "samsung-spdif", + .id = -1, + .num_resources = ARRAY_SIZE(s5pv210_spdif_resource), + .resource = s5pv210_spdif_resource, + .dev = { + .platform_data = &samsung_spdif_pdata, + .dma_mask = &s5pv210_spdif_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; diff --git a/arch/arm/mach-s5pv210/dev-spi.c b/arch/arm/mach-s5pv210/dev-spi.c index 826cdbc43e20..e3249a47e3b1 100644 --- a/arch/arm/mach-s5pv210/dev-spi.c +++ b/arch/arm/mach-s5pv210/dev-spi.c @@ -35,23 +35,15 @@ static char *spi_src_clks[] = { */ static int s5pv210_spi_cfg_gpio(struct platform_device *pdev) { + unsigned int base; + switch (pdev->id) { case 0: - s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPB(1), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPB(2), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5PV210_GPB(1), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5PV210_GPB(2), S3C_GPIO_PULL_UP); + base = S5PV210_GPB(0); break; case 1: - s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPB(5), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5PV210_GPB(6), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5PV210_GPB(5), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5PV210_GPB(6), S3C_GPIO_PULL_UP); + base = S5PV210_GPB(4); break; default: @@ -59,6 +51,9 @@ static int s5pv210_spi_cfg_gpio(struct platform_device *pdev) return -EINVAL; } + s3c_gpio_cfgall_range(base, 3, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); + return 0; } diff --git a/arch/arm/mach-s5pv210/gpiolib.c b/arch/arm/mach-s5pv210/gpiolib.c index 0d459112d039..ab673effd767 100644 --- a/arch/arm/mach-s5pv210/gpiolib.c +++ b/arch/arm/mach-s5pv210/gpiolib.c @@ -150,6 +150,7 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = { .label = "GPG3", }, }, { + .config = &gpio_cfg_noint, .chip = { .base = S5PV210_GPI(0), .ngpio = S5PV210_GPIO_I_NR, @@ -223,34 +224,42 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = { }, { .base = (S5P_VA_GPIO + 0xC00), .config = &gpio_cfg_noint, + .irq_base = IRQ_EINT(0), .chip = { .base = S5PV210_GPH0(0), .ngpio = S5PV210_GPIO_H0_NR, .label = "GPH0", + .to_irq = samsung_gpiolib_to_irq, }, }, { .base = (S5P_VA_GPIO + 0xC20), .config = &gpio_cfg_noint, + .irq_base = IRQ_EINT(8), .chip = { .base = S5PV210_GPH1(0), .ngpio = S5PV210_GPIO_H1_NR, .label = "GPH1", + .to_irq = samsung_gpiolib_to_irq, }, }, { .base = (S5P_VA_GPIO + 0xC40), .config = &gpio_cfg_noint, + .irq_base = IRQ_EINT(16), .chip = { .base = S5PV210_GPH2(0), .ngpio = S5PV210_GPIO_H2_NR, .label = "GPH2", + .to_irq = samsung_gpiolib_to_irq, }, }, { .base = (S5P_VA_GPIO + 0xC60), .config = &gpio_cfg_noint, + .irq_base = IRQ_EINT(24), .chip = { .base = S5PV210_GPH3(0), .ngpio = S5PV210_GPIO_H3_NR, .label = "GPH3", + .to_irq = samsung_gpiolib_to_irq, }, }, }; @@ -259,11 +268,14 @@ static __init int s5pv210_gpiolib_init(void) { struct s3c_gpio_chip *chip = s5pv210_gpio_4bit; int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit); + int gpioint_group = 0; int i = 0; for (i = 0; i < nr_chips; i++, chip++) { - if (chip->config == NULL) + if (chip->config == NULL) { chip->config = &gpio_cfg; + chip->group = gpioint_group++; + } if (chip->base == NULL) chip->base = S5PV210_BANK_BASE(i); } diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h index e1c020e5a49b..119b95fdc3ce 100644 --- a/arch/arm/mach-s5pv210/include/mach/irqs.h +++ b/arch/arm/mach-s5pv210/include/mach/irqs.h @@ -55,8 +55,8 @@ #define IRQ_SPI1 S5P_IRQ_VIC1(16) #define IRQ_SPI2 S5P_IRQ_VIC1(17) #define IRQ_IRDA S5P_IRQ_VIC1(18) -#define IRQ_CAN0 S5P_IRQ_VIC1(19) -#define IRQ_CAN1 S5P_IRQ_VIC1(20) +#define IRQ_IIC2 S5P_IRQ_VIC1(19) +#define IRQ_IIC3 S5P_IRQ_VIC1(20) #define IRQ_HSIRX S5P_IRQ_VIC1(21) #define IRQ_HSITX S5P_IRQ_VIC1(22) #define IRQ_UHOST S5P_IRQ_VIC1(23) @@ -109,7 +109,7 @@ #define IRQ_IPC S5P_IRQ_VIC3(0) #define IRQ_HOSTIF S5P_IRQ_VIC3(1) -#define IRQ_MMC3 S5P_IRQ_VIC3(2) +#define IRQ_HSMMC3 S5P_IRQ_VIC3(2) #define IRQ_CEC S5P_IRQ_VIC3(3) #define IRQ_TSI S5P_IRQ_VIC3(4) #define IRQ_MDNIE0 S5P_IRQ_VIC3(5) @@ -121,8 +121,12 @@ #define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) #define S5P_EINT_BASE2 (IRQ_VIC_END + 1) +/* GPIO interrupt */ +#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1) +#define S5P_GPIOINT_GROUP_MAXNR 22 + /* Set the default NR_IRQS */ -#define NR_IRQS (IRQ_EINT(31) + 1) +#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1) /* Compatibility */ #define IRQ_LCD_FIFO IRQ_LCD0 diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index dd4fb6bf14b5..861d7fe11fc9 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -17,7 +17,10 @@ #include <plat/map-s5p.h> #define S5PC110_PA_ONENAND (0xB0000000) +#define S5P_PA_ONENAND S5PC110_PA_ONENAND + #define S5PC110_PA_ONENAND_DMA (0xB0600000) +#define S5P_PA_ONENAND_DMA S5PC110_PA_ONENAND_DMA #define S5PV210_PA_CHIPID (0xE0000000) #define S5P_PA_CHIPID S5PV210_PA_CHIPID @@ -26,7 +29,6 @@ #define S5P_PA_SYSCON S5PV210_PA_SYSCON #define S5PV210_PA_GPIO (0xE0200000) -#define S5P_PA_GPIO S5PV210_PA_GPIO /* SPI */ #define S5PV210_PA_SPI0 0xE1300000 @@ -55,6 +57,8 @@ #define S5P_SZ_UART SZ_256 +#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) + #define S5PV210_PA_SROMC (0xE8000000) #define S5PV210_PA_CFCON (0xE8200000) @@ -71,21 +75,20 @@ #define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000)) -#define S5PV210_PA_VIC0 (0xF2000000) -#define S5P_PA_VIC0 S5PV210_PA_VIC0 +#define S5PV210_PA_HSOTG (0xEC000000) +#define S5PV210_PA_HSPHY (0xEC100000) +#define S5PV210_PA_VIC0 (0xF2000000) #define S5PV210_PA_VIC1 (0xF2100000) -#define S5P_PA_VIC1 S5PV210_PA_VIC1 - #define S5PV210_PA_VIC2 (0xF2200000) -#define S5P_PA_VIC2 S5PV210_PA_VIC2 - #define S5PV210_PA_VIC3 (0xF2300000) -#define S5P_PA_VIC3 S5PV210_PA_VIC3 #define S5PV210_PA_SDRAM (0x20000000) #define S5P_PA_SDRAM S5PV210_PA_SDRAM +/* S/PDIF */ +#define S5PV210_PA_SPDIF 0xE1100000 + /* I2S */ #define S5PV210_PA_IIS0 0xEEE30000 #define S5PV210_PA_IIS1 0xE2100000 @@ -101,6 +104,9 @@ #define S5PV210_PA_ADC (0xE1700000) +#define S5PV210_PA_DMC0 (0xF0000000) +#define S5PV210_PA_DMC1 (0xF1400000) + /* compatibiltiy defines. */ #define S3C_PA_UART S5PV210_PA_UART #define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0) @@ -113,6 +119,7 @@ #define S3C_PA_FB S5PV210_PA_FB #define S3C_PA_RTC S5PV210_PA_RTC #define S3C_PA_WDT S5PV210_PA_WATCHDOG +#define S3C_PA_USB_HSOTG S5PV210_PA_HSOTG #define S5P_PA_FIMC0 S5PV210_PA_FIMC0 #define S5P_PA_FIMC1 S5PV210_PA_FIMC1 #define S5P_PA_FIMC2 S5PV210_PA_FIMC2 diff --git a/arch/arm/mach-s5pv210/include/mach/pm-core.h b/arch/arm/mach-s5pv210/include/mach/pm-core.h new file mode 100644 index 000000000000..e8d394f8b057 --- /dev/null +++ b/arch/arm/mach-s5pv210/include/mach/pm-core.h @@ -0,0 +1,43 @@ +/* linux/arch/arm/mach-s5pv210/include/mach/pm-core.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h, + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S5PV210 - PM core support for arch/arm/plat-s5p/pm.c + * + * 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. +*/ + +static inline void s3c_pm_debug_init_uart(void) +{ + /* nothing here yet */ +} + +static inline void s3c_pm_arch_prepare_irqs(void) +{ + __raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK); + __raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK); +} + +static inline void s3c_pm_arch_stop_clocks(void) +{ + /* nothing here yet */ +} + +static inline void s3c_pm_arch_show_resume_irqs(void) +{ + /* nothing here yet */ +} + +static inline void s3c_pm_arch_update_uart(void __iomem *regs, + struct pm_uart_save *save) +{ + /* nothing here yet */ +} diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h index 499aef737476..ebaabe021af9 100644 --- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h +++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h @@ -25,6 +25,7 @@ #define S5P_APLL_CON S5P_CLKREG(0x100) #define S5P_MPLL_CON S5P_CLKREG(0x108) #define S5P_EPLL_CON S5P_CLKREG(0x110) +#define S5P_EPLL_CON1 S5P_CLKREG(0x114) #define S5P_VPLL_CON S5P_CLKREG(0x120) #define S5P_CLK_SRC0 S5P_CLKREG(0x200) @@ -67,11 +68,28 @@ #define S5P_CLKGATE_BUS1 S5P_CLKREG(0x488) #define S5P_CLK_OUT S5P_CLKREG(0x500) +/* DIV/MUX STATUS */ +#define S5P_CLKDIV_STAT0 S5P_CLKREG(0x1000) +#define S5P_CLKDIV_STAT1 S5P_CLKREG(0x1004) +#define S5P_CLKMUX_STAT0 S5P_CLKREG(0x1100) +#define S5P_CLKMUX_STAT1 S5P_CLKREG(0x1104) + /* CLKSRC0 */ -#define S5P_CLKSRC0_MUX200_MASK (0x1<<16) +#define S5P_CLKSRC0_MUX200_SHIFT (16) +#define S5P_CLKSRC0_MUX200_MASK (0x1 << S5P_CLKSRC0_MUX200_SHIFT) #define S5P_CLKSRC0_MUX166_MASK (0x1<<20) #define S5P_CLKSRC0_MUX133_MASK (0x1<<24) +/* CLKSRC2 */ +#define S5P_CLKSRC2_G3D_SHIFT (0) +#define S5P_CLKSRC2_G3D_MASK (0x3 << S5P_CLKSRC2_G3D_SHIFT) +#define S5P_CLKSRC2_MFC_SHIFT (4) +#define S5P_CLKSRC2_MFC_MASK (0x3 << S5P_CLKSRC2_MFC_SHIFT) + +/* CLKSRC6*/ +#define S5P_CLKSRC6_ONEDRAM_SHIFT (24) +#define S5P_CLKSRC6_ONEDRAM_MASK (0x3 << S5P_CLKSRC6_ONEDRAM_SHIFT) + /* CLKDIV0 */ #define S5P_CLKDIV0_APLL_SHIFT (0) #define S5P_CLKDIV0_APLL_MASK (0x7 << S5P_CLKDIV0_APLL_SHIFT) @@ -90,12 +108,24 @@ #define S5P_CLKDIV0_PCLK66_SHIFT (28) #define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT) +/* CLKDIV2 */ +#define S5P_CLKDIV2_G3D_SHIFT (0) +#define S5P_CLKDIV2_G3D_MASK (0xF << S5P_CLKDIV2_G3D_SHIFT) +#define S5P_CLKDIV2_MFC_SHIFT (4) +#define S5P_CLKDIV2_MFC_MASK (0xF << S5P_CLKDIV2_MFC_SHIFT) + +/* CLKDIV6 */ +#define S5P_CLKDIV6_ONEDRAM_SHIFT (28) +#define S5P_CLKDIV6_ONEDRAM_MASK (0xF << S5P_CLKDIV6_ONEDRAM_SHIFT) + #define S5P_SWRESET S5P_CLKREG(0x2000) +#define S5P_ARM_MCS_CON S5P_CLKREG(0x6100) + /* Registers related to power management */ #define S5P_PWR_CFG S5P_CLKREG(0xC000) #define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0xC004) -#define S5P_WAKEUP_MASK S5P_CLKREG(0xC008) +#define S5P_WAKEUP_MASK S5P_CLKREG(0xC008) #define S5P_PWR_MODE S5P_CLKREG(0xC00C) #define S5P_NORMAL_CFG S5P_CLKREG(0xC010) #define S5P_IDLE_CFG S5P_CLKREG(0xC020) @@ -159,8 +189,11 @@ #define S5P_SLEEP_CFG_USBOSC_EN (1 << 1) /* OTHERS Resgister */ +#define S5P_OTHERS_RET_IO (1 << 31) +#define S5P_OTHERS_RET_CF (1 << 30) +#define S5P_OTHERS_RET_MMC (1 << 29) +#define S5P_OTHERS_RET_UART (1 << 28) #define S5P_OTHERS_USB_SIG_MASK (1 << 16) -#define S5P_OTHERS_MIPI_DPHY_EN (1 << 28) /* MIPI */ #define S5P_MIPI_DPHY_EN (3) diff --git a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h index 49e029b4978a..de0c89976078 100644 --- a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h +++ b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h @@ -31,13 +31,6 @@ #define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7)) -/* values for S5P_EXTINT0 */ -#define S5P_EXTINT_LOWLEV (0x00) -#define S5P_EXTINT_HILEV (0x01) -#define S5P_EXTINT_FALLEDGE (0x02) -#define S5P_EXTINT_RISEEDGE (0x03) -#define S5P_EXTINT_BOTHEDGE (0x04) - #define EINT_MODE S3C_GPIO_SFN(0xf) #define EINT_GPIO_0(x) S5PV210_GPH0(x) diff --git a/arch/arm/mach-s5pv210/include/mach/regs-sys.h b/arch/arm/mach-s5pv210/include/mach/regs-sys.h new file mode 100644 index 000000000000..26691d39d0f4 --- /dev/null +++ b/arch/arm/mach-s5pv210/include/mach/regs-sys.h @@ -0,0 +1,19 @@ +/* arch/arm/mach-s5pv210/include/mach/regs-sys.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV210 - System registers 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. +*/ + +#define S5PV210_USB_PHY_CON (S3C_VA_SYS + 0xE80C) +#define S5PV210_USB_PHY0_EN (1 << 0) +#define S5PV210_USB_PHY1_EN (1 << 1) + +/* compatibility defines for s3c-hsotg driver */ +#define S3C64XX_OTHERS S5PV210_USB_PHY_CON +#define S3C64XX_OTHERS_USBMASK S5PV210_USB_PHY0_EN diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 0dda8012d6b2..4b15549bd142 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -16,6 +16,8 @@ #include <linux/i2c.h> #include <linux/i2c-gpio.h> #include <linux/mfd/max8998.h> +#include <linux/mfd/wm8994/pdata.h> +#include <linux/regulator/fixed.h> #include <linux/gpio_keys.h> #include <linux/input.h> #include <linux/gpio.h> @@ -379,6 +381,119 @@ static struct max8998_platform_data aquila_max8998_pdata = { }; #endif +static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = { + { + .dev_name = "5-001a", + .supply = "DBVDD", + }, { + .dev_name = "5-001a", + .supply = "AVDD2", + }, { + .dev_name = "5-001a", + .supply = "CPVDD", + }, +}; + +static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = { + { + .dev_name = "5-001a", + .supply = "SPKVDD1", + }, { + .dev_name = "5-001a", + .supply = "SPKVDD2", + }, +}; + +static struct regulator_init_data wm8994_fixed_voltage0_init_data = { + .constraints = { + .always_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies), + .consumer_supplies = wm8994_fixed_voltage0_supplies, +}; + +static struct regulator_init_data wm8994_fixed_voltage1_init_data = { + .constraints = { + .always_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies), + .consumer_supplies = wm8994_fixed_voltage1_supplies, +}; + +static struct fixed_voltage_config wm8994_fixed_voltage0_config = { + .supply_name = "VCC_1.8V_PDA", + .microvolts = 1800000, + .gpio = -EINVAL, + .init_data = &wm8994_fixed_voltage0_init_data, +}; + +static struct fixed_voltage_config wm8994_fixed_voltage1_config = { + .supply_name = "V_BAT", + .microvolts = 3700000, + .gpio = -EINVAL, + .init_data = &wm8994_fixed_voltage1_init_data, +}; + +static struct platform_device wm8994_fixed_voltage0 = { + .name = "reg-fixed-voltage", + .id = 0, + .dev = { + .platform_data = &wm8994_fixed_voltage0_config, + }, +}; + +static struct platform_device wm8994_fixed_voltage1 = { + .name = "reg-fixed-voltage", + .id = 1, + .dev = { + .platform_data = &wm8994_fixed_voltage1_config, + }, +}; + +static struct regulator_consumer_supply wm8994_avdd1_supply = { + .dev_name = "5-001a", + .supply = "AVDD1", +}; + +static struct regulator_consumer_supply wm8994_dcvdd_supply = { + .dev_name = "5-001a", + .supply = "DCVDD", +}; + +static struct regulator_init_data wm8994_ldo1_data = { + .constraints = { + .name = "AVDD1_3.0V", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &wm8994_avdd1_supply, +}; + +static struct regulator_init_data wm8994_ldo2_data = { + .constraints = { + .name = "DCVDD_1.0V", + }, + .num_consumer_supplies = 1, + .consumer_supplies = &wm8994_dcvdd_supply, +}; + +static struct wm8994_pdata wm8994_platform_data = { + /* configure gpio1 function: 0x0001(Logic level input/output) */ + .gpio_defaults[0] = 0x0001, + /* configure gpio3/4/5/7 function for AIF2 voice */ + .gpio_defaults[2] = 0x8100, + .gpio_defaults[3] = 0x8100, + .gpio_defaults[4] = 0x8100, + .gpio_defaults[6] = 0x0100, + /* configure gpio8/9/10/11 function for AIF3 BT */ + .gpio_defaults[7] = 0x8100, + .gpio_defaults[8] = 0x0100, + .gpio_defaults[9] = 0x0100, + .gpio_defaults[10] = 0x0100, + .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */ + .ldo[1] = { 0, NULL, &wm8994_ldo2_data }, +}; + /* GPIO I2C PMIC */ #define AP_I2C_GPIO_PMIC_BUS_4 4 static struct i2c_gpio_platform_data aquila_i2c_gpio_pmic_data = { @@ -404,6 +519,29 @@ static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = { #endif }; +/* GPIO I2C AP 1.8V */ +#define AP_I2C_GPIO_BUS_5 5 +static struct i2c_gpio_platform_data aquila_i2c_gpio5_data = { + .sda_pin = S5PV210_MP05(3), /* XM0ADDR_11 */ + .scl_pin = S5PV210_MP05(2), /* XM0ADDR_10 */ +}; + +static struct platform_device aquila_i2c_gpio5 = { + .name = "i2c-gpio", + .id = AP_I2C_GPIO_BUS_5, + .dev = { + .platform_data = &aquila_i2c_gpio5_data, + }, +}; + +static struct i2c_board_info i2c_gpio5_devs[] __initdata = { + { + /* CS/ADDR = low 0x34 (FYI: high = 0x36) */ + I2C_BOARD_INFO("wm8994", 0x1a), + .platform_data = &wm8994_platform_data, + }, +}; + /* PMIC Power button */ static struct gpio_keys_button aquila_gpio_keys_table[] = { { @@ -475,17 +613,43 @@ static void aquila_setup_sdhci(void) static struct platform_device *aquila_devices[] __initdata = { &aquila_i2c_gpio_pmic, + &aquila_i2c_gpio5, &aquila_device_gpiokeys, &s3c_device_fb, - &s5pc110_device_onenand, + &s5p_device_onenand, &s3c_device_hsmmc0, &s3c_device_hsmmc1, &s3c_device_hsmmc2, &s5p_device_fimc0, &s5p_device_fimc1, &s5p_device_fimc2, + &s5pv210_device_iis0, + &wm8994_fixed_voltage0, + &wm8994_fixed_voltage1, }; +static void __init aquila_sound_init(void) +{ + unsigned int gpio; + + /* CODEC_XTAL_EN + * + * The Aquila board have a oscillator which provide main clock + * to WM8994 codec. The oscillator provide 24MHz clock to WM8994 + * clock. Set gpio setting of "CODEC_XTAL_EN" to enable a oscillator. + * */ + gpio = S5PV210_GPH3(2); /* XEINT_26 */ + gpio_request(gpio, "CODEC_XTAL_EN"); + s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + + /* Ths main clock of WM8994 codec uses the output of CLKOUT pin. + * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS) + * because it needs 24MHz clock to operate WM8994 codec. + */ + __raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS); +} + static void __init aquila_map_io(void) { s5p_init_io(NULL, 0, S5P_VA_CHIPID); @@ -506,6 +670,11 @@ static void __init aquila_machine_init(void) s3c_fimc_setname(1, "s5p-fimc"); s3c_fimc_setname(2, "s5p-fimc"); + /* SOUND */ + aquila_sound_init(); + i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs, + ARRAY_SIZE(i2c_gpio5_devs)); + /* FB */ s3c_fb_set_platdata(&aquila_lcd_pdata); diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index 53754d7d364e..bae573b4ff7a 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -15,7 +15,13 @@ #include <linux/fb.h> #include <linux/i2c.h> #include <linux/i2c-gpio.h> +#include <linux/i2c/qt602240_ts.h> #include <linux/mfd/max8998.h> +#include <linux/mfd/wm8994/pdata.h> +#include <linux/regulator/fixed.h> +#include <linux/spi/spi.h> +#include <linux/spi/spi_gpio.h> +#include <linux/lcd.h> #include <linux/gpio_keys.h> #include <linux/input.h> #include <linux/gpio.h> @@ -35,7 +41,10 @@ #include <plat/devs.h> #include <plat/cpu.h> #include <plat/fb.h> +#include <plat/iic.h> +#include <plat/keypad.h> #include <plat/sdhci.h> +#include <plat/clock.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ #define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ @@ -87,13 +96,12 @@ static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win goni_fb_win0 = { .win_mode = { - .pixclock = 1000000000000ULL / ((16+16+2+480)*(28+3+2+800)*55), .left_margin = 16, .right_margin = 16, - .upper_margin = 3, + .upper_margin = 2, .lower_margin = 28, .hsync_len = 2, - .vsync_len = 2, + .vsync_len = 1, .xres = 480, .yres = 800, .refresh = 55, @@ -111,9 +119,160 @@ static struct s3c_fb_platdata goni_lcd_pdata __initdata = { .setup_gpio = s5pv210_fb_gpio_setup_24bpp, }; +static int lcd_power_on(struct lcd_device *ld, int enable) +{ + return 1; +} + +static int reset_lcd(struct lcd_device *ld) +{ + static unsigned int first = 1; + int reset_gpio = -1; + + reset_gpio = S5PV210_MP05(5); + + if (first) { + gpio_request(reset_gpio, "MLCD_RST"); + first = 0; + } + + gpio_direction_output(reset_gpio, 1); + return 1; +} + +static struct lcd_platform_data goni_lcd_platform_data = { + .reset = reset_lcd, + .power_on = lcd_power_on, + .lcd_enabled = 0, + .reset_delay = 120, /* 120ms */ + .power_on_delay = 25, /* 25ms */ + .power_off_delay = 200, /* 200ms */ +}; + +#define LCD_BUS_NUM 3 +static struct spi_board_info spi_board_info[] __initdata = { + { + .modalias = "s6e63m0", + .platform_data = &goni_lcd_platform_data, + .max_speed_hz = 1200000, + .bus_num = LCD_BUS_NUM, + .chip_select = 0, + .mode = SPI_MODE_3, + .controller_data = (void *)S5PV210_MP01(1), /* DISPLAY_CS */ + }, +}; + +static struct spi_gpio_platform_data lcd_spi_gpio_data = { + .sck = S5PV210_MP04(1), /* DISPLAY_CLK */ + .mosi = S5PV210_MP04(3), /* DISPLAY_SI */ + .miso = SPI_GPIO_NO_MISO, + .num_chipselect = 1, +}; + +static struct platform_device goni_spi_gpio = { + .name = "spi_gpio", + .id = LCD_BUS_NUM, + .dev = { + .parent = &s3c_device_fb.dev, + .platform_data = &lcd_spi_gpio_data, + }, +}; + +/* KEYPAD */ +static uint32_t keymap[] __initdata = { + /* KEY(row, col, keycode) */ + KEY(0, 1, KEY_MENU), /* Send */ + KEY(0, 2, KEY_BACK), /* End */ + KEY(1, 1, KEY_CONFIG), /* Half shot */ + KEY(1, 2, KEY_VOLUMEUP), + KEY(2, 1, KEY_CAMERA), /* Full shot */ + KEY(2, 2, KEY_VOLUMEDOWN), +}; + +static struct matrix_keymap_data keymap_data __initdata = { + .keymap = keymap, + .keymap_size = ARRAY_SIZE(keymap), +}; + +static struct samsung_keypad_platdata keypad_data __initdata = { + .keymap_data = &keymap_data, + .rows = 3, + .cols = 3, +}; + +/* Radio */ +static struct i2c_board_info i2c1_devs[] __initdata = { + { + I2C_BOARD_INFO("si470x", 0x10), + }, +}; + +static void __init goni_radio_init(void) +{ + int gpio; + + gpio = S5PV210_GPJ2(4); /* XMSMDATA_4 */ + gpio_request(gpio, "FM_INT"); + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf)); + i2c1_devs[0].irq = gpio_to_irq(gpio); + + gpio = S5PV210_GPJ2(5); /* XMSMDATA_5 */ + gpio_request(gpio, "FM_RST"); + gpio_direction_output(gpio, 1); +} + +/* TSP */ +static struct qt602240_platform_data qt602240_platform_data = { + .x_line = 17, + .y_line = 11, + .x_size = 800, + .y_size = 480, + .blen = 0x21, + .threshold = 0x28, + .voltage = 2800000, /* 2.8V */ + .orient = QT602240_DIAGONAL, +}; + +static struct s3c2410_platform_i2c i2c2_data __initdata = { + .flags = 0, + .bus_num = 2, + .slave_addr = 0x10, + .frequency = 400 * 1000, + .sda_delay = 100, +}; + +static struct i2c_board_info i2c2_devs[] __initdata = { + { + I2C_BOARD_INFO("qt602240_ts", 0x4a), + .platform_data = &qt602240_platform_data, + }, +}; + +static void __init goni_tsp_init(void) +{ + int gpio; + + gpio = S5PV210_GPJ1(3); /* XMSMADDR_11 */ + gpio_request(gpio, "TSP_LDO_ON"); + gpio_direction_output(gpio, 1); + gpio_export(gpio, 0); + + gpio = S5PV210_GPJ0(5); /* XMSMADDR_5 */ + gpio_request(gpio, "TSP_INT"); + + s5p_register_gpio_interrupt(gpio); + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); + i2c2_devs[0].irq = gpio_to_irq(gpio); +} + /* MAX8998 regulators */ #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE) +static struct regulator_consumer_supply goni_ldo5_consumers[] = { + REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"), +}; + static struct regulator_init_data goni_ldo2_data = { .constraints = { .name = "VALIVE_1.1V", @@ -153,6 +312,8 @@ static struct regulator_init_data goni_ldo5_data = { .max_uV = 2800000, .apply_uV = 1, }, + .num_consumer_supplies = ARRAY_SIZE(goni_ldo5_consumers), + .consumer_supplies = goni_ldo5_consumers, }; static struct regulator_init_data goni_ldo6_data = { @@ -360,6 +521,119 @@ static struct max8998_platform_data goni_max8998_pdata = { }; #endif +static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = { + { + .dev_name = "5-001a", + .supply = "DBVDD", + }, { + .dev_name = "5-001a", + .supply = "AVDD2", + }, { + .dev_name = "5-001a", + .supply = "CPVDD", + }, +}; + +static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = { + { + .dev_name = "5-001a", + .supply = "SPKVDD1", + }, { + .dev_name = "5-001a", + .supply = "SPKVDD2", + }, +}; + +static struct regulator_init_data wm8994_fixed_voltage0_init_data = { + .constraints = { + .always_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies), + .consumer_supplies = wm8994_fixed_voltage0_supplies, +}; + +static struct regulator_init_data wm8994_fixed_voltage1_init_data = { + .constraints = { + .always_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies), + .consumer_supplies = wm8994_fixed_voltage1_supplies, +}; + +static struct fixed_voltage_config wm8994_fixed_voltage0_config = { + .supply_name = "VCC_1.8V_PDA", + .microvolts = 1800000, + .gpio = -EINVAL, + .init_data = &wm8994_fixed_voltage0_init_data, +}; + +static struct fixed_voltage_config wm8994_fixed_voltage1_config = { + .supply_name = "V_BAT", + .microvolts = 3700000, + .gpio = -EINVAL, + .init_data = &wm8994_fixed_voltage1_init_data, +}; + +static struct platform_device wm8994_fixed_voltage0 = { + .name = "reg-fixed-voltage", + .id = 0, + .dev = { + .platform_data = &wm8994_fixed_voltage0_config, + }, +}; + +static struct platform_device wm8994_fixed_voltage1 = { + .name = "reg-fixed-voltage", + .id = 1, + .dev = { + .platform_data = &wm8994_fixed_voltage1_config, + }, +}; + +static struct regulator_consumer_supply wm8994_avdd1_supply = { + .dev_name = "5-001a", + .supply = "AVDD1", +}; + +static struct regulator_consumer_supply wm8994_dcvdd_supply = { + .dev_name = "5-001a", + .supply = "DCVDD", +}; + +static struct regulator_init_data wm8994_ldo1_data = { + .constraints = { + .name = "AVDD1_3.0V", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &wm8994_avdd1_supply, +}; + +static struct regulator_init_data wm8994_ldo2_data = { + .constraints = { + .name = "DCVDD_1.0V", + }, + .num_consumer_supplies = 1, + .consumer_supplies = &wm8994_dcvdd_supply, +}; + +static struct wm8994_pdata wm8994_platform_data = { + /* configure gpio1 function: 0x0001(Logic level input/output) */ + .gpio_defaults[0] = 0x0001, + /* configure gpio3/4/5/7 function for AIF2 voice */ + .gpio_defaults[2] = 0x8100, + .gpio_defaults[3] = 0x8100, + .gpio_defaults[4] = 0x8100, + .gpio_defaults[6] = 0x0100, + /* configure gpio8/9/10/11 function for AIF3 BT */ + .gpio_defaults[7] = 0x8100, + .gpio_defaults[8] = 0x0100, + .gpio_defaults[9] = 0x0100, + .gpio_defaults[10] = 0x0100, + .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */ + .ldo[1] = { 0, NULL, &wm8994_ldo2_data }, +}; + /* GPIO I2C PMIC */ #define AP_I2C_GPIO_PMIC_BUS_4 4 static struct i2c_gpio_platform_data goni_i2c_gpio_pmic_data = { @@ -385,6 +659,29 @@ static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = { #endif }; +/* GPIO I2C AP 1.8V */ +#define AP_I2C_GPIO_BUS_5 5 +static struct i2c_gpio_platform_data goni_i2c_gpio5_data = { + .sda_pin = S5PV210_MP05(3), /* XM0ADDR_11 */ + .scl_pin = S5PV210_MP05(2), /* XM0ADDR_10 */ +}; + +static struct platform_device goni_i2c_gpio5 = { + .name = "i2c-gpio", + .id = AP_I2C_GPIO_BUS_5, + .dev = { + .platform_data = &goni_i2c_gpio5_data, + }, +}; + +static struct i2c_board_info i2c_gpio5_devs[] __initdata = { + { + /* CS/ADDR = low 0x34 (FYI: high = 0x36) */ + I2C_BOARD_INFO("wm8994", 0x1a), + .platform_data = &wm8994_platform_data, + }, +}; + /* PMIC Power button */ static struct gpio_keys_button goni_gpio_keys_table[] = { { @@ -444,11 +741,37 @@ static struct s3c_sdhci_platdata goni_hsmmc2_data __initdata = { .ext_cd_gpio_invert = 1, }; +static struct regulator_consumer_supply mmc2_supplies[] = { + REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), +}; + +static struct regulator_init_data mmc2_fixed_voltage_init_data = { + .constraints = { + .name = "V_TF_2.8V", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(mmc2_supplies), + .consumer_supplies = mmc2_supplies, +}; + +static struct fixed_voltage_config mmc2_fixed_voltage_config = { + .supply_name = "EXT_FLASH_EN", + .microvolts = 2800000, + .gpio = GONI_EXT_FLASH_EN, + .enable_high = true, + .init_data = &mmc2_fixed_voltage_init_data, +}; + +static struct platform_device mmc2_fixed_voltage = { + .name = "reg-fixed-voltage", + .id = 2, + .dev = { + .platform_data = &mmc2_fixed_voltage_config, + }, +}; + static void goni_setup_sdhci(void) { - gpio_request(GONI_EXT_FLASH_EN, "FLASH_EN"); - gpio_direction_output(GONI_EXT_FLASH_EN, 1); - s3c_sdhci0_set_platdata(&goni_hsmmc0_data); s3c_sdhci1_set_platdata(&goni_hsmmc1_data); s3c_sdhci2_set_platdata(&goni_hsmmc2_data); @@ -456,8 +779,11 @@ static void goni_setup_sdhci(void) static struct platform_device *goni_devices[] __initdata = { &s3c_device_fb, - &s5pc110_device_onenand, + &s5p_device_onenand, + &goni_spi_gpio, &goni_i2c_gpio_pmic, + &goni_i2c_gpio5, + &mmc2_fixed_voltage, &goni_device_gpiokeys, &s5p_device_fimc0, &s5p_device_fimc1, @@ -465,8 +791,24 @@ static struct platform_device *goni_devices[] __initdata = { &s3c_device_hsmmc0, &s3c_device_hsmmc1, &s3c_device_hsmmc2, + &s5pv210_device_iis0, + &s3c_device_usb_hsotg, + &samsung_device_keypad, + &s3c_device_i2c1, + &s3c_device_i2c2, + &wm8994_fixed_voltage0, + &wm8994_fixed_voltage1, }; +static void __init goni_sound_init(void) +{ + /* Ths main clock of WM8994 codec uses the output of CLKOUT pin. + * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS) + * because it needs 24MHz clock to operate WM8994 codec. + */ + __raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS); +} + static void __init goni_map_io(void) { s5p_init_io(NULL, 0, S5P_VA_CHIPID); @@ -476,6 +818,20 @@ static void __init goni_map_io(void) static void __init goni_machine_init(void) { + /* Radio: call before I2C 1 registeration */ + goni_radio_init(); + + /* I2C1 */ + s3c_i2c1_set_platdata(NULL); + i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs)); + + /* TSP: call before I2C 2 registeration */ + goni_tsp_init(); + + /* I2C2 */ + s3c_i2c2_set_platdata(&i2c2_data); + i2c_register_board_info(2, i2c2_devs, ARRAY_SIZE(i2c2_devs)); + /* PMIC */ goni_pmic_init(); i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs, @@ -483,9 +839,22 @@ static void __init goni_machine_init(void) /* SDHCI */ goni_setup_sdhci(); + /* SOUND */ + goni_sound_init(); + i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs, + ARRAY_SIZE(i2c_gpio5_devs)); + /* FB */ s3c_fb_set_platdata(&goni_lcd_pdata); + /* SPI */ + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); + + /* KEYPAD */ + samsung_keypad_set_platdata(&keypad_data); + + clk_xusbxti.rate = 24000000; + platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices)); } diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c index 8211bb87c54b..19b532432da2 100644 --- a/arch/arm/mach-s5pv210/mach-smdkc110.c +++ b/arch/arm/mach-s5pv210/mach-smdkc110.c @@ -28,6 +28,7 @@ #include <plat/cpu.h> #include <plat/ata.h> #include <plat/iic.h> +#include <plat/pm.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ #define SMDKC110_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ @@ -81,6 +82,7 @@ static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = { static struct platform_device *smdkc110_devices[] __initdata = { &s5pv210_device_iis0, &s5pv210_device_ac97, + &s5pv210_device_spdif, &s3c_device_cfcon, &s3c_device_i2c0, &s3c_device_i2c1, @@ -110,6 +112,8 @@ static void __init smdkc110_map_io(void) static void __init smdkc110_machine_init(void) { + s3c_pm_init(); + s3c_i2c0_set_platdata(NULL); s3c_i2c1_set_platdata(NULL); s3c_i2c2_set_platdata(NULL); diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index fbbc0a3c3738..ad5f7ea46817 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -31,6 +31,7 @@ #include <plat/ata.h> #include <plat/iic.h> #include <plat/keypad.h> +#include <plat/pm.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ #define SMDKV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ @@ -103,6 +104,7 @@ static struct samsung_keypad_platdata smdkv210_keypad_data __initdata = { static struct platform_device *smdkv210_devices[] __initdata = { &s5pv210_device_iis0, &s5pv210_device_ac97, + &s5pv210_device_spdif, &s3c_device_adc, &s3c_device_cfcon, &s3c_device_hsmmc0, @@ -145,6 +147,8 @@ static void __init smdkv210_map_io(void) static void __init smdkv210_machine_init(void) { + s3c_pm_init(); + samsung_keypad_set_platdata(&smdkv210_keypad_data); s3c24xx_ts_set_platdata(&s3c_ts_platform); diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c new file mode 100644 index 000000000000..043c938806b0 --- /dev/null +++ b/arch/arm/mach-s5pv210/mach-torbreck.c @@ -0,0 +1,131 @@ +/* linux/arch/arm/mach-s5pv210/mach-torbreck.c + * + * Copyright (c) 2010 aESOP Community + * http://www.aesop.or.kr/ + * + * 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/i2c.h> +#include <linux/init.h> +#include <linux/serial_core.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/setup.h> +#include <asm/mach-types.h> + +#include <mach/map.h> +#include <mach/regs-clock.h> + +#include <plat/regs-serial.h> +#include <plat/s5pv210.h> +#include <plat/devs.h> +#include <plat/cpu.h> +#include <plat/iic.h> + +/* Following are default values for UCON, ULCON and UFCON UART registers */ +#define TORBRECK_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ + S3C2410_UCON_RXILEVEL | \ + S3C2410_UCON_TXIRQMODE | \ + S3C2410_UCON_RXIRQMODE | \ + S3C2410_UCON_RXFIFO_TOI | \ + S3C2443_UCON_RXERR_IRQEN) + +#define TORBRECK_ULCON_DEFAULT S3C2410_LCON_CS8 + +#define TORBRECK_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ + S5PV210_UFCON_TXTRIG4 | \ + S5PV210_UFCON_RXTRIG4) + +static struct s3c2410_uartcfg torbreck_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = TORBRECK_UCON_DEFAULT, + .ulcon = TORBRECK_ULCON_DEFAULT, + .ufcon = TORBRECK_UFCON_DEFAULT, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = TORBRECK_UCON_DEFAULT, + .ulcon = TORBRECK_ULCON_DEFAULT, + .ufcon = TORBRECK_UFCON_DEFAULT, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = TORBRECK_UCON_DEFAULT, + .ulcon = TORBRECK_ULCON_DEFAULT, + .ufcon = TORBRECK_UFCON_DEFAULT, + }, + [3] = { + .hwport = 3, + .flags = 0, + .ucon = TORBRECK_UCON_DEFAULT, + .ulcon = TORBRECK_ULCON_DEFAULT, + .ufcon = TORBRECK_UFCON_DEFAULT, + }, +}; + +static struct platform_device *torbreck_devices[] __initdata = { + &s5pv210_device_iis0, + &s3c_device_cfcon, + &s3c_device_hsmmc0, + &s3c_device_hsmmc1, + &s3c_device_hsmmc2, + &s3c_device_hsmmc3, + &s3c_device_i2c0, + &s3c_device_i2c1, + &s3c_device_i2c2, + &s3c_device_rtc, + &s3c_device_wdt, +}; + +static struct i2c_board_info torbreck_i2c_devs0[] __initdata = { + /* To Be Updated */ +}; + +static struct i2c_board_info torbreck_i2c_devs1[] __initdata = { + /* To Be Updated */ +}; + +static struct i2c_board_info torbreck_i2c_devs2[] __initdata = { + /* To Be Updated */ +}; + +static void __init torbreck_map_io(void) +{ + s5p_init_io(NULL, 0, S5P_VA_CHIPID); + s3c24xx_init_clocks(24000000); + s3c24xx_init_uarts(torbreck_uartcfgs, ARRAY_SIZE(torbreck_uartcfgs)); +} + +static void __init torbreck_machine_init(void) +{ + s3c_i2c0_set_platdata(NULL); + s3c_i2c1_set_platdata(NULL); + s3c_i2c2_set_platdata(NULL); + i2c_register_board_info(0, torbreck_i2c_devs0, + ARRAY_SIZE(torbreck_i2c_devs0)); + i2c_register_board_info(1, torbreck_i2c_devs1, + ARRAY_SIZE(torbreck_i2c_devs1)); + i2c_register_board_info(2, torbreck_i2c_devs2, + ARRAY_SIZE(torbreck_i2c_devs2)); + + platform_add_devices(torbreck_devices, ARRAY_SIZE(torbreck_devices)); +} + +MACHINE_START(TORBRECK, "TORBRECK") + /* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */ + .boot_params = S5P_PA_SDRAM + 0x100, + .init_irq = s5pv210_init_irq, + .map_io = torbreck_map_io, + .init_machine = torbreck_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c new file mode 100644 index 000000000000..549d7924fd4c --- /dev/null +++ b/arch/arm/mach-s5pv210/pm.c @@ -0,0 +1,166 @@ +/* linux/arch/arm/mach-s5pv210/pm.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5PV210 - Power Management support + * + * Based on arch/arm/mach-s3c2410/pm.c + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * 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/init.h> +#include <linux/suspend.h> +#include <linux/io.h> + +#include <plat/cpu.h> +#include <plat/pm.h> +#include <plat/regs-timer.h> + +#include <mach/regs-irq.h> +#include <mach/regs-clock.h> + +static struct sleep_save s5pv210_core_save[] = { + /* Clock source */ + SAVE_ITEM(S5P_CLK_SRC0), + SAVE_ITEM(S5P_CLK_SRC1), + SAVE_ITEM(S5P_CLK_SRC2), + SAVE_ITEM(S5P_CLK_SRC3), + SAVE_ITEM(S5P_CLK_SRC4), + SAVE_ITEM(S5P_CLK_SRC5), + SAVE_ITEM(S5P_CLK_SRC6), + + /* Clock source Mask */ + SAVE_ITEM(S5P_CLK_SRC_MASK0), + SAVE_ITEM(S5P_CLK_SRC_MASK1), + + /* Clock Divider */ + SAVE_ITEM(S5P_CLK_DIV0), + SAVE_ITEM(S5P_CLK_DIV1), + SAVE_ITEM(S5P_CLK_DIV2), + SAVE_ITEM(S5P_CLK_DIV3), + SAVE_ITEM(S5P_CLK_DIV4), + SAVE_ITEM(S5P_CLK_DIV5), + SAVE_ITEM(S5P_CLK_DIV6), + SAVE_ITEM(S5P_CLK_DIV7), + + /* Clock Main Gate */ + SAVE_ITEM(S5P_CLKGATE_MAIN0), + SAVE_ITEM(S5P_CLKGATE_MAIN1), + SAVE_ITEM(S5P_CLKGATE_MAIN2), + + /* Clock source Peri Gate */ + SAVE_ITEM(S5P_CLKGATE_PERI0), + SAVE_ITEM(S5P_CLKGATE_PERI1), + + /* Clock source SCLK Gate */ + SAVE_ITEM(S5P_CLKGATE_SCLK0), + SAVE_ITEM(S5P_CLKGATE_SCLK1), + + /* Clock IP Clock gate */ + SAVE_ITEM(S5P_CLKGATE_IP0), + SAVE_ITEM(S5P_CLKGATE_IP1), + SAVE_ITEM(S5P_CLKGATE_IP2), + SAVE_ITEM(S5P_CLKGATE_IP3), + SAVE_ITEM(S5P_CLKGATE_IP4), + + /* Clock Blcok and Bus gate */ + SAVE_ITEM(S5P_CLKGATE_BLOCK), + SAVE_ITEM(S5P_CLKGATE_BUS0), + + /* Clock ETC */ + SAVE_ITEM(S5P_CLK_OUT), + SAVE_ITEM(S5P_MDNIE_SEL), + + /* PWM Register */ + SAVE_ITEM(S3C2410_TCFG0), + SAVE_ITEM(S3C2410_TCFG1), + SAVE_ITEM(S3C64XX_TINT_CSTAT), + SAVE_ITEM(S3C2410_TCON), + SAVE_ITEM(S3C2410_TCNTB(0)), + SAVE_ITEM(S3C2410_TCMPB(0)), + SAVE_ITEM(S3C2410_TCNTO(0)), +}; + +void s5pv210_cpu_suspend(void) +{ + unsigned long tmp; + + /* issue the standby signal into the pm unit. Note, we + * issue a write-buffer drain just in case */ + + tmp = 0; + + 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" + "wfi" : : "r" (tmp)); + + /* we should never get past here */ + panic("sleep resumed to originator?"); +} + +static void s5pv210_pm_prepare(void) +{ + unsigned int tmp; + + /* ensure at least INFORM0 has the resume address */ + __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0); + + tmp = __raw_readl(S5P_SLEEP_CFG); + tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN); + __raw_writel(tmp, S5P_SLEEP_CFG); + + /* WFI for SLEEP mode configuration by SYSCON */ + tmp = __raw_readl(S5P_PWR_CFG); + tmp &= S5P_CFG_WFI_CLEAN; + tmp |= S5P_CFG_WFI_SLEEP; + __raw_writel(tmp, S5P_PWR_CFG); + + /* SYSCON interrupt handling disable */ + tmp = __raw_readl(S5P_OTHERS); + tmp |= S5P_OTHER_SYSC_INTOFF; + __raw_writel(tmp, S5P_OTHERS); + + s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save)); +} + +static int s5pv210_pm_add(struct sys_device *sysdev) +{ + pm_cpu_prep = s5pv210_pm_prepare; + pm_cpu_sleep = s5pv210_cpu_suspend; + + return 0; +} + +static int s5pv210_pm_resume(struct sys_device *dev) +{ + u32 tmp; + + tmp = __raw_readl(S5P_OTHERS); + tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF |\ + S5P_OTHERS_RET_MMC | S5P_OTHERS_RET_UART); + __raw_writel(tmp , S5P_OTHERS); + + s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save)); + + return 0; +} + +static struct sysdev_driver s5pv210_pm_driver = { + .add = s5pv210_pm_add, + .resume = s5pv210_pm_resume, +}; + +static __init int s5pv210_pm_drvinit(void) +{ + return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver); +} +arch_initcall(s5pv210_pm_drvinit); diff --git a/arch/arm/mach-s5pv210/setup-fb-24bpp.c b/arch/arm/mach-s5pv210/setup-fb-24bpp.c index 928cf1f125fa..e932ebfac56d 100644 --- a/arch/arm/mach-s5pv210/setup-fb-24bpp.c +++ b/arch/arm/mach-s5pv210/setup-fb-24bpp.c @@ -21,33 +21,21 @@ #include <mach/regs-clock.h> #include <plat/gpio-cfg.h> -void s5pv210_fb_gpio_setup_24bpp(void) +static void s5pv210_fb_cfg_gpios(unsigned int base, unsigned int nr) { - unsigned int gpio = 0; - - for (gpio = S5PV210_GPF0(0); gpio <= S5PV210_GPF0(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } + s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2)); - for (gpio = S5PV210_GPF1(0); gpio <= S5PV210_GPF1(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } + for (; nr > 0; nr--, base++) + s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4); +} - for (gpio = S5PV210_GPF2(0); gpio <= S5PV210_GPF2(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } - for (gpio = S5PV210_GPF3(0); gpio <= S5PV210_GPF3(3); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } +void s5pv210_fb_gpio_setup_24bpp(void) +{ + s5pv210_fb_cfg_gpios(S5PV210_GPF0(0), 8); + s5pv210_fb_cfg_gpios(S5PV210_GPF1(0), 8); + s5pv210_fb_cfg_gpios(S5PV210_GPF2(0), 8); + s5pv210_fb_cfg_gpios(S5PV210_GPF3(0), 4); /* Set DISPLAY_CONTROL register for Display path selection. * diff --git a/arch/arm/mach-s5pv210/setup-i2c0.c b/arch/arm/mach-s5pv210/setup-i2c0.c index d38f7cb7e662..0f1cc3a1c1e8 100644 --- a/arch/arm/mach-s5pv210/setup-i2c0.c +++ b/arch/arm/mach-s5pv210/setup-i2c0.c @@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */ void s3c_i2c0_cfg_gpio(struct platform_device *dev) { - s3c_gpio_cfgpin(S5PV210_GPD1(0), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV210_GPD1(0), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5PV210_GPD1(1), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV210_GPD1(1), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PV210_GPD1(0), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); } diff --git a/arch/arm/mach-s5pv210/setup-i2c1.c b/arch/arm/mach-s5pv210/setup-i2c1.c index 148bb7857d89..f61365a34c56 100644 --- a/arch/arm/mach-s5pv210/setup-i2c1.c +++ b/arch/arm/mach-s5pv210/setup-i2c1.c @@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */ void s3c_i2c1_cfg_gpio(struct platform_device *dev) { - s3c_gpio_cfgpin(S5PV210_GPD1(2), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV210_GPD1(2), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5PV210_GPD1(3), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV210_GPD1(3), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PV210_GPD1(2), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); } diff --git a/arch/arm/mach-s5pv210/setup-i2c2.c b/arch/arm/mach-s5pv210/setup-i2c2.c index 2396cb8c373e..2f91b5cefbc6 100644 --- a/arch/arm/mach-s5pv210/setup-i2c2.c +++ b/arch/arm/mach-s5pv210/setup-i2c2.c @@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */ void s3c_i2c2_cfg_gpio(struct platform_device *dev) { - s3c_gpio_cfgpin(S5PV210_GPD1(4), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV210_GPD1(4), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5PV210_GPD1(5), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV210_GPD1(5), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PV210_GPD1(4), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); } diff --git a/arch/arm/mach-s5pv210/setup-ide.c b/arch/arm/mach-s5pv210/setup-ide.c index b558b1cc8d60..ea123d546bd2 100644 --- a/arch/arm/mach-s5pv210/setup-ide.c +++ b/arch/arm/mach-s5pv210/setup-ide.c @@ -15,36 +15,25 @@ #include <plat/gpio-cfg.h> +static void s5pv210_ide_cfg_gpios(unsigned int base, unsigned int nr) +{ + s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4)); + + for (; nr > 0; nr--, base++) + s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4); +} + void s5pv210_ide_setup_gpio(void) { - unsigned int gpio = 0; - - for (gpio = S5PV210_GPJ0(0); gpio <= S5PV210_GPJ0(7); gpio++) { - /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, - CF_DMACK */ - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } - - for (gpio = S5PV210_GPJ2(0); gpio <= S5PV210_GPJ2(7); gpio++) { - /*CF_Data[0 - 7] */ - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } - - for (gpio = S5PV210_GPJ3(0); gpio <= S5PV210_GPJ3(7); gpio++) { - /* CF_Data[8 - 15] */ - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } - - for (gpio = S5PV210_GPJ4(0); gpio <= S5PV210_GPJ4(3); gpio++) { - /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */ - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); - } + /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */ + s5pv210_ide_cfg_gpios(S5PV210_GPJ0(0), 8); + + /* CF_Data[0 - 7] */ + s5pv210_ide_cfg_gpios(S5PV210_GPJ2(0), 8); + + /* CF_Data[8 - 15] */ + s5pv210_ide_cfg_gpios(S5PV210_GPJ3(0), 8); + + /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */ + s5pv210_ide_cfg_gpios(S5PV210_GPJ4(0), 4); } diff --git a/arch/arm/mach-s5pv210/setup-keypad.c b/arch/arm/mach-s5pv210/setup-keypad.c index 37b2790aafc3..c56420a52f48 100644 --- a/arch/arm/mach-s5pv210/setup-keypad.c +++ b/arch/arm/mach-s5pv210/setup-keypad.c @@ -16,19 +16,9 @@ void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) { - unsigned int gpio, end; - /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */ - end = S5PV210_GPH3(rows); - for (gpio = S5PV210_GPH3(0); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPH3(0), rows, S3C_GPIO_SFN(3)); /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */ - end = S5PV210_GPH2(cols); - for (gpio = S5PV210_GPH2(0); gpio < end; gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPH2(0), cols, S3C_GPIO_SFN(3)); } diff --git a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c index b18587b1ec58..746777d56df9 100644 --- a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c +++ b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c @@ -26,26 +26,17 @@ void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) { struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; - unsigned int gpio; /* Set all the necessary GPG0/GPG1 pins to special-function 2 */ - for (gpio = S5PV210_GPG0(0); gpio < S5PV210_GPG0(2); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPG0(0), 2, S3C_GPIO_SFN(2)); + switch (width) { case 8: /* GPG1[3:6] special-funtion 3 */ - for (gpio = S5PV210_GPG1(3); gpio <= S5PV210_GPG1(6); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(3)); case 4: /* GPG0[3:6] special-funtion 2 */ - for (gpio = S5PV210_GPG0(3); gpio <= S5PV210_GPG0(6); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPG0(3), 4, S3C_GPIO_SFN(2)); default: break; } @@ -59,19 +50,12 @@ void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) { struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; - unsigned int gpio; /* Set all the necessary GPG1[0:1] pins to special-function 2 */ - for (gpio = S5PV210_GPG1(0); gpio < S5PV210_GPG1(2); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPG1(0), 2, S3C_GPIO_SFN(2)); /* Data pin GPG1[3:6] to special-function 2 */ - for (gpio = S5PV210_GPG1(3); gpio <= S5PV210_GPG1(6); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(2)); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP); @@ -82,27 +66,17 @@ void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) { struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; - unsigned int gpio; /* Set all the necessary GPG2[0:1] pins to special-function 2 */ - for (gpio = S5PV210_GPG2(0); gpio < S5PV210_GPG2(2); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPG2(0), 2, S3C_GPIO_SFN(2)); switch (width) { case 8: /* Data pin GPG3[3:6] to special-function 3 */ - for (gpio = S5PV210_GPG3(3); gpio <= S5PV210_GPG3(6); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(3)); case 4: /* Data pin GPG2[3:6] to special-function 2 */ - for (gpio = S5PV210_GPG2(3); gpio <= S5PV210_GPG2(6); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPG2(3), 4, S3C_GPIO_SFN(2)); default: break; } @@ -116,19 +90,12 @@ void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width) { struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; - unsigned int gpio; - /* Set all the necessary GPG3[0:2] pins to special-function 2 */ - for (gpio = S5PV210_GPG3(0); gpio < S5PV210_GPG3(2); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + /* Set all the necessary GPG3[0:1] pins to special-function 2 */ + s3c_gpio_cfgrange_nopull(S5PV210_GPG3(0), 2, S3C_GPIO_SFN(2)); /* Data pin GPG3[3:6] to special-function 2 */ - for (gpio = S5PV210_GPG3(3); gpio <= S5PV210_GPG3(6); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } + s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(2)); if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { s3c_gpio_setpull(S5PV210_GPG3(2), S3C_GPIO_PULL_UP); diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S new file mode 100644 index 000000000000..d4d222b716b4 --- /dev/null +++ b/arch/arm/mach-s5pv210/sleep.S @@ -0,0 +1,170 @@ +/* linux/arch/arm/plat-s5p/sleep.S + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5PV210 power Manager (Suspend-To-RAM) support + * Based on S3C2410 sleep code by: + * Ben Dooks, (c) 2004 Simtec Electronics + * + * Based on PXA/SA1100 sleep code by: + * Nicolas Pitre, (c) 2002 Monta Vista Software Inc + * Cliff Brake, (c) 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/memory.h> + + .text + + /* s3c_cpu_save + * + * entry: + * r0 = save address (virtual addr of s3c_sleep_save_phys) + */ + +ENTRY(s3c_cpu_save) + + stmfd sp!, { r3 - r12, lr } + + mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID + mrc p15, 0, r5, c3, c0, 0 @ Domain ID + mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 + mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 + mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control + mrc p15, 0, r9, c1, c0, 0 @ Control register + mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register + mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls + mrc p15, 0, r12, c10, c2, 0 @ Read PRRR + mrc p15, 0, r3, c10, c2, 1 @ READ NMRR + + stmia r0, { r3 - r13 } + + bl s3c_pm_cb_flushcache + + ldr r0, =pm_cpu_sleep + ldr r0, [ r0 ] + mov pc, r0 + +resume_with_mmu: + /* + * After MMU is turned on, restore the previous MMU table. + */ + ldr r9 , =(PAGE_OFFSET - PHYS_OFFSET) + add r4, r4, r9 + str r12, [r4] + + ldmfd sp!, { r3 - r12, pc } + + .ltorg + + .data + + .global s3c_sleep_save_phys +s3c_sleep_save_phys: + .word 0 + + /* sleep magic, to allow the bootloader to check for an valid + * image to resume to. Must be the first word before the + * s3c_cpu_resume entry. + */ + + .word 0x2bedf00d + + /* s3c_cpu_resume + * + * resume code entry for bootloader to call + * + * we must put this code here in the data segment as we have no + * other way of restoring the stack pointer after sleep, and we + * must not write to the code segment (code is read-only) + */ + +ENTRY(s3c_cpu_resume) + mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE + msr cpsr_c, r0 + + mov r1, #0 + mcr p15, 0, r1, c8, c7, 0 @ invalidate TLBs + mcr p15, 0, r1, c7, c5, 0 @ invalidate I Cache + + ldr r0, s3c_sleep_save_phys @ address of restore block + ldmia r0, { r3 - r13 } + + mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID + mcr p15, 0, r5, c3, c0, 0 @ Domain ID + + mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control + mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 + mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 + + mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register + + mov r0, #0 + mcr p15, 0, r0, c8, c7, 0 @ Invalidate I & D TLB + + mov r0, #0 @ restore copro access + mcr p15, 0, r11, c1, c0, 2 @ Co-processor access + mcr p15, 0, r0, c7, c5, 4 + + mcr p15, 0, r12, c10, c2, 0 @ write PRRR + mcr p15, 0, r3, c10, c2, 1 @ write NMRR + + /* + * In Cortex-A8, when MMU is turned on, the pipeline is flushed. + * And there are no valid entries in the MMU table at this point. + * So before turning on the MMU, the MMU entry for the DRAM address + * range is added. After the MMU is turned on, the other entries + * in the MMU table will be restored. + */ + + /* r6 = Translation Table BASE0 */ + mov r4, r6 + mov r4, r4, LSR #14 + mov r4, r4, LSL #14 + + /* Load address for adding to MMU table list */ + ldr r11, =0xE010F000 @ INFORM0 reg. + ldr r10, [r11, #0] + mov r10, r10, LSR #18 + bic r10, r10, #0x3 + orr r4, r4, r10 + + /* Calculate MMU table entry */ + mov r10, r10, LSL #18 + ldr r5, =0x40E + orr r10, r10, r5 + + /* Back up originally data */ + ldr r12, [r4] + + /* Add calculated MMU table entry into MMU table list */ + str r10, [r4] + + ldr r2, =resume_with_mmu + mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc + + nop + nop + nop + nop + nop @ second-to-last before mmu + + mov pc, r2 @ go back to virtual address + + .ltorg diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig index 331b5bd97aba..1150b360f38c 100644 --- a/arch/arm/mach-s5pv310/Kconfig +++ b/arch/arm/mach-s5pv310/Kconfig @@ -11,7 +11,6 @@ if ARCH_S5PV310 config CPU_S5PV310 bool - select PLAT_S5P help Enable S5PV310 CPU support @@ -25,21 +24,105 @@ config S5PV310_SETUP_I2C2 help Common setup code for i2c bus 2. +config S5PV310_SETUP_I2C3 + bool + help + Common setup code for i2c bus 3. + +config S5PV310_SETUP_I2C4 + bool + help + Common setup code for i2c bus 4. + +config S5PV310_SETUP_I2C5 + bool + help + Common setup code for i2c bus 5. + +config S5PV310_SETUP_I2C6 + bool + help + Common setup code for i2c bus 6. + +config S5PV310_SETUP_I2C7 + bool + help + Common setup code for i2c bus 7. + +config S5PV310_SETUP_SDHCI + bool + select S5PV310_SETUP_SDHCI_GPIO + help + Internal helper functions for S5PV310 based SDHCI systems. + +config S5PV310_SETUP_SDHCI_GPIO + bool + help + Common setup code for SDHCI gpio. + # machine support -config MACH_SMDKV310 - bool "SMDKV310" +menu "S5PC210 Machines" + +config MACH_SMDKC210 + bool "SMDKC210" select CPU_S5PV310 - select ARCH_SPARSEMEM_ENABLE + select S3C_DEV_RTC + select S3C_DEV_WDT + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_HSMMC2 + select S3C_DEV_HSMMC3 + select S5PV310_SETUP_SDHCI help - Machine support for Samsung SMDKV310 + Machine support for Samsung SMDKC210 + S5PC210(MCP) is one of package option of S5PV310 config MACH_UNIVERSAL_C210 bool "Mobile UNIVERSAL_C210 Board" select CPU_S5PV310 - select ARCH_SPARSEMEM_ENABLE + select S5P_DEV_ONENAND + select S3C_DEV_I2C1 + select S5PV310_SETUP_I2C1 help Machine support for Samsung Mobile Universal S5PC210 Reference Board. S5PC210(MCP) is one of package option of S5PV310 +endmenu + +menu "S5PV310 Machines" + +config MACH_SMDKV310 + bool "SMDKV310" + select CPU_S5PV310 + select S3C_DEV_RTC + select S3C_DEV_WDT + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_HSMMC2 + select S3C_DEV_HSMMC3 + select S5PV310_SETUP_SDHCI + help + Machine support for Samsung SMDKV310 + +endmenu + +comment "Configuration for HSMMC bus width" + +menu "Use 8-bit bus width" + +config S5PV310_SDHCI_CH0_8BIT + bool "Channel 0 with 8-bit bus" + help + Support HSMMC Channel 0 8-bit bus. + If selected, Channel 1 is disabled. + +config S5PV310_SDHCI_CH2_8BIT + bool "Channel 2 with 8-bit bus" + help + Support HSMMC Channel 2 8-bit bus. + If selected, Channel 3 is disabled. + +endmenu + endif diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile index d5b51c72340f..ac3b4c125558 100644 --- a/arch/arm/mach-s5pv310/Makefile +++ b/arch/arm/mach-s5pv310/Makefile @@ -13,7 +13,7 @@ obj- := # Core support for S5PV310 system obj-$(CONFIG_CPU_S5PV310) += cpu.o init.o clock.o irq-combiner.o -obj-$(CONFIG_CPU_S5PV310) += setup-i2c0.o time.o +obj-$(CONFIG_CPU_S5PV310) += setup-i2c0.o time.o gpiolib.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o @@ -21,6 +21,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o # machine support +obj-$(CONFIG_MACH_SMDKC210) += mach-smdkc210.o obj-$(CONFIG_MACH_SMDKV310) += mach-smdkv310.o obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o @@ -28,3 +29,10 @@ obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o obj-$(CONFIG_S5PV310_SETUP_I2C1) += setup-i2c1.o obj-$(CONFIG_S5PV310_SETUP_I2C2) += setup-i2c2.o +obj-$(CONFIG_S5PV310_SETUP_I2C3) += setup-i2c3.o +obj-$(CONFIG_S5PV310_SETUP_I2C4) += setup-i2c4.o +obj-$(CONFIG_S5PV310_SETUP_I2C5) += setup-i2c5.o +obj-$(CONFIG_S5PV310_SETUP_I2C6) += setup-i2c6.o +obj-$(CONFIG_S5PV310_SETUP_I2C7) += setup-i2c7.o +obj-$(CONFIG_S5PV310_SETUP_SDHCI) += setup-sdhci.o +obj-$(CONFIG_S5PV310_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c index 26a0f03df8ea..58c9d33f36fe 100644 --- a/arch/arm/mach-s5pv310/clock.c +++ b/arch/arm/mach-s5pv310/clock.c @@ -30,16 +30,92 @@ static struct clk clk_sclk_hdmi27m = { .rate = 27000000, }; +static struct clk clk_sclk_hdmiphy = { + .name = "sclk_hdmiphy", + .id = -1, +}; + +static struct clk clk_sclk_usbphy0 = { + .name = "sclk_usbphy0", + .id = -1, + .rate = 27000000, +}; + +static struct clk clk_sclk_usbphy1 = { + .name = "sclk_usbphy1", + .id = -1, +}; + +static int s5pv310_clksrc_mask_top_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable); +} + +static int s5pv310_clksrc_mask_cam_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKSRC_MASK_CAM, clk, enable); +} + +static int s5pv310_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable); +} + +static int s5pv310_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable); +} + +static int s5pv310_clksrc_mask_fsys_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable); +} + static int s5pv310_clksrc_mask_peril0_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable); } +static int s5pv310_clksrc_mask_peril1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable); +} + +static int s5pv310_clk_ip_cam_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable); +} + +static int s5pv310_clk_ip_image_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable); +} + +static int s5pv310_clk_ip_lcd0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable); +} + +static int s5pv310_clk_ip_lcd1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable); +} + +static int s5pv310_clk_ip_fsys_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable); +} + static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable); } +static int s5pv310_clk_ip_perir_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable); +} + /* Core list of CMU_CPU side */ static struct clksrc_clk clk_mout_apll = { @@ -79,7 +155,7 @@ static struct clksrc_clk clk_mout_mpll = { }; static struct clk *clkset_moutcore_list[] = { - [0] = &clk_sclk_apll.clk, + [0] = &clk_mout_apll.clk, [1] = &clk_mout_mpll.clk, }; @@ -150,24 +226,6 @@ static struct clksrc_clk clk_periphclk = { .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 }, }; -static struct clksrc_clk clk_atclk = { - .clk = { - .name = "atclk", - .id = -1, - .parent = &clk_moutcore.clk, - }, - .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 16, .size = 3 }, -}; - -static struct clksrc_clk clk_pclk_dbg = { - .clk = { - .name = "pclk_dbg", - .id = -1, - .parent = &clk_atclk.clk, - }, - .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 20, .size = 3 }, -}; - /* Core list of CMU_CORE side */ static struct clk *clkset_corebus_list[] = { @@ -241,7 +299,7 @@ static struct clk *clkset_aclk_top_list[] = { [1] = &clk_sclk_apll.clk, }; -static struct clksrc_sources clkset_aclk_200 = { +static struct clksrc_sources clkset_aclk = { .sources = clkset_aclk_top_list, .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), }; @@ -251,52 +309,37 @@ static struct clksrc_clk clk_aclk_200 = { .name = "aclk_200", .id = -1, }, - .sources = &clkset_aclk_200, + .sources = &clkset_aclk, .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 }, .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 }, }; -static struct clksrc_sources clkset_aclk_100 = { - .sources = clkset_aclk_top_list, - .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), -}; - static struct clksrc_clk clk_aclk_100 = { .clk = { .name = "aclk_100", .id = -1, }, - .sources = &clkset_aclk_100, + .sources = &clkset_aclk, .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 }, .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 }, }; -static struct clksrc_sources clkset_aclk_160 = { - .sources = clkset_aclk_top_list, - .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), -}; - static struct clksrc_clk clk_aclk_160 = { .clk = { .name = "aclk_160", .id = -1, }, - .sources = &clkset_aclk_160, + .sources = &clkset_aclk, .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 }, .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 }, }; -static struct clksrc_sources clkset_aclk_133 = { - .sources = clkset_aclk_top_list, - .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), -}; - static struct clksrc_clk clk_aclk_133 = { .clk = { .name = "aclk_133", .id = -1, }, - .sources = &clkset_aclk_133, + .sources = &clkset_aclk, .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 }, .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 }, }; @@ -315,6 +358,8 @@ static struct clksrc_clk clk_vpllsrc = { .clk = { .name = "vpll_src", .id = -1, + .enable = s5pv310_clksrc_mask_top_ctrl, + .ctrlbit = (1 << 0), }, .sources = &clkset_vpllsrc, .reg_src = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 }, @@ -346,7 +391,175 @@ static struct clk init_clocks_disable[] = { .parent = &clk_aclk_100.clk, .enable = s5pv310_clk_ip_peril_ctrl, .ctrlbit = (1<<24), - } + }, { + .name = "csis", + .id = 0, + .enable = s5pv310_clk_ip_cam_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "csis", + .id = 1, + .enable = s5pv310_clk_ip_cam_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "fimc", + .id = 0, + .enable = s5pv310_clk_ip_cam_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "fimc", + .id = 1, + .enable = s5pv310_clk_ip_cam_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "fimc", + .id = 2, + .enable = s5pv310_clk_ip_cam_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "fimc", + .id = 3, + .enable = s5pv310_clk_ip_cam_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "fimd", + .id = 0, + .enable = s5pv310_clk_ip_lcd0_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "fimd", + .id = 1, + .enable = s5pv310_clk_ip_lcd1_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_aclk_133.clk, + .enable = s5pv310_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "hsmmc", + .id = 1, + .parent = &clk_aclk_133.clk, + .enable = s5pv310_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "hsmmc", + .id = 2, + .parent = &clk_aclk_133.clk, + .enable = s5pv310_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "hsmmc", + .id = 3, + .parent = &clk_aclk_133.clk, + .enable = s5pv310_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "hsmmc", + .id = 4, + .parent = &clk_aclk_133.clk, + .enable = s5pv310_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 9), + }, { + .name = "sata", + .id = -1, + .enable = s5pv310_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 10), + }, { + .name = "adc", + .id = -1, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 15), + }, { + .name = "rtc", + .id = -1, + .enable = s5pv310_clk_ip_perir_ctrl, + .ctrlbit = (1 << 15), + }, { + .name = "watchdog", + .id = -1, + .enable = s5pv310_clk_ip_perir_ctrl, + .ctrlbit = (1 << 14), + }, { + .name = "usbhost", + .id = -1, + .enable = s5pv310_clk_ip_fsys_ctrl , + .ctrlbit = (1 << 12), + }, { + .name = "otg", + .id = -1, + .enable = s5pv310_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 13), + }, { + .name = "spi", + .id = 0, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 16), + }, { + .name = "spi", + .id = 1, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 17), + }, { + .name = "spi", + .id = 2, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 18), + }, { + .name = "fimg2d", + .id = -1, + .enable = s5pv310_clk_ip_image_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "i2c", + .id = 0, + .parent = &clk_aclk_100.clk, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "i2c", + .id = 1, + .parent = &clk_aclk_100.clk, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "i2c", + .id = 2, + .parent = &clk_aclk_100.clk, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "i2c", + .id = 3, + .parent = &clk_aclk_100.clk, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 9), + }, { + .name = "i2c", + .id = 4, + .parent = &clk_aclk_100.clk, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 10), + }, { + .name = "i2c", + .id = 5, + .parent = &clk_aclk_100.clk, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 11), + }, { + .name = "i2c", + .id = 6, + .parent = &clk_aclk_100.clk, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "i2c", + .id = 7, + .parent = &clk_aclk_100.clk, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 13), + }, }; static struct clk init_clocks[] = { @@ -387,6 +600,9 @@ static struct clk *clkset_group_list[] = { [0] = &clk_ext_xtal_mux, [1] = &clk_xusbxti, [2] = &clk_sclk_hdmi27m, + [3] = &clk_sclk_usbphy0, + [4] = &clk_sclk_usbphy1, + [5] = &clk_sclk_hdmiphy, [6] = &clk_mout_mpll.clk, [7] = &clk_mout_epll.clk, [8] = &clk_sclk_vpll.clk, @@ -397,6 +613,104 @@ static struct clksrc_sources clkset_group = { .nr_sources = ARRAY_SIZE(clkset_group_list), }; +static struct clk *clkset_mout_g2d0_list[] = { + [0] = &clk_mout_mpll.clk, + [1] = &clk_sclk_apll.clk, +}; + +static struct clksrc_sources clkset_mout_g2d0 = { + .sources = clkset_mout_g2d0_list, + .nr_sources = ARRAY_SIZE(clkset_mout_g2d0_list), +}; + +static struct clksrc_clk clk_mout_g2d0 = { + .clk = { + .name = "mout_g2d0", + .id = -1, + }, + .sources = &clkset_mout_g2d0, + .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 }, +}; + +static struct clk *clkset_mout_g2d1_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_sclk_vpll.clk, +}; + +static struct clksrc_sources clkset_mout_g2d1 = { + .sources = clkset_mout_g2d1_list, + .nr_sources = ARRAY_SIZE(clkset_mout_g2d1_list), +}; + +static struct clksrc_clk clk_mout_g2d1 = { + .clk = { + .name = "mout_g2d1", + .id = -1, + }, + .sources = &clkset_mout_g2d1, + .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 }, +}; + +static struct clk *clkset_mout_g2d_list[] = { + [0] = &clk_mout_g2d0.clk, + [1] = &clk_mout_g2d1.clk, +}; + +static struct clksrc_sources clkset_mout_g2d = { + .sources = clkset_mout_g2d_list, + .nr_sources = ARRAY_SIZE(clkset_mout_g2d_list), +}; + +static struct clksrc_clk clk_dout_mmc0 = { + .clk = { + .name = "dout_mmc0", + .id = -1, + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk clk_dout_mmc1 = { + .clk = { + .name = "dout_mmc1", + .id = -1, + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 16, .size = 4 }, +}; + +static struct clksrc_clk clk_dout_mmc2 = { + .clk = { + .name = "dout_mmc2", + .id = -1, + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk clk_dout_mmc3 = { + .clk = { + .name = "dout_mmc3", + .id = -1, + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 16, .size = 4 }, +}; + +static struct clksrc_clk clk_dout_mmc4 = { + .clk = { + .name = "dout_mmc4", + .id = -1, + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 0, .size = 4 }, +}; + static struct clksrc_clk clksrcs[] = { { .clk = { @@ -448,7 +762,200 @@ static struct clksrc_clk clksrcs[] = { .sources = &clkset_group, .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 }, .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 }, - }, + }, { + .clk = { + .name = "sclk_csis", + .id = 0, + .enable = s5pv310_clksrc_mask_cam_ctrl, + .ctrlbit = (1 << 24), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 24, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 24, .size = 4 }, + }, { + .clk = { + .name = "sclk_csis", + .id = 1, + .enable = s5pv310_clksrc_mask_cam_ctrl, + .ctrlbit = (1 << 28), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 28, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 }, + }, { + .clk = { + .name = "sclk_cam", + .id = 0, + .enable = s5pv310_clksrc_mask_cam_ctrl, + .ctrlbit = (1 << 16), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 16, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_cam", + .id = 1, + .enable = s5pv310_clksrc_mask_cam_ctrl, + .ctrlbit = (1 << 20), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 20, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = 0, + .enable = s5pv310_clksrc_mask_cam_ctrl, + .ctrlbit = (1 << 0), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 0, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = 1, + .enable = s5pv310_clksrc_mask_cam_ctrl, + .ctrlbit = (1 << 4), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 4, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = 2, + .enable = s5pv310_clksrc_mask_cam_ctrl, + .ctrlbit = (1 << 8), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 8, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 8, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = 3, + .enable = s5pv310_clksrc_mask_cam_ctrl, + .ctrlbit = (1 << 12), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 12, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimd", + .id = 0, + .enable = s5pv310_clksrc_mask_lcd0_ctrl, + .ctrlbit = (1 << 0), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_LCD0, .shift = 0, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimd", + .id = 1, + .enable = s5pv310_clksrc_mask_lcd1_ctrl, + .ctrlbit = (1 << 0), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_sata", + .id = -1, + .enable = s5pv310_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 24), + }, + .sources = &clkset_mout_corebus, + .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 }, + .reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_spi", + .id = 0, + .enable = s5pv310_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", + .id = 1, + .enable = s5pv310_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", + .id = 2, + .enable = s5pv310_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", + .id = -1, + }, + .sources = &clkset_mout_g2d, + .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 }, + .reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 0, + .parent = &clk_dout_mmc0.clk, + .enable = s5pv310_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 0), + }, + .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 1, + .parent = &clk_dout_mmc1.clk, + .enable = s5pv310_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 4), + }, + .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 2, + .parent = &clk_dout_mmc2.clk, + .enable = s5pv310_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 8), + }, + .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 3, + .parent = &clk_dout_mmc3.clk, + .enable = s5pv310_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 12), + }, + .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 4, + .parent = &clk_dout_mmc4.clk, + .enable = s5pv310_clksrc_mask_fsys_ctrl, + .ctrlbit = (1 << 16), + }, + .reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 8, .size = 8 }, + } }; /* Clock initialization code */ @@ -464,8 +971,6 @@ static struct clksrc_clk *sysclks[] = { &clk_aclk_cores, &clk_aclk_corem1, &clk_periphclk, - &clk_atclk, - &clk_pclk_dbg, &clk_mout_corebus, &clk_sclk_dmc, &clk_aclk_cored, @@ -478,6 +983,11 @@ static struct clksrc_clk *sysclks[] = { &clk_aclk_100, &clk_aclk_160, &clk_aclk_133, + &clk_dout_mmc0, + &clk_dout_mmc1, + &clk_dout_mmc2, + &clk_dout_mmc3, + &clk_dout_mmc4, }; void __init_or_cpufreq s5pv310_setup_clocks(void) @@ -490,15 +1000,11 @@ void __init_or_cpufreq s5pv310_setup_clocks(void) unsigned long vpllsrc; unsigned long xtal; unsigned long armclk; - unsigned long aclk_corem0; - unsigned long aclk_cores; - unsigned long aclk_corem1; - unsigned long periphclk; unsigned long sclk_dmc; - unsigned long aclk_cored; - unsigned long aclk_corep; - unsigned long aclk_acp; - unsigned long pclk_acp; + unsigned long aclk_200; + unsigned long aclk_100; + unsigned long aclk_160; + unsigned long aclk_133; unsigned int ptr; printk(KERN_DEBUG "%s: registering clocks\n", __func__); @@ -529,26 +1035,21 @@ void __init_or_cpufreq s5pv310_setup_clocks(void) apll, mpll, epll, vpll); armclk = clk_get_rate(&clk_armclk.clk); - aclk_corem0 = clk_get_rate(&clk_aclk_corem0.clk); - aclk_cores = clk_get_rate(&clk_aclk_cores.clk); - aclk_corem1 = clk_get_rate(&clk_aclk_corem1.clk); - periphclk = clk_get_rate(&clk_periphclk.clk); sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk); - aclk_cored = clk_get_rate(&clk_aclk_cored.clk); - aclk_corep = clk_get_rate(&clk_aclk_corep.clk); - aclk_acp = clk_get_rate(&clk_aclk_acp.clk); - pclk_acp = clk_get_rate(&clk_pclk_acp.clk); - - printk(KERN_INFO "S5PV310: ARMCLK=%ld, COREM0=%ld, CORES=%ld\n" - "COREM1=%ld, PERI=%ld, DMC=%ld, CORED=%ld\n" - "COREP=%ld, ACLK_ACP=%ld, PCLK_ACP=%ld", - armclk, aclk_corem0, aclk_cores, aclk_corem1, - periphclk, sclk_dmc, aclk_cored, aclk_corep, - aclk_acp, pclk_acp); + + aclk_200 = clk_get_rate(&clk_aclk_200.clk); + aclk_100 = clk_get_rate(&clk_aclk_100.clk); + aclk_160 = clk_get_rate(&clk_aclk_160.clk); + aclk_133 = clk_get_rate(&clk_aclk_133.clk); + + printk(KERN_INFO "S5PV310: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n" + "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n", + armclk, sclk_dmc, aclk_200, + aclk_100, aclk_160, aclk_133); clk_f.rate = armclk; clk_h.rate = sclk_dmc; - clk_p.rate = periphclk; + clk_p.rate = aclk_100; for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_set_clksrc(&clksrcs[ptr], true); diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c index e5b261a99ab2..5b9790054421 100644 --- a/arch/arm/mach-s5pv310/cpu.c +++ b/arch/arm/mach-s5pv310/cpu.c @@ -19,6 +19,7 @@ #include <plat/cpu.h> #include <plat/clock.h> #include <plat/s5pv310.h> +#include <plat/sdhci.h> #include <mach/regs-irq.h> @@ -31,9 +32,14 @@ extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq); /* Initial IO mappings */ static struct map_desc s5pv310_iodesc[] __initdata = { { - .virtual = (unsigned long)S5P_VA_COREPERI_BASE, - .pfn = __phys_to_pfn(S5PV310_PA_COREPERI), - .length = SZ_8K, + .virtual = (unsigned long)S5P_VA_SYSRAM, + .pfn = __phys_to_pfn(S5PV310_PA_SYSRAM), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_CMU, + .pfn = __phys_to_pfn(S5PV310_PA_CMU), + .length = SZ_128K, .type = MT_DEVICE, }, { .virtual = (unsigned long)S5P_VA_COMBINER_BASE, @@ -41,19 +47,34 @@ static struct map_desc s5pv310_iodesc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S5P_VA_COREPERI_BASE, + .pfn = __phys_to_pfn(S5PV310_PA_COREPERI), + .length = SZ_8K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)S5P_VA_L2CC, .pfn = __phys_to_pfn(S5PV310_PA_L2CC), .length = SZ_4K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S5P_VA_SYSRAM, - .pfn = __phys_to_pfn(S5PV310_PA_SYSRAM), + .virtual = (unsigned long)S5P_VA_GPIO1, + .pfn = __phys_to_pfn(S5PV310_PA_GPIO1), .length = SZ_4K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S5P_VA_CMU, - .pfn = __phys_to_pfn(S5PV310_PA_CMU), - .length = SZ_128K, + .virtual = (unsigned long)S5P_VA_GPIO2, + .pfn = __phys_to_pfn(S5PV310_PA_GPIO2), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_GPIO3, + .pfn = __phys_to_pfn(S5PV310_PA_GPIO3), + .length = SZ_256, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_512K, .type = MT_DEVICE, }, }; @@ -73,6 +94,12 @@ static void s5pv310_idle(void) void __init s5pv310_map_io(void) { iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc)); + + /* initialize device information early */ + s5pv310_default_sdhci0(); + s5pv310_default_sdhci1(); + s5pv310_default_sdhci2(); + s5pv310_default_sdhci3(); } void __init s5pv310_init_clocks(int xtal) diff --git a/arch/arm/mach-s5pv310/gpiolib.c b/arch/arm/mach-s5pv310/gpiolib.c new file mode 100644 index 000000000000..55217b8923ec --- /dev/null +++ b/arch/arm/mach-s5pv310/gpiolib.c @@ -0,0 +1,304 @@ +/* linux/arch/arm/mach-s5pv310/gpiolib.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5PV310 - GPIOlib 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/irq.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <mach/map.h> + +#include <plat/gpio-core.h> +#include <plat/gpio-cfg.h> +#include <plat/gpio-cfg-helpers.h> + +static struct s3c_gpio_cfg gpio_cfg = { + .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_cfg gpio_cfg_noint = { + .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +/* + * Following are the gpio banks in v310. + * + * The 'config' member when left to NULL, is initialized to the default + * structure gpio_cfg in the init function below. + * + * The 'base' member is also initialized in the init function below. + * Note: The initialization of 'base' member of s3c_gpio_chip structure + * uses the above macro and depends on the banks being listed in order here. + */ +static struct s3c_gpio_chip s5pv310_gpio_part1_4bit[] = { + { + .chip = { + .base = S5PV310_GPA0(0), + .ngpio = S5PV310_GPIO_A0_NR, + .label = "GPA0", + }, + }, { + .chip = { + .base = S5PV310_GPA1(0), + .ngpio = S5PV310_GPIO_A1_NR, + .label = "GPA1", + }, + }, { + .chip = { + .base = S5PV310_GPB(0), + .ngpio = S5PV310_GPIO_B_NR, + .label = "GPB", + }, + }, { + .chip = { + .base = S5PV310_GPC0(0), + .ngpio = S5PV310_GPIO_C0_NR, + .label = "GPC0", + }, + }, { + .chip = { + .base = S5PV310_GPC1(0), + .ngpio = S5PV310_GPIO_C1_NR, + .label = "GPC1", + }, + }, { + .chip = { + .base = S5PV310_GPD0(0), + .ngpio = S5PV310_GPIO_D0_NR, + .label = "GPD0", + }, + }, { + .chip = { + .base = S5PV310_GPD1(0), + .ngpio = S5PV310_GPIO_D1_NR, + .label = "GPD1", + }, + }, { + .chip = { + .base = S5PV310_GPE0(0), + .ngpio = S5PV310_GPIO_E0_NR, + .label = "GPE0", + }, + }, { + .chip = { + .base = S5PV310_GPE1(0), + .ngpio = S5PV310_GPIO_E1_NR, + .label = "GPE1", + }, + }, { + .chip = { + .base = S5PV310_GPE2(0), + .ngpio = S5PV310_GPIO_E2_NR, + .label = "GPE2", + }, + }, { + .chip = { + .base = S5PV310_GPE3(0), + .ngpio = S5PV310_GPIO_E3_NR, + .label = "GPE3", + }, + }, { + .chip = { + .base = S5PV310_GPE4(0), + .ngpio = S5PV310_GPIO_E4_NR, + .label = "GPE4", + }, + }, { + .chip = { + .base = S5PV310_GPF0(0), + .ngpio = S5PV310_GPIO_F0_NR, + .label = "GPF0", + }, + }, { + .chip = { + .base = S5PV310_GPF1(0), + .ngpio = S5PV310_GPIO_F1_NR, + .label = "GPF1", + }, + }, { + .chip = { + .base = S5PV310_GPF2(0), + .ngpio = S5PV310_GPIO_F2_NR, + .label = "GPF2", + }, + }, { + .chip = { + .base = S5PV310_GPF3(0), + .ngpio = S5PV310_GPIO_F3_NR, + .label = "GPF3", + }, + }, +}; + +static struct s3c_gpio_chip s5pv310_gpio_part2_4bit[] = { + { + .chip = { + .base = S5PV310_GPJ0(0), + .ngpio = S5PV310_GPIO_J0_NR, + .label = "GPJ0", + }, + }, { + .chip = { + .base = S5PV310_GPJ1(0), + .ngpio = S5PV310_GPIO_J1_NR, + .label = "GPJ1", + }, + }, { + .chip = { + .base = S5PV310_GPK0(0), + .ngpio = S5PV310_GPIO_K0_NR, + .label = "GPK0", + }, + }, { + .chip = { + .base = S5PV310_GPK1(0), + .ngpio = S5PV310_GPIO_K1_NR, + .label = "GPK1", + }, + }, { + .chip = { + .base = S5PV310_GPK2(0), + .ngpio = S5PV310_GPIO_K2_NR, + .label = "GPK2", + }, + }, { + .chip = { + .base = S5PV310_GPK3(0), + .ngpio = S5PV310_GPIO_K3_NR, + .label = "GPK3", + }, + }, { + .chip = { + .base = S5PV310_GPL0(0), + .ngpio = S5PV310_GPIO_L0_NR, + .label = "GPL0", + }, + }, { + .chip = { + .base = S5PV310_GPL1(0), + .ngpio = S5PV310_GPIO_L1_NR, + .label = "GPL1", + }, + }, { + .chip = { + .base = S5PV310_GPL2(0), + .ngpio = S5PV310_GPIO_L2_NR, + .label = "GPL2", + }, + }, { + .base = (S5P_VA_GPIO2 + 0xC00), + .config = &gpio_cfg_noint, + .irq_base = IRQ_EINT(0), + .chip = { + .base = S5PV310_GPX0(0), + .ngpio = S5PV310_GPIO_X0_NR, + .label = "GPX0", + .to_irq = samsung_gpiolib_to_irq, + }, + }, { + .base = (S5P_VA_GPIO2 + 0xC20), + .config = &gpio_cfg_noint, + .irq_base = IRQ_EINT(8), + .chip = { + .base = S5PV310_GPX1(0), + .ngpio = S5PV310_GPIO_X1_NR, + .label = "GPX1", + .to_irq = samsung_gpiolib_to_irq, + }, + }, { + .base = (S5P_VA_GPIO2 + 0xC40), + .config = &gpio_cfg_noint, + .irq_base = IRQ_EINT(16), + .chip = { + .base = S5PV310_GPX2(0), + .ngpio = S5PV310_GPIO_X2_NR, + .label = "GPX2", + .to_irq = samsung_gpiolib_to_irq, + }, + }, { + .base = (S5P_VA_GPIO2 + 0xC60), + .config = &gpio_cfg_noint, + .irq_base = IRQ_EINT(24), + .chip = { + .base = S5PV310_GPX3(0), + .ngpio = S5PV310_GPIO_X3_NR, + .label = "GPX3", + .to_irq = samsung_gpiolib_to_irq, + }, + }, +}; + +static struct s3c_gpio_chip s5pv310_gpio_part3_4bit[] = { + { + .chip = { + .base = S5PV310_GPZ(0), + .ngpio = S5PV310_GPIO_Z_NR, + .label = "GPZ", + }, + }, +}; + +static __init int s5pv310_gpiolib_init(void) +{ + struct s3c_gpio_chip *chip; + int i; + int nr_chips; + + /* GPIO part 1 */ + + chip = s5pv310_gpio_part1_4bit; + nr_chips = ARRAY_SIZE(s5pv310_gpio_part1_4bit); + + for (i = 0; i < nr_chips; i++, chip++) { + if (chip->config == NULL) + chip->config = &gpio_cfg; + if (chip->base == NULL) + chip->base = S5P_VA_GPIO1 + (i) * 0x20; + } + + samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part1_4bit, nr_chips); + + /* GPIO part 2 */ + + chip = s5pv310_gpio_part2_4bit; + nr_chips = ARRAY_SIZE(s5pv310_gpio_part2_4bit); + + for (i = 0; i < nr_chips; i++, chip++) { + if (chip->config == NULL) + chip->config = &gpio_cfg; + if (chip->base == NULL) + chip->base = S5P_VA_GPIO2 + (i) * 0x20; + } + + samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part2_4bit, nr_chips); + + /* GPIO part 3 */ + + chip = s5pv310_gpio_part3_4bit; + nr_chips = ARRAY_SIZE(s5pv310_gpio_part3_4bit); + + for (i = 0; i < nr_chips; i++, chip++) { + if (chip->config == NULL) + chip->config = &gpio_cfg; + if (chip->base == NULL) + chip->base = S5P_VA_GPIO3 + (i) * 0x20; + } + + samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part3_4bit, nr_chips); + + return 0; +} +core_initcall(s5pv310_gpiolib_init); diff --git a/arch/arm/mach-s5pv310/hotplug.c b/arch/arm/mach-s5pv310/hotplug.c new file mode 100644 index 000000000000..03652c3605f6 --- /dev/null +++ b/arch/arm/mach-s5pv310/hotplug.c @@ -0,0 +1,144 @@ +/* linux arch/arm/mach-s5pv310/hotplug.c + * + * Cloned from linux/arch/arm/mach-realview/hotplug.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * 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/errno.h> +#include <linux/smp.h> +#include <linux/completion.h> + +#include <asm/cacheflush.h> + +extern volatile int pen_release; + +static DECLARE_COMPLETION(cpu_killed); + +static inline void cpu_enter_lowpower(void) +{ + unsigned int v; + + flush_cache_all(); + asm volatile( + " mcr p15, 0, %1, c7, c5, 0\n" + " mcr p15, 0, %1, c7, c10, 4\n" + /* + * Turn off coherency + */ + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, #0x20\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, #0x04\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0) + : "cc"); +} + +static inline void cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile( + "mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, #0x04\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, #0x20\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : + : "cc"); +} + +static inline void platform_do_lowpower(unsigned int cpu) +{ + /* + * there is no power-control hardware on this platform, so all + * we can do is put the core into WFI; this is safe as the calling + * code will have already disabled interrupts + */ + for (;;) { + /* + * here's the WFI + */ + asm(".word 0xe320f003\n" + : + : + : "memory", "cc"); + + if (pen_release == cpu) { + /* + * OK, proper wakeup, we're done + */ + break; + } + + /* + * getting here, means that we have come out of WFI without + * having been woken up - this shouldn't happen + * + * The trouble is, letting people know about this is not really + * possible, since we are currently running incoherently, and + * therefore cannot safely call printk() or anything else + */ +#ifdef DEBUG + printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu); +#endif + } +} + +int platform_cpu_kill(unsigned int cpu) +{ + return wait_for_completion_timeout(&cpu_killed, 5000); +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void platform_cpu_die(unsigned int cpu) +{ +#ifdef DEBUG + unsigned int this_cpu = hard_smp_processor_id(); + + if (cpu != this_cpu) { + printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", + this_cpu, cpu); + BUG(); + } +#endif + + printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); + complete(&cpu_killed); + + /* + * we're ready for shutdown now, so do it + */ + cpu_enter_lowpower(); + platform_do_lowpower(cpu); + + /* + * bring this CPU back into the world of cache + * coherency, and then restore interrupts + */ + cpu_leave_lowpower(); +} + +int platform_cpu_disable(unsigned int cpu) +{ + /* + * we don't allow CPU 0 to be shutdown (it is still too special + * e.g. clock tick interrupts) + */ + return cpu == 0 ? -EPERM : 0; +} diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h index 4cdedda6e652..fa7a8a3f463f 100644 --- a/arch/arm/mach-s5pv310/include/mach/irqs.h +++ b/arch/arm/mach-s5pv310/include/mach/irqs.h @@ -3,7 +3,7 @@ * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * - * S5PV210 - IRQ definitions + * S5PV310 - IRQ 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 @@ -60,6 +60,9 @@ #define IRQ_TIMER3_VIC COMBINER_IRQ(22, 3) #define IRQ_TIMER4_VIC COMBINER_IRQ(22, 4) +#define IRQ_RTC_ALARM COMBINER_IRQ(23, 0) +#define IRQ_RTC_TIC COMBINER_IRQ(23, 1) + #define IRQ_UART0 COMBINER_IRQ(26, 0) #define IRQ_UART1 COMBINER_IRQ(26, 1) #define IRQ_UART2 COMBINER_IRQ(26, 2) @@ -67,11 +70,30 @@ #define IRQ_UART4 COMBINER_IRQ(26, 4) #define IRQ_IIC COMBINER_IRQ(27, 0) +#define IRQ_IIC1 COMBINER_IRQ(27, 1) +#define IRQ_IIC2 COMBINER_IRQ(27, 2) +#define IRQ_IIC3 COMBINER_IRQ(27, 3) +#define IRQ_IIC4 COMBINER_IRQ(27, 4) +#define IRQ_IIC5 COMBINER_IRQ(27, 5) +#define IRQ_IIC6 COMBINER_IRQ(27, 6) +#define IRQ_IIC7 COMBINER_IRQ(27, 7) -/* Set the default NR_IRQS */ +#define IRQ_HSMMC0 COMBINER_IRQ(29, 0) +#define IRQ_HSMMC1 COMBINER_IRQ(29, 1) +#define IRQ_HSMMC2 COMBINER_IRQ(29, 2) +#define IRQ_HSMMC3 COMBINER_IRQ(29, 3) + +#define IRQ_ONENAND_AUDI COMBINER_IRQ(34, 0) + +#define MAX_COMBINER_NR 40 -#define NR_IRQS COMBINER_IRQ(MAX_COMBINER_NR, 0) +#define S5P_IRQ_EINT_BASE COMBINER_IRQ(MAX_COMBINER_NR, 0) + +#define S5P_EINT_BASE1 (S5P_IRQ_EINT_BASE + 0) +#define S5P_EINT_BASE2 (S5P_IRQ_EINT_BASE + 16) + +/* Set the default NR_IRQS */ -#define MAX_COMBINER_NR 39 +#define NR_IRQS (S5P_IRQ_EINT_BASE + 32) #endif /* __ASM_ARCH_IRQS_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h index 213e1101a3b3..1e3384fba13a 100644 --- a/arch/arm/mach-s5pv310/include/mach/map.h +++ b/arch/arm/mach-s5pv310/include/mach/map.h @@ -25,15 +25,22 @@ #define S5PV310_PA_SYSRAM (0x02025000) +#define S5PC210_PA_ONENAND (0x0C000000) +#define S5P_PA_ONENAND S5PC210_PA_ONENAND + +#define S5PC210_PA_ONENAND_DMA (0x0C600000) +#define S5P_PA_ONENAND_DMA S5PC210_PA_ONENAND_DMA + #define S5PV310_PA_CHIPID (0x10000000) #define S5P_PA_CHIPID S5PV310_PA_CHIPID -#define S5PV310_PA_SYSCON (0x10020000) +#define S5PV310_PA_SYSCON (0x10010000) #define S5P_PA_SYSCON S5PV310_PA_SYSCON #define S5PV310_PA_CMU (0x10030000) #define S5PV310_PA_WATCHDOG (0x10060000) +#define S5PV310_PA_RTC (0x10070000) #define S5PV310_PA_COMBINER (0x10448000) @@ -46,7 +53,6 @@ #define S5PV310_PA_GPIO1 (0x11400000) #define S5PV310_PA_GPIO2 (0x11000000) #define S5PV310_PA_GPIO3 (0x03860000) -#define S5P_PA_GPIO S5PV310_PA_GPIO1 #define S5PV310_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000)) @@ -61,7 +67,7 @@ #define S5P_SZ_UART SZ_256 -#define S5PV310_PA_IIC0 (0x13860000) +#define S5PV310_PA_IIC(x) (0x13860000 + ((x) * 0x10000)) #define S5PV310_PA_TIMER (0x139D0000) #define S5P_PA_TIMER S5PV310_PA_TIMER @@ -75,7 +81,15 @@ #define S3C_PA_HSMMC1 S5PV310_PA_HSMMC(1) #define S3C_PA_HSMMC2 S5PV310_PA_HSMMC(2) #define S3C_PA_HSMMC3 S5PV310_PA_HSMMC(3) -#define S3C_PA_IIC S5PV310_PA_IIC0 +#define S3C_PA_IIC S5PV310_PA_IIC(0) +#define S3C_PA_IIC1 S5PV310_PA_IIC(1) +#define S3C_PA_IIC2 S5PV310_PA_IIC(2) +#define S3C_PA_IIC3 S5PV310_PA_IIC(3) +#define S3C_PA_IIC4 S5PV310_PA_IIC(4) +#define S3C_PA_IIC5 S5PV310_PA_IIC(5) +#define S3C_PA_IIC6 S5PV310_PA_IIC(6) +#define S3C_PA_IIC7 S5PV310_PA_IIC(7) +#define S3C_PA_RTC S5PV310_PA_RTC #define S3C_PA_WDT S5PV310_PA_WATCHDOG #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h index 4013553cd9be..f1028cad9788 100644 --- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h +++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h @@ -26,11 +26,23 @@ #define S5P_CLKSRC_TOP0 S5P_CLKREG(0x0C210) #define S5P_CLKSRC_TOP1 S5P_CLKREG(0x0C214) - +#define S5P_CLKSRC_CAM S5P_CLKREG(0x0C220) +#define S5P_CLKSRC_IMAGE S5P_CLKREG(0x0C230) +#define S5P_CLKSRC_LCD0 S5P_CLKREG(0x0C234) +#define S5P_CLKSRC_LCD1 S5P_CLKREG(0x0C238) +#define S5P_CLKSRC_FSYS S5P_CLKREG(0x0C240) #define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x0C250) +#define S5P_CLKSRC_PERIL1 S5P_CLKREG(0x0C254) #define S5P_CLKDIV_TOP S5P_CLKREG(0x0C510) - +#define S5P_CLKDIV_CAM S5P_CLKREG(0x0C520) +#define S5P_CLKDIV_IMAGE S5P_CLKREG(0x0C530) +#define S5P_CLKDIV_LCD0 S5P_CLKREG(0x0C534) +#define S5P_CLKDIV_LCD1 S5P_CLKREG(0x0C538) +#define S5P_CLKDIV_FSYS0 S5P_CLKREG(0x0C540) +#define S5P_CLKDIV_FSYS1 S5P_CLKREG(0x0C544) +#define S5P_CLKDIV_FSYS2 S5P_CLKREG(0x0C548) +#define S5P_CLKDIV_FSYS3 S5P_CLKREG(0x0C54C) #define S5P_CLKDIV_PERIL0 S5P_CLKREG(0x0C550) #define S5P_CLKDIV_PERIL1 S5P_CLKREG(0x0C554) #define S5P_CLKDIV_PERIL2 S5P_CLKREG(0x0C558) @@ -38,9 +50,21 @@ #define S5P_CLKDIV_PERIL4 S5P_CLKREG(0x0C560) #define S5P_CLKDIV_PERIL5 S5P_CLKREG(0x0C564) +#define S5P_CLKSRC_MASK_TOP S5P_CLKREG(0x0C310) +#define S5P_CLKSRC_MASK_CAM S5P_CLKREG(0x0C320) +#define S5P_CLKSRC_MASK_LCD0 S5P_CLKREG(0x0C334) +#define S5P_CLKSRC_MASK_LCD1 S5P_CLKREG(0x0C338) +#define S5P_CLKSRC_MASK_FSYS S5P_CLKREG(0x0C340) #define S5P_CLKSRC_MASK_PERIL0 S5P_CLKREG(0x0C350) +#define S5P_CLKSRC_MASK_PERIL1 S5P_CLKREG(0x0C354) +#define S5P_CLKGATE_IP_CAM S5P_CLKREG(0x0C920) +#define S5P_CLKGATE_IP_IMAGE S5P_CLKREG(0x0C930) +#define S5P_CLKGATE_IP_LCD0 S5P_CLKREG(0x0C934) +#define S5P_CLKGATE_IP_LCD1 S5P_CLKREG(0x0C938) +#define S5P_CLKGATE_IP_FSYS S5P_CLKREG(0x0C940) #define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x0C950) +#define S5P_CLKGATE_IP_PERIR S5P_CLKREG(0x0C960) #define S5P_CLKSRC_CORE S5P_CLKREG(0x10200) #define S5P_CLKDIV_CORE0 S5P_CLKREG(0x10500) @@ -60,4 +84,8 @@ #define S5P_CLKGATE_SCLKCPU S5P_CLKREG(0x14800) +/* Compatibility defines */ + +#define S5P_EPLL_CON S5P_EPLL_CON0 + #endif /* __ASM_ARCH_REGS_CLOCK_H */ diff --git a/arch/arm/mach-s5pv310/irq-combiner.c b/arch/arm/mach-s5pv310/irq-combiner.c index 0f7052164f23..c3f88c3faf6c 100644 --- a/arch/arm/mach-s5pv310/irq-combiner.c +++ b/arch/arm/mach-s5pv310/irq-combiner.c @@ -66,11 +66,7 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) if (status == 0) goto out; - for (combiner_irq = 0; combiner_irq < 32; combiner_irq++) { - if (status & 0x1) - break; - status >>= 1; - } + combiner_irq = __ffs(status); cascade_irq = combiner_irq + (chip_data->irq_offset & ~31); if (unlikely(cascade_irq >= NR_IRQS)) diff --git a/arch/arm/mach-s5pv310/mach-smdkc210.c b/arch/arm/mach-s5pv310/mach-smdkc210.c new file mode 100644 index 000000000000..93d537b8dadf --- /dev/null +++ b/arch/arm/mach-s5pv310/mach-smdkc210.c @@ -0,0 +1,146 @@ +/* linux/arch/arm/mach-s5pv310/mach-smdkc210.c + * + * Copyright (c) 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/serial_core.h> +#include <linux/gpio.h> +#include <linux/mmc/host.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach-types.h> +#include <asm/hardware/cache-l2x0.h> + +#include <plat/regs-serial.h> +#include <plat/s5pv310.h> +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/sdhci.h> + +#include <mach/map.h> + +/* Following are default values for UCON, ULCON and UFCON UART registers */ +#define SMDKC210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ + S3C2410_UCON_RXILEVEL | \ + S3C2410_UCON_TXIRQMODE | \ + S3C2410_UCON_RXIRQMODE | \ + S3C2410_UCON_RXFIFO_TOI | \ + S3C2443_UCON_RXERR_IRQEN) + +#define SMDKC210_ULCON_DEFAULT S3C2410_LCON_CS8 + +#define SMDKC210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ + S5PV210_UFCON_TXTRIG4 | \ + S5PV210_UFCON_RXTRIG4) + +static struct s3c2410_uartcfg smdkc210_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = SMDKC210_UCON_DEFAULT, + .ulcon = SMDKC210_ULCON_DEFAULT, + .ufcon = SMDKC210_UFCON_DEFAULT, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = SMDKC210_UCON_DEFAULT, + .ulcon = SMDKC210_ULCON_DEFAULT, + .ufcon = SMDKC210_UFCON_DEFAULT, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = SMDKC210_UCON_DEFAULT, + .ulcon = SMDKC210_ULCON_DEFAULT, + .ufcon = SMDKC210_UFCON_DEFAULT, + }, + [3] = { + .hwport = 3, + .flags = 0, + .ucon = SMDKC210_UCON_DEFAULT, + .ulcon = SMDKC210_ULCON_DEFAULT, + .ufcon = SMDKC210_UFCON_DEFAULT, + }, +}; + +static struct s3c_sdhci_platdata smdkc210_hsmmc0_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = S5PV310_GPK0(2), + .ext_cd_gpio_invert = 1, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +#ifdef CONFIG_S5PV310_SDHCI_CH0_8BIT + .max_width = 8, + .host_caps = MMC_CAP_8_BIT_DATA, +#endif +}; + +static struct s3c_sdhci_platdata smdkc210_hsmmc1_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = S5PV310_GPK0(2), + .ext_cd_gpio_invert = 1, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +}; + +static struct s3c_sdhci_platdata smdkc210_hsmmc2_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = S5PV310_GPK2(2), + .ext_cd_gpio_invert = 1, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +#ifdef CONFIG_S5PV310_SDHCI_CH2_8BIT + .max_width = 8, + .host_caps = MMC_CAP_8_BIT_DATA, +#endif +}; + +static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = S5PV310_GPK2(2), + .ext_cd_gpio_invert = 1, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +}; + +static struct platform_device *smdkc210_devices[] __initdata = { + &s3c_device_hsmmc0, + &s3c_device_hsmmc1, + &s3c_device_hsmmc2, + &s3c_device_hsmmc3, + &s3c_device_rtc, + &s3c_device_wdt, +}; + +static void __init smdkc210_map_io(void) +{ + s5p_init_io(NULL, 0, S5P_VA_CHIPID); + s3c24xx_init_clocks(24000000); + s3c24xx_init_uarts(smdkc210_uartcfgs, ARRAY_SIZE(smdkc210_uartcfgs)); +} + +static void __init smdkc210_machine_init(void) +{ + s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata); + s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata); + s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata); + s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata); + +#ifdef CONFIG_CACHE_L2X0 + l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff); +#endif + + platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices)); +} + +MACHINE_START(SMDKC210, "SMDKC210") + /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ + .boot_params = S5P_PA_SDRAM + 0x100, + .init_irq = s5pv310_init_irq, + .map_io = smdkc210_map_io, + .init_machine = smdkc210_machine_init, + .timer = &s5pv310_timer, +MACHINE_END diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c index 0d6ab77709d2..10f80566516d 100644 --- a/arch/arm/mach-s5pv310/mach-smdkv310.c +++ b/arch/arm/mach-s5pv310/mach-smdkv310.c @@ -9,6 +9,9 @@ */ #include <linux/serial_core.h> +#include <linux/gpio.h> +#include <linux/mmc/host.h> +#include <linux/platform_device.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> @@ -17,6 +20,8 @@ #include <plat/regs-serial.h> #include <plat/s5pv310.h> #include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/sdhci.h> #include <mach/map.h> @@ -65,6 +70,51 @@ static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = { }, }; +static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = S5PV310_GPK0(2), + .ext_cd_gpio_invert = 1, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +#ifdef CONFIG_S5PV310_SDHCI_CH0_8BIT + .max_width = 8, + .host_caps = MMC_CAP_8_BIT_DATA, +#endif +}; + +static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = S5PV310_GPK0(2), + .ext_cd_gpio_invert = 1, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +}; + +static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = S5PV310_GPK2(2), + .ext_cd_gpio_invert = 1, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +#ifdef CONFIG_S5PV310_SDHCI_CH2_8BIT + .max_width = 8, + .host_caps = MMC_CAP_8_BIT_DATA, +#endif +}; + +static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = S5PV310_GPK2(2), + .ext_cd_gpio_invert = 1, + .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, +}; + +static struct platform_device *smdkv310_devices[] __initdata = { + &s3c_device_hsmmc0, + &s3c_device_hsmmc1, + &s3c_device_hsmmc2, + &s3c_device_hsmmc3, + &s3c_device_rtc, + &s3c_device_wdt, +}; + static void __init smdkv310_map_io(void) { s5p_init_io(NULL, 0, S5P_VA_CHIPID); @@ -74,9 +124,16 @@ static void __init smdkv310_map_io(void) static void __init smdkv310_machine_init(void) { + s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata); + s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata); + s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata); + s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata); + #ifdef CONFIG_CACHE_L2X0 l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff); #endif + + platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices)); } MACHINE_START(SMDKV310, "SMDKV310") diff --git a/arch/arm/mach-s5pv310/mach-universal_c210.c b/arch/arm/mach-s5pv310/mach-universal_c210.c index 2388cb947936..deffeb1be3b9 100644 --- a/arch/arm/mach-s5pv310/mach-universal_c210.c +++ b/arch/arm/mach-s5pv310/mach-universal_c210.c @@ -7,7 +7,12 @@ * published by the Free Software Foundation. */ +#include <linux/platform_device.h> #include <linux/serial_core.h> +#include <linux/input.h> +#include <linux/i2c.h> +#include <linux/gpio_keys.h> +#include <linux/gpio.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> @@ -16,6 +21,7 @@ #include <plat/regs-serial.h> #include <plat/s5pv310.h> #include <plat/cpu.h> +#include <plat/devs.h> #include <mach/map.h> @@ -60,6 +66,72 @@ static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = { }, }; +static struct gpio_keys_button universal_gpio_keys_tables[] = { + { + .code = KEY_VOLUMEUP, + .gpio = S5PV310_GPX2(0), /* XEINT16 */ + .desc = "gpio-keys: KEY_VOLUMEUP", + .type = EV_KEY, + .active_low = 1, + .debounce_interval = 1, + }, { + .code = KEY_VOLUMEDOWN, + .gpio = S5PV310_GPX2(1), /* XEINT17 */ + .desc = "gpio-keys: KEY_VOLUMEDOWN", + .type = EV_KEY, + .active_low = 1, + .debounce_interval = 1, + }, { + .code = KEY_CONFIG, + .gpio = S5PV310_GPX2(2), /* XEINT18 */ + .desc = "gpio-keys: KEY_CONFIG", + .type = EV_KEY, + .active_low = 1, + .debounce_interval = 1, + }, { + .code = KEY_CAMERA, + .gpio = S5PV310_GPX2(3), /* XEINT19 */ + .desc = "gpio-keys: KEY_CAMERA", + .type = EV_KEY, + .active_low = 1, + .debounce_interval = 1, + }, { + .code = KEY_OK, + .gpio = S5PV310_GPX3(5), /* XEINT29 */ + .desc = "gpio-keys: KEY_OK", + .type = EV_KEY, + .active_low = 1, + .debounce_interval = 1, + }, +}; + +static struct gpio_keys_platform_data universal_gpio_keys_data = { + .buttons = universal_gpio_keys_tables, + .nbuttons = ARRAY_SIZE(universal_gpio_keys_tables), +}; + +static struct platform_device universal_gpio_keys = { + .name = "gpio-keys", + .dev = { + .platform_data = &universal_gpio_keys_data, + }, +}; + +/* I2C0 */ +static struct i2c_board_info i2c0_devs[] __initdata = { + /* Camera, To be updated */ +}; + +/* I2C1 */ +static struct i2c_board_info i2c1_devs[] __initdata = { + /* Gyro, To be updated */ +}; + +static struct platform_device *universal_devices[] __initdata = { + &universal_gpio_keys, + &s5p_device_onenand, +}; + static void __init universal_map_io(void) { s5p_init_io(NULL, 0, S5P_VA_CHIPID); @@ -72,6 +144,12 @@ static void __init universal_machine_init(void) #ifdef CONFIG_CACHE_L2X0 l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff); #endif + + i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs)); + i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs)); + + /* Last */ + platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices)); } MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210") diff --git a/arch/arm/mach-s5pv310/setup-i2c0.c b/arch/arm/mach-s5pv310/setup-i2c0.c index 436712807383..f47f8f3152ec 100644 --- a/arch/arm/mach-s5pv310/setup-i2c0.c +++ b/arch/arm/mach-s5pv310/setup-i2c0.c @@ -21,8 +21,6 @@ struct platform_device; /* don't need the contents */ void s3c_i2c0_cfg_gpio(struct platform_device *dev) { - s3c_gpio_cfgpin(S5PV310_GPD1(0), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV310_GPD1(0), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5PV310_GPD1(1), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV310_GPD1(1), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PV310_GPD1(0), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); } diff --git a/arch/arm/mach-s5pv310/setup-i2c1.c b/arch/arm/mach-s5pv310/setup-i2c1.c index 1ecd5bc35b5a..9d07e4e2f14c 100644 --- a/arch/arm/mach-s5pv310/setup-i2c1.c +++ b/arch/arm/mach-s5pv310/setup-i2c1.c @@ -18,8 +18,6 @@ struct platform_device; /* don't need the contents */ void s3c_i2c1_cfg_gpio(struct platform_device *dev) { - s3c_gpio_cfgpin(S5PV310_GPD1(2), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV310_GPD1(2), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5PV310_GPD1(3), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PV310_GPD1(3), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PV310_GPD1(2), 2, + S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); } diff --git a/arch/arm/mach-s5pv310/setup-i2c2.c b/arch/arm/mach-s5pv310/setup-i2c2.c index 4c0d8def660a..4163b1233daf 100644 --- a/arch/arm/mach-s5pv310/setup-i2c2.c +++ b/arch/arm/mach-s5pv310/setup-i2c2.c @@ -18,8 +18,6 @@ struct platform_device; /* don't need the contents */ void s3c_i2c2_cfg_gpio(struct platform_device *dev) { - s3c_gpio_cfgpin(S5PV310_GPA0(6), S3C_GPIO_SFN(3)); - s3c_gpio_setpull(S5PV310_GPA0(6), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5PV310_GPA0(7), S3C_GPIO_SFN(3)); - s3c_gpio_setpull(S5PV310_GPA0(7), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(S5PV310_GPA0(6), 2, + S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); } diff --git a/arch/arm/mach-s5pv310/setup-i2c3.c b/arch/arm/mach-s5pv310/setup-i2c3.c new file mode 100644 index 000000000000..180f153d2a20 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c3.c @@ -0,0 +1,23 @@ +/* + * linux/arch/arm/mach-s5pv310/setup-i2c3.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * + * I2C3 GPIO configuration. + * + * 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. +*/ + +struct platform_device; /* don't need the contents */ + +#include <linux/gpio.h> +#include <plat/iic.h> +#include <plat/gpio-cfg.h> + +void s3c_i2c3_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgall_range(S5PV310_GPA1(2), 2, + S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); +} diff --git a/arch/arm/mach-s5pv310/setup-i2c4.c b/arch/arm/mach-s5pv310/setup-i2c4.c new file mode 100644 index 000000000000..909e8dfc5316 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c4.c @@ -0,0 +1,23 @@ +/* + * linux/arch/arm/mach-s5pv310/setup-i2c4.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * + * I2C4 GPIO configuration. + * + * 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. +*/ + +struct platform_device; /* don't need the contents */ + +#include <linux/gpio.h> +#include <plat/iic.h> +#include <plat/gpio-cfg.h> + +void s3c_i2c4_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgall_range(S5PV310_GPB(2), 2, + S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); +} diff --git a/arch/arm/mach-s5pv310/setup-i2c5.c b/arch/arm/mach-s5pv310/setup-i2c5.c new file mode 100644 index 000000000000..5d0fa4ac0283 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c5.c @@ -0,0 +1,23 @@ +/* + * linux/arch/arm/mach-s5pv310/setup-i2c5.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * + * I2C5 GPIO configuration. + * + * 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. +*/ + +struct platform_device; /* don't need the contents */ + +#include <linux/gpio.h> +#include <plat/iic.h> +#include <plat/gpio-cfg.h> + +void s3c_i2c5_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgall_range(S5PV310_GPB(6), 2, + S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); +} diff --git a/arch/arm/mach-s5pv310/setup-i2c6.c b/arch/arm/mach-s5pv310/setup-i2c6.c new file mode 100644 index 000000000000..34aafab92ac4 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c6.c @@ -0,0 +1,23 @@ +/* + * linux/arch/arm/mach-s5pv310/setup-i2c6.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * + * I2C6 GPIO configuration. + * + * 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. +*/ + +struct platform_device; /* don't need the contents */ + +#include <linux/gpio.h> +#include <plat/iic.h> +#include <plat/gpio-cfg.h> + +void s3c_i2c6_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgall_range(S5PV310_GPC1(3), 2, + S3C_GPIO_SFN(4), S3C_GPIO_PULL_UP); +} diff --git a/arch/arm/mach-s5pv310/setup-i2c7.c b/arch/arm/mach-s5pv310/setup-i2c7.c new file mode 100644 index 000000000000..9b25b8d18920 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c7.c @@ -0,0 +1,23 @@ +/* + * linux/arch/arm/mach-s5pv310/setup-i2c7.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * + * I2C7 GPIO configuration. + * + * 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. +*/ + +struct platform_device; /* don't need the contents */ + +#include <linux/gpio.h> +#include <plat/iic.h> +#include <plat/gpio-cfg.h> + +void s3c_i2c7_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgall_range(S5PV310_GPD0(2), 2, + S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); +} diff --git a/arch/arm/mach-s5pv310/setup-sdhci-gpio.c b/arch/arm/mach-s5pv310/setup-sdhci-gpio.c new file mode 100644 index 000000000000..86d38cc49135 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-sdhci-gpio.c @@ -0,0 +1,152 @@ +/* linux/arch/arm/mach-s5pv310/setup-sdhci-gpio.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - 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/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/mmc/host.h> +#include <linux/mmc/card.h> + +#include <plat/gpio-cfg.h> +#include <plat/regs-sdhci.h> +#include <plat/sdhci.h> + +void s5pv310_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) +{ + struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; + unsigned int gpio; + + /* Set all the necessary GPK0[0:1] pins to special-function 2 */ + for (gpio = S5PV310_GPK0(0); gpio < S5PV310_GPK0(2); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } + + switch (width) { + case 8: + for (gpio = S5PV310_GPK1(3); gpio <= S5PV310_GPK1(6); gpio++) { + /* Data pin GPK1[3:6] to special-funtion 3 */ + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } + case 4: + for (gpio = S5PV310_GPK0(3); gpio <= S5PV310_GPK0(6); gpio++) { + /* Data pin GPK0[3:6] to special-funtion 2 */ + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } + default: + break; + } + + if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { + s3c_gpio_cfgpin(S5PV310_GPK0(2), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5PV310_GPK0(2), S3C_GPIO_PULL_UP); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } +} + +void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) +{ + struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; + unsigned int gpio; + + /* Set all the necessary GPK1[0:1] pins to special-function 2 */ + for (gpio = S5PV310_GPK1(0); gpio < S5PV310_GPK1(2); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } + + for (gpio = S5PV310_GPK1(3); gpio <= S5PV310_GPK1(6); gpio++) { + /* Data pin GPK1[3:6] to special-function 2 */ + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } + + if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { + s3c_gpio_cfgpin(S5PV310_GPK1(2), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5PV310_GPK1(2), S3C_GPIO_PULL_UP); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } +} + +void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) +{ + struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; + unsigned int gpio; + + /* Set all the necessary GPK2[0:1] pins to special-function 2 */ + for (gpio = S5PV310_GPK2(0); gpio < S5PV310_GPK2(2); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } + + switch (width) { + case 8: + for (gpio = S5PV310_GPK3(3); gpio <= S5PV310_GPK3(6); gpio++) { + /* Data pin GPK3[3:6] to special-function 3 */ + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } + case 4: + for (gpio = S5PV310_GPK2(3); gpio <= S5PV310_GPK2(6); gpio++) { + /* Data pin GPK2[3:6] to special-function 2 */ + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } + default: + break; + } + + if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { + s3c_gpio_cfgpin(S5PV310_GPK2(2), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5PV310_GPK2(2), S3C_GPIO_PULL_UP); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } +} + +void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width) +{ + struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; + unsigned int gpio; + + /* Set all the necessary GPK3[0:1] pins to special-function 2 */ + for (gpio = S5PV310_GPK3(0); gpio < S5PV310_GPK3(2); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } + + for (gpio = S5PV310_GPK3(3); gpio <= S5PV310_GPK3(6); gpio++) { + /* Data pin GPK3[3:6] to special-function 2 */ + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } + + if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { + s3c_gpio_cfgpin(S5PV310_GPK3(2), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5PV310_GPK3(2), S3C_GPIO_PULL_UP); + s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); + } +} diff --git a/arch/arm/mach-s5pv310/setup-sdhci.c b/arch/arm/mach-s5pv310/setup-sdhci.c new file mode 100644 index 000000000000..db8358fc4662 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-sdhci.c @@ -0,0 +1,69 @@ +/* linux/arch/arm/mach-s5pv310/setup-sdhci.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - Helper functions for settign up SDHCI device(s) (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/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#include <linux/mmc/card.h> +#include <linux/mmc/host.h> + +#include <plat/regs-sdhci.h> + +/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */ + +char *s5pv310_hsmmc_clksrcs[4] = { + [0] = NULL, + [1] = NULL, + [2] = "sclk_mmc", /* mmc_bus */ + [3] = NULL, +}; + +void s5pv310_setup_sdhci_cfg_card(struct platform_device *dev, void __iomem *r, + struct mmc_ios *ios, struct mmc_card *card) +{ + u32 ctrl2, ctrl3; + + /* don't need to alter anything acording to card-type */ + + ctrl2 = readl(r + S3C_SDHCI_CONTROL2); + + /* select base clock source to HCLK */ + + ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK; + + /* + * clear async mode, enable conflict mask, rx feedback ctrl, SD + * clk hold and no use debounce count + */ + + ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR | + S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK | + S3C_SDHCI_CTRL2_ENFBCLKRX | + S3C_SDHCI_CTRL2_DFCNT_NONE | + S3C_SDHCI_CTRL2_ENCLKOUTHOLD); + + /* Tx and Rx feedback clock delay control */ + + if (ios->clock < 25 * 1000000) + ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 | + S3C_SDHCI_CTRL3_FCSEL2 | + S3C_SDHCI_CTRL3_FCSEL1 | + S3C_SDHCI_CTRL3_FCSEL0); + else + ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0); + + writel(ctrl2, r + S3C_SDHCI_CONTROL2); + writel(ctrl3, r + S3C_SDHCI_CONTROL3); +} diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c index 4c0896f2572d..243b6411050d 100644 --- a/arch/arm/plat-s3c24xx/gpiolib.c +++ b/arch/arm/plat-s3c24xx/gpiolib.c @@ -74,11 +74,6 @@ static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset) return -EINVAL; } -static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset) -{ - return IRQ_EINT8 + offset; -} - static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = { .set_config = s3c_gpio_setcfg_s3c24xx_a, .get_config = s3c_gpio_getcfg_s3c24xx_a, @@ -157,12 +152,13 @@ struct s3c_gpio_chip s3c24xx_gpios[] = { [6] = { .base = S3C2410_GPGCON, .pm = __gpio_pm(&s3c_gpio_pm_2bit), + .irq_base = IRQ_EINT8, .chip = { .base = S3C2410_GPG(0), .owner = THIS_MODULE, .label = "GPIOG", .ngpio = 16, - .to_irq = s3c24xx_gpiolib_bankg_toirq, + .to_irq = samsung_gpiolib_to_irq, }, }, { .base = S3C2410_GPHCON, diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index c6a855db2fb6..65dbfa8e0a86 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -7,7 +7,7 @@ config PLAT_S5P bool - depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310) + depends on (ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310) default y select ARM_VIC if !ARCH_S5PV310 select ARM_GIC if ARCH_S5PV310 @@ -30,7 +30,12 @@ config S5P_EXT_INT bool help Use the external interrupts (other than GPIO interrupts.) - Note: Do not choose this for S5P6440. + Note: Do not choose this for S5P6440 and S5P6450. + +config S5P_GPIO_INT + bool + help + Common code for the GPIO interrupts (other than external interrupts.) config S5P_DEV_FIMC0 bool @@ -46,3 +51,8 @@ config S5P_DEV_FIMC2 bool help Compile in platform device definitions for FIMC controller 2 + +config S5P_DEV_ONENAND + bool + help + Compile in platform device definition for OneNAND controller diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index b2e029673950..de65238a7aef 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -18,9 +18,13 @@ obj-y += cpu.o obj-y += clock.o obj-y += irq.o obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o +obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o +obj-$(CONFIG_PM) += pm.o +obj-$(CONFIG_PM) += irq-pm.o # devices obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o +obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c index b5e255265f20..8d081d968c58 100644 --- a/arch/arm/plat-s5p/clock.c +++ b/arch/arm/plat-s5p/clock.c @@ -21,6 +21,8 @@ #include <linux/io.h> #include <asm/div64.h> +#include <mach/regs-clock.h> + #include <plat/clock.h> #include <plat/clock-clksrc.h> #include <plat/s5p-clock.h> @@ -74,19 +76,18 @@ struct clk clk_fout_epll = { .ctrlbit = (1 << 31), }; -/* VPLL clock output */ -struct clk clk_fout_vpll = { - .name = "fout_vpll", +/* DPLL clock output */ +struct clk clk_fout_dpll = { + .name = "fout_dpll", .id = -1, .ctrlbit = (1 << 31), }; -/* ARM clock */ -struct clk clk_arm = { - .name = "armclk", +/* VPLL clock output */ +struct clk clk_fout_vpll = { + .name = "fout_vpll", .id = -1, - .rate = 0, - .ctrlbit = 0, + .ctrlbit = (1 << 31), }; /* Possible clock sources for APLL Mux */ @@ -122,6 +123,17 @@ struct clksrc_sources clk_src_epll = { .nr_sources = ARRAY_SIZE(clk_src_epll_list), }; +/* Possible clock sources for DPLL Mux */ +static struct clk *clk_src_dpll_list[] = { + [0] = &clk_fin_dpll, + [1] = &clk_fout_dpll, +}; + +struct clksrc_sources clk_src_dpll = { + .sources = clk_src_dpll_list, + .nr_sources = ARRAY_SIZE(clk_src_dpll_list), +}; + struct clk clk_vpll = { .name = "vpll", .id = -1, @@ -138,6 +150,24 @@ int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable) return 0; } +int s5p_epll_enable(struct clk *clk, int enable) +{ + unsigned int ctrlbit = clk->ctrlbit; + unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit; + + if (enable) + __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON); + else + __raw_writel(epll_con, S5P_EPLL_CON); + + return 0; +} + +unsigned long s5p_epll_get_rate(struct clk *clk) +{ + return clk->rate; +} + static struct clk *s5p_clks[] __initdata = { &clk_ext_xtal_mux, &clk_48m, @@ -145,8 +175,8 @@ static struct clk *s5p_clks[] __initdata = { &clk_fout_apll, &clk_fout_mpll, &clk_fout_epll, + &clk_fout_dpll, &clk_fout_vpll, - &clk_arm, &clk_vpll, &clk_xusbxti, }; diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c index b07a078fd284..74f7f5a5446c 100644 --- a/arch/arm/plat-s5p/cpu.c +++ b/arch/arm/plat-s5p/cpu.c @@ -19,6 +19,7 @@ #include <plat/cpu.h> #include <plat/s5p6440.h> #include <plat/s5p6442.h> +#include <plat/s5p6450.h> #include <plat/s5pc100.h> #include <plat/s5pv210.h> #include <plat/s5pv310.h> @@ -27,6 +28,7 @@ static const char name_s5p6440[] = "S5P6440"; static const char name_s5p6442[] = "S5P6442"; +static const char name_s5p6450[] = "S5P6450"; static const char name_s5pc100[] = "S5PC100"; static const char name_s5pv210[] = "S5PV210/S5PC110"; static const char name_s5pv310[] = "S5PV310"; @@ -38,7 +40,7 @@ static struct cpu_table cpu_ids[] __initdata = { .map_io = s5p6440_map_io, .init_clocks = s5p6440_init_clocks, .init_uarts = s5p6440_init_uarts, - .init = s5p6440_init, + .init = s5p64x0_init, .name = name_s5p6440, }, { .idcode = 0x36442000, @@ -49,6 +51,14 @@ static struct cpu_table cpu_ids[] __initdata = { .init = s5p6442_init, .name = name_s5p6442, }, { + .idcode = 0x36450000, + .idmask = 0xffffff00, + .map_io = s5p6450_map_io, + .init_clocks = s5p6450_init_clocks, + .init_uarts = s5p6450_init_uarts, + .init = s5p64x0_init, + .name = name_s5p6450, + }, { .idcode = 0x43100000, .idmask = 0xfffff000, .map_io = s5pc100_map_io, @@ -89,33 +99,11 @@ static struct map_desc s5p_iodesc[] __initdata = { .length = SZ_64K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S3C_VA_UART, - .pfn = __phys_to_pfn(S3C_PA_UART), - .length = SZ_512K, - .type = MT_DEVICE, -#ifdef CONFIG_ARM_VIC - }, { - .virtual = (unsigned long)VA_VIC0, - .pfn = __phys_to_pfn(S5P_PA_VIC0), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)VA_VIC1, - .pfn = __phys_to_pfn(S5P_PA_VIC1), - .length = SZ_16K, - .type = MT_DEVICE, -#endif - }, { .virtual = (unsigned long)S3C_VA_TIMER, .pfn = __phys_to_pfn(S5P_PA_TIMER), .length = SZ_16K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S5P_VA_GPIO, - .pfn = __phys_to_pfn(S5P_PA_GPIO), - .length = SZ_4K, - .type = MT_DEVICE, - }, { .virtual = (unsigned long)S3C_VA_WATCHDOG, .pfn = __phys_to_pfn(S3C_PA_WDT), .length = SZ_4K, diff --git a/arch/arm/mach-s5pv210/dev-onenand.c b/arch/arm/plat-s5p/dev-onenand.c index f8ede33ee82b..6db926202caa 100644 --- a/arch/arm/mach-s5pv210/dev-onenand.c +++ b/arch/arm/plat-s5p/dev-onenand.c @@ -1,10 +1,12 @@ -/* - * linux/arch/arm/mach-s5pv210/dev-onenand.c +/* linux/arch/arm/plat-s5p/dev-onenand.c + * + * Copyright 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * Copyright (c) 2008-2010 Samsung Electronics * Kyungmin Park <kyungmin.park@samsung.com> * - * S5PC110 series device definition for OneNAND devices + * S5P series device definition for OneNAND devices * * 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 @@ -19,15 +21,15 @@ #include <mach/irqs.h> #include <mach/map.h> -static struct resource s5pc110_onenand_resources[] = { +static struct resource s5p_onenand_resources[] = { [0] = { - .start = S5PC110_PA_ONENAND, - .end = S5PC110_PA_ONENAND + SZ_128K - 1, + .start = S5P_PA_ONENAND, + .end = S5P_PA_ONENAND + SZ_128K - 1, .flags = IORESOURCE_MEM, }, [1] = { - .start = S5PC110_PA_ONENAND_DMA, - .end = S5PC110_PA_ONENAND_DMA + SZ_8K - 1, + .start = S5P_PA_ONENAND_DMA, + .end = S5P_PA_ONENAND_DMA + SZ_8K - 1, .flags = IORESOURCE_MEM, }, [2] = { @@ -37,19 +39,19 @@ static struct resource s5pc110_onenand_resources[] = { }, }; -struct platform_device s5pc110_device_onenand = { +struct platform_device s5p_device_onenand = { .name = "s5pc110-onenand", .id = -1, - .num_resources = ARRAY_SIZE(s5pc110_onenand_resources), - .resource = s5pc110_onenand_resources, + .num_resources = ARRAY_SIZE(s5p_onenand_resources), + .resource = s5p_onenand_resources, }; -void s5pc110_onenand_set_platdata(struct onenand_platform_data *pdata) +void s5p_onenand_set_platdata(struct onenand_platform_data *pdata) { struct onenand_platform_data *pd; pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL); if (!pd) printk(KERN_ERR "%s: no memory for platform data\n", __func__); - s5pc110_device_onenand.dev.platform_data = pd; + s5p_device_onenand.dev.platform_data = pd; } diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c index a89331ef4ae1..6a7342886171 100644 --- a/arch/arm/plat-s5p/dev-uart.c +++ b/arch/arm/plat-s5p/dev-uart.c @@ -119,6 +119,56 @@ static struct resource s5p_uart3_resource[] = { #endif }; +static struct resource s5p_uart4_resource[] = { +#if CONFIG_SERIAL_SAMSUNG_UARTS > 4 + [0] = { + .start = S5P_PA_UART4, + .end = S5P_PA_UART4 + S5P_SZ_UART, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S5P_UART_RX4, + .end = IRQ_S5P_UART_RX4, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S5P_UART_TX4, + .end = IRQ_S5P_UART_TX4, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_S5P_UART_ERR4, + .end = IRQ_S5P_UART_ERR4, + .flags = IORESOURCE_IRQ, + }, +#endif +}; + +static struct resource s5p_uart5_resource[] = { +#if CONFIG_SERIAL_SAMSUNG_UARTS > 5 + [0] = { + .start = S5P_PA_UART5, + .end = S5P_PA_UART5 + S5P_SZ_UART, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S5P_UART_RX5, + .end = IRQ_S5P_UART_RX5, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S5P_UART_TX5, + .end = IRQ_S5P_UART_TX5, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_S5P_UART_ERR5, + .end = IRQ_S5P_UART_ERR5, + .flags = IORESOURCE_IRQ, + }, +#endif +}; + struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = { [0] = { .resources = s5p_uart0_resource, @@ -136,4 +186,12 @@ struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = { .resources = s5p_uart3_resource, .nr_resources = ARRAY_SIZE(s5p_uart3_resource), }, + [4] = { + .resources = s5p_uart4_resource, + .nr_resources = ARRAY_SIZE(s5p_uart4_resource), + }, + [5] = { + .resources = s5p_uart5_resource, + .nr_resources = ARRAY_SIZE(s5p_uart5_resource), + }, }; diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h index 3fb3a3a17465..ba9121c60a2a 100644 --- a/arch/arm/plat-s5p/include/plat/irqs.h +++ b/arch/arm/plat-s5p/include/plat/irqs.h @@ -94,4 +94,22 @@ ((irq) - S5P_EINT_BASE1) : \ ((irq) + 16 - S5P_EINT_BASE2)) +#define IRQ_EINT_BIT(x) EINT_OFFSET(x) + +/* Typically only a few gpio chips require gpio interrupt support. + To avoid memory waste irq descriptors are allocated only for + S5P_GPIOINT_GROUP_COUNT chips, each with total number of + S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged + to any gpio chip with the s5p_register_gpio_interrupt() function */ +#define S5P_GPIOINT_GROUP_COUNT 4 +#define S5P_GPIOINT_GROUP_SIZE 8 +#define S5P_GPIOINT_COUNT (S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE) + +/* IRQ types common for all s5p platforms */ +#define S5P_IRQ_TYPE_LEVEL_LOW (0x00) +#define S5P_IRQ_TYPE_LEVEL_HIGH (0x01) +#define S5P_IRQ_TYPE_EDGE_FALLING (0x02) +#define S5P_IRQ_TYPE_EDGE_RISING (0x03) +#define S5P_IRQ_TYPE_EDGE_BOTH (0x04) + #endif /* __ASM_PLAT_S5P_IRQS_H */ diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h index c4ff88bf6477..fef353d44513 100644 --- a/arch/arm/plat-s5p/include/plat/map-s5p.h +++ b/arch/arm/plat-s5p/include/plat/map-s5p.h @@ -13,24 +13,38 @@ #ifndef __ASM_PLAT_MAP_S5P_H #define __ASM_PLAT_MAP_S5P_H __FILE__ -#define S5P_VA_CHIPID S3C_ADDR(0x00700000) -#define S5P_VA_GPIO S3C_ADDR(0x00500000) -#define S5P_VA_SYSTIMER S3C_ADDR(0x01200000) -#define S5P_VA_SROMC S3C_ADDR(0x01100000) -#define S5P_VA_SYSRAM S3C_ADDR(0x01180000) - -#define S5P_VA_COMBINER_BASE S3C_ADDR(0x00600000) +#define S5P_VA_CHIPID S3C_ADDR(0x02000000) +#define S5P_VA_CMU S3C_ADDR(0x02100000) +#define S5P_VA_GPIO S3C_ADDR(0x02200000) +#define S5P_VA_GPIO1 S5P_VA_GPIO +#define S5P_VA_GPIO2 S3C_ADDR(0x02240000) +#define S5P_VA_GPIO3 S3C_ADDR(0x02280000) + +#define S5P_VA_SYSRAM S3C_ADDR(0x02400000) +#define S5P_VA_DMC0 S3C_ADDR(0x02440000) +#define S5P_VA_DMC1 S3C_ADDR(0x02480000) +#define S5P_VA_SROMC S3C_ADDR(0x024C0000) + +#define S5P_VA_SYSTIMER S3C_ADDR(0x02500000) +#define S5P_VA_L2CC S3C_ADDR(0x02600000) + +#define S5P_VA_COMBINER_BASE S3C_ADDR(0x02700000) #define S5P_VA_COMBINER(x) (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10) -#define S5P_VA_COREPERI_BASE S3C_ADDR(0x00800000) +#define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000) #define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x)) #define S5P_VA_SCU S5P_VA_COREPERI(0x0) #define S5P_VA_GIC_CPU S5P_VA_COREPERI(0x100) #define S5P_VA_TWD S5P_VA_COREPERI(0x600) #define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000) -#define S5P_VA_L2CC S3C_ADDR(0x00900000) -#define S5P_VA_CMU S3C_ADDR(0x00920000) +#define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000) + +#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) +#define VA_VIC0 VA_VIC(0) +#define VA_VIC1 VA_VIC(1) +#define VA_VIC2 VA_VIC(2) +#define VA_VIC3 VA_VIC(3) #define S5P_VA_UART(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) #define S5P_VA_UART0 S5P_VA_UART(0) @@ -42,10 +56,4 @@ #define S3C_UART_OFFSET (0x400) #endif -#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) -#define VA_VIC0 VA_VIC(0) -#define VA_VIC1 VA_VIC(1) -#define VA_VIC2 VA_VIC(2) -#define VA_VIC3 VA_VIC(3) - #endif /* __ASM_PLAT_MAP_S5P_H */ diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h index 4e8fe08cb70d..bf28fadee7ae 100644 --- a/arch/arm/plat-s5p/include/plat/pll.h +++ b/arch/arm/plat-s5p/include/plat/pll.h @@ -47,6 +47,7 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con, } #define PLL46XX_KDIV_MASK (0xFFFF) +#define PLL4650C_KDIV_MASK (0xFFF) #define PLL46XX_MDIV_MASK (0x1FF) #define PLL46XX_PDIV_MASK (0x3F) #define PLL46XX_SDIV_MASK (0x7) @@ -57,6 +58,7 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con, enum pll46xx_type_t { pll_4600, pll_4650, + pll_4650c, }; static inline unsigned long s5p_get_pll46xx(unsigned long baseclk, @@ -72,6 +74,11 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk, sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK; kdiv = pll_con1 & PLL46XX_KDIV_MASK; + if (pll_type == pll_4650c) + kdiv = pll_con1 & PLL4650C_KDIV_MASK; + else + kdiv = pll_con1 & PLL46XX_KDIV_MASK; + tmp = baseclk; if (pll_type == pll_4600) { diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h index 09418b1101fe..2b6dcff8ab2b 100644 --- a/arch/arm/plat-s5p/include/plat/s5p-clock.h +++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h @@ -1,7 +1,7 @@ /* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h * - * Copyright 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * Header file for s5p clock support * @@ -20,6 +20,7 @@ #define clk_fin_apll clk_ext_xtal_mux #define clk_fin_mpll clk_ext_xtal_mux #define clk_fin_epll clk_ext_xtal_mux +#define clk_fin_dpll clk_ext_xtal_mux #define clk_fin_vpll clk_ext_xtal_mux #define clk_fin_hpll clk_ext_xtal_mux @@ -30,6 +31,7 @@ extern struct clk s5p_clk_27m; extern struct clk clk_fout_apll; extern struct clk clk_fout_mpll; extern struct clk clk_fout_epll; +extern struct clk clk_fout_dpll; extern struct clk clk_fout_vpll; extern struct clk clk_arm; extern struct clk clk_vpll; @@ -37,8 +39,12 @@ extern struct clk clk_vpll; extern struct clksrc_sources clk_src_apll; extern struct clksrc_sources clk_src_mpll; extern struct clksrc_sources clk_src_epll; +extern struct clksrc_sources clk_src_dpll; -extern int s5p6440_clk48m_ctrl(struct clk *clk, int enable); extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable); +/* Common EPLL operations for S5P platform */ +extern int s5p_epll_enable(struct clk *clk, int enable); +extern unsigned long s5p_epll_get_rate(struct clk *clk); + #endif /* __ASM_PLAT_S5P_CLOCK_H */ diff --git a/arch/arm/plat-s5p/include/plat/s5p6440.h b/arch/arm/plat-s5p/include/plat/s5p6440.h index a4cd75afeb3b..528585d2cafc 100644 --- a/arch/arm/plat-s5p/include/plat/s5p6440.h +++ b/arch/arm/plat-s5p/include/plat/s5p6440.h @@ -12,24 +12,23 @@ /* Common init code for S5P6440 related SoCs */ -extern void s5p6440_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); extern void s5p6440_register_clocks(void); extern void s5p6440_setup_clocks(void); #ifdef CONFIG_CPU_S5P6440 -extern int s5p6440_init(void); +extern int s5p64x0_init(void); extern void s5p6440_init_irq(void); extern void s5p6440_map_io(void); extern void s5p6440_init_clocks(int xtal); -#define s5p6440_init_uarts s5p6440_common_init_uarts +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 s5p6440_init NULL +#define s5p64x0_init NULL #endif /* S5P6440 timer */ diff --git a/arch/arm/plat-s5p/include/plat/s5p6450.h b/arch/arm/plat-s5p/include/plat/s5p6450.h new file mode 100644 index 000000000000..640a41c26be3 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/s5p6450.h @@ -0,0 +1,36 @@ +/* arch/arm/plat-s5p/include/plat/s5p6450.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Header file for s5p6450 cpu 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. +*/ + +/* Common init code for S5P6450 related SoCs */ + +extern void s5p6450_register_clocks(void); +extern void s5p6450_setup_clocks(void); + +#ifdef CONFIG_CPU_S5P6450 + +extern int s5p64x0_init(void); +extern void s5p6450_init_irq(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 + +/* S5P6450 timer */ + +extern struct sys_timer s5p6450_timer; diff --git a/arch/arm/plat-s5p/irq-eint.c b/arch/arm/plat-s5p/irq-eint.c index f36cd3327025..752f1a645f9d 100644 --- a/arch/arm/plat-s5p/irq-eint.c +++ b/arch/arm/plat-s5p/irq-eint.c @@ -67,23 +67,23 @@ static int s5p_irq_eint_set_type(unsigned int irq, unsigned int type) switch (type) { case IRQ_TYPE_EDGE_RISING: - newvalue = S5P_EXTINT_RISEEDGE; + newvalue = S5P_IRQ_TYPE_EDGE_RISING; break; case IRQ_TYPE_EDGE_FALLING: - newvalue = S5P_EXTINT_FALLEDGE; + newvalue = S5P_IRQ_TYPE_EDGE_FALLING; break; case IRQ_TYPE_EDGE_BOTH: - newvalue = S5P_EXTINT_BOTHEDGE; + newvalue = S5P_IRQ_TYPE_EDGE_BOTH; break; case IRQ_TYPE_LEVEL_LOW: - newvalue = S5P_EXTINT_LOWLEV; + newvalue = S5P_IRQ_TYPE_LEVEL_LOW; break; case IRQ_TYPE_LEVEL_HIGH: - newvalue = S5P_EXTINT_HILEV; + newvalue = S5P_IRQ_TYPE_LEVEL_HIGH; break; default: diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c new file mode 100644 index 000000000000..0e5dc8cbf5e3 --- /dev/null +++ b/arch/arm/plat-s5p/irq-gpioint.c @@ -0,0 +1,237 @@ +/* linux/arch/arm/plat-s5p/irq-gpioint.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * Author: Kyungmin Park <kyungmin.park@samsung.com> + * Author: Joonyoung Shim <jy0922.shim@samsung.com> + * Author: Marek Szyprowski <m.szyprowski@samsung.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <mach/map.h> +#include <plat/gpio-core.h> +#include <plat/gpio-cfg.h> + +#define S5P_GPIOREG(x) (S5P_VA_GPIO + (x)) + +#define GPIOINT_CON_OFFSET 0x700 +#define GPIOINT_MASK_OFFSET 0x900 +#define GPIOINT_PEND_OFFSET 0xA00 + +static struct s3c_gpio_chip *irq_chips[S5P_GPIOINT_GROUP_MAXNR]; + +static int s5p_gpioint_get_group(unsigned int irq) +{ + struct gpio_chip *chip = get_irq_data(irq); + struct s3c_gpio_chip *s3c_chip = container_of(chip, + struct s3c_gpio_chip, chip); + int group; + + for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) + if (s3c_chip == irq_chips[group]) + break; + + return group; +} + +static int s5p_gpioint_get_offset(unsigned int irq) +{ + struct gpio_chip *chip = get_irq_data(irq); + struct s3c_gpio_chip *s3c_chip = container_of(chip, + struct s3c_gpio_chip, chip); + + return irq - s3c_chip->irq_base; +} + +static void s5p_gpioint_ack(unsigned int irq) +{ + int group, offset, pend_offset; + unsigned int value; + + group = s5p_gpioint_get_group(irq); + offset = s5p_gpioint_get_offset(irq); + pend_offset = group << 2; + + value = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset); + value |= 1 << offset; + __raw_writel(value, S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset); +} + +static void s5p_gpioint_mask(unsigned int irq) +{ + int group, offset, mask_offset; + unsigned int value; + + group = s5p_gpioint_get_group(irq); + offset = s5p_gpioint_get_offset(irq); + mask_offset = group << 2; + + value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset); + value |= 1 << offset; + __raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset); +} + +static void s5p_gpioint_unmask(unsigned int irq) +{ + int group, offset, mask_offset; + unsigned int value; + + group = s5p_gpioint_get_group(irq); + offset = s5p_gpioint_get_offset(irq); + mask_offset = group << 2; + + value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset); + value &= ~(1 << offset); + __raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset); +} + +static void s5p_gpioint_mask_ack(unsigned int irq) +{ + s5p_gpioint_mask(irq); + s5p_gpioint_ack(irq); +} + +static int s5p_gpioint_set_type(unsigned int irq, unsigned int type) +{ + int group, offset, con_offset; + unsigned int value; + + group = s5p_gpioint_get_group(irq); + offset = s5p_gpioint_get_offset(irq); + con_offset = group << 2; + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + type = S5P_IRQ_TYPE_EDGE_RISING; + break; + case IRQ_TYPE_EDGE_FALLING: + type = S5P_IRQ_TYPE_EDGE_FALLING; + break; + case IRQ_TYPE_EDGE_BOTH: + type = S5P_IRQ_TYPE_EDGE_BOTH; + break; + case IRQ_TYPE_LEVEL_HIGH: + type = S5P_IRQ_TYPE_LEVEL_HIGH; + break; + case IRQ_TYPE_LEVEL_LOW: + type = S5P_IRQ_TYPE_LEVEL_LOW; + break; + case IRQ_TYPE_NONE: + default: + printk(KERN_WARNING "No irq type\n"); + return -EINVAL; + } + + value = __raw_readl(S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset); + value &= ~(0x7 << (offset * 0x4)); + value |= (type << (offset * 0x4)); + __raw_writel(value, S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset); + + return 0; +} + +struct irq_chip s5p_gpioint = { + .name = "s5p_gpioint", + .ack = s5p_gpioint_ack, + .mask = s5p_gpioint_mask, + .mask_ack = s5p_gpioint_mask_ack, + .unmask = s5p_gpioint_unmask, + .set_type = s5p_gpioint_set_type, +}; + +static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc) +{ + int group, offset, pend_offset, mask_offset; + int real_irq; + unsigned int pend, mask; + + for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) { + pend_offset = group << 2; + pend = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + + pend_offset); + if (!pend) + continue; + + mask_offset = group << 2; + mask = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + + mask_offset); + pend &= ~mask; + + for (offset = 0; offset < 8; offset++) { + if (pend & (1 << offset)) { + struct s3c_gpio_chip *chip = irq_chips[group]; + if (chip) { + real_irq = chip->irq_base + offset; + generic_handle_irq(real_irq); + } + } + } + } +} + +static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip) +{ + static int used_gpioint_groups = 0; + static bool handler_registered = 0; + int irq, group = chip->group; + int i; + + if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT) + return -ENOMEM; + + chip->irq_base = S5P_GPIOINT_BASE + + used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE; + used_gpioint_groups++; + + if (!handler_registered) { + set_irq_chained_handler(IRQ_GPIOINT, s5p_gpioint_handler); + handler_registered = 1; + } + + irq_chips[group] = chip; + for (i = 0; i < chip->chip.ngpio; i++) { + irq = chip->irq_base + i; + set_irq_chip(irq, &s5p_gpioint); + set_irq_data(irq, &chip->chip); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + return 0; +} + +int __init s5p_register_gpio_interrupt(int pin) +{ + struct s3c_gpio_chip *my_chip = s3c_gpiolib_getchip(pin); + int offset, group; + int ret; + + if (!my_chip) + return -EINVAL; + + offset = pin - my_chip->chip.base; + group = my_chip->group; + + /* check if the group has been already registered */ + if (my_chip->irq_base) + return my_chip->irq_base + offset; + + /* register gpio group */ + ret = s5p_gpioint_add(my_chip); + if (ret == 0) { + my_chip->chip.to_irq = samsung_gpiolib_to_irq; + printk(KERN_INFO "Registered interrupt support for gpio group %d.\n", + group); + return my_chip->irq_base + offset; + } + return ret; +} diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c new file mode 100644 index 000000000000..dc33b9ecda45 --- /dev/null +++ b/arch/arm/plat-s5p/irq-pm.c @@ -0,0 +1,93 @@ +/* linux/arch/arm/plat-s5p/irq-pm.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Based on arch/arm/plat-s3c24xx/irq-pm.c, + * Copyright (c) 2003,2004 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * 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/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/sysdev.h> + +#include <plat/cpu.h> +#include <plat/irqs.h> +#include <plat/pm.h> +#include <mach/map.h> + +#include <mach/regs-gpio.h> +#include <mach/regs-irq.h> + +/* state for IRQs over sleep */ + +/* default is to allow for EINT0..EINT31, and IRQ_RTC_TIC, IRQ_RTC_ALARM, + * as wakeup sources + * + * set bit to 1 in allow bitfield to enable the wakeup settings on it +*/ + +unsigned long s3c_irqwake_intallow = 0x00000006L; +unsigned long s3c_irqwake_eintallow = 0xffffffffL; + +int s3c_irq_wake(unsigned int irqno, unsigned int state) +{ + unsigned long irqbit; + + switch (irqno) { + case IRQ_RTC_TIC: + case IRQ_RTC_ALARM: + irqbit = 1 << (irqno + 1 - IRQ_RTC_ALARM); + if (!state) + s3c_irqwake_intmask |= irqbit; + else + s3c_irqwake_intmask &= ~irqbit; + break; + default: + return -ENOENT; + } + return 0; +} + +static struct sleep_save eint_save[] = { + SAVE_ITEM(S5P_EINT_CON(0)), + SAVE_ITEM(S5P_EINT_CON(1)), + SAVE_ITEM(S5P_EINT_CON(2)), + SAVE_ITEM(S5P_EINT_CON(3)), + + SAVE_ITEM(S5P_EINT_FLTCON(0)), + SAVE_ITEM(S5P_EINT_FLTCON(1)), + SAVE_ITEM(S5P_EINT_FLTCON(2)), + SAVE_ITEM(S5P_EINT_FLTCON(3)), + SAVE_ITEM(S5P_EINT_FLTCON(4)), + SAVE_ITEM(S5P_EINT_FLTCON(5)), + SAVE_ITEM(S5P_EINT_FLTCON(6)), + SAVE_ITEM(S5P_EINT_FLTCON(7)), + + SAVE_ITEM(S5P_EINT_MASK(0)), + SAVE_ITEM(S5P_EINT_MASK(1)), + SAVE_ITEM(S5P_EINT_MASK(2)), + SAVE_ITEM(S5P_EINT_MASK(3)), +}; + +int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state) +{ + s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save)); + + return 0; +} + +int s3c24xx_irq_resume(struct sys_device *dev) +{ + s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save)); + + return 0; +} + diff --git a/arch/arm/plat-s5p/pm.c b/arch/arm/plat-s5p/pm.c new file mode 100644 index 000000000000..d592b6304b48 --- /dev/null +++ b/arch/arm/plat-s5p/pm.c @@ -0,0 +1,52 @@ +/* linux/arch/arm/plat-s5p/pm.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P Power Manager (Suspend-To-RAM) support + * + * Based on arch/arm/plat-s3c24xx/pm.c + * Copyright (c) 2004,2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * 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 <plat/pm.h> + +#define PFX "s5p pm: " + +/* s3c_pm_check_resume_pin + * + * check to see if the pin is configured correctly for sleep mode, and + * make any necessary adjustments if it is not +*/ + +static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs) +{ + /* nothing here yet */ +} + +/* s3c_pm_configure_extint + * + * configure all external interrupt pins +*/ + +void s3c_pm_configure_extint(void) +{ + /* nothing here yet */ +} + +void s3c_pm_restore_core(void) +{ + /* nothing here yet */ +} + +void s3c_pm_save_core(void) +{ + /* nothing here yet */ +} + diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 7c0bde781167..dcd6eff4ee53 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -180,6 +180,31 @@ config S3C_DEV_I2C2 help Compile in platform device definitions for I2C channel 2 +config S3C_DEV_I2C3 + bool + help + Compile in platform device definition for I2C controller 3 + +config S3C_DEV_I2C4 + bool + help + Compile in platform device definition for I2C controller 4 + +config S3C_DEV_I2C5 + bool + help + Compile in platform device definition for I2C controller 5 + +config S3C_DEV_I2C6 + bool + help + Compile in platform device definition for I2C controller 6 + +config S3C_DEV_I2C7 + bool + help + Compile in platform device definition for I2C controller 7 + config S3C_DEV_FB bool help diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 4d8ff923207a..afcce474af8e 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -40,6 +40,11 @@ obj-$(CONFIG_S3C_DEV_HWMON) += dev-hwmon.o obj-y += dev-i2c0.o obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o obj-$(CONFIG_S3C_DEV_I2C2) += dev-i2c2.o +obj-$(CONFIG_S3C_DEV_I2C3) += dev-i2c3.o +obj-$(CONFIG_S3C_DEV_I2C4) += dev-i2c4.o +obj-$(CONFIG_S3C_DEV_I2C5) += dev-i2c5.o +obj-$(CONFIG_S3C_DEV_I2C6) += dev-i2c6.o +obj-$(CONFIG_S3C_DEV_I2C7) += dev-i2c7.o obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o obj-y += dev-uart.o obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c index 9d2be0941410..db7a65c7f127 100644 --- a/arch/arm/plat-samsung/dev-hsmmc.c +++ b/arch/arm/plat-samsung/dev-hsmmc.c @@ -41,6 +41,7 @@ struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = { .max_width = 4, .host_caps = (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), + .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, }; struct platform_device s3c_device_hsmmc0 = { @@ -59,17 +60,20 @@ void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd) { struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata; - set->max_width = pd->max_width; set->cd_type = pd->cd_type; set->ext_cd_init = pd->ext_cd_init; set->ext_cd_cleanup = pd->ext_cd_cleanup; set->ext_cd_gpio = pd->ext_cd_gpio; set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; + if (pd->max_width) + set->max_width = pd->max_width; if (pd->cfg_gpio) set->cfg_gpio = pd->cfg_gpio; if (pd->cfg_card) set->cfg_card = pd->cfg_card; if (pd->host_caps) - set->host_caps = pd->host_caps; + set->host_caps |= pd->host_caps; + if (pd->clk_type) + set->clk_type = pd->clk_type; } diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c index a6c8295840af..2497321f08d7 100644 --- a/arch/arm/plat-samsung/dev-hsmmc1.c +++ b/arch/arm/plat-samsung/dev-hsmmc1.c @@ -41,6 +41,7 @@ struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = { .max_width = 4, .host_caps = (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), + .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, }; struct platform_device s3c_device_hsmmc1 = { @@ -59,17 +60,20 @@ void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd) { struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata; - set->max_width = pd->max_width; set->cd_type = pd->cd_type; set->ext_cd_init = pd->ext_cd_init; set->ext_cd_cleanup = pd->ext_cd_cleanup; set->ext_cd_gpio = pd->ext_cd_gpio; set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; + if (pd->max_width) + set->max_width = pd->max_width; if (pd->cfg_gpio) set->cfg_gpio = pd->cfg_gpio; if (pd->cfg_card) set->cfg_card = pd->cfg_card; if (pd->host_caps) - set->host_caps = pd->host_caps; + set->host_caps |= pd->host_caps; + if (pd->clk_type) + set->clk_type = pd->clk_type; } diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c index cb0d7143381a..f60aedba417c 100644 --- a/arch/arm/plat-samsung/dev-hsmmc2.c +++ b/arch/arm/plat-samsung/dev-hsmmc2.c @@ -42,6 +42,7 @@ struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = { .max_width = 4, .host_caps = (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), + .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, }; struct platform_device s3c_device_hsmmc2 = { @@ -60,17 +61,20 @@ void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd) { struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata; - set->max_width = pd->max_width; set->cd_type = pd->cd_type; set->ext_cd_init = pd->ext_cd_init; set->ext_cd_cleanup = pd->ext_cd_cleanup; set->ext_cd_gpio = pd->ext_cd_gpio; set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; + if (pd->max_width) + set->max_width = pd->max_width; if (pd->cfg_gpio) set->cfg_gpio = pd->cfg_gpio; if (pd->cfg_card) set->cfg_card = pd->cfg_card; if (pd->host_caps) - set->host_caps = pd->host_caps; + set->host_caps |= pd->host_caps; + if (pd->clk_type) + set->clk_type = pd->clk_type; } diff --git a/arch/arm/plat-samsung/dev-hsmmc3.c b/arch/arm/plat-samsung/dev-hsmmc3.c index 85aaf0f2842f..ede776f20e62 100644 --- a/arch/arm/plat-samsung/dev-hsmmc3.c +++ b/arch/arm/plat-samsung/dev-hsmmc3.c @@ -33,8 +33,8 @@ static struct resource s3c_hsmmc3_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_MMC3, - .end = IRQ_MMC3, + .start = IRQ_HSMMC3, + .end = IRQ_HSMMC3, .flags = IORESOURCE_IRQ, } }; @@ -45,6 +45,7 @@ struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = { .max_width = 4, .host_caps = (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), + .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, }; struct platform_device s3c_device_hsmmc3 = { @@ -63,15 +64,20 @@ void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd) { struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata; - set->max_width = pd->max_width; set->cd_type = pd->cd_type; set->ext_cd_init = pd->ext_cd_init; set->ext_cd_cleanup = pd->ext_cd_cleanup; set->ext_cd_gpio = pd->ext_cd_gpio; set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; + if (pd->max_width) + set->max_width = pd->max_width; if (pd->cfg_gpio) set->cfg_gpio = pd->cfg_gpio; if (pd->cfg_card) set->cfg_card = pd->cfg_card; + if (pd->host_caps) + set->host_caps |= pd->host_caps; + if (pd->clk_type) + set->clk_type = pd->clk_type; } diff --git a/arch/arm/plat-samsung/dev-i2c2.c b/arch/arm/plat-samsung/dev-i2c2.c index 07036dee09e7..ff4ba69b6830 100644 --- a/arch/arm/plat-samsung/dev-i2c2.c +++ b/arch/arm/plat-samsung/dev-i2c2.c @@ -32,8 +32,8 @@ static struct resource s3c_i2c_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_CAN0, - .end = IRQ_CAN0, + .start = IRQ_IIC2, + .end = IRQ_IIC2, .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/arm/plat-samsung/dev-i2c3.c b/arch/arm/plat-samsung/dev-i2c3.c new file mode 100644 index 000000000000..8586a10014b7 --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c3.c @@ -0,0 +1,68 @@ +/* linux/arch/arm/plat-samsung/dev-i2c3.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5P series device definition for i2c device 3 + * + * 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/gfp.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/platform_device.h> + +#include <mach/irqs.h> +#include <mach/map.h> + +#include <plat/regs-iic.h> +#include <plat/iic.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +static struct resource s3c_i2c_resource[] = { + [0] = { + .start = S3C_PA_IIC3, + .end = S3C_PA_IIC3 + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IIC3, + .end = IRQ_IIC3, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_i2c3 = { + .name = "s3c2440-i2c", + .id = 3, + .num_resources = ARRAY_SIZE(s3c_i2c_resource), + .resource = s3c_i2c_resource, +}; + +static struct s3c2410_platform_i2c default_i2c_data3 __initdata = { + .flags = 0, + .bus_num = 3, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, +}; + +void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd) +{ + struct s3c2410_platform_i2c *npd; + + if (!pd) + pd = &default_i2c_data3; + + npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + else if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c3_cfg_gpio; + + s3c_device_i2c3.dev.platform_data = npd; +} diff --git a/arch/arm/plat-samsung/dev-i2c4.c b/arch/arm/plat-samsung/dev-i2c4.c new file mode 100644 index 000000000000..df2159e2daa6 --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c4.c @@ -0,0 +1,68 @@ +/* linux/arch/arm/plat-samsung/dev-i2c4.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5P series device definition for i2c device 3 + * + * 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/gfp.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/platform_device.h> + +#include <mach/irqs.h> +#include <mach/map.h> + +#include <plat/regs-iic.h> +#include <plat/iic.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +static struct resource s3c_i2c_resource[] = { + [0] = { + .start = S3C_PA_IIC4, + .end = S3C_PA_IIC4 + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IIC4, + .end = IRQ_IIC4, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_i2c4 = { + .name = "s3c2440-i2c", + .id = 4, + .num_resources = ARRAY_SIZE(s3c_i2c_resource), + .resource = s3c_i2c_resource, +}; + +static struct s3c2410_platform_i2c default_i2c_data4 __initdata = { + .flags = 0, + .bus_num = 4, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, +}; + +void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd) +{ + struct s3c2410_platform_i2c *npd; + + if (!pd) + pd = &default_i2c_data4; + + npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + else if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c4_cfg_gpio; + + s3c_device_i2c4.dev.platform_data = npd; +} diff --git a/arch/arm/plat-samsung/dev-i2c5.c b/arch/arm/plat-samsung/dev-i2c5.c new file mode 100644 index 000000000000..0499c2c3877b --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c5.c @@ -0,0 +1,68 @@ +/* linux/arch/arm/plat-samsung/dev-i2c3.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5P series device definition for i2c device 3 + * + * 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/gfp.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/platform_device.h> + +#include <mach/irqs.h> +#include <mach/map.h> + +#include <plat/regs-iic.h> +#include <plat/iic.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +static struct resource s3c_i2c_resource[] = { + [0] = { + .start = S3C_PA_IIC5, + .end = S3C_PA_IIC5 + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IIC5, + .end = IRQ_IIC5, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_i2c5 = { + .name = "s3c2440-i2c", + .id = 5, + .num_resources = ARRAY_SIZE(s3c_i2c_resource), + .resource = s3c_i2c_resource, +}; + +static struct s3c2410_platform_i2c default_i2c_data5 __initdata = { + .flags = 0, + .bus_num = 5, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, +}; + +void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd) +{ + struct s3c2410_platform_i2c *npd; + + if (!pd) + pd = &default_i2c_data5; + + npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + else if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c5_cfg_gpio; + + s3c_device_i2c5.dev.platform_data = npd; +} diff --git a/arch/arm/plat-samsung/dev-i2c6.c b/arch/arm/plat-samsung/dev-i2c6.c new file mode 100644 index 000000000000..4083108908a8 --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c6.c @@ -0,0 +1,68 @@ +/* linux/arch/arm/plat-samsung/dev-i2c6.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5P series device definition for i2c device 6 + * + * 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/gfp.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/platform_device.h> + +#include <mach/irqs.h> +#include <mach/map.h> + +#include <plat/regs-iic.h> +#include <plat/iic.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +static struct resource s3c_i2c_resource[] = { + [0] = { + .start = S3C_PA_IIC6, + .end = S3C_PA_IIC6 + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IIC6, + .end = IRQ_IIC6, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_i2c6 = { + .name = "s3c2440-i2c", + .id = 6, + .num_resources = ARRAY_SIZE(s3c_i2c_resource), + .resource = s3c_i2c_resource, +}; + +static struct s3c2410_platform_i2c default_i2c_data6 __initdata = { + .flags = 0, + .bus_num = 6, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, +}; + +void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd) +{ + struct s3c2410_platform_i2c *npd; + + if (!pd) + pd = &default_i2c_data6; + + npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + else if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c6_cfg_gpio; + + s3c_device_i2c6.dev.platform_data = npd; +} diff --git a/arch/arm/plat-samsung/dev-i2c7.c b/arch/arm/plat-samsung/dev-i2c7.c new file mode 100644 index 000000000000..1182451d7dce --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c7.c @@ -0,0 +1,68 @@ +/* linux/arch/arm/plat-samsung/dev-i2c7.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5P series device definition for i2c device 7 + * + * 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/gfp.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/platform_device.h> + +#include <mach/irqs.h> +#include <mach/map.h> + +#include <plat/regs-iic.h> +#include <plat/iic.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +static struct resource s3c_i2c_resource[] = { + [0] = { + .start = S3C_PA_IIC7, + .end = S3C_PA_IIC7 + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IIC7, + .end = IRQ_IIC7, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_i2c7 = { + .name = "s3c2440-i2c", + .id = 7, + .num_resources = ARRAY_SIZE(s3c_i2c_resource), + .resource = s3c_i2c_resource, +}; + +static struct s3c2410_platform_i2c default_i2c_data7 __initdata = { + .flags = 0, + .bus_num = 7, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, +}; + +void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd) +{ + struct s3c2410_platform_i2c *npd; + + if (!pd) + pd = &default_i2c_data7; + + npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + else if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c7_cfg_gpio; + + s3c_device_i2c7.dev.platform_data = npd; +} diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index e3d41eaed1ff..8a372110a850 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -41,6 +41,37 @@ int s3c_gpio_cfgpin(unsigned int pin, unsigned int config) } EXPORT_SYMBOL(s3c_gpio_cfgpin); +int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, + unsigned int cfg) +{ + int ret; + + for (; nr > 0; nr--, start++) { + ret = s3c_gpio_cfgpin(start, cfg); + if (ret != 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range); + +int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr, + unsigned int cfg, s3c_gpio_pull_t pull) +{ + int ret; + + for (; nr > 0; nr--, start++) { + s3c_gpio_setpull(start, pull); + ret = s3c_gpio_cfgpin(start, cfg); + if (ret != 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range); + unsigned s3c_gpio_getcfg(unsigned int pin) { struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c index b83a83351cea..7743c4b8b2fb 100644 --- a/arch/arm/plat-samsung/gpio.c +++ b/arch/arm/plat-samsung/gpio.c @@ -157,3 +157,11 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip) if (ret >= 0) s3c_gpiolib_track(chip); } + +int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) +{ + struct s3c_gpio_chip *s3c_chip = container_of(chip, + struct s3c_gpio_chip, chip); + + return s3c_chip->irq_base + offset; +} diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h index e32f9edfd4b7..7712ff6336f4 100644 --- a/arch/arm/plat-samsung/include/plat/audio.h +++ b/arch/arm/plat-samsung/include/plat/audio.h @@ -16,6 +16,15 @@ #define S3C64XX_AC97_GPE 1 extern void s3c64xx_ac97_setup_gpio(int); +/* + * The machine init code calls s5p*_spdif_setup_gpio with + * one of these defines in order to select appropriate bank + * of GPIO for S/PDIF pins + */ +#define S5PC100_SPDIF_GPD 0 +#define S5PC100_SPDIF_GPG3 1 +extern void s5pc100_spdif_setup_gpio(int); + /** * struct s3c_audio_pdata - common platform data for audio device drivers * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index 6412933d6fbb..9addb3dfb4bc 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -79,7 +79,7 @@ extern struct sysdev_class s3c2442_sysclass; extern struct sysdev_class s3c2443_sysclass; extern struct sysdev_class s3c6410_sysclass; extern struct sysdev_class s3c64xx_sysclass; -extern struct sysdev_class s5p6440_sysclass; +extern struct sysdev_class s5p64x0_sysclass; extern struct sysdev_class s5p6442_sysclass; extern struct sysdev_class s5pv210_sysclass; diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 85f6f23a510f..16521cc12532 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -46,6 +46,11 @@ extern struct platform_device s3c_device_wdt; extern struct platform_device s3c_device_i2c0; extern struct platform_device s3c_device_i2c1; extern struct platform_device s3c_device_i2c2; +extern struct platform_device s3c_device_i2c3; +extern struct platform_device s3c_device_i2c4; +extern struct platform_device s3c_device_i2c5; +extern struct platform_device s3c_device_i2c6; +extern struct platform_device s3c_device_i2c7; extern struct platform_device s3c_device_rtc; extern struct platform_device s3c_device_adc; extern struct platform_device s3c_device_sdi; @@ -67,13 +72,15 @@ extern struct platform_device s5pv210_device_spi0; extern struct platform_device s5pv210_device_spi1; extern struct platform_device s5p6440_device_spi0; extern struct platform_device s5p6440_device_spi1; +extern struct platform_device s5p6450_device_spi0; +extern struct platform_device s5p6450_device_spi1; extern struct platform_device s3c_device_hwmon; extern struct platform_device s3c_device_nand; extern struct platform_device s3c_device_onenand; extern struct platform_device s3c64xx_device_onenand1; -extern struct platform_device s5pc110_device_onenand; +extern struct platform_device s5p_device_onenand; extern struct platform_device s3c_device_usbgadget; extern struct platform_device s3c_device_usb_hsotg; @@ -85,6 +92,7 @@ extern struct platform_device s5pv210_device_pcm2; extern struct platform_device s5pv210_device_iis0; extern struct platform_device s5pv210_device_iis1; extern struct platform_device s5pv210_device_iis2; +extern struct platform_device s5pv210_device_spdif; extern struct platform_device s5p6442_device_pcm0; extern struct platform_device s5p6442_device_pcm1; @@ -95,12 +103,16 @@ extern struct platform_device s5p6442_device_spi; extern struct platform_device s5p6440_device_pcm; extern struct platform_device s5p6440_device_iis; +extern struct platform_device s5p6450_device_iis0; +extern struct platform_device s5p6450_device_pcm0; + extern struct platform_device s5pc100_device_ac97; extern struct platform_device s5pc100_device_pcm0; extern struct platform_device s5pc100_device_pcm1; extern struct platform_device s5pc100_device_iis0; extern struct platform_device s5pc100_device_iis1; extern struct platform_device s5pc100_device_iis2; +extern struct platform_device s5pc100_device_spdif; extern struct platform_device samsung_device_keypad; diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index 1c6b92947c5d..e4b5cf126fa9 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h @@ -108,6 +108,19 @@ extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to); */ extern unsigned s3c_gpio_getcfg(unsigned int pin); +/** + * s3c_gpio_cfgpin_range() - Change the GPIO function for configuring pin range + * @start: The pin number to start at + * @nr: The number of pins to configure from @start. + * @cfg: The configuration for the pin's function + * + * Call s3c_gpio_cfgpin() for the @nr pins starting at @start. + * + * @sa s3c_gpio_cfgpin. + */ +extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, + unsigned int cfg); + /* Define values for the pull-{up,down} available for each gpio pin. * * These values control the state of the weak pull-{up,down} resistors @@ -140,6 +153,31 @@ extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull); */ extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin); +/* configure `all` aspects of an gpio */ + +/** + * s3c_gpio_cfgall_range() - configure range of gpio functtion and pull. + * @start: The gpio number to start at. + * @nr: The number of gpio to configure from @start. + * @cfg: The configuration to use + * @pull: The pull setting to use. + * + * Run s3c_gpio_cfgpin() and s3c_gpio_setpull() over the gpio range starting + * @gpio and running for @size. + * + * @sa s3c_gpio_cfgpin + * @sa s3c_gpio_setpull + * @sa s3c_gpio_cfgpin_range + */ +extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr, + unsigned int cfg, s3c_gpio_pull_t pull); + +static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size, + unsigned int cfg) +{ + return s3c_gpio_cfgall_range(pin, size, cfg, S3C_GPIO_PULL_NONE); +} + /* Define values for the drvstr available for each gpio pin. * * These values control the value of the output signal driver strength, @@ -169,4 +207,22 @@ extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin); */ extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr); +/** + * s5p_register_gpio_interrupt() - register interrupt support for a gpio group + * @pin: The pin number from the group to be registered + * + * This function registers gpio interrupt support for the group that the + * specified pin belongs to. + * + * The total number of gpio pins is quite large ob s5p series. Registering + * irq support for all of them would be a resource waste. Because of that the + * interrupt support for standard gpio pins is registered dynamically. + * + * It will return the irq number of the interrupt that has been registered + * or -ENOMEM if no more gpio interrupts can be registered. It is allowed + * to call this function more than once for the same gpio group (the group + * will be registered only once). + */ +extern int s5p_register_gpio_interrupt(int pin); + #endif /* __PLAT_GPIO_CFG_H */ diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index e358c7da8480..13a22b8861ef 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h @@ -43,6 +43,8 @@ struct s3c_gpio_cfg; * struct s3c_gpio_chip - wrapper for specific implementation of gpio * @chip: The chip structure to be exported via gpiolib. * @base: The base pointer to the gpio configuration registers. + * @group: The group register number for gpio interrupt support. + * @irq_base: The base irq number. * @config: special function and pull-resistor control information. * @lock: Lock for exclusive access to this gpio bank. * @pm_save: Save information for suspend/resume support. @@ -63,6 +65,8 @@ struct s3c_gpio_chip { struct s3c_gpio_cfg *config; struct s3c_gpio_pm *pm; void __iomem *base; + int irq_base; + int group; spinlock_t lock; #ifdef CONFIG_PM u32 pm_save[4]; @@ -118,6 +122,17 @@ extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip, extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip); extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip); + +/** + * samsung_gpiolib_to_irq - convert gpio pin to irq number + * @chip: The gpio chip that the pin belongs to. + * @offset: The offset of the pin in the chip. + * + * This helper returns the irq number calculated from the chip->irq_base and + * the provided offset. + */ +extern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset); + /* exported for core SoC support to change */ extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default; diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h index 133308bf595d..1543da8f85c1 100644 --- a/arch/arm/plat-samsung/include/plat/iic.h +++ b/arch/arm/plat-samsung/include/plat/iic.h @@ -55,10 +55,20 @@ struct s3c2410_platform_i2c { extern void s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *i2c); extern void s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *i2c); extern void s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *i2c); +extern void s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *i2c); +extern void s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *i2c); +extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c); +extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c); +extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c); /* defined by architecture to configure gpio */ extern void s3c_i2c0_cfg_gpio(struct platform_device *dev); extern void s3c_i2c1_cfg_gpio(struct platform_device *dev); extern void s3c_i2c2_cfg_gpio(struct platform_device *dev); +extern void s3c_i2c3_cfg_gpio(struct platform_device *dev); +extern void s3c_i2c4_cfg_gpio(struct platform_device *dev); +extern void s3c_i2c5_cfg_gpio(struct platform_device *dev); +extern void s3c_i2c6_cfg_gpio(struct platform_device *dev); +extern void s3c_i2c7_cfg_gpio(struct platform_device *dev); #endif /* __ASM_ARCH_IIC_H */ diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h index 5fe6721b57f7..810744213120 100644 --- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h +++ b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h @@ -32,6 +32,12 @@ enum dma_ch { DMACH_UART2_TX, DMACH_UART3_RX, DMACH_UART3_TX, + DMACH_UART4_RX, + DMACH_UART4_TX, + DMACH_UART5_RX, + DMACH_UART5_TX, + DMACH_USI_RX, + DMACH_USI_TX, DMACH_IRDA, DMACH_I2S0_RX, DMACH_I2S0_TX, @@ -64,6 +70,20 @@ enum dma_ch { DMACH_MSM_REQ2, DMACH_MSM_REQ1, DMACH_MSM_REQ0, + DMACH_SLIMBUS0_RX, + DMACH_SLIMBUS0_TX, + DMACH_SLIMBUS0AUX_RX, + DMACH_SLIMBUS0AUX_TX, + DMACH_SLIMBUS1_RX, + DMACH_SLIMBUS1_TX, + DMACH_SLIMBUS2_RX, + DMACH_SLIMBUS2_TX, + DMACH_SLIMBUS3_RX, + DMACH_SLIMBUS3_TX, + DMACH_SLIMBUS4_RX, + DMACH_SLIMBUS4_TX, + DMACH_SLIMBUS5_RX, + DMACH_SLIMBUS5_TX, /* END Marker, also used to denote a reserved channel */ DMACH_MAX, }; diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h index e5aba8f95b79..ae8e802bdca8 100644 --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h @@ -65,7 +65,7 @@ struct s3c64xx_spi_info { extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); -extern void s5p6440_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); +extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); extern void s5p6442_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); #endif /* __S3C64XX_PLAT_SPI_H */ diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h index 30844c263d03..85853f8c4c5d 100644 --- a/arch/arm/plat-samsung/include/plat/sdhci.h +++ b/arch/arm/plat-samsung/include/plat/sdhci.h @@ -28,11 +28,17 @@ enum cd_types { S3C_SDHCI_CD_PERMANENT, /* no CD line, card permanently wired to host */ }; +enum clk_types { + S3C_SDHCI_CLK_DIV_INTERNAL, /* use mmc internal clock divider */ + S3C_SDHCI_CLK_DIV_EXTERNAL, /* use external clock divider */ +}; + /** * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI * @max_width: The maximum number of data bits supported. * @host_caps: Standard MMC host capabilities bit field. * @cd_type: Type of Card Detection method (see cd_types enum above) + * @clk_type: Type of clock divider method (see clk_types enum above) * @ext_cd_init: Initialize external card detect subsystem. Called on * sdhci-s3c driver probe when cd_type == S3C_SDHCI_CD_EXTERNAL. * notify_func argument is a callback to the sdhci-s3c driver @@ -59,6 +65,7 @@ struct s3c_sdhci_platdata { unsigned int max_width; unsigned int host_caps; enum cd_types cd_type; + enum clk_types clk_type; char **clocks; /* set of clock sources */ @@ -110,6 +117,10 @@ extern void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *, int w); extern void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *, int w); extern void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *, int w); extern void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *, int w); +extern void s5pv310_setup_sdhci0_cfg_gpio(struct platform_device *, int w); +extern void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *, int w); +extern void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *, int w); +extern void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *, int w); /* S3C64XX SDHCI setup */ @@ -288,4 +299,57 @@ static inline void s5pv210_default_sdhci3(void) { } #endif /* CONFIG_S5PV210_SETUP_SDHCI */ +/* S5PV310 SDHCI setup */ +#ifdef CONFIG_S5PV310_SETUP_SDHCI +extern char *s5pv310_hsmmc_clksrcs[4]; + +extern void s5pv310_setup_sdhci_cfg_card(struct platform_device *dev, + void __iomem *r, + struct mmc_ios *ios, + struct mmc_card *card); + +static inline void s5pv310_default_sdhci0(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC + s3c_hsmmc0_def_platdata.clocks = s5pv310_hsmmc_clksrcs; + s3c_hsmmc0_def_platdata.cfg_gpio = s5pv310_setup_sdhci0_cfg_gpio; + s3c_hsmmc0_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card; +#endif +} + +static inline void s5pv310_default_sdhci1(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC1 + s3c_hsmmc1_def_platdata.clocks = s5pv310_hsmmc_clksrcs; + s3c_hsmmc1_def_platdata.cfg_gpio = s5pv310_setup_sdhci1_cfg_gpio; + s3c_hsmmc1_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card; +#endif +} + +static inline void s5pv310_default_sdhci2(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC2 + s3c_hsmmc2_def_platdata.clocks = s5pv310_hsmmc_clksrcs; + s3c_hsmmc2_def_platdata.cfg_gpio = s5pv310_setup_sdhci2_cfg_gpio; + s3c_hsmmc2_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card; +#endif +} + +static inline void s5pv310_default_sdhci3(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC3 + s3c_hsmmc3_def_platdata.clocks = s5pv310_hsmmc_clksrcs; + s3c_hsmmc3_def_platdata.cfg_gpio = s5pv310_setup_sdhci3_cfg_gpio; + s3c_hsmmc3_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card; +#endif +} + +#else +static inline void s5pv310_default_sdhci0(void) { } +static inline void s5pv310_default_sdhci1(void) { } +static inline void s5pv310_default_sdhci2(void) { } +static inline void s5pv310_default_sdhci3(void) { } + +#endif /* CONFIG_S5PV310_SETUP_SDHCI */ + #endif /* __PLAT_S3C_SDHCI_H */ diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c index 7df03f87fbfa..96528200eb79 100644 --- a/arch/arm/plat-samsung/pm-gpio.c +++ b/arch/arm/plat-samsung/pm-gpio.c @@ -192,7 +192,7 @@ struct s3c_gpio_pm s3c_gpio_pm_2bit = { .resume = s3c_gpio_pm_2bit_resume, }; -#ifdef CONFIG_ARCH_S3C64XX +#if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P) static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip) { chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON); @@ -302,7 +302,7 @@ struct s3c_gpio_pm s3c_gpio_pm_4bit = { .save = s3c_gpio_pm_4bit_save, .resume = s3c_gpio_pm_4bit_resume, }; -#endif /* CONFIG_ARCH_S3C64XX */ +#endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */ /** * s3c_pm_save_gpio() - save gpio chip data for suspend diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 12900f7083b0..3198c5335f0b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -458,6 +458,7 @@ config SERIAL_SAMSUNG_UARTS int depends on ARM && PLAT_SAMSUNG default 2 if ARCH_S3C2400 + default 6 if ARCH_S5P6450 default 4 if SERIAL_SAMSUNG_UARTS_4 default 3 help @@ -526,12 +527,12 @@ config SERIAL_S3C24A0 Serial port support for the Samsung S3C24A0 SoC config SERIAL_S3C6400 - tristate "Samsung S3C6400/S3C6410/S5P6440/S5PC100 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5PC100) + tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support" + depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100) select SERIAL_SAMSUNG_UARTS_4 default y help - Serial port support for the Samsung S3C6400, S3C6410, S5P6440 + Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450 and S5PC100 SoCs config SERIAL_S5PV210 diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index b1156ba8ad14..7ac2bf5167cd 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -1101,7 +1101,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); port->mapbase = res->start; - port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000); + port->membase = S3C_VA_UART + (res->start & 0xfffff); ret = platform_get_irq(platdev, 0); if (ret < 0) port->irq = 0; |