diff options
98 files changed, 4256 insertions, 260 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3b5add123396..c797a8b4d8cc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -717,6 +717,15 @@ config ARCH_S5PV210 help Samsung S5PV210/S5PC110 series based systems +config ARCH_S5PV310 + bool "Samsung S5PV310/S5PC210" + select CPU_V7 + select GENERIC_GPIO + select HAVE_CLK + select GENERIC_CLOCKEVENTS + help + Samsung S5PV310 series based systems + config ARCH_SHARK bool "Shark" select CPU_SA110 @@ -917,6 +926,8 @@ source "arch/arm/mach-s5pc100/Kconfig" source "arch/arm/mach-s5pv210/Kconfig" +source "arch/arm/mach-s5pv310/Kconfig" + source "arch/arm/mach-shmobile/Kconfig" source "arch/arm/plat-stmp3xxx/Kconfig" @@ -1113,10 +1124,11 @@ config SMP bool "Symmetric Multi-Processing (EXPERIMENTAL)" depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\ MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\ - ARCH_U8500 || ARCH_VEXPRESS_CA9X4) + ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_S5PV310) depends on GENERIC_CLOCKEVENTS select USE_GENERIC_SMP_HELPERS - select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4) + select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 ||\ + ARCH_S5PV310) help This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If @@ -1185,9 +1197,10 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \ - REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || ARCH_U8500) + REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ + ARCH_U8500 || ARCH_S5PV310) default y - select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500) + select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_S5PV310) help Enable support for local timers on SMP platforms, rather then the legacy IPI broadcast method. Local timers allows the system @@ -1199,7 +1212,8 @@ source kernel/Kconfig.preempt config HZ int default 128 if ARCH_L7200 - default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PV210 + default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || ARCH_S5P6442 || \ + ARCH_S5PV210 || ARCH_S5PV310 default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER default AT91_TIMER_HZ if ARCH_AT91 default 100 diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 64ba313724d2..d80c9f98d1bf 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -170,6 +170,7 @@ machine-$(CONFIG_ARCH_S5P6440) := s5p6440 machine-$(CONFIG_ARCH_S5P6442) := s5p6442 machine-$(CONFIG_ARCH_S5PC100) := s5pc100 machine-$(CONFIG_ARCH_S5PV210) := s5pv210 +machine-$(CONFIG_ARCH_S5PV310) := s5pv310 machine-$(CONFIG_ARCH_SA1100) := sa1100 machine-$(CONFIG_ARCH_SHARK) := shark machine-$(CONFIG_ARCH_SHMOBILE) := shmobile diff --git a/arch/arm/configs/s5pc110_defconfig b/arch/arm/configs/s5pc110_defconfig deleted file mode 100644 index 22c2d147f793..000000000000 --- a/arch/arm/configs/s5pc110_defconfig +++ /dev/null @@ -1,66 +0,0 @@ -CONFIG_EXPERIMENTAL=y -CONFIG_SYSFS_DEPRECATED_V2=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_KALLSYMS_ALL=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_ARCH_S5PV210=y -CONFIG_S3C_LOWLEVEL_UART_PORT=1 -CONFIG_MACH_SMDKC110=y -CONFIG_VMSPLIT_2G=y -CONFIG_PREEMPT=y -CONFIG_AEABI=y -CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc" -CONFIG_VFP=y -CONFIG_NEON=y -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -# CONFIG_MISC_DEVICES is not set -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_SG=y -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_SAMSUNG=y -CONFIG_SERIAL_SAMSUNG_CONSOLE=y -CONFIG_HW_RANDOM=y -# CONFIG_HWMON is not set -# CONFIG_VGA_CONSOLE is not set -# CONFIG_HID_SUPPORT is not set -# CONFIG_USB_SUPPORT is not set -CONFIG_EXT2_FS=y -CONFIG_INOTIFY=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_CRAMFS=y -CONFIG_ROMFS_FS=y -CONFIG_PARTITION_ADVANCED=y -CONFIG_BSD_DISKLABEL=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_PREEMPT is not set -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y -CONFIG_DEBUG_INFO=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_LL=y -CONFIG_EARLY_PRINTK=y -CONFIG_DEBUG_S3C_UART=1 -CONFIG_CRC_CCITT=y diff --git a/arch/arm/configs/s5pv210_defconfig b/arch/arm/configs/s5pv210_defconfig index 1753836d0055..0488a1eb4d7d 100644 --- a/arch/arm/configs/s5pv210_defconfig +++ b/arch/arm/configs/s5pv210_defconfig @@ -7,6 +7,11 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set CONFIG_ARCH_S5PV210=y CONFIG_S3C_LOWLEVEL_UART_PORT=1 +CONFIG_S3C_DEV_FB=y +CONFIG_S5PV210_SETUP_FB_24BPP=y +CONFIG_MACH_AQUILA=y +CONFIG_MACH_GONI=y +CONFIG_MACH_SMDKC110=y CONFIG_MACH_SMDKV210=y CONFIG_VMSPLIT_2G=y CONFIG_PREEMPT=y diff --git a/arch/arm/mach-s5p6440/Kconfig b/arch/arm/mach-s5p6440/Kconfig index 084c0bced13c..6a4af7f57584 100644 --- a/arch/arm/mach-s5p6440/Kconfig +++ b/arch/arm/mach-s5p6440/Kconfig @@ -13,12 +13,20 @@ config CPU_S5P6440 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 SAMSUNG_DEV_TS - select SAMSUNG_DEV_ADC + 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 diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile index be3c53aab23f..c3fe4d3662a9 100644 --- a/arch/arm/mach-s5p6440/Makefile +++ b/arch/arm/mach-s5p6440/Makefile @@ -22,3 +22,4 @@ 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/include/mach/irqs.h b/arch/arm/mach-s5p6440/include/mach/irqs.h index 911854d9ad42..16a761270de1 100644 --- a/arch/arm/mach-s5p6440/include/mach/irqs.h +++ b/arch/arm/mach-s5p6440/include/mach/irqs.h @@ -51,7 +51,7 @@ #define IRQ_DISPCON3 S5P_IRQ_VIC1(19) #define IRQ_FIMGVG S5P_IRQ_VIC1(20) #define IRQ_EINT_GROUPS S5P_IRQ_VIC1(21) -#define IRQ_PMUIRQ S5P_IRQ_VIC1(23) +#define IRQ_PMU S5P_IRQ_VIC1(23) #define IRQ_HSMMC0 S5P_IRQ_VIC1(24) #define IRQ_HSMMC1 S5P_IRQ_VIC1(25) #define IRQ_HSMMC2 IRQ_SPI1 /* shared with SPI1 */ diff --git a/arch/arm/mach-s5p6440/include/mach/map.h b/arch/arm/mach-s5p6440/include/mach/map.h index 44011b91fbd1..6cc5cbc88ffb 100644 --- a/arch/arm/mach-s5p6440/include/mach/map.h +++ b/arch/arm/mach-s5p6440/include/mach/map.h @@ -38,7 +38,6 @@ #define S5P_PA_TIMER S5P6440_PA_TIMER #define S5P6440_PA_RTC (0xEA100000) -#define S5P_PA_RTC S5P6440_PA_RTC #define S5P6440_PA_WDT (0xEA200000) #define S5P_PA_WDT S5P6440_PA_WDT @@ -53,6 +52,7 @@ #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 @@ -77,6 +77,8 @@ /* 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 diff --git a/arch/arm/mach-s5p6440/include/mach/system.h b/arch/arm/mach-s5p6440/include/mach/system.h index d2dd817da66a..a359ee3fa510 100644 --- a/arch/arm/mach-s5p6440/include/mach/system.h +++ b/arch/arm/mach-s5p6440/include/mach/system.h @@ -13,12 +13,9 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H __FILE__ -static void arch_idle(void) -{ - /* nothing here yet */ -} +#include <plat/system-reset.h> -static void arch_reset(char mode, const char *cmd) +static void arch_idle(void) { /* nothing here yet */ } diff --git a/arch/arm/mach-s5p6440/mach-smdk6440.c b/arch/arm/mach-s5p6440/mach-smdk6440.c index 8291fecc701a..9202aaac3b56 100644 --- a/arch/arm/mach-s5p6440/mach-smdk6440.c +++ b/arch/arm/mach-s5p6440/mach-smdk6440.c @@ -15,6 +15,7 @@ #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> @@ -37,20 +38,21 @@ #include <mach/regs-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 S5P6440_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ +#define SMDK6440_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ S3C2410_UCON_TXIRQMODE | \ S3C2410_UCON_RXIRQMODE | \ S3C2410_UCON_RXFIFO_TOI | \ S3C2443_UCON_RXERR_IRQEN) -#define S5P6440_ULCON_DEFAULT S3C2410_LCON_CS8 +#define SMDK6440_ULCON_DEFAULT S3C2410_LCON_CS8 -#define S5P6440_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ +#define SMDK6440_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ S3C2440_UFCON_TXTRIG16 | \ S3C2410_UFCON_RXTRIG8) @@ -58,40 +60,51 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, - .ucon = S5P6440_UCON_DEFAULT, - .ulcon = S5P6440_ULCON_DEFAULT, - .ufcon = S5P6440_UFCON_DEFAULT, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, [1] = { .hwport = 1, .flags = 0, - .ucon = S5P6440_UCON_DEFAULT, - .ulcon = S5P6440_ULCON_DEFAULT, - .ufcon = S5P6440_UFCON_DEFAULT, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, [2] = { .hwport = 2, .flags = 0, - .ucon = S5P6440_UCON_DEFAULT, - .ulcon = S5P6440_ULCON_DEFAULT, - .ufcon = S5P6440_UFCON_DEFAULT, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, [3] = { .hwport = 3, .flags = 0, - .ucon = S5P6440_UCON_DEFAULT, - .ulcon = S5P6440_ULCON_DEFAULT, - .ufcon = S5P6440_UFCON_DEFAULT, + .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, }; +static struct i2c_board_info smdk6440_i2c_devs0[] __initdata = { + { I2C_BOARD_INFO("24c08", 0x50), }, +}; + +static struct i2c_board_info smdk6440_i2c_devs1[] __initdata = { + /* To be populated */ +}; + static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { .delay = 10000, .presc = 49, @@ -109,6 +122,14 @@ 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); + i2c_register_board_info(0, smdk6440_i2c_devs0, + ARRAY_SIZE(smdk6440_i2c_devs0)); + i2c_register_board_info(1, smdk6440_i2c_devs1, + ARRAY_SIZE(smdk6440_i2c_devs1)); + platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices)); } diff --git a/arch/arm/mach-s5p6440/setup-i2c0.c b/arch/arm/mach-s5p6440/setup-i2c0.c index 69e8a664aedb..2c99d14f7ac7 100644 --- a/arch/arm/mach-s5p6440/setup-i2c0.c +++ b/arch/arm/mach-s5p6440/setup-i2c0.c @@ -17,9 +17,14 @@ 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) { - /* Will be populated later */ + 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 new file mode 100644 index 000000000000..9a1537f786e0 --- /dev/null +++ b/arch/arm/mach-s5p6440/setup-i2c1.c @@ -0,0 +1,30 @@ +/* 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/clock.c b/arch/arm/mach-s5p6442/clock.c index 087e57f20ad5..dcd20f17212a 100644 --- a/arch/arm/mach-s5p6442/clock.c +++ b/arch/arm/mach-s5p6442/clock.c @@ -361,6 +361,12 @@ static struct clk init_clocks[] = { .enable = s5p6442_clk_ip3_ctrl, .ctrlbit = (1<<19), }, { + .name = "watchdog", + .id = -1, + .parent = &clk_pclkd1, + .enable = s5p6442_clk_ip3_ctrl, + .ctrlbit = (1 << 22), + }, { .name = "timers", .id = -1, .parent = &clk_pclkd1, diff --git a/arch/arm/mach-s5p6442/include/mach/irqs.h b/arch/arm/mach-s5p6442/include/mach/irqs.h index 02c23749c023..3fbc6c3ad2da 100644 --- a/arch/arm/mach-s5p6442/include/mach/irqs.h +++ b/arch/arm/mach-s5p6442/include/mach/irqs.h @@ -32,7 +32,7 @@ #define IRQ_GPIOINT S5P_IRQ_VIC0(30) /* VIC1 */ -#define IRQ_nPMUIRQ S5P_IRQ_VIC1(0) +#define IRQ_PMU S5P_IRQ_VIC1(0) #define IRQ_ONENAND S5P_IRQ_VIC1(7) #define IRQ_UART0 S5P_IRQ_VIC1(10) #define IRQ_UART1 S5P_IRQ_VIC1(11) diff --git a/arch/arm/mach-s5p6442/include/mach/map.h b/arch/arm/mach-s5p6442/include/mach/map.h index 32ca424ef7f9..281d256faafb 100644 --- a/arch/arm/mach-s5p6442/include/mach/map.h +++ b/arch/arm/mach-s5p6442/include/mach/map.h @@ -42,6 +42,8 @@ #define S5P6442_PA_SYSTIMER (0xEA100000) +#define S5P6442_PA_WATCHDOG (0xEA200000) + #define S5P6442_PA_UART (0xEC000000) #define S5P_PA_UART0 (S5P6442_PA_UART + 0x0) @@ -65,6 +67,7 @@ #define S5P6442_PA_PCM1 0xF2500000 /* compatibiltiy defines. */ +#define S3C_PA_WDT S5P6442_PA_WATCHDOG #define S3C_PA_UART S5P6442_PA_UART #define S3C_PA_IIC S5P6442_PA_IIC0 diff --git a/arch/arm/mach-s5p6442/include/mach/system.h b/arch/arm/mach-s5p6442/include/mach/system.h index 8bcd8ed0c3c3..c30c1cc1b97e 100644 --- a/arch/arm/mach-s5p6442/include/mach/system.h +++ b/arch/arm/mach-s5p6442/include/mach/system.h @@ -13,12 +13,9 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H __FILE__ -static void arch_idle(void) -{ - /* nothing here yet */ -} +#include <plat/system-reset.h> -static void arch_reset(char mode, const char *cmd) +static void arch_idle(void) { /* nothing here yet */ } diff --git a/arch/arm/mach-s5p6442/mach-smdk6442.c b/arch/arm/mach-s5p6442/mach-smdk6442.c index ebcf99777259..8d8d04272f85 100644 --- a/arch/arm/mach-s5p6442/mach-smdk6442.c +++ b/arch/arm/mach-s5p6442/mach-smdk6442.c @@ -27,16 +27,16 @@ #include <plat/cpu.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ -#define S5P6442_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ +#define SMDK6442_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ S3C2410_UCON_TXIRQMODE | \ S3C2410_UCON_RXIRQMODE | \ S3C2410_UCON_RXFIFO_TOI | \ S3C2443_UCON_RXERR_IRQEN) -#define S5P6442_ULCON_DEFAULT S3C2410_LCON_CS8 +#define SMDK6442_ULCON_DEFAULT S3C2410_LCON_CS8 -#define S5P6442_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ +#define SMDK6442_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ S5PV210_UFCON_TXTRIG4 | \ S5PV210_UFCON_RXTRIG4) @@ -44,28 +44,29 @@ static struct s3c2410_uartcfg smdk6442_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, - .ucon = S5P6442_UCON_DEFAULT, - .ulcon = S5P6442_ULCON_DEFAULT, - .ufcon = S5P6442_UFCON_DEFAULT, + .ucon = SMDK6442_UCON_DEFAULT, + .ulcon = SMDK6442_ULCON_DEFAULT, + .ufcon = SMDK6442_UFCON_DEFAULT, }, [1] = { .hwport = 1, .flags = 0, - .ucon = S5P6442_UCON_DEFAULT, - .ulcon = S5P6442_ULCON_DEFAULT, - .ufcon = S5P6442_UFCON_DEFAULT, + .ucon = SMDK6442_UCON_DEFAULT, + .ulcon = SMDK6442_ULCON_DEFAULT, + .ufcon = SMDK6442_UFCON_DEFAULT, }, [2] = { .hwport = 2, .flags = 0, - .ucon = S5P6442_UCON_DEFAULT, - .ulcon = S5P6442_ULCON_DEFAULT, - .ufcon = S5P6442_UFCON_DEFAULT, + .ucon = SMDK6442_UCON_DEFAULT, + .ulcon = SMDK6442_ULCON_DEFAULT, + .ufcon = SMDK6442_UFCON_DEFAULT, }, }; static struct platform_device *smdk6442_devices[] __initdata = { &s5p6442_device_iis0, + &s3c_device_wdt, }; static void __init smdk6442_map_io(void) diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig index 0593b3fb0d4b..ab038d090764 100644 --- a/arch/arm/mach-s5pc100/Kconfig +++ b/arch/arm/mach-s5pc100/Kconfig @@ -25,6 +25,16 @@ config S5PC100_SETUP_I2C1 help Common setup code for i2c bus 1. +config S5PC100_SETUP_IDE + bool + help + Common setup code for S5PC100 IDE GPIO configurations + +config S5PC100_SETUP_KEYPAD + bool + help + Common setup code for KEYPAD GPIO configurations. + config S5PC100_SETUP_SDHCI bool select S5PC100_SETUP_SDHCI_GPIO @@ -40,13 +50,20 @@ config MACH_SMDKC100 bool "SMDKC100" select CPU_S5PC100 select S3C_DEV_FB - select S3C_DEV_I2C1 select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 select S3C_DEV_HSMMC2 + select S3C_DEV_I2C1 + select S3C_DEV_RTC select S3C_DEV_WDT + select SAMSUNG_DEV_ADC + select SAMSUNG_DEV_IDE + select SAMSUNG_DEV_KEYPAD + select SAMSUNG_DEV_TS select S5PC100_SETUP_FB_24BPP select S5PC100_SETUP_I2C1 + select S5PC100_SETUP_IDE + select S5PC100_SETUP_KEYPAD select S5PC100_SETUP_SDHCI help Machine support for the Samsung SMDKC100 diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile index 543f3de5131e..a021ed1fb4b6 100644 --- a/arch/arm/mach-s5pc100/Makefile +++ b/arch/arm/mach-s5pc100/Makefile @@ -19,6 +19,8 @@ obj-$(CONFIG_CPU_S5PC100) += dma.o obj-$(CONFIG_S5PC100_SETUP_FB_24BPP) += setup-fb-24bpp.o obj-$(CONFIG_S5PC100_SETUP_I2C1) += setup-i2c1.o +obj-$(CONFIG_S5PC100_SETUP_IDE) += setup-ide.o +obj-$(CONFIG_S5PC100_SETUP_KEYPAD) += setup-keypad.o obj-$(CONFIG_S5PC100_SETUP_SDHCI) += setup-sdhci.o obj-$(CONFIG_S5PC100_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c index e3fed4cfe7ad..084abd13b0a5 100644 --- a/arch/arm/mach-s5pc100/clock.c +++ b/arch/arm/mach-s5pc100/clock.c @@ -737,7 +737,7 @@ static struct clk init_clocks_disable[] = { .enable = s5pc100_d1_5_ctrl, .ctrlbit = (1 << 7), }, { - .name = "keyif", + .name = "keypad", .id = -1, .parent = &clk_div_d1_bus.clk, .enable = s5pc100_d1_5_ctrl, @@ -1078,7 +1078,7 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLK_DIV3, .shift = 24, .size = 4 }, }, { .clk = { - .name = "mmc_bus", + .name = "sclk_mmc", .id = 0, .ctrlbit = (1 << 12), .enable = s5pc100_sclk1_ctrl, @@ -1089,7 +1089,7 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 }, }, { .clk = { - .name = "mmc_bus", + .name = "sclk_mmc", .id = 1, .ctrlbit = (1 << 13), .enable = s5pc100_sclk1_ctrl, @@ -1100,7 +1100,7 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 }, }, { .clk = { - .name = "mmc_bus", + .name = "sclk_mmc", .id = 2, .ctrlbit = (1 << 14), .enable = s5pc100_sclk1_ctrl, diff --git a/arch/arm/mach-s5pc100/cpu.c b/arch/arm/mach-s5pc100/cpu.c index 7b5bdbc9a5df..799d22f41fcd 100644 --- a/arch/arm/mach-s5pc100/cpu.c +++ b/arch/arm/mach-s5pc100/cpu.c @@ -38,8 +38,10 @@ #include <plat/cpu.h> #include <plat/devs.h> #include <plat/clock.h> +#include <plat/ata-core.h> #include <plat/iic-core.h> #include <plat/sdhci.h> +#include <plat/adc-core.h> #include <plat/onenand-core.h> #include <plat/s5pc100.h> @@ -87,11 +89,14 @@ void __init s5pc100_map_io(void) s5pc100_default_sdhci1(); s5pc100_default_sdhci2(); + s3c_adc_setname("s3c64xx-adc"); + /* the i2c devices are directly compatible with s3c2440 */ s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); s3c_onenand_setname("s5pc100-onenand"); + s3c_cfcon_setname("s5pc100-pata"); } void __init s5pc100_init_clocks(int xtal) diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h index 28aa551dc3a8..06513e647242 100644 --- a/arch/arm/mach-s5pc100/include/mach/irqs.h +++ b/arch/arm/mach-s5pc100/include/mach/irqs.h @@ -29,7 +29,7 @@ #define IRQ_GPIOINT S5P_IRQ_VIC0(30) /* VIC1: ARM, power, memory, connectivity */ -#define IRQ_CORTEX0 S5P_IRQ_VIC1(0) +#define IRQ_PMU S5P_IRQ_VIC1(0) #define IRQ_CORTEX1 S5P_IRQ_VIC1(1) #define IRQ_CORTEX2 S5P_IRQ_VIC1(2) #define IRQ_CORTEX3 S5P_IRQ_VIC1(3) @@ -38,7 +38,7 @@ #define IRQ_IEMIEC S5P_IRQ_VIC1(6) #define IRQ_ONENAND S5P_IRQ_VIC1(7) #define IRQ_NFC S5P_IRQ_VIC1(8) -#define IRQ_CFC S5P_IRQ_VIC1(9) +#define IRQ_CFCON S5P_IRQ_VIC1(9) #define IRQ_UART0 S5P_IRQ_VIC1(10) #define IRQ_UART1 S5P_IRQ_VIC1(11) #define IRQ_UART2 S5P_IRQ_VIC1(12) diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h index abf17e8eb321..01b9134feff0 100644 --- a/arch/arm/mach-s5pc100/include/mach/map.h +++ b/arch/arm/mach-s5pc100/include/mach/map.h @@ -61,6 +61,8 @@ #define S5PC100_PA_ONENAND (0xE7100000) +#define S5PC100_PA_CFCON (0xE7800000) + /* DMA */ #define S5PC100_PA_MDMA (0xE8100000) #define S5PC100_PA_PDMA0 (0xE9000000) @@ -72,6 +74,9 @@ #define S5PC100_PA_SYSTIMER (0xEA100000) +#define S5PC100_PA_WATCHDOG (0xEA200000) +#define S5PC100_PA_RTC (0xEA300000) + #define S5PC100_PA_UART (0xEC000000) #define S5P_PA_UART0 (S5PC100_PA_UART + 0x0) @@ -108,6 +113,8 @@ #define S5PC100_PA_PCM0 0xF2400000 #define S5PC100_PA_PCM1 0xF2500000 +#define S5PC100_PA_TSADC (0xF3000000) + /* KEYPAD */ #define S5PC100_PA_KEYPAD (0xF3100000) @@ -134,10 +141,16 @@ #define S3C_PA_HSMMC1 S5PC100_PA_HSMMC(1) #define S3C_PA_HSMMC2 S5PC100_PA_HSMMC(2) #define S3C_PA_KEYPAD S5PC100_PA_KEYPAD +#define S3C_PA_WDT S5PC100_PA_WATCHDOG #define S3C_PA_TSADC S5PC100_PA_TSADC #define S3C_PA_ONENAND S5PC100_PA_ONENAND #define S3C_PA_ONENAND_BUF S5PC100_PA_ONENAND_BUF #define S3C_SZ_ONENAND_BUF S5PC100_SZ_ONENAND_BUF +#define S3C_PA_RTC S5PC100_PA_RTC + +#define SAMSUNG_PA_ADC S5PC100_PA_TSADC +#define SAMSUNG_PA_CFCON S5PC100_PA_CFCON +#define SAMSUNG_PA_KEYPAD S5PC100_PA_KEYPAD #define S5P_PA_FIMC0 S5PC100_PA_FIMC0 #define S5P_PA_FIMC1 S5PC100_PA_FIMC1 diff --git a/arch/arm/mach-s5pc100/include/mach/regs-clock.h b/arch/arm/mach-s5pc100/include/mach/regs-clock.h index 5d27d286d504..bc92da2e0ba2 100644 --- a/arch/arm/mach-s5pc100/include/mach/regs-clock.h +++ b/arch/arm/mach-s5pc100/include/mach/regs-clock.h @@ -71,7 +71,10 @@ #define S5P_CLKDIV1_PCLKD1_SHIFT (16) #define S5PC100_SWRESET S5PC100_REG_OTHERS(0x000) +#define S5PC100_MEM_SYS_CFG S5PC100_REG_OTHERS(0x200) #define S5PC100_SWRESET_RESETVAL 0xc100 +#define MEM_SYS_CFG_EBI_FIX_PRI_CFCON 0x30 + #endif /* __ASM_ARCH_REGS_CLOCK_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/system.h b/arch/arm/mach-s5pc100/include/mach/system.h index 681f626a9ae1..a9ea57c06600 100644 --- a/arch/arm/mach-s5pc100/include/mach/system.h +++ b/arch/arm/mach-s5pc100/include/mach/system.h @@ -11,18 +11,11 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H __FILE__ -#include <linux/io.h> -#include <mach/map.h> -#include <mach/regs-clock.h> +#include <plat/system-reset.h> static void arch_idle(void) { /* nothing here yet */ } -static void arch_reset(char mode, const char *cmd) -{ - __raw_writel(S5PC100_SWRESET_RESETVAL, S5PC100_SWRESET); - return; -} #endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c index af22f8202a07..a63c8a46571d 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -22,6 +22,7 @@ #include <linux/i2c.h> #include <linux/fb.h> #include <linux/delay.h> +#include <linux/input.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -42,18 +43,22 @@ #include <plat/s5pc100.h> #include <plat/fb.h> #include <plat/iic.h> +#include <plat/ata.h> +#include <plat/adc.h> +#include <plat/keypad.h> +#include <plat/ts.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ -#define S5PC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ +#define SMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ S3C2410_UCON_TXIRQMODE | \ S3C2410_UCON_RXIRQMODE | \ S3C2410_UCON_RXFIFO_TOI | \ S3C2443_UCON_RXERR_IRQEN) -#define S5PC100_ULCON_DEFAULT S3C2410_LCON_CS8 +#define SMDKC100_ULCON_DEFAULT S3C2410_LCON_CS8 -#define S5PC100_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ +#define SMDKC100_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ S3C2440_UFCON_RXTRIG8 | \ S3C2440_UFCON_TXTRIG16) @@ -61,30 +66,30 @@ static struct s3c2410_uartcfg smdkc100_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, - .ucon = S5PC100_UCON_DEFAULT, - .ulcon = S5PC100_ULCON_DEFAULT, - .ufcon = S5PC100_UFCON_DEFAULT, + .ucon = SMDKC100_UCON_DEFAULT, + .ulcon = SMDKC100_ULCON_DEFAULT, + .ufcon = SMDKC100_UFCON_DEFAULT, }, [1] = { .hwport = 1, .flags = 0, - .ucon = S5PC100_UCON_DEFAULT, - .ulcon = S5PC100_ULCON_DEFAULT, - .ufcon = S5PC100_UFCON_DEFAULT, + .ucon = SMDKC100_UCON_DEFAULT, + .ulcon = SMDKC100_ULCON_DEFAULT, + .ufcon = SMDKC100_UFCON_DEFAULT, }, [2] = { .hwport = 2, .flags = 0, - .ucon = S5PC100_UCON_DEFAULT, - .ulcon = S5PC100_ULCON_DEFAULT, - .ufcon = S5PC100_UFCON_DEFAULT, + .ucon = SMDKC100_UCON_DEFAULT, + .ulcon = SMDKC100_ULCON_DEFAULT, + .ufcon = SMDKC100_UFCON_DEFAULT, }, [3] = { .hwport = 3, .flags = 0, - .ucon = S5PC100_UCON_DEFAULT, - .ulcon = S5PC100_ULCON_DEFAULT, - .ufcon = S5PC100_UFCON_DEFAULT, + .ucon = SMDKC100_UCON_DEFAULT, + .ulcon = SMDKC100_ULCON_DEFAULT, + .ufcon = SMDKC100_UFCON_DEFAULT, }, }; @@ -149,16 +154,51 @@ static struct s3c_fb_platdata smdkc100_lcd_pdata __initdata = { .setup_gpio = s5pc100_fb_gpio_setup_24bpp, }; +static struct s3c_ide_platdata smdkc100_ide_pdata __initdata = { + .setup_gpio = s5pc100_ide_setup_gpio, +}; + +static uint32_t smdkc100_keymap[] __initdata = { + /* KEY(row, col, keycode) */ + KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3), + KEY(0, 6, KEY_4), KEY(0, 7, KEY_5), + KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C), + KEY(1, 6, KEY_D), KEY(1, 7, KEY_E) +}; + +static struct matrix_keymap_data smdkc100_keymap_data __initdata = { + .keymap = smdkc100_keymap, + .keymap_size = ARRAY_SIZE(smdkc100_keymap), +}; + +static struct samsung_keypad_platdata smdkc100_keypad_data __initdata = { + .keymap_data = &smdkc100_keymap_data, + .rows = 2, + .cols = 8, +}; + static struct platform_device *smdkc100_devices[] __initdata = { + &s3c_device_adc, + &s3c_device_cfcon, &s3c_device_i2c0, &s3c_device_i2c1, &s3c_device_fb, &s3c_device_hsmmc0, &s3c_device_hsmmc1, &s3c_device_hsmmc2, + &s3c_device_ts, + &s3c_device_wdt, &smdkc100_lcd_powerdev, &s5pc100_device_iis0, + &samsung_device_keypad, &s5pc100_device_ac97, + &s3c_device_rtc, +}; + +static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { + .delay = 10000, + .presc = 49, + .oversampling_shift = 2, }; static void __init smdkc100_map_io(void) @@ -170,6 +210,8 @@ static void __init smdkc100_map_io(void) static void __init smdkc100_machine_init(void) { + s3c24xx_ts_set_platdata(&s3c_ts_platform); + /* I2C */ s3c_i2c0_set_platdata(NULL); s3c_i2c1_set_platdata(NULL); @@ -177,6 +219,9 @@ static void __init smdkc100_machine_init(void) i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1)); s3c_fb_set_platdata(&smdkc100_lcd_pdata); + s3c_ide_set_platdata(&smdkc100_ide_pdata); + + samsung_keypad_set_platdata(&smdkc100_keypad_data); /* LCD init */ gpio_request(S5PC100_GPD(0), "GPD"); diff --git a/arch/arm/mach-s5pc100/setup-ide.c b/arch/arm/mach-s5pc100/setup-ide.c new file mode 100644 index 000000000000..83575671fb59 --- /dev/null +++ b/arch/arm/mach-s5pc100/setup-ide.c @@ -0,0 +1,70 @@ +/* linux/arch/arm/mach-s5pc100/setup-ide.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5PC100 setup information for IDE + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/io.h> + +#include <mach/regs-clock.h> +#include <plat/gpio-cfg.h> + +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); + } + + /*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); + } + + /* 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); + } + + /* 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); + } + + /* EBI_OE, EBI_WE */ + for (gpio = S5PC100_GPK0(6); gpio <= S5PC100_GPK0(7); gpio++) + s3c_gpio_cfgpin(gpio, 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); + } + + /* CF_CD */ + s3c_gpio_cfgpin(S5PC100_GPK3(5), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5PC100_GPK3(5), S3C_GPIO_PULL_NONE); +} diff --git a/arch/arm/mach-s5pc100/setup-keypad.c b/arch/arm/mach-s5pc100/setup-keypad.c new file mode 100644 index 000000000000..d0837a72a58e --- /dev/null +++ b/arch/arm/mach-s5pc100/setup-keypad.c @@ -0,0 +1,34 @@ +/* linux/arch/arm/mach-s5pc100/setup-keypad.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * GPIO configuration for S5PC100 KeyPad device + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/gpio.h> +#include <plat/gpio-cfg.h> + +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); + } + + /* 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); + } +} diff --git a/arch/arm/mach-s5pc100/setup-sdhci.c b/arch/arm/mach-s5pc100/setup-sdhci.c index ea7ff19adb95..f16946e456e9 100644 --- a/arch/arm/mach-s5pc100/setup-sdhci.c +++ b/arch/arm/mach-s5pc100/setup-sdhci.c @@ -26,10 +26,10 @@ /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */ char *s5pc100_hsmmc_clksrcs[4] = { - [0] = "hsmmc", - [1] = "hsmmc", - /* [2] = "mmc_bus", not yet successfully used yet */ - /* [3] = "48m", - note not successfully used yet */ + [0] = "hsmmc", /* HCLK */ + /* [1] = "hsmmc", - duplicate HCLK entry */ + [2] = "sclk_mmc", /* mmc_bus */ + /* [3] = "48m", - note not successfully used yet */ }; diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig index 2e3ed1847ca6..ea9d147d4585 100644 --- a/arch/arm/mach-s5pv210/Kconfig +++ b/arch/arm/mach-s5pv210/Kconfig @@ -27,11 +27,21 @@ config S5PV210_SETUP_I2C2 help Common setup code for i2c bus 2. +config S5PV210_SETUP_IDE + bool + help + Common setup code for S5PV210 IDE GPIO configurations + config S5PV210_SETUP_FB_24BPP bool help Common setup code for S5PV210 with an 24bpp RGB display helper. +config S5PV210_SETUP_KEYPAD + bool + help + Common setup code for keypad. + config S5PV210_SETUP_SDHCI bool select S5PV210_SETUP_SDHCI_GPIO @@ -43,14 +53,24 @@ config S5PV210_SETUP_SDHCI_GPIO help Common setup code for SDHCI gpio. -# machine support +config S5PC110_DEV_ONENAND + bool + help + Compile in platform device definition for OneNAND1 controller + +menu "S5PC110 Machines" config MACH_AQUILA - bool "Samsung Aquila" + bool "Aquila" select CPU_S5PV210 select ARCH_SPARSEMEM_ENABLE - select S5PV210_SETUP_FB_24BPP select S3C_DEV_FB + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_HSMMC2 + select S5PC110_DEV_ONENAND + select S5PV210_SETUP_FB_24BPP + select S5PV210_SETUP_SDHCI help Machine support for the Samsung Aquila target based on S5PC110 SoC @@ -58,32 +78,61 @@ config MACH_GONI bool "GONI" select CPU_S5PV210 select ARCH_SPARSEMEM_ENABLE + select S3C_DEV_FB + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_HSMMC2 + select S5PC110_DEV_ONENAND + select S5PV210_SETUP_FB_24BPP + select S5PV210_SETUP_SDHCI help Machine support for Samsung GONI board S5PC110(MCP) is one of package option of S5PV210 -config S5PC110_DEV_ONENAND - bool +config MACH_SMDKC110 + bool "SMDKC110" + select CPU_S5PV210 + select ARCH_SPARSEMEM_ENABLE + select S3C_DEV_I2C1 + select S3C_DEV_I2C2 + select S3C_DEV_RTC + select S3C_DEV_WDT + select SAMSUNG_DEV_IDE + select S5PV210_SETUP_I2C1 + select S5PV210_SETUP_I2C2 + select S5PV210_SETUP_IDE help - Compile in platform device definition for OneNAND1 controller + Machine support for Samsung SMDKC110 + S5PC110(MCP) is one of package option of S5PV210 + +endmenu + +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 + select S3C_DEV_HSMMC3 + select S3C_DEV_I2C1 + select S3C_DEV_I2C2 + select S3C_DEV_RTC + select S3C_DEV_WDT select SAMSUNG_DEV_ADC + select SAMSUNG_DEV_IDE + select SAMSUNG_DEV_KEYPAD select SAMSUNG_DEV_TS - select S3C_DEV_WDT + select S5PV210_SETUP_I2C1 + select S5PV210_SETUP_I2C2 + select S5PV210_SETUP_IDE + select S5PV210_SETUP_KEYPAD + select S5PV210_SETUP_SDHCI help Machine support for Samsung SMDKV210 -config MACH_SMDKC110 - bool "SMDKC110" - select CPU_S5PV210 - select ARCH_SPARSEMEM_ENABLE - select S3C_DEV_WDT - help - Machine support for Samsung SMDKC110 - S5PC110(MCP) is one of package option of S5PV210 +endmenu endif diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile index 30be9a6a4620..05048c5aa4c6 100644 --- a/arch/arm/mach-s5pv210/Makefile +++ b/arch/arm/mach-s5pv210/Makefile @@ -31,5 +31,7 @@ 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 obj-$(CONFIG_S5PV210_SETUP_I2C2) += setup-i2c2.o +obj-$(CONFIG_S5PV210_SETUP_IDE) += setup-ide.o +obj-$(CONFIG_S5PV210_SETUP_KEYPAD) += setup-keypad.o obj-$(CONFIG_S5PV210_SETUP_SDHCI) += setup-sdhci.o obj-$(CONFIG_S5PV210_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c index 1acf9ac7ad35..c7e0b8a65c4a 100644 --- a/arch/arm/mach-s5pv210/cpu.c +++ b/arch/arm/mach-s5pv210/cpu.c @@ -33,9 +33,12 @@ #include <plat/clock.h> #include <plat/s5pv210.h> #include <plat/adc-core.h> +#include <plat/ata-core.h> #include <plat/fimc-core.h> #include <plat/iic-core.h> +#include <plat/keypad-core.h> #include <plat/sdhci.h> +#include <plat/reset.h> /* Initial IO mappings */ @@ -71,6 +74,11 @@ static void s5pv210_idle(void) local_irq_enable(); } +static void s5pv210_sw_reset(void) +{ + __raw_writel(0x1, S5P_SWRESET); +} + /* s5pv210_map_io * * register the standard cpu IO areas @@ -84,17 +92,23 @@ void __init s5pv210_map_io(void) s5pv210_default_sdhci0(); s5pv210_default_sdhci1(); s5pv210_default_sdhci2(); + s5pv210_default_sdhci3(); s3c_adc_setname("s3c64xx-adc"); + s3c_cfcon_setname("s5pv210-pata"); + + s3c_fimc_setname(0, "s5pv210-fimc"); + s3c_fimc_setname(1, "s5pv210-fimc"); + s3c_fimc_setname(2, "s5pv210-fimc"); + /* the i2c devices are directly compatible with s3c2440 */ s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); s3c_i2c2_setname("s3c2440-i2c"); - s3c_fimc_setname(0, "s5pv210-fimc"); - s3c_fimc_setname(1, "s5pv210-fimc"); - s3c_fimc_setname(2, "s5pv210-fimc"); + /* Use s5pv210-keypad instead of samsung-keypad */ + samsung_keypad_setname("s5pv210-keypad"); } void __init s5pv210_init_clocks(int xtal) @@ -142,5 +156,8 @@ int __init s5pv210_init(void) /* set idle function */ pm_idle = s5pv210_idle; + /* set sw_reset function */ + s5p_reset_hook = s5pv210_sw_reset; + return sysdev_register(&s5pv210_sysdev); } diff --git a/arch/arm/mach-s5pv210/dev-onenand.c b/arch/arm/mach-s5pv210/dev-onenand.c index 34997b752f93..f8ede33ee82b 100644 --- a/arch/arm/mach-s5pv210/dev-onenand.c +++ b/arch/arm/mach-s5pv210/dev-onenand.c @@ -27,9 +27,14 @@ static struct resource s5pc110_onenand_resources[] = { }, [1] = { .start = S5PC110_PA_ONENAND_DMA, - .end = S5PC110_PA_ONENAND_DMA + SZ_2K - 1, + .end = S5PC110_PA_ONENAND_DMA + SZ_8K - 1, .flags = IORESOURCE_MEM, }, + [2] = { + .start = IRQ_ONENAND_AUDI, + .end = IRQ_ONENAND_AUDI, + .flags = IORESOURCE_IRQ, + }, }; struct platform_device s5pc110_device_onenand = { diff --git a/arch/arm/mach-s5pv210/gpiolib.c b/arch/arm/mach-s5pv210/gpiolib.c index 9ea8972e023d..0d459112d039 100644 --- a/arch/arm/mach-s5pv210/gpiolib.c +++ b/arch/arm/mach-s5pv210/gpiolib.c @@ -207,6 +207,20 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = { .label = "MP03", }, }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP04(0), + .ngpio = S5PV210_GPIO_MP04_NR, + .label = "MP04", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP05(0), + .ngpio = S5PV210_GPIO_MP05_NR, + .label = "MP05", + }, + }, { .base = (S5P_VA_GPIO + 0xC00), .config = &gpio_cfg_noint, .chip = { diff --git a/arch/arm/mach-s5pv210/include/mach/gpio.h b/arch/arm/mach-s5pv210/include/mach/gpio.h index d6461ba2b71d..1f4b595534c2 100644 --- a/arch/arm/mach-s5pv210/include/mach/gpio.h +++ b/arch/arm/mach-s5pv210/include/mach/gpio.h @@ -52,6 +52,8 @@ #define S5PV210_GPIO_MP01_NR (8) #define S5PV210_GPIO_MP02_NR (4) #define S5PV210_GPIO_MP03_NR (8) +#define S5PV210_GPIO_MP04_NR (8) +#define S5PV210_GPIO_MP05_NR (8) /* GPIO bank numbers */ @@ -94,6 +96,8 @@ enum s5p_gpio_number { S5PV210_GPIO_MP01_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J4), S5PV210_GPIO_MP02_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP01), S5PV210_GPIO_MP03_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP02), + S5PV210_GPIO_MP04_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP03), + S5PV210_GPIO_MP05_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP04), }; /* S5PV210 GPIO number definitions */ @@ -127,13 +131,15 @@ enum s5p_gpio_number { #define S5PV210_MP01(_nr) (S5PV210_GPIO_MP01_START + (_nr)) #define S5PV210_MP02(_nr) (S5PV210_GPIO_MP02_START + (_nr)) #define S5PV210_MP03(_nr) (S5PV210_GPIO_MP03_START + (_nr)) +#define S5PV210_MP04(_nr) (S5PV210_GPIO_MP04_START + (_nr)) +#define S5PV210_MP05(_nr) (S5PV210_GPIO_MP05_START + (_nr)) /* the end of the S5PV210 specific gpios */ -#define S5PV210_GPIO_END (S5PV210_MP03(S5PV210_GPIO_MP03_NR) + 1) +#define S5PV210_GPIO_END (S5PV210_MP05(S5PV210_GPIO_MP05_NR) + 1) #define S3C_GPIO_END S5PV210_GPIO_END -/* define the number of gpios we need to the one after the MP03() range */ -#define ARCH_NR_GPIOS (S5PV210_MP03(S5PV210_GPIO_MP03_NR) + \ +/* define the number of gpios we need to the one after the MP05() range */ +#define ARCH_NR_GPIOS (S5PV210_MP05(S5PV210_GPIO_MP05_NR) + \ CONFIG_SAMSUNG_GPIO_EXTRA + 1) #include <asm-generic/gpio.h> diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h index 96895378ea27..e1c020e5a49b 100644 --- a/arch/arm/mach-s5pv210/include/mach/irqs.h +++ b/arch/arm/mach-s5pv210/include/mach/irqs.h @@ -36,7 +36,7 @@ /* VIC1: ARM, Power, Memory, Connectivity, Storage */ -#define IRQ_CORTEX0 S5P_IRQ_VIC1(0) +#define IRQ_PMU S5P_IRQ_VIC1(0) #define IRQ_CORTEX1 S5P_IRQ_VIC1(1) #define IRQ_CORTEX2 S5P_IRQ_VIC1(2) #define IRQ_CORTEX3 S5P_IRQ_VIC1(3) @@ -45,7 +45,7 @@ #define IRQ_IEMIEC S5P_IRQ_VIC1(6) #define IRQ_ONENAND S5P_IRQ_VIC1(7) #define IRQ_NFC S5P_IRQ_VIC1(8) -#define IRQ_CFC S5P_IRQ_VIC1(9) +#define IRQ_CFCON S5P_IRQ_VIC1(9) #define IRQ_UART0 S5P_IRQ_VIC1(10) #define IRQ_UART1 S5P_IRQ_VIC1(11) #define IRQ_UART2 S5P_IRQ_VIC1(12) diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index 69210bf76c47..dd4fb6bf14b5 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -32,6 +32,8 @@ #define S5PV210_PA_SPI0 0xE1300000 #define S5PV210_PA_SPI1 0xE1400000 +#define S5PV210_PA_KEYPAD (0xE1600000) + #define S5PV210_PA_IIC0 (0xE1800000) #define S5PV210_PA_IIC1 (0xFAB00000) #define S5PV210_PA_IIC2 (0xE1A00000) @@ -43,6 +45,7 @@ #define S5PV210_PA_WATCHDOG (0xE2700000) +#define S5PV210_PA_RTC (0xE2800000) #define S5PV210_PA_UART (0xE2900000) #define S5P_PA_UART0 (S5PV210_PA_UART + 0x0) @@ -54,6 +57,8 @@ #define S5PV210_PA_SROMC (0xE8000000) +#define S5PV210_PA_CFCON (0xE8200000) + #define S5PV210_PA_MDMA 0xFA200000 #define S5PV210_PA_PDMA0 0xE0900000 #define S5PV210_PA_PDMA1 0xE0A00000 @@ -101,15 +106,19 @@ #define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0) #define S3C_PA_HSMMC1 S5PV210_PA_HSMMC(1) #define S3C_PA_HSMMC2 S5PV210_PA_HSMMC(2) +#define S3C_PA_HSMMC3 S5PV210_PA_HSMMC(3) #define S3C_PA_IIC S5PV210_PA_IIC0 #define S3C_PA_IIC1 S5PV210_PA_IIC1 #define S3C_PA_IIC2 S5PV210_PA_IIC2 #define S3C_PA_FB S5PV210_PA_FB +#define S3C_PA_RTC S5PV210_PA_RTC #define S3C_PA_WDT S5PV210_PA_WATCHDOG #define S5P_PA_FIMC0 S5PV210_PA_FIMC0 #define S5P_PA_FIMC1 S5PV210_PA_FIMC1 #define S5P_PA_FIMC2 S5PV210_PA_FIMC2 #define SAMSUNG_PA_ADC S5PV210_PA_ADC +#define SAMSUNG_PA_CFCON S5PV210_PA_CFCON +#define SAMSUNG_PA_KEYPAD S5PV210_PA_KEYPAD #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5pv210/include/mach/memory.h b/arch/arm/mach-s5pv210/include/mach/memory.h index 379117e27600..d503e0c4ce4f 100644 --- a/arch/arm/mach-s5pv210/include/mach/memory.h +++ b/arch/arm/mach-s5pv210/include/mach/memory.h @@ -16,8 +16,13 @@ #define PHYS_OFFSET UL(0x20000000) #define CONSISTENT_DMA_SIZE (SZ_8M + SZ_4M + SZ_2M) -/* Maximum of 256MiB in one bank */ -#define MAX_PHYSMEM_BITS 32 +/* + * Sparsemem support + * Physical memory can be located from 0x20000000 to 0x7fffffff, + * so MAX_PHYSMEM_BITS is 31. + */ + +#define MAX_PHYSMEM_BITS 31 #define SECTION_SIZE_BITS 28 #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h index 2a25ab40c863..499aef737476 100644 --- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h +++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h @@ -90,6 +90,8 @@ #define S5P_CLKDIV0_PCLK66_SHIFT (28) #define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT) +#define S5P_SWRESET S5P_CLKREG(0x2000) + /* Registers related to power management */ #define S5P_PWR_CFG S5P_CLKREG(0xC000) #define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0xC004) diff --git a/arch/arm/mach-s5pv210/include/mach/system.h b/arch/arm/mach-s5pv210/include/mach/system.h index 1ca04d5025b3..af8a200b2135 100644 --- a/arch/arm/mach-s5pv210/include/mach/system.h +++ b/arch/arm/mach-s5pv210/include/mach/system.h @@ -13,12 +13,9 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H __FILE__ -static void arch_idle(void) -{ - /* nothing here yet */ -} +#include <plat/system-reset.h> -static void arch_reset(char mode, const char *cmd) +static void arch_idle(void) { /* nothing here yet */ } diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 10bc76ec4025..a6b4ed364840 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -13,6 +13,12 @@ #include <linux/init.h> #include <linux/serial_core.h> #include <linux/fb.h> +#include <linux/i2c.h> +#include <linux/i2c-gpio.h> +#include <linux/mfd/max8998.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/gpio.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -23,54 +29,62 @@ #include <mach/regs-clock.h> #include <mach/regs-fb.h> +#include <plat/gpio-cfg.h> #include <plat/regs-serial.h> #include <plat/s5pv210.h> #include <plat/devs.h> #include <plat/cpu.h> #include <plat/fb.h> +#include <plat/sdhci.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ -#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ +#define AQUILA_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ S3C2410_UCON_TXIRQMODE | \ S3C2410_UCON_RXIRQMODE | \ S3C2410_UCON_RXFIFO_TOI | \ S3C2443_UCON_RXERR_IRQEN) -#define S5PV210_ULCON_DEFAULT S3C2410_LCON_CS8 +#define AQUILA_ULCON_DEFAULT S3C2410_LCON_CS8 -#define S5PV210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ - S5PV210_UFCON_TXTRIG4 | \ - S5PV210_UFCON_RXTRIG4) +#define AQUILA_UFCON_DEFAULT S3C2410_UFCON_FIFOMODE -static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = { +static struct s3c2410_uartcfg aquila_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = AQUILA_UCON_DEFAULT, + .ulcon = AQUILA_ULCON_DEFAULT, + /* + * Actually UART0 can support 256 bytes fifo, but aquila board + * supports 128 bytes fifo because of initial chip bug + */ + .ufcon = AQUILA_UFCON_DEFAULT | + S5PV210_UFCON_TXTRIG128 | S5PV210_UFCON_RXTRIG128, }, [1] = { .hwport = 1, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = AQUILA_UCON_DEFAULT, + .ulcon = AQUILA_ULCON_DEFAULT, + .ufcon = AQUILA_UFCON_DEFAULT | + S5PV210_UFCON_TXTRIG64 | S5PV210_UFCON_RXTRIG64, }, [2] = { .hwport = 2, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = AQUILA_UCON_DEFAULT, + .ulcon = AQUILA_ULCON_DEFAULT, + .ufcon = AQUILA_UFCON_DEFAULT | + S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16, }, [3] = { .hwport = 3, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = AQUILA_UCON_DEFAULT, + .ulcon = AQUILA_ULCON_DEFAULT, + .ufcon = AQUILA_UFCON_DEFAULT | + S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16, }, }; @@ -116,19 +130,376 @@ static struct s3c_fb_platdata aquila_lcd_pdata __initdata = { .setup_gpio = s5pv210_fb_gpio_setup_24bpp, }; +/* MAX8998 regulators */ +#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE) + +static struct regulator_init_data aquila_ldo2_data = { + .constraints = { + .name = "VALIVE_1.1V", + .min_uV = 1100000, + .max_uV = 1100000, + .apply_uV = 1, + .always_on = 1, + .state_mem = { + .enabled = 1, + }, + }, +}; + +static struct regulator_init_data aquila_ldo3_data = { + .constraints = { + .name = "VUSB/MIPI_1.1V", + .min_uV = 1100000, + .max_uV = 1100000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo4_data = { + .constraints = { + .name = "VDAC_3.3V", + .min_uV = 3300000, + .max_uV = 3300000, + .apply_uV = 1, + }, +}; + +static struct regulator_init_data aquila_ldo5_data = { + .constraints = { + .name = "VTF_2.8V", + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = 1, + }, +}; + +static struct regulator_init_data aquila_ldo6_data = { + .constraints = { + .name = "VCC_3.3V", + .min_uV = 3300000, + .max_uV = 3300000, + .apply_uV = 1, + }, +}; + +static struct regulator_init_data aquila_ldo7_data = { + .constraints = { + .name = "VCC_3.0V", + .min_uV = 3000000, + .max_uV = 3000000, + .apply_uV = 1, + .boot_on = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo8_data = { + .constraints = { + .name = "VUSB/VADC_3.3V", + .min_uV = 3300000, + .max_uV = 3300000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo9_data = { + .constraints = { + .name = "VCC/VCAM_2.8V", + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo10_data = { + .constraints = { + .name = "VPLL_1.1V", + .min_uV = 1100000, + .max_uV = 1100000, + .apply_uV = 1, + .boot_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo11_data = { + .constraints = { + .name = "CAM_IO_2.8V", + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo12_data = { + .constraints = { + .name = "CAM_ISP_1.2V", + .min_uV = 1200000, + .max_uV = 1200000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo13_data = { + .constraints = { + .name = "CAM_A_2.8V", + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo14_data = { + .constraints = { + .name = "CAM_CIF_1.8V", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo15_data = { + .constraints = { + .name = "CAM_AF_3.3V", + .min_uV = 3300000, + .max_uV = 3300000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo16_data = { + .constraints = { + .name = "VMIPI_1.8V", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data aquila_ldo17_data = { + .constraints = { + .name = "CAM_8M_1.8V", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +/* BUCK */ +static struct regulator_consumer_supply buck1_consumer[] = { + { .supply = "vddarm", }, +}; + +static struct regulator_consumer_supply buck2_consumer[] = { + { .supply = "vddint", }, +}; + +static struct regulator_init_data aquila_buck1_data = { + .constraints = { + .name = "VARM_1.2V", + .min_uV = 1200000, + .max_uV = 1200000, + .apply_uV = 1, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(buck1_consumer), + .consumer_supplies = buck1_consumer, +}; + +static struct regulator_init_data aquila_buck2_data = { + .constraints = { + .name = "VINT_1.2V", + .min_uV = 1200000, + .max_uV = 1200000, + .apply_uV = 1, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(buck2_consumer), + .consumer_supplies = buck2_consumer, +}; + +static struct regulator_init_data aquila_buck3_data = { + .constraints = { + .name = "VCC_1.8V", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = 1, + .state_mem = { + .enabled = 1, + }, + }, +}; + +static struct regulator_init_data aquila_buck4_data = { + .constraints = { + .name = "CAM_CORE_1.2V", + .min_uV = 1200000, + .max_uV = 1200000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct max8998_regulator_data aquila_regulators[] = { + { MAX8998_LDO2, &aquila_ldo2_data }, + { MAX8998_LDO3, &aquila_ldo3_data }, + { MAX8998_LDO4, &aquila_ldo4_data }, + { MAX8998_LDO5, &aquila_ldo5_data }, + { MAX8998_LDO6, &aquila_ldo6_data }, + { MAX8998_LDO7, &aquila_ldo7_data }, + { MAX8998_LDO8, &aquila_ldo8_data }, + { MAX8998_LDO9, &aquila_ldo9_data }, + { MAX8998_LDO10, &aquila_ldo10_data }, + { MAX8998_LDO11, &aquila_ldo11_data }, + { MAX8998_LDO12, &aquila_ldo12_data }, + { MAX8998_LDO13, &aquila_ldo13_data }, + { MAX8998_LDO14, &aquila_ldo14_data }, + { MAX8998_LDO15, &aquila_ldo15_data }, + { MAX8998_LDO16, &aquila_ldo16_data }, + { MAX8998_LDO17, &aquila_ldo17_data }, + { MAX8998_BUCK1, &aquila_buck1_data }, + { MAX8998_BUCK2, &aquila_buck2_data }, + { MAX8998_BUCK3, &aquila_buck3_data }, + { MAX8998_BUCK4, &aquila_buck4_data }, +}; + +static struct max8998_platform_data aquila_max8998_pdata = { + .num_regulators = ARRAY_SIZE(aquila_regulators), + .regulators = aquila_regulators, +}; +#endif + +/* GPIO I2C PMIC */ +#define AP_I2C_GPIO_PMIC_BUS_4 4 +static struct i2c_gpio_platform_data aquila_i2c_gpio_pmic_data = { + .sda_pin = S5PV210_GPJ4(0), /* XMSMCSN */ + .scl_pin = S5PV210_GPJ4(3), /* XMSMIRQN */ +}; + +static struct platform_device aquila_i2c_gpio_pmic = { + .name = "i2c-gpio", + .id = AP_I2C_GPIO_PMIC_BUS_4, + .dev = { + .platform_data = &aquila_i2c_gpio_pmic_data, + }, +}; + +static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = { +#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE) + { + /* 0xCC when SRAD = 0 */ + I2C_BOARD_INFO("max8998", 0xCC >> 1), + .platform_data = &aquila_max8998_pdata, + }, +#endif +}; + +/* PMIC Power button */ +static struct gpio_keys_button aquila_gpio_keys_table[] = { + { + .code = KEY_POWER, + .gpio = S5PV210_GPH2(6), + .desc = "gpio-keys: KEY_POWER", + .type = EV_KEY, + .active_low = 1, + .wakeup = 1, + .debounce_interval = 1, + }, +}; + +static struct gpio_keys_platform_data aquila_gpio_keys_data = { + .buttons = aquila_gpio_keys_table, + .nbuttons = ARRAY_SIZE(aquila_gpio_keys_table), +}; + +static struct platform_device aquila_device_gpiokeys = { + .name = "gpio-keys", + .dev = { + .platform_data = &aquila_gpio_keys_data, + }, +}; + +static void __init aquila_pmic_init(void) +{ + /* AP_PMIC_IRQ: EINT7 */ + s3c_gpio_cfgpin(S5PV210_GPH0(7), S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(S5PV210_GPH0(7), S3C_GPIO_PULL_UP); + + /* nPower: EINT22 */ + s3c_gpio_cfgpin(S5PV210_GPH2(6), S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(S5PV210_GPH2(6), S3C_GPIO_PULL_UP); +} + +/* MoviNAND */ +static struct s3c_sdhci_platdata aquila_hsmmc0_data __initdata = { + .max_width = 4, + .cd_type = S3C_SDHCI_CD_PERMANENT, +}; + +/* Wireless LAN */ +static struct s3c_sdhci_platdata aquila_hsmmc1_data __initdata = { + .max_width = 4, + .cd_type = S3C_SDHCI_CD_EXTERNAL, + /* ext_cd_{init,cleanup} callbacks will be added later */ +}; + +/* External Flash */ +#define AQUILA_EXT_FLASH_EN S5PV210_MP05(4) +#define AQUILA_EXT_FLASH_CD S5PV210_GPH3(4) +static struct s3c_sdhci_platdata aquila_hsmmc2_data __initdata = { + .max_width = 4, + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = AQUILA_EXT_FLASH_CD, + .ext_cd_gpio_invert = 1, +}; + +static void aquila_setup_sdhci(void) +{ + gpio_request(AQUILA_EXT_FLASH_EN, "FLASH_EN"); + gpio_direction_output(AQUILA_EXT_FLASH_EN, 1); + + s3c_sdhci0_set_platdata(&aquila_hsmmc0_data); + s3c_sdhci1_set_platdata(&aquila_hsmmc1_data); + s3c_sdhci2_set_platdata(&aquila_hsmmc2_data); +}; + static struct platform_device *aquila_devices[] __initdata = { + &aquila_i2c_gpio_pmic, + &aquila_device_gpiokeys, &s3c_device_fb, + &s5pc110_device_onenand, + &s3c_device_hsmmc0, + &s3c_device_hsmmc1, + &s3c_device_hsmmc2, }; static void __init aquila_map_io(void) { s5p_init_io(NULL, 0, S5P_VA_CHIPID); s3c24xx_init_clocks(24000000); - s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs)); + s3c24xx_init_uarts(aquila_uartcfgs, ARRAY_SIZE(aquila_uartcfgs)); } static void __init aquila_machine_init(void) { + /* PMIC */ + aquila_pmic_init(); + i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs, + ARRAY_SIZE(i2c_gpio_pmic_devs)); + /* SDHCI */ + aquila_setup_sdhci(); + /* 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 4863b13824e4..0be739e5bfe6 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -12,6 +12,13 @@ #include <linux/types.h> #include <linux/init.h> #include <linux/serial_core.h> +#include <linux/fb.h> +#include <linux/i2c.h> +#include <linux/i2c-gpio.h> +#include <linux/mfd/max8998.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/gpio.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -20,58 +27,441 @@ #include <mach/map.h> #include <mach/regs-clock.h> +#include <mach/regs-fb.h> +#include <plat/gpio-cfg.h> #include <plat/regs-serial.h> #include <plat/s5pv210.h> #include <plat/devs.h> #include <plat/cpu.h> +#include <plat/fb.h> +#include <plat/sdhci.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ -#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ +#define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ S3C2410_UCON_TXIRQMODE | \ S3C2410_UCON_RXIRQMODE | \ S3C2410_UCON_RXFIFO_TOI | \ S3C2443_UCON_RXERR_IRQEN) -#define S5PV210_ULCON_DEFAULT S3C2410_LCON_CS8 +#define GONI_ULCON_DEFAULT S3C2410_LCON_CS8 -#define S5PV210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ - S5PV210_UFCON_TXTRIG4 | \ - S5PV210_UFCON_RXTRIG4) +#define GONI_UFCON_DEFAULT S3C2410_UFCON_FIFOMODE static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = GONI_UCON_DEFAULT, + .ulcon = GONI_ULCON_DEFAULT, + .ufcon = GONI_UFCON_DEFAULT | + S5PV210_UFCON_TXTRIG256 | S5PV210_UFCON_RXTRIG256, }, [1] = { .hwport = 1, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = GONI_UCON_DEFAULT, + .ulcon = GONI_ULCON_DEFAULT, + .ufcon = GONI_UFCON_DEFAULT | + S5PV210_UFCON_TXTRIG64 | S5PV210_UFCON_RXTRIG64, }, [2] = { .hwport = 2, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = GONI_UCON_DEFAULT, + .ulcon = GONI_ULCON_DEFAULT, + .ufcon = GONI_UFCON_DEFAULT | + S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16, }, [3] = { .hwport = 3, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = GONI_UCON_DEFAULT, + .ulcon = GONI_ULCON_DEFAULT, + .ufcon = GONI_UFCON_DEFAULT | + S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16, }, }; +/* 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, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 2, + .xres = 480, + .yres = 800, + .refresh = 55, + }, + .max_bpp = 32, + .default_bpp = 16, +}; + +static struct s3c_fb_platdata goni_lcd_pdata __initdata = { + .win[0] = &goni_fb_win0, + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | + VIDCON0_CLKSEL_LCD, + .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN + | VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .setup_gpio = s5pv210_fb_gpio_setup_24bpp, +}; + +/* MAX8998 regulators */ +#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE) + +static struct regulator_init_data goni_ldo2_data = { + .constraints = { + .name = "VALIVE_1.1V", + .min_uV = 1100000, + .max_uV = 1100000, + .apply_uV = 1, + .always_on = 1, + .state_mem = { + .enabled = 1, + }, + }, +}; + +static struct regulator_init_data goni_ldo3_data = { + .constraints = { + .name = "VUSB/MIPI_1.1V", + .min_uV = 1100000, + .max_uV = 1100000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo4_data = { + .constraints = { + .name = "VDAC_3.3V", + .min_uV = 3300000, + .max_uV = 3300000, + .apply_uV = 1, + }, +}; + +static struct regulator_init_data goni_ldo5_data = { + .constraints = { + .name = "VTF_2.8V", + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = 1, + }, +}; + +static struct regulator_init_data goni_ldo6_data = { + .constraints = { + .name = "VCC_3.3V", + .min_uV = 3300000, + .max_uV = 3300000, + .apply_uV = 1, + }, +}; + +static struct regulator_init_data goni_ldo7_data = { + .constraints = { + .name = "VLCD_1.8V", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo8_data = { + .constraints = { + .name = "VUSB/VADC_3.3V", + .min_uV = 3300000, + .max_uV = 3300000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo9_data = { + .constraints = { + .name = "VCC/VCAM_2.8V", + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo10_data = { + .constraints = { + .name = "VPLL_1.1V", + .min_uV = 1100000, + .max_uV = 1100000, + .apply_uV = 1, + .boot_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo11_data = { + .constraints = { + .name = "CAM_IO_2.8V", + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo12_data = { + .constraints = { + .name = "CAM_ISP_1.2V", + .min_uV = 1200000, + .max_uV = 1200000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo13_data = { + .constraints = { + .name = "CAM_A_2.8V", + .min_uV = 2800000, + .max_uV = 2800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo14_data = { + .constraints = { + .name = "CAM_CIF_1.8V", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo15_data = { + .constraints = { + .name = "CAM_AF_3.3V", + .min_uV = 3300000, + .max_uV = 3300000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo16_data = { + .constraints = { + .name = "VMIPI_1.8V", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct regulator_init_data goni_ldo17_data = { + .constraints = { + .name = "VCC_3.0V_LCD", + .min_uV = 3000000, + .max_uV = 3000000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +/* BUCK */ +static struct regulator_consumer_supply buck1_consumer[] = { + { .supply = "vddarm", }, +}; + +static struct regulator_consumer_supply buck2_consumer[] = { + { .supply = "vddint", }, +}; + +static struct regulator_init_data goni_buck1_data = { + .constraints = { + .name = "VARM_1.2V", + .min_uV = 1200000, + .max_uV = 1200000, + .apply_uV = 1, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(buck1_consumer), + .consumer_supplies = buck1_consumer, +}; + +static struct regulator_init_data goni_buck2_data = { + .constraints = { + .name = "VINT_1.2V", + .min_uV = 1200000, + .max_uV = 1200000, + .apply_uV = 1, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(buck2_consumer), + .consumer_supplies = buck2_consumer, +}; + +static struct regulator_init_data goni_buck3_data = { + .constraints = { + .name = "VCC_1.8V", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = 1, + .state_mem = { + .enabled = 1, + }, + }, +}; + +static struct regulator_init_data goni_buck4_data = { + .constraints = { + .name = "CAM_CORE_1.2V", + .min_uV = 1200000, + .max_uV = 1200000, + .apply_uV = 1, + .always_on = 1, + }, +}; + +static struct max8998_regulator_data goni_regulators[] = { + { MAX8998_LDO2, &goni_ldo2_data }, + { MAX8998_LDO3, &goni_ldo3_data }, + { MAX8998_LDO4, &goni_ldo4_data }, + { MAX8998_LDO5, &goni_ldo5_data }, + { MAX8998_LDO6, &goni_ldo6_data }, + { MAX8998_LDO7, &goni_ldo7_data }, + { MAX8998_LDO8, &goni_ldo8_data }, + { MAX8998_LDO9, &goni_ldo9_data }, + { MAX8998_LDO10, &goni_ldo10_data }, + { MAX8998_LDO11, &goni_ldo11_data }, + { MAX8998_LDO12, &goni_ldo12_data }, + { MAX8998_LDO13, &goni_ldo13_data }, + { MAX8998_LDO14, &goni_ldo14_data }, + { MAX8998_LDO15, &goni_ldo15_data }, + { MAX8998_LDO16, &goni_ldo16_data }, + { MAX8998_LDO17, &goni_ldo17_data }, + { MAX8998_BUCK1, &goni_buck1_data }, + { MAX8998_BUCK2, &goni_buck2_data }, + { MAX8998_BUCK3, &goni_buck3_data }, + { MAX8998_BUCK4, &goni_buck4_data }, +}; + +static struct max8998_platform_data goni_max8998_pdata = { + .num_regulators = ARRAY_SIZE(goni_regulators), + .regulators = goni_regulators, +}; +#endif + +/* GPIO I2C PMIC */ +#define AP_I2C_GPIO_PMIC_BUS_4 4 +static struct i2c_gpio_platform_data goni_i2c_gpio_pmic_data = { + .sda_pin = S5PV210_GPJ4(0), /* XMSMCSN */ + .scl_pin = S5PV210_GPJ4(3), /* XMSMIRQN */ +}; + +static struct platform_device goni_i2c_gpio_pmic = { + .name = "i2c-gpio", + .id = AP_I2C_GPIO_PMIC_BUS_4, + .dev = { + .platform_data = &goni_i2c_gpio_pmic_data, + }, +}; + +static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = { +#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE) + { + /* 0xCC when SRAD = 0 */ + I2C_BOARD_INFO("max8998", 0xCC >> 1), + .platform_data = &goni_max8998_pdata, + }, +#endif +}; + +/* PMIC Power button */ +static struct gpio_keys_button goni_gpio_keys_table[] = { + { + .code = KEY_POWER, + .gpio = S5PV210_GPH2(6), + .desc = "gpio-keys: KEY_POWER", + .type = EV_KEY, + .active_low = 1, + .wakeup = 1, + .debounce_interval = 1, + }, +}; + +static struct gpio_keys_platform_data goni_gpio_keys_data = { + .buttons = goni_gpio_keys_table, + .nbuttons = ARRAY_SIZE(goni_gpio_keys_table), +}; + +static struct platform_device goni_device_gpiokeys = { + .name = "gpio-keys", + .dev = { + .platform_data = &goni_gpio_keys_data, + }, +}; + +static void __init goni_pmic_init(void) +{ + /* AP_PMIC_IRQ: EINT7 */ + s3c_gpio_cfgpin(S5PV210_GPH0(7), S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(S5PV210_GPH0(7), S3C_GPIO_PULL_UP); + + /* nPower: EINT22 */ + s3c_gpio_cfgpin(S5PV210_GPH2(6), S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(S5PV210_GPH2(6), S3C_GPIO_PULL_UP); +} + +/* MoviNAND */ +static struct s3c_sdhci_platdata goni_hsmmc0_data __initdata = { + .max_width = 4, + .cd_type = S3C_SDHCI_CD_PERMANENT, +}; + +/* Wireless LAN */ +static struct s3c_sdhci_platdata goni_hsmmc1_data __initdata = { + .max_width = 4, + .cd_type = S3C_SDHCI_CD_EXTERNAL, + /* ext_cd_{init,cleanup} callbacks will be added later */ +}; + +/* External Flash */ +#define GONI_EXT_FLASH_EN S5PV210_MP05(4) +#define GONI_EXT_FLASH_CD S5PV210_GPH3(4) +static struct s3c_sdhci_platdata goni_hsmmc2_data __initdata = { + .max_width = 4, + .cd_type = S3C_SDHCI_CD_GPIO, + .ext_cd_gpio = GONI_EXT_FLASH_CD, + .ext_cd_gpio_invert = 1, +}; + +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); +}; + static struct platform_device *goni_devices[] __initdata = { + &s3c_device_fb, + &s5pc110_device_onenand, + &goni_i2c_gpio_pmic, + &goni_device_gpiokeys, + &s3c_device_hsmmc0, + &s3c_device_hsmmc1, + &s3c_device_hsmmc2, }; static void __init goni_map_io(void) @@ -83,6 +473,16 @@ static void __init goni_map_io(void) static void __init goni_machine_init(void) { + /* PMIC */ + goni_pmic_init(); + i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs, + ARRAY_SIZE(i2c_gpio_pmic_devs)); + /* SDHCI */ + goni_setup_sdhci(); + + /* FB */ + s3c_fb_set_platdata(&goni_lcd_pdata); + 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 4c8903c6d104..8211bb87c54b 100644 --- a/arch/arm/mach-s5pv210/mach-smdkc110.c +++ b/arch/arm/mach-s5pv210/mach-smdkc110.c @@ -12,6 +12,7 @@ #include <linux/types.h> #include <linux/init.h> #include <linux/serial_core.h> +#include <linux/i2c.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -25,18 +26,20 @@ #include <plat/s5pv210.h> #include <plat/devs.h> #include <plat/cpu.h> +#include <plat/ata.h> +#include <plat/iic.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ -#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ +#define SMDKC110_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ S3C2410_UCON_TXIRQMODE | \ S3C2410_UCON_RXIRQMODE | \ S3C2410_UCON_RXFIFO_TOI | \ S3C2443_UCON_RXERR_IRQEN) -#define S5PV210_ULCON_DEFAULT S3C2410_LCON_CS8 +#define SMDKC110_ULCON_DEFAULT S3C2410_LCON_CS8 -#define S5PV210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ +#define SMDKC110_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ S5PV210_UFCON_TXTRIG4 | \ S5PV210_UFCON_RXTRIG4) @@ -44,39 +47,60 @@ static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = SMDKC110_UCON_DEFAULT, + .ulcon = SMDKC110_ULCON_DEFAULT, + .ufcon = SMDKC110_UFCON_DEFAULT, }, [1] = { .hwport = 1, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = SMDKC110_UCON_DEFAULT, + .ulcon = SMDKC110_ULCON_DEFAULT, + .ufcon = SMDKC110_UFCON_DEFAULT, }, [2] = { .hwport = 2, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = SMDKC110_UCON_DEFAULT, + .ulcon = SMDKC110_ULCON_DEFAULT, + .ufcon = SMDKC110_UFCON_DEFAULT, }, [3] = { .hwport = 3, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = SMDKC110_UCON_DEFAULT, + .ulcon = SMDKC110_ULCON_DEFAULT, + .ufcon = SMDKC110_UFCON_DEFAULT, }, }; +static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = { + .setup_gpio = s5pv210_ide_setup_gpio, +}; + static struct platform_device *smdkc110_devices[] __initdata = { &s5pv210_device_iis0, &s5pv210_device_ac97, + &s3c_device_cfcon, + &s3c_device_i2c0, + &s3c_device_i2c1, + &s3c_device_i2c2, + &s3c_device_rtc, &s3c_device_wdt, }; +static struct i2c_board_info smdkc110_i2c_devs0[] __initdata = { + { I2C_BOARD_INFO("24c08", 0x50), }, /* Samsung S524AD0XD1 */ +}; + +static struct i2c_board_info smdkc110_i2c_devs1[] __initdata = { + /* To Be Updated */ +}; + +static struct i2c_board_info smdkc110_i2c_devs2[] __initdata = { + /* To Be Updated */ +}; + static void __init smdkc110_map_io(void) { s5p_init_io(NULL, 0, S5P_VA_CHIPID); @@ -86,6 +110,18 @@ static void __init smdkc110_map_io(void) static void __init smdkc110_machine_init(void) { + s3c_i2c0_set_platdata(NULL); + s3c_i2c1_set_platdata(NULL); + s3c_i2c2_set_platdata(NULL); + i2c_register_board_info(0, smdkc110_i2c_devs0, + ARRAY_SIZE(smdkc110_i2c_devs0)); + i2c_register_board_info(1, smdkc110_i2c_devs1, + ARRAY_SIZE(smdkc110_i2c_devs1)); + i2c_register_board_info(2, smdkc110_i2c_devs2, + ARRAY_SIZE(smdkc110_i2c_devs2)); + + s3c_ide_set_platdata(&smdkc110_ide_pdata); + platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices)); } diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index 0d4627948040..fbbc0a3c3738 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/types.h> +#include <linux/i2c.h> #include <linux/init.h> #include <linux/serial_core.h> @@ -27,18 +28,21 @@ #include <plat/cpu.h> #include <plat/adc.h> #include <plat/ts.h> +#include <plat/ata.h> +#include <plat/iic.h> +#include <plat/keypad.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ -#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ +#define SMDKV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ S3C2410_UCON_TXIRQMODE | \ S3C2410_UCON_RXIRQMODE | \ S3C2410_UCON_RXFIFO_TOI | \ S3C2443_UCON_RXERR_IRQEN) -#define S5PV210_ULCON_DEFAULT S3C2410_LCON_CS8 +#define SMDKV210_ULCON_DEFAULT S3C2410_LCON_CS8 -#define S5PV210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ +#define SMDKV210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ S5PV210_UFCON_TXTRIG4 | \ S5PV210_UFCON_RXTRIG4) @@ -46,41 +50,86 @@ static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = SMDKV210_UCON_DEFAULT, + .ulcon = SMDKV210_ULCON_DEFAULT, + .ufcon = SMDKV210_UFCON_DEFAULT, }, [1] = { .hwport = 1, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = SMDKV210_UCON_DEFAULT, + .ulcon = SMDKV210_ULCON_DEFAULT, + .ufcon = SMDKV210_UFCON_DEFAULT, }, [2] = { .hwport = 2, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = SMDKV210_UCON_DEFAULT, + .ulcon = SMDKV210_ULCON_DEFAULT, + .ufcon = SMDKV210_UFCON_DEFAULT, }, [3] = { .hwport = 3, .flags = 0, - .ucon = S5PV210_UCON_DEFAULT, - .ulcon = S5PV210_ULCON_DEFAULT, - .ufcon = S5PV210_UFCON_DEFAULT, + .ucon = SMDKV210_UCON_DEFAULT, + .ulcon = SMDKV210_ULCON_DEFAULT, + .ufcon = SMDKV210_UFCON_DEFAULT, }, }; +static struct s3c_ide_platdata smdkv210_ide_pdata __initdata = { + .setup_gpio = s5pv210_ide_setup_gpio, +}; + +static uint32_t smdkv210_keymap[] __initdata = { + /* KEY(row, col, keycode) */ + KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3), + KEY(0, 6, KEY_4), KEY(0, 7, KEY_5), + KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C), + KEY(1, 6, KEY_D), KEY(1, 7, KEY_E) +}; + +static struct matrix_keymap_data smdkv210_keymap_data __initdata = { + .keymap = smdkv210_keymap, + .keymap_size = ARRAY_SIZE(smdkv210_keymap), +}; + +static struct samsung_keypad_platdata smdkv210_keypad_data __initdata = { + .keymap_data = &smdkv210_keymap_data, + .rows = 8, + .cols = 8, +}; + static struct platform_device *smdkv210_devices[] __initdata = { &s5pv210_device_iis0, &s5pv210_device_ac97, &s3c_device_adc, + &s3c_device_cfcon, + &s3c_device_hsmmc0, + &s3c_device_hsmmc1, + &s3c_device_hsmmc2, + &s3c_device_hsmmc3, + &s3c_device_i2c0, + &s3c_device_i2c1, + &s3c_device_i2c2, + &samsung_device_keypad, + &s3c_device_rtc, &s3c_device_ts, &s3c_device_wdt, }; +static struct i2c_board_info smdkv210_i2c_devs0[] __initdata = { + { I2C_BOARD_INFO("24c08", 0x50), }, /* Samsung S524AD0XD1 */ +}; + +static struct i2c_board_info smdkv210_i2c_devs1[] __initdata = { + /* To Be Updated */ +}; + +static struct i2c_board_info smdkv210_i2c_devs2[] __initdata = { + /* To Be Updated */ +}; + static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { .delay = 10000, .presc = 49, @@ -96,7 +145,21 @@ static void __init smdkv210_map_io(void) static void __init smdkv210_machine_init(void) { + samsung_keypad_set_platdata(&smdkv210_keypad_data); s3c24xx_ts_set_platdata(&s3c_ts_platform); + + s3c_i2c0_set_platdata(NULL); + s3c_i2c1_set_platdata(NULL); + s3c_i2c2_set_platdata(NULL); + i2c_register_board_info(0, smdkv210_i2c_devs0, + ARRAY_SIZE(smdkv210_i2c_devs0)); + i2c_register_board_info(1, smdkv210_i2c_devs1, + ARRAY_SIZE(smdkv210_i2c_devs1)); + i2c_register_board_info(2, smdkv210_i2c_devs2, + ARRAY_SIZE(smdkv210_i2c_devs2)); + + s3c_ide_set_platdata(&smdkv210_ide_pdata); + platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices)); } diff --git a/arch/arm/mach-s5pv210/setup-ide.c b/arch/arm/mach-s5pv210/setup-ide.c new file mode 100644 index 000000000000..b558b1cc8d60 --- /dev/null +++ b/arch/arm/mach-s5pv210/setup-ide.c @@ -0,0 +1,50 @@ +/* linux/arch/arm/mach-s5pv210/setup-ide.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5PV210 setup information for IDE + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/gpio.h> + +#include <plat/gpio-cfg.h> + +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); + } +} diff --git a/arch/arm/mach-s5pv210/setup-keypad.c b/arch/arm/mach-s5pv210/setup-keypad.c new file mode 100644 index 000000000000..37b2790aafc3 --- /dev/null +++ b/arch/arm/mach-s5pv210/setup-keypad.c @@ -0,0 +1,34 @@ +/* + * linux/arch/arm/mach-s5pv210/setup-keypad.c + * + * Copyright (C) 2010 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim <jy0922.shim@samsung.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/gpio.h> +#include <plat/gpio-cfg.h> + +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); + } + + /* 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); + } +} diff --git a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c index 88bdec35ff36..9f0f63ddd66a 100644 --- a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c +++ b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c @@ -112,3 +112,23 @@ void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) s3c_gpio_cfgpin(S5PV210_GPG2(2), S3C_GPIO_SFN(2)); } } + +void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width) +{ + 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); + } + + /* 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_setpull(S5PV210_GPG3(2), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5PV210_GPG3(2), S3C_GPIO_SFN(2)); +} diff --git a/arch/arm/mach-s5pv210/setup-sdhci.c b/arch/arm/mach-s5pv210/setup-sdhci.c index 51815ec60c2a..c32e202731c1 100644 --- a/arch/arm/mach-s5pv210/setup-sdhci.c +++ b/arch/arm/mach-s5pv210/setup-sdhci.c @@ -26,9 +26,9 @@ char *s5pv210_hsmmc_clksrcs[4] = { [0] = "hsmmc", /* HCLK */ - [1] = "hsmmc", /* HCLK */ + /* [1] = "hsmmc", - duplicate HCLK entry */ [2] = "sclk_mmc", /* mmc_bus */ - /*[4] = reserved */ + /* [3] = NULL, - reserved */ }; void s5pv210_setup_sdhci_cfg_card(struct platform_device *dev, diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig new file mode 100644 index 000000000000..331b5bd97aba --- /dev/null +++ b/arch/arm/mach-s5pv310/Kconfig @@ -0,0 +1,45 @@ +# arch/arm/mach-s5pv310/Kconfig +# +# Copyright (c) 2010 Samsung Electronics Co., Ltd. +# http://www.samsung.com/ +# +# Licensed under GPLv2 + +# Configuration options for the S5PV310 + +if ARCH_S5PV310 + +config CPU_S5PV310 + bool + select PLAT_S5P + help + Enable S5PV310 CPU support + +config S5PV310_SETUP_I2C1 + bool + help + Common setup code for i2c bus 1. + +config S5PV310_SETUP_I2C2 + bool + help + Common setup code for i2c bus 2. + +# machine support + +config MACH_SMDKV310 + bool "SMDKV310" + select CPU_S5PV310 + select ARCH_SPARSEMEM_ENABLE + help + Machine support for Samsung SMDKV310 + +config MACH_UNIVERSAL_C210 + bool "Mobile UNIVERSAL_C210 Board" + select CPU_S5PV310 + select ARCH_SPARSEMEM_ENABLE + help + Machine support for Samsung Mobile Universal S5PC210 Reference + Board. S5PC210(MCP) is one of package option of S5PV310 + +endif diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile new file mode 100644 index 000000000000..d5b51c72340f --- /dev/null +++ b/arch/arm/mach-s5pv310/Makefile @@ -0,0 +1,30 @@ +# arch/arm/mach-s5pv310/Makefile +# +# Copyright (c) 2010 Samsung Electronics Co., Ltd. +# http://www.samsung.com/ +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := +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_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o + +# machine support + +obj-$(CONFIG_MACH_SMDKV310) += mach-smdkv310.o +obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o + +# device support + +obj-$(CONFIG_S5PV310_SETUP_I2C1) += setup-i2c1.o +obj-$(CONFIG_S5PV310_SETUP_I2C2) += setup-i2c2.o diff --git a/arch/arm/mach-s5pv310/Makefile.boot b/arch/arm/mach-s5pv310/Makefile.boot new file mode 100644 index 000000000000..d65956ffb43d --- /dev/null +++ b/arch/arm/mach-s5pv310/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y := 0x40008000 +params_phys-y := 0x40000100 diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c new file mode 100644 index 000000000000..77f2b4d85e6b --- /dev/null +++ b/arch/arm/mach-s5pv310/clock.c @@ -0,0 +1,544 @@ +/* linux/arch/arm/mach-s5pv310/clock.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - 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/kernel.h> +#include <linux/err.h> +#include <linux/io.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 <mach/map.h> +#include <mach/regs-clock.h> + +static struct clk clk_sclk_hdmi27m = { + .name = "sclk_hdmi27m", + .id = -1, + .rate = 27000000, +}; + +/* Core list of CMU_CPU side */ + +static struct clksrc_clk clk_mout_apll = { + .clk = { + .name = "mout_apll", + .id = -1, + }, + .sources = &clk_src_apll, + .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 }, + .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 }, +}; + +static struct clksrc_clk clk_mout_epll = { + .clk = { + .name = "mout_epll", + .id = -1, + }, + .sources = &clk_src_epll, + .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 }, +}; + +static struct clksrc_clk clk_mout_mpll = { + .clk = { + .name = "mout_mpll", + .id = -1, + }, + .sources = &clk_src_mpll, + .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 }, +}; + +static struct clk *clkset_moutcore_list[] = { + [0] = &clk_mout_apll.clk, + [1] = &clk_mout_mpll.clk, +}; + +static struct clksrc_sources clkset_moutcore = { + .sources = clkset_moutcore_list, + .nr_sources = ARRAY_SIZE(clkset_moutcore_list), +}; + +static struct clksrc_clk clk_moutcore = { + .clk = { + .name = "moutcore", + .id = -1, + }, + .sources = &clkset_moutcore, + .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 }, +}; + +static struct clksrc_clk clk_coreclk = { + .clk = { + .name = "core_clk", + .id = -1, + .parent = &clk_moutcore.clk, + }, + .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 }, +}; + +static struct clksrc_clk clk_armclk = { + .clk = { + .name = "armclk", + .id = -1, + .parent = &clk_coreclk.clk, + }, +}; + +static struct clksrc_clk clk_aclk_corem0 = { + .clk = { + .name = "aclk_corem0", + .id = -1, + .parent = &clk_coreclk.clk, + }, + .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 }, +}; + +static struct clksrc_clk clk_aclk_cores = { + .clk = { + .name = "aclk_cores", + .id = -1, + .parent = &clk_coreclk.clk, + }, + .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 }, +}; + +static struct clksrc_clk clk_aclk_corem1 = { + .clk = { + .name = "aclk_corem1", + .id = -1, + .parent = &clk_coreclk.clk, + }, + .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 }, +}; + +static struct clksrc_clk clk_periphclk = { + .clk = { + .name = "periphclk", + .id = -1, + .parent = &clk_coreclk.clk, + }, + .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[] = { + [0] = &clk_mout_mpll.clk, + [1] = &clk_mout_apll.clk, +}; + +static struct clksrc_sources clkset_mout_corebus = { + .sources = clkset_corebus_list, + .nr_sources = ARRAY_SIZE(clkset_corebus_list), +}; + +static struct clksrc_clk clk_mout_corebus = { + .clk = { + .name = "mout_corebus", + .id = -1, + }, + .sources = &clkset_mout_corebus, + .reg_src = { .reg = S5P_CLKSRC_CORE, .shift = 4, .size = 1 }, +}; + +static struct clksrc_clk clk_sclk_dmc = { + .clk = { + .name = "sclk_dmc", + .id = -1, + .parent = &clk_mout_corebus.clk, + }, + .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 12, .size = 3 }, +}; + +static struct clksrc_clk clk_aclk_cored = { + .clk = { + .name = "aclk_cored", + .id = -1, + .parent = &clk_sclk_dmc.clk, + }, + .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 16, .size = 3 }, +}; + +static struct clksrc_clk clk_aclk_corep = { + .clk = { + .name = "aclk_corep", + .id = -1, + .parent = &clk_aclk_cored.clk, + }, + .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 20, .size = 3 }, +}; + +static struct clksrc_clk clk_aclk_acp = { + .clk = { + .name = "aclk_acp", + .id = -1, + .parent = &clk_mout_corebus.clk, + }, + .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 0, .size = 3 }, +}; + +static struct clksrc_clk clk_pclk_acp = { + .clk = { + .name = "pclk_acp", + .id = -1, + .parent = &clk_aclk_acp.clk, + }, + .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 4, .size = 3 }, +}; + +/* Core list of CMU_TOP side */ + +static struct clk *clkset_aclk_top_list[] = { + [0] = &clk_mout_mpll.clk, + [1] = &clk_mout_apll.clk, +}; + +static struct clksrc_sources clkset_aclk_200 = { + .sources = clkset_aclk_top_list, + .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), +}; + +static struct clksrc_clk clk_aclk_200 = { + .clk = { + .name = "aclk_200", + .id = -1, + }, + .sources = &clkset_aclk_200, + .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, + .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, + .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, + .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 }, + .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 }, +}; + +static struct clk *clkset_vpllsrc_list[] = { + [0] = &clk_fin_vpll, + [1] = &clk_sclk_hdmi27m, +}; + +static struct clksrc_sources clkset_vpllsrc = { + .sources = clkset_vpllsrc_list, + .nr_sources = ARRAY_SIZE(clkset_vpllsrc_list), +}; + +static struct clksrc_clk clk_vpllsrc = { + .clk = { + .name = "vpll_src", + .id = -1, + }, + .sources = &clkset_vpllsrc, + .reg_src = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 }, +}; + +static struct clk *clkset_sclk_vpll_list[] = { + [0] = &clk_vpllsrc.clk, + [1] = &clk_fout_vpll, +}; + +static struct clksrc_sources clkset_sclk_vpll = { + .sources = clkset_sclk_vpll_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_vpll_list), +}; + +static struct clksrc_clk clk_sclk_vpll = { + .clk = { + .name = "sclk_vpll", + .id = -1, + }, + .sources = &clkset_sclk_vpll, + .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 }, +}; + +static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable); +} + +static struct clk init_clocks_disable[] = { + { + .name = "timers", + .id = -1, + .parent = &clk_aclk_100.clk, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1<<24), + } +}; + +static struct clk init_clocks[] = { + /* Nothing here yet */ +}; + +static struct clk *clkset_group_list[] = { + [0] = &clk_ext_xtal_mux, + [1] = &clk_xusbxti, + [2] = &clk_sclk_hdmi27m, + [6] = &clk_mout_mpll.clk, + [7] = &clk_mout_epll.clk, + [8] = &clk_sclk_vpll.clk, +}; + +static struct clksrc_sources clkset_group = { + .sources = clkset_group_list, + .nr_sources = ARRAY_SIZE(clkset_group_list), +}; + +static struct clksrc_clk clksrcs[] = { + { + .clk = { + .name = "uclk1", + .id = 0, + .ctrlbit = (1 << 0), + .enable = s5pv310_clk_ip_peril_ctrl, + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "uclk1", + .id = 1, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 1), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "uclk1", + .id = 2, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 2), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 }, + }, { + .clk = { + .name = "uclk1", + .id = 3, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 3), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "sclk_pwm", + .id = -1, + .enable = s5pv310_clk_ip_peril_ctrl, + .ctrlbit = (1 << 24), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 }, + }, +}; + +/* Clock initialization code */ +static struct clksrc_clk *sysclks[] = { + &clk_mout_apll, + &clk_mout_epll, + &clk_mout_mpll, + &clk_moutcore, + &clk_coreclk, + &clk_armclk, + &clk_aclk_corem0, + &clk_aclk_cores, + &clk_aclk_corem1, + &clk_periphclk, + &clk_atclk, + &clk_pclk_dbg, + &clk_mout_corebus, + &clk_sclk_dmc, + &clk_aclk_cored, + &clk_aclk_corep, + &clk_aclk_acp, + &clk_pclk_acp, + &clk_vpllsrc, + &clk_sclk_vpll, + &clk_aclk_200, + &clk_aclk_100, + &clk_aclk_160, + &clk_aclk_133, +}; + +void __init_or_cpufreq s5pv310_setup_clocks(void) +{ + struct clk *xtal_clk; + unsigned long apll; + unsigned long mpll; + unsigned long epll; + unsigned long vpll; + 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 int ptr; + + printk(KERN_DEBUG "%s: registering clocks\n", __func__); + + xtal_clk = clk_get(NULL, "xtal"); + BUG_ON(IS_ERR(xtal_clk)); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal); + + apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508); + mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508); + epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0), + __raw_readl(S5P_EPLL_CON1), pll_4500); + + vpllsrc = clk_get_rate(&clk_vpllsrc.clk); + vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0), + __raw_readl(S5P_VPLL_CON1), pll_4502); + + clk_fout_apll.rate = apll; + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + clk_fout_vpll.rate = vpll; + + printk(KERN_INFO "S5PV310: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", + 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); + + clk_f.rate = armclk; + clk_h.rate = sclk_dmc; + clk_p.rate = periphclk; + + for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) + s3c_set_clksrc(&clksrcs[ptr], true); +} + +static struct clk *clks[] __initdata = { + /* Nothing here yet */ +}; + +void __init s5pv310_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-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c new file mode 100644 index 000000000000..196c9f12ed85 --- /dev/null +++ b/arch/arm/mach-s5pv310/cpu.c @@ -0,0 +1,122 @@ +/* linux/arch/arm/mach-s5pv310/cpu.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/sched.h> +#include <linux/sysdev.h> + +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/proc-fns.h> + +#include <plat/cpu.h> +#include <plat/clock.h> +#include <plat/s5pv310.h> + +#include <mach/regs-irq.h> + +void __iomem *gic_cpu_base_addr; + +extern int combiner_init(unsigned int combiner_nr, void __iomem *base, + unsigned int irq_start); +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, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_COMBINER_BASE, + .pfn = __phys_to_pfn(S5PV310_PA_COMBINER), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_L2CC, + .pfn = __phys_to_pfn(S5PV310_PA_L2CC), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +static void s5pv310_idle(void) +{ + if (!need_resched()) + cpu_do_idle(); + + local_irq_enable(); +} + +/* s5pv310_map_io + * + * register the standard cpu IO areas +*/ +void __init s5pv310_map_io(void) +{ + iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc)); +} + +void __init s5pv310_init_clocks(int xtal) +{ + printk(KERN_DEBUG "%s: initializing clocks\n", __func__); + + s3c24xx_register_baseclocks(xtal); + s5p_register_clocks(xtal); + s5pv310_register_clocks(); + s5pv310_setup_clocks(); +} + +void __init s5pv310_init_irq(void) +{ + int irq; + + gic_cpu_base_addr = S5P_VA_GIC_CPU; + gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER); + gic_cpu_init(0, S5P_VA_GIC_CPU); + + for (irq = 0; irq < MAX_COMBINER_NR; irq++) { + combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), + COMBINER_IRQ(irq, 0)); + combiner_cascade_irq(irq, IRQ_SPI(irq)); + } + + /* The parameters of s5p_init_irq() are for VIC init. + * Theses parameters should be NULL and 0 because S5PV310 + * uses GIC instead of VIC. + */ + s5p_init_irq(NULL, 0); +} + +struct sysdev_class s5pv310_sysclass = { + .name = "s5pv310-core", +}; + +static struct sys_device s5pv310_sysdev = { + .cls = &s5pv310_sysclass, +}; + +static int __init s5pv310_core_init(void) +{ + return sysdev_class_register(&s5pv310_sysclass); +} + +core_initcall(s5pv310_core_init); + +int __init s5pv310_init(void) +{ + printk(KERN_INFO "S5PV310: Initializing architecture\n"); + + /* set idle function */ + pm_idle = s5pv310_idle; + + return sysdev_register(&s5pv310_sysdev); +} diff --git a/arch/arm/mach-s5pv310/headsmp.S b/arch/arm/mach-s5pv310/headsmp.S new file mode 100644 index 000000000000..164b7b045713 --- /dev/null +++ b/arch/arm/mach-s5pv310/headsmp.S @@ -0,0 +1,41 @@ +/* + * linux/arch/arm/mach-s5pv310/headsmp.S + * + * Cloned from linux/arch/arm/mach-realview/headsmp.S + * + * Copyright (c) 2003 ARM Limited + * 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/linkage.h> +#include <linux/init.h> + + __INIT + +/* + * s5pv310 specific entry point for secondary CPUs. This provides + * a "holding pen" into which all secondary cores are held until we're + * ready for them to initialise. + */ +ENTRY(s5pv310_secondary_startup) + mrc p15, 0, r0, c0, c0, 5 + and r0, r0, #15 + adr r4, 1f + ldmia r4, {r5, r6} + sub r4, r4, r5 + add r6, r6, r4 +pen: ldr r7, [r6] + cmp r7, r0 + bne pen + + /* + * we've been released from the holding pen: secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup + +1: .long . + .long pen_release diff --git a/arch/arm/mach-s5pv310/include/mach/debug-macro.S b/arch/arm/mach-s5pv310/include/mach/debug-macro.S new file mode 100644 index 000000000000..6fb3893486be --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/debug-macro.S @@ -0,0 +1,36 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/debug-macro.S + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S + * + * 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> + + /* 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, tmp + 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, #(0x10000 * CONFIG_DEBUG_S3C_UART) +#endif + .endm + +#define fifo_full fifo_full_s5pv210 +#define fifo_level fifo_level_s5pv210 + +#include <plat/debug-macro.S> diff --git a/arch/arm/mach-s5pv310/include/mach/entry-macro.S b/arch/arm/mach-s5pv310/include/mach/entry-macro.S new file mode 100644 index 000000000000..e600e1d522df --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/entry-macro.S @@ -0,0 +1,84 @@ +/* arch/arm/mach-s5pv310/include/mach/entry-macro.S + * + * Cloned from arch/arm/mach-realview/include/mach/entry-macro.S + * + * Low-level IRQ helper macros for S5PV310 platforms + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. +*/ + +#include <mach/hardware.h> +#include <asm/hardware/gic.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =gic_cpu_base_addr + ldr \base, [\base] + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an interrupt if it's + * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. + * + * A simple read from the controller will tell us the number of the highest + * priority enabled interrupt. We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ + + ldr \tmp, =1021 + + bic \irqnr, \irqstat, #0x1c00 + + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + addne \irqnr, \irqnr, #32 + + .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm diff --git a/arch/arm/mach-s5pv310/include/mach/gpio.h b/arch/arm/mach-s5pv310/include/mach/gpio.h new file mode 100644 index 000000000000..20cb80c23466 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/gpio.h @@ -0,0 +1,135 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/gpio.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - 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 + +/* Practically, GPIO banks upto GPZ are the configurable gpio banks */ + +/* GPIO bank sizes */ +#define S5PV310_GPIO_A0_NR (8) +#define S5PV310_GPIO_A1_NR (6) +#define S5PV310_GPIO_B_NR (8) +#define S5PV310_GPIO_C0_NR (5) +#define S5PV310_GPIO_C1_NR (5) +#define S5PV310_GPIO_D0_NR (4) +#define S5PV310_GPIO_D1_NR (4) +#define S5PV310_GPIO_E0_NR (5) +#define S5PV310_GPIO_E1_NR (8) +#define S5PV310_GPIO_E2_NR (6) +#define S5PV310_GPIO_E3_NR (8) +#define S5PV310_GPIO_E4_NR (8) +#define S5PV310_GPIO_F0_NR (8) +#define S5PV310_GPIO_F1_NR (8) +#define S5PV310_GPIO_F2_NR (8) +#define S5PV310_GPIO_F3_NR (6) +#define S5PV310_GPIO_J0_NR (8) +#define S5PV310_GPIO_J1_NR (5) +#define S5PV310_GPIO_K0_NR (7) +#define S5PV310_GPIO_K1_NR (7) +#define S5PV310_GPIO_K2_NR (7) +#define S5PV310_GPIO_K3_NR (7) +#define S5PV310_GPIO_L0_NR (8) +#define S5PV310_GPIO_L1_NR (3) +#define S5PV310_GPIO_L2_NR (8) +#define S5PV310_GPIO_X0_NR (8) +#define S5PV310_GPIO_X1_NR (8) +#define S5PV310_GPIO_X2_NR (8) +#define S5PV310_GPIO_X3_NR (8) +#define S5PV310_GPIO_Z_NR (7) + +/* GPIO bank numbers */ + +#define S5PV310_GPIO_NEXT(__gpio) \ + ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1) + +enum s5p_gpio_number { + S5PV310_GPIO_A0_START = 0, + S5PV310_GPIO_A1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_A0), + S5PV310_GPIO_B_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_A1), + S5PV310_GPIO_C0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_B), + S5PV310_GPIO_C1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_C0), + S5PV310_GPIO_D0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_C1), + S5PV310_GPIO_D1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_D0), + S5PV310_GPIO_E0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_D1), + S5PV310_GPIO_E1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_E0), + S5PV310_GPIO_E2_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_E1), + S5PV310_GPIO_E3_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_E2), + S5PV310_GPIO_E4_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_E3), + S5PV310_GPIO_F0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_E4), + S5PV310_GPIO_F1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_F0), + S5PV310_GPIO_F2_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_F1), + S5PV310_GPIO_F3_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_F2), + S5PV310_GPIO_J0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_F3), + S5PV310_GPIO_J1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_J0), + S5PV310_GPIO_K0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_J1), + S5PV310_GPIO_K1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_K0), + S5PV310_GPIO_K2_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_K1), + S5PV310_GPIO_K3_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_K2), + S5PV310_GPIO_L0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_K3), + S5PV310_GPIO_L1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_L0), + S5PV310_GPIO_L2_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_L1), + S5PV310_GPIO_X0_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_L2), + S5PV310_GPIO_X1_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_X0), + S5PV310_GPIO_X2_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_X1), + S5PV310_GPIO_X3_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_X2), + S5PV310_GPIO_Z_START = S5PV310_GPIO_NEXT(S5PV310_GPIO_X3), +}; + +/* S5PV310 GPIO number definitions */ +#define S5PV310_GPA0(_nr) (S5PV310_GPIO_A0_START + (_nr)) +#define S5PV310_GPA1(_nr) (S5PV310_GPIO_A1_START + (_nr)) +#define S5PV310_GPB(_nr) (S5PV310_GPIO_B_START + (_nr)) +#define S5PV310_GPC0(_nr) (S5PV310_GPIO_C0_START + (_nr)) +#define S5PV310_GPC1(_nr) (S5PV310_GPIO_C1_START + (_nr)) +#define S5PV310_GPD0(_nr) (S5PV310_GPIO_D0_START + (_nr)) +#define S5PV310_GPD1(_nr) (S5PV310_GPIO_D1_START + (_nr)) +#define S5PV310_GPE0(_nr) (S5PV310_GPIO_E0_START + (_nr)) +#define S5PV310_GPE1(_nr) (S5PV310_GPIO_E1_START + (_nr)) +#define S5PV310_GPE2(_nr) (S5PV310_GPIO_E2_START + (_nr)) +#define S5PV310_GPE3(_nr) (S5PV310_GPIO_E3_START + (_nr)) +#define S5PV310_GPE4(_nr) (S5PV310_GPIO_E4_START + (_nr)) +#define S5PV310_GPF0(_nr) (S5PV310_GPIO_F0_START + (_nr)) +#define S5PV310_GPF1(_nr) (S5PV310_GPIO_F1_START + (_nr)) +#define S5PV310_GPF2(_nr) (S5PV310_GPIO_F2_START + (_nr)) +#define S5PV310_GPF3(_nr) (S5PV310_GPIO_F3_START + (_nr)) +#define S5PV310_GPJ0(_nr) (S5PV310_GPIO_J0_START + (_nr)) +#define S5PV310_GPJ1(_nr) (S5PV310_GPIO_J1_START + (_nr)) +#define S5PV310_GPK0(_nr) (S5PV310_GPIO_K0_START + (_nr)) +#define S5PV310_GPK1(_nr) (S5PV310_GPIO_K1_START + (_nr)) +#define S5PV310_GPK2(_nr) (S5PV310_GPIO_K2_START + (_nr)) +#define S5PV310_GPK3(_nr) (S5PV310_GPIO_K3_START + (_nr)) +#define S5PV310_GPL0(_nr) (S5PV310_GPIO_L0_START + (_nr)) +#define S5PV310_GPL1(_nr) (S5PV310_GPIO_L1_START + (_nr)) +#define S5PV310_GPL2(_nr) (S5PV310_GPIO_L2_START + (_nr)) +#define S5PV310_GPX0(_nr) (S5PV310_GPIO_X0_START + (_nr)) +#define S5PV310_GPX1(_nr) (S5PV310_GPIO_X1_START + (_nr)) +#define S5PV310_GPX2(_nr) (S5PV310_GPIO_X2_START + (_nr)) +#define S5PV310_GPX3(_nr) (S5PV310_GPIO_X3_START + (_nr)) +#define S5PV310_GPZ(_nr) (S5PV310_GPIO_Z_START + (_nr)) + +/* the end of the S5PV310 specific gpios */ +#define S5PV310_GPIO_END (S5PV310_GPZ(S5PV310_GPIO_Z_NR) + 1) +#define S3C_GPIO_END S5PV310_GPIO_END + +/* define the number of gpios we need to the one after the GPZ() range */ +#define ARCH_NR_GPIOS (S5PV310_GPZ(S5PV310_GPIO_Z_NR) + \ + CONFIG_SAMSUNG_GPIO_EXTRA + 1) + +#include <asm-generic/gpio.h> + +#endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/hardware.h b/arch/arm/mach-s5pv310/include/mach/hardware.h new file mode 100644 index 000000000000..28ff9881f1a6 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/hardware.h @@ -0,0 +1,18 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/hardware.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - 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 + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H __FILE__ + +/* currently nothing here, placeholder */ + +#endif /* __ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/io.h b/arch/arm/mach-s5pv310/include/mach/io.h new file mode 100644 index 000000000000..8a7f9128391f --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/io.h @@ -0,0 +1,26 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/io.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org> + * + * Based on arch/arm/mach-s5p6442/include/mach/io.h + * + * Default IO routines for S5PV310 + * + * 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 __FILE__ + +/* No current ISA/PCI bus support. */ +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#define IO_SPACE_LIMIT (0xFFFFFFFF) + +#endif /* __ASM_ARM_ARCH_IO_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h new file mode 100644 index 000000000000..56885ca3773c --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/irqs.h @@ -0,0 +1,74 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/irqs.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV210 - 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_IRQS_H +#define __ASM_ARCH_IRQS_H __FILE__ + +#include <plat/irqs.h> + +/* Private Peripheral Interrupt */ +#define IRQ_PPI(x) S5P_IRQ(x+16) + +#define IRQ_LOCALTIMER IRQ_PPI(13) + +/* Shared Peripheral Interrupt */ +#define IRQ_SPI(x) S5P_IRQ(x+32) + +#define IRQ_EINT0 IRQ_SPI(40) +#define IRQ_EINT1 IRQ_SPI(41) +#define IRQ_EINT2 IRQ_SPI(42) +#define IRQ_EINT3 IRQ_SPI(43) +#define IRQ_USB_HSOTG IRQ_SPI(44) +#define IRQ_USB_HOST IRQ_SPI(45) +#define IRQ_MODEM_IF IRQ_SPI(46) +#define IRQ_ROTATOR IRQ_SPI(47) +#define IRQ_JPEG IRQ_SPI(48) +#define IRQ_2D IRQ_SPI(49) +#define IRQ_PCIE IRQ_SPI(50) +#define IRQ_SYSTEM_TIMER IRQ_SPI(51) +#define IRQ_MFC IRQ_SPI(52) +#define IRQ_WTD IRQ_SPI(53) +#define IRQ_AUDIO_SS IRQ_SPI(54) +#define IRQ_AC97 IRQ_SPI(55) +#define IRQ_SPDIF IRQ_SPI(56) +#define IRQ_KEYPAD IRQ_SPI(57) +#define IRQ_INTFEEDCTRL_SSS IRQ_SPI(58) +#define IRQ_SLIMBUS IRQ_SPI(59) +#define IRQ_PMU IRQ_SPI(60) +#define IRQ_TSI IRQ_SPI(61) +#define IRQ_SATA IRQ_SPI(62) +#define IRQ_GPS IRQ_SPI(63) + +#define MAX_IRQ_IN_COMBINER 8 +#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64)) +#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y) + +#define IRQ_TIMER0_VIC COMBINER_IRQ(22, 0) +#define IRQ_TIMER1_VIC COMBINER_IRQ(22, 1) +#define IRQ_TIMER2_VIC COMBINER_IRQ(22, 2) +#define IRQ_TIMER3_VIC COMBINER_IRQ(22, 3) +#define IRQ_TIMER4_VIC COMBINER_IRQ(22, 4) + +#define IRQ_UART0 COMBINER_IRQ(26, 0) +#define IRQ_UART1 COMBINER_IRQ(26, 1) +#define IRQ_UART2 COMBINER_IRQ(26, 2) +#define IRQ_UART3 COMBINER_IRQ(26, 3) +#define IRQ_UART4 COMBINER_IRQ(26, 4) + +#define IRQ_IIC COMBINER_IRQ(27, 0) + +/* Set the default NR_IRQS */ +#define NR_IRQS COMBINER_IRQ(MAX_COMBINER_NR, 0) + +#define MAX_COMBINER_NR 39 + +#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 new file mode 100644 index 000000000000..87697c9fca5b --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/map.h @@ -0,0 +1,69 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/map.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - 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> + +/* + * S5PV310 UART offset is 0x10000 but the older S5P SoCs are 0x400. + * So need to define it, and here is to avoid redefinition warning. + */ +#define S3C_UART_OFFSET (0x10000) + +#include <plat/map-s5p.h> + +#define S5PV310_PA_CHIPID (0x10000000) +#define S5P_PA_CHIPID S5PV310_PA_CHIPID + +#define S5PV310_PA_SYSCON (0x10020000) +#define S5P_PA_SYSCON S5PV310_PA_SYSCON + +#define S5PV310_PA_WATCHDOG (0x10060000) + +#define S5PV310_PA_COMBINER (0x10448000) + +#define S5PV310_PA_COREPERI (0x10500000) +#define S5PV310_PA_GIC_CPU (0x10500100) +#define S5PV310_PA_TWD (0x10500600) +#define S5PV310_PA_GIC_DIST (0x10501000) +#define S5PV310_PA_L2CC (0x10502000) + +#define S5PV310_PA_GPIO (0x11000000) +#define S5P_PA_GPIO S5PV310_PA_GPIO + +#define S5PV310_PA_UART (0x13800000) + +#define S5P_PA_UART(x) (S5PV310_PA_UART + ((x) * S3C_UART_OFFSET)) +#define S5P_PA_UART0 S5P_PA_UART(0) +#define S5P_PA_UART1 S5P_PA_UART(1) +#define S5P_PA_UART2 S5P_PA_UART(2) +#define S5P_PA_UART3 S5P_PA_UART(3) +#define S5P_PA_UART4 S5P_PA_UART(4) + +#define S5P_SZ_UART SZ_256 + +#define S5PV310_PA_IIC0 (0x13860000) + +#define S5PV310_PA_TIMER (0x139D0000) +#define S5P_PA_TIMER S5PV310_PA_TIMER + +#define S5PV310_PA_SDRAM (0x40000000) +#define S5P_PA_SDRAM S5PV310_PA_SDRAM + +/* compatibiltiy defines. */ +#define S3C_PA_UART S5PV310_PA_UART +#define S3C_PA_IIC S5PV310_PA_IIC0 +#define S3C_PA_WDT S5PV310_PA_WATCHDOG + +#endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/memory.h b/arch/arm/mach-s5pv310/include/mach/memory.h new file mode 100644 index 000000000000..1dffb4823245 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/memory.h @@ -0,0 +1,22 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/memory.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - Memory definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H __FILE__ + +#define PHYS_OFFSET UL(0x40000000) + +/* Maximum of 256MiB in one bank */ +#define MAX_PHYSMEM_BITS 32 +#define SECTION_SIZE_BITS 28 + +#endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/pwm-clock.h b/arch/arm/mach-s5pv310/include/mach/pwm-clock.h new file mode 100644 index 000000000000..7e6da2701088 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/pwm-clock.h @@ -0,0 +1,70 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/pwm-clock.h + * + * Copyright (c) 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 + * + * S5PV310 - pwm clock and timer support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_PWMCLK_H +#define __ASM_ARCH_PWMCLK_H __FILE__ + +/** + * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk + * @tcfg: The timer TCFG1 register bits shifted down to 0. + * + * Return true if the given configuration from TCFG1 is a TCLK instead + * any of the TDIV clocks. + */ +static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) +{ + return tcfg == S3C64XX_TCFG1_MUX_TCLK; +} + +/** + * tcfg_to_divisor() - convert tcfg1 setting to a divisor + * @tcfg1: The tcfg1 setting, shifted down. + * + * Get the divisor value for the given tcfg1 setting. We assume the + * caller has already checked to see if this is not a TCLK source. + */ +static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) +{ + return 1 << tcfg1; +} + +/** + * pwm_tdiv_has_div1() - does the tdiv setting have a /1 + * + * Return true if we have a /1 in the tdiv setting. + */ +static inline unsigned int pwm_tdiv_has_div1(void) +{ + return 1; +} + +/** + * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. + * @div: The divisor to calculate the bit information for. + * + * Turn a divisor into the necessary bit field for TCFG1. + */ +static inline unsigned long pwm_tdiv_div_bits(unsigned int div) +{ + return ilog2(div); +} + +#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK + +#endif /* __ASM_ARCH_PWMCLK_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h new file mode 100644 index 000000000000..59e3a7e94d80 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h @@ -0,0 +1,62 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/regs-clock.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - 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_INFORM0 S5P_CLKREG(0x800) + +#define S5P_EPLL_CON0 S5P_CLKREG(0x1C110) +#define S5P_EPLL_CON1 S5P_CLKREG(0x1C114) +#define S5P_VPLL_CON0 S5P_CLKREG(0x1C120) +#define S5P_VPLL_CON1 S5P_CLKREG(0x1C124) + +#define S5P_CLKSRC_TOP0 S5P_CLKREG(0x1C210) +#define S5P_CLKSRC_TOP1 S5P_CLKREG(0x1C214) + +#define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x1C250) + +#define S5P_CLKDIV_TOP S5P_CLKREG(0x1C510) + +#define S5P_CLKDIV_PERIL0 S5P_CLKREG(0x1C550) +#define S5P_CLKDIV_PERIL1 S5P_CLKREG(0x1C554) +#define S5P_CLKDIV_PERIL2 S5P_CLKREG(0x1C558) +#define S5P_CLKDIV_PERIL3 S5P_CLKREG(0x1C55C) +#define S5P_CLKDIV_PERIL4 S5P_CLKREG(0x1C560) +#define S5P_CLKDIV_PERIL5 S5P_CLKREG(0x1C564) + +#define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x1C950) + +#define S5P_CLKSRC_CORE S5P_CLKREG(0x20200) + +#define S5P_CLKDIV_CORE0 S5P_CLKREG(0x20500) + +#define S5P_APLL_LOCK S5P_CLKREG(0x24000) +#define S5P_MPLL_LOCK S5P_CLKREG(0x24004) +#define S5P_APLL_CON0 S5P_CLKREG(0x24100) +#define S5P_APLL_CON1 S5P_CLKREG(0x24104) +#define S5P_MPLL_CON0 S5P_CLKREG(0x24108) +#define S5P_MPLL_CON1 S5P_CLKREG(0x2410C) + +#define S5P_CLKSRC_CPU S5P_CLKREG(0x24200) +#define S5P_CLKMUX_STATCPU S5P_CLKREG(0x24400) + +#define S5P_CLKDIV_CPU S5P_CLKREG(0x24500) +#define S5P_CLKDIV_STATCPU S5P_CLKREG(0x24600) + +#define S5P_CLKGATE_SCLKCPU S5P_CLKREG(0x24800) + +#endif /* __ASM_ARCH_REGS_CLOCK_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/regs-irq.h b/arch/arm/mach-s5pv310/include/mach/regs-irq.h new file mode 100644 index 000000000000..c6e09c7f9161 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/regs-irq.h @@ -0,0 +1,19 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/regs-irq.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - 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 + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_REGS_IRQ_H +#define __ASM_ARCH_REGS_IRQ_H __FILE__ + +#include <asm/hardware/gic.h> +#include <mach/map.h> + +#endif /* __ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h new file mode 100644 index 000000000000..990f3ba88a1f --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/smp.h @@ -0,0 +1,29 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/smp.h + * + * Cloned from arch/arm/mach-realview/include/mach/smp.h +*/ + +#ifndef ASM_ARCH_SMP_H +#define ASM_ARCH_SMP_H __FILE__ + +#include <asm/hardware/gic.h> + +extern void __iomem *gic_cpu_base_addr; + +#define hard_smp_processor_id() \ + ({ \ + unsigned int cpunum; \ + __asm__("mrc p15, 0, %0, c0, c0, 5" \ + : "=r" (cpunum)); \ + cpunum &= 0x03; \ + }) + +/* + * We use IRQ1 as the IPI + */ +static inline void smp_cross_call(const struct cpumask *mask) +{ + gic_raise_softirq(mask, 1); +} + +#endif diff --git a/arch/arm/mach-s5pv310/include/mach/system.h b/arch/arm/mach-s5pv310/include/mach/system.h new file mode 100644 index 000000000000..d10c009cf0f1 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/system.h @@ -0,0 +1,22 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/system.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - 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 + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H __FILE__ + +#include <plat/system-reset.h> + +static void arch_idle(void) +{ + /* nothing here yet */ +} +#endif /* __ASM_ARCH_SYSTEM_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/timex.h b/arch/arm/mach-s5pv310/include/mach/timex.h new file mode 100644 index 000000000000..bd2359b952b4 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/timex.h @@ -0,0 +1,29 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/timex.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Copyright (c) 2003-2010 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * Based on arch/arm/mach-s5p6442/include/mach/timex.h + * + * S5PV310 - 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 + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_TIMEX_H +#define __ASM_ARCH_TIMEX_H __FILE__ + +/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it + * a variable is useless. It seems as long as we make our timers an + * exact multiple of HZ, any value that makes a 1->1 correspondence + * for the time conversion functions to/from jiffies is acceptable. +*/ + +#define CLOCK_TICK_RATE 12000000 + +#endif /* __ASM_ARCH_TIMEX_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/uncompress.h b/arch/arm/mach-s5pv310/include/mach/uncompress.h new file mode 100644 index 000000000000..59593c1e2416 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/uncompress.h @@ -0,0 +1,30 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/uncompress.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV310 - 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 __FILE__ + +#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. */ + + /* + * For preventing FIFO overrun or infinite loop of UART console, + * fifo_max should be the minimum fifo size of all of the UART channels + */ + fifo_mask = S5PV210_UFSTAT_TXMASK; + fifo_max = 15 << S5PV210_UFSTAT_TXSHIFT; +} +#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/vmalloc.h b/arch/arm/mach-s5pv310/include/mach/vmalloc.h new file mode 100644 index 000000000000..3f565ebb7daa --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/vmalloc.h @@ -0,0 +1,22 @@ +/* linux/arch/arm/mach-s5pv310/include/mach/vmalloc.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Copyright 2010 Ben Dooks <ben-linux@fluff.org> + * + * Based on arch/arm/mach-s5p6440/include/mach/vmalloc.h + * + * 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. + * + * S5PV310 vmalloc definition +*/ + +#ifndef __ASM_ARCH_VMALLOC_H +#define __ASM_ARCH_VMALLOC_H __FILE__ + +#define VMALLOC_END (0xF0000000) + +#endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/mach-s5pv310/init.c b/arch/arm/mach-s5pv310/init.c new file mode 100644 index 000000000000..182dcf42cfb4 --- /dev/null +++ b/arch/arm/mach-s5pv310/init.c @@ -0,0 +1,41 @@ +/* linux/arch/arm/mach-s5pv310/init.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 <plat/cpu.h> +#include <plat/devs.h> +#include <plat/regs-serial.h> + +static struct s3c24xx_uart_clksrc s5pv310_serial_clocks[] = { + [0] = { + .name = "uclk1", + .divisor = 1, + .min_baud = 0, + .max_baud = 0, + }, +}; + +/* uart registration process */ +void __init s5pv310_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->has_fracval = 1; + tcfg->clocks = s5pv310_serial_clocks; + tcfg->clocks_size = ARRAY_SIZE(s5pv310_serial_clocks); + } + } + + s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no); +} diff --git a/arch/arm/mach-s5pv310/irq-combiner.c b/arch/arm/mach-s5pv310/irq-combiner.c new file mode 100644 index 000000000000..0f7052164f23 --- /dev/null +++ b/arch/arm/mach-s5pv310/irq-combiner.c @@ -0,0 +1,125 @@ +/* linux/arch/arm/mach-s5pv310/irq-combiner.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Based on arch/arm/common/gic.c + * + * IRQ COMBINER 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/io.h> + +#include <asm/mach/irq.h> + +#define COMBINER_ENABLE_SET 0x0 +#define COMBINER_ENABLE_CLEAR 0x4 +#define COMBINER_INT_STATUS 0xC + +static DEFINE_SPINLOCK(irq_controller_lock); + +struct combiner_chip_data { + unsigned int irq_offset; + void __iomem *base; +}; + +static struct combiner_chip_data combiner_data[MAX_COMBINER_NR]; + +static inline void __iomem *combiner_base(unsigned int irq) +{ + struct combiner_chip_data *combiner_data = get_irq_chip_data(irq); + return combiner_data->base; +} + +static void combiner_mask_irq(unsigned int irq) +{ + u32 mask = 1 << (irq % 32); + + __raw_writel(mask, combiner_base(irq) + COMBINER_ENABLE_CLEAR); +} + +static void combiner_unmask_irq(unsigned int irq) +{ + u32 mask = 1 << (irq % 32); + + __raw_writel(mask, combiner_base(irq) + COMBINER_ENABLE_SET); +} + +static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) +{ + struct combiner_chip_data *chip_data = get_irq_data(irq); + struct irq_chip *chip = get_irq_chip(irq); + unsigned int cascade_irq, combiner_irq; + unsigned long status; + + /* primary controller ack'ing */ + chip->ack(irq); + + spin_lock(&irq_controller_lock); + status = __raw_readl(chip_data->base + COMBINER_INT_STATUS); + spin_unlock(&irq_controller_lock); + + if (status == 0) + goto out; + + for (combiner_irq = 0; combiner_irq < 32; combiner_irq++) { + if (status & 0x1) + break; + status >>= 1; + } + + cascade_irq = combiner_irq + (chip_data->irq_offset & ~31); + if (unlikely(cascade_irq >= NR_IRQS)) + do_bad_IRQ(cascade_irq, desc); + else + generic_handle_irq(cascade_irq); + + out: + /* primary controller unmasking */ + chip->unmask(irq); +} + +static struct irq_chip combiner_chip = { + .name = "COMBINER", + .mask = combiner_mask_irq, + .unmask = combiner_unmask_irq, +}; + +void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq) +{ + if (combiner_nr >= MAX_COMBINER_NR) + BUG(); + if (set_irq_data(irq, &combiner_data[combiner_nr]) != 0) + BUG(); + set_irq_chained_handler(irq, combiner_handle_cascade_irq); +} + +void __init combiner_init(unsigned int combiner_nr, void __iomem *base, + unsigned int irq_start) +{ + unsigned int i; + + if (combiner_nr >= MAX_COMBINER_NR) + BUG(); + + combiner_data[combiner_nr].base = base; + combiner_data[combiner_nr].irq_offset = irq_start; + + /* Disable all interrupts */ + + __raw_writel(0xffffffff, base + COMBINER_ENABLE_CLEAR); + + /* Setup the Linux IRQ subsystem */ + + for (i = irq_start; i < combiner_data[combiner_nr].irq_offset + + MAX_IRQ_IN_COMBINER; i++) { + set_irq_chip(i, &combiner_chip); + set_irq_chip_data(i, &combiner_data[combiner_nr]); + set_irq_handler(i, handle_level_irq); + set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + } +} diff --git a/arch/arm/mach-s5pv310/localtimer.c b/arch/arm/mach-s5pv310/localtimer.c new file mode 100644 index 000000000000..2784036cd8b1 --- /dev/null +++ b/arch/arm/mach-s5pv310/localtimer.c @@ -0,0 +1,25 @@ +/* linux/arch/arm/mach-s5pv310/localtimer.c + * + * Cloned from linux/arch/arm/mach-realview/localtimer.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/clockchips.h> + +#include <asm/irq.h> +#include <asm/localtimer.h> + +/* + * Setup the local clock events for a CPU. + */ +void __cpuinit local_timer_setup(struct clock_event_device *evt) +{ + evt->irq = IRQ_LOCALTIMER; + twd_timer_setup(evt); +} diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c new file mode 100644 index 000000000000..0d6ab77709d2 --- /dev/null +++ b/arch/arm/mach-s5pv310/mach-smdkv310.c @@ -0,0 +1,92 @@ +/* linux/arch/arm/mach-s5pv310/mach-smdkv310.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 <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 <mach/map.h> + +/* Following are default values for UCON, ULCON and UFCON UART registers */ +#define SMDKV310_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ + S3C2410_UCON_RXILEVEL | \ + S3C2410_UCON_TXIRQMODE | \ + S3C2410_UCON_RXIRQMODE | \ + S3C2410_UCON_RXFIFO_TOI | \ + S3C2443_UCON_RXERR_IRQEN) + +#define SMDKV310_ULCON_DEFAULT S3C2410_LCON_CS8 + +#define SMDKV310_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ + S5PV210_UFCON_TXTRIG4 | \ + S5PV210_UFCON_RXTRIG4) + +static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = SMDKV310_UCON_DEFAULT, + .ulcon = SMDKV310_ULCON_DEFAULT, + .ufcon = SMDKV310_UFCON_DEFAULT, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = SMDKV310_UCON_DEFAULT, + .ulcon = SMDKV310_ULCON_DEFAULT, + .ufcon = SMDKV310_UFCON_DEFAULT, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = SMDKV310_UCON_DEFAULT, + .ulcon = SMDKV310_ULCON_DEFAULT, + .ufcon = SMDKV310_UFCON_DEFAULT, + }, + [3] = { + .hwport = 3, + .flags = 0, + .ucon = SMDKV310_UCON_DEFAULT, + .ulcon = SMDKV310_ULCON_DEFAULT, + .ufcon = SMDKV310_UFCON_DEFAULT, + }, +}; + +static void __init smdkv310_map_io(void) +{ + s5p_init_io(NULL, 0, S5P_VA_CHIPID); + s3c24xx_init_clocks(24000000); + s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs)); +} + +static void __init smdkv310_machine_init(void) +{ +#ifdef CONFIG_CACHE_L2X0 + l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff); +#endif +} + +MACHINE_START(SMDKV310, "SMDKV310") + /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ + /* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */ + .phys_io = S3C_PA_UART & 0xfff00000, + .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, + .boot_params = S5P_PA_SDRAM + 0x100, + .init_irq = s5pv310_init_irq, + .map_io = smdkv310_map_io, + .init_machine = smdkv310_machine_init, + .timer = &s5pv310_timer, +MACHINE_END diff --git a/arch/arm/mach-s5pv310/mach-universal_c210.c b/arch/arm/mach-s5pv310/mach-universal_c210.c new file mode 100644 index 000000000000..2388cb947936 --- /dev/null +++ b/arch/arm/mach-s5pv310/mach-universal_c210.c @@ -0,0 +1,86 @@ +/* linux/arch/arm/mach-s5pv310/mach-universal_c210.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/serial_core.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 <mach/map.h> + +/* Following are default values for UCON, ULCON and UFCON UART registers */ +#define UNIVERSAL_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ + S3C2410_UCON_RXILEVEL | \ + S3C2410_UCON_TXIRQMODE | \ + S3C2410_UCON_RXIRQMODE | \ + S3C2410_UCON_RXFIFO_TOI | \ + S3C2443_UCON_RXERR_IRQEN) + +#define UNIVERSAL_ULCON_DEFAULT S3C2410_LCON_CS8 + +#define UNIVERSAL_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ + S5PV210_UFCON_TXTRIG256 | \ + S5PV210_UFCON_RXTRIG256) + +static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .ucon = UNIVERSAL_UCON_DEFAULT, + .ulcon = UNIVERSAL_ULCON_DEFAULT, + .ufcon = UNIVERSAL_UFCON_DEFAULT, + }, + [1] = { + .hwport = 1, + .ucon = UNIVERSAL_UCON_DEFAULT, + .ulcon = UNIVERSAL_ULCON_DEFAULT, + .ufcon = UNIVERSAL_UFCON_DEFAULT, + }, + [2] = { + .hwport = 2, + .ucon = UNIVERSAL_UCON_DEFAULT, + .ulcon = UNIVERSAL_ULCON_DEFAULT, + .ufcon = UNIVERSAL_UFCON_DEFAULT, + }, + [3] = { + .hwport = 3, + .ucon = UNIVERSAL_UCON_DEFAULT, + .ulcon = UNIVERSAL_ULCON_DEFAULT, + .ufcon = UNIVERSAL_UFCON_DEFAULT, + }, +}; + +static void __init universal_map_io(void) +{ + s5p_init_io(NULL, 0, S5P_VA_CHIPID); + s3c24xx_init_clocks(24000000); + s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs)); +} + +static void __init universal_machine_init(void) +{ +#ifdef CONFIG_CACHE_L2X0 + l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff); +#endif +} + +MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210") + /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */ + .phys_io = S3C_PA_UART & 0xfff00000, + .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, + .boot_params = S5P_PA_SDRAM + 0x100, + .init_irq = s5pv310_init_irq, + .map_io = universal_map_io, + .init_machine = universal_machine_init, + .timer = &s5pv310_timer, +MACHINE_END diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c new file mode 100644 index 000000000000..fe9469abd006 --- /dev/null +++ b/arch/arm/mach-s5pv310/platsmp.c @@ -0,0 +1,192 @@ +/* linux/arch/arm/mach-s5pv310/platsmp.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Cloned from linux/arch/arm/mach-vexpress/platsmp.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/init.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/jiffies.h> +#include <linux/smp.h> +#include <linux/io.h> + +#include <asm/cacheflush.h> +#include <asm/localtimer.h> +#include <asm/smp_scu.h> +#include <asm/unified.h> + +#include <mach/hardware.h> +#include <mach/regs-clock.h> + +extern void s5pv310_secondary_startup(void); + +/* + * control for which core is the next to come out of the secondary + * boot "holding pen" + */ + +volatile int __cpuinitdata pen_release = -1; + +static void __iomem *scu_base_addr(void) +{ + return (void __iomem *)(S5P_VA_SCU); +} + +static DEFINE_SPINLOCK(boot_lock); + +void __cpuinit platform_secondary_init(unsigned int cpu) +{ + trace_hardirqs_off(); + + /* + * if any interrupts are already enabled for the primary + * core (e.g. timer irq), then they will not have been enabled + * for us: do so + */ + gic_cpu_init(0, gic_cpu_base_addr); + + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + pen_release = -1; + smp_wmb(); + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * Set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * The secondary processor is waiting to be released from + * the holding pen - release it, then wait for it to flag + * that it has been released by resetting pen_release. + * + * Note that "pen_release" is the hardware CPU ID, whereas + * "cpu" is Linux's internal ID. + */ + pen_release = cpu; + __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); + outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); + + /* + * Send the secondary CPU a soft interrupt, thereby causing + * the boot monitor to read the system wide flags register, + * and branch to the address found there. + */ + smp_cross_call(cpumask_of(cpu)); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + smp_rmb(); + if (pen_release == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return pen_release != -1 ? -ENOSYS : 0; +} + +/* + * Initialise the CPU possible map early - this describes the CPUs + * which may be present or become present in the system. + */ + +void __init smp_init_cpus(void) +{ + void __iomem *scu_base = scu_base_addr(); + unsigned int i, ncores; + + ncores = scu_base ? scu_get_core_count(scu_base) : 1; + + /* sanity check */ + if (ncores == 0) { + printk(KERN_ERR + "S5PV310: strange CM count of 0? Default to 1\n"); + + ncores = 1; + } + + if (ncores > NR_CPUS) { + printk(KERN_WARNING + "S5PV310: no. of cores (%d) greater than configured " + "maximum of %d - clipping\n", + ncores, NR_CPUS); + ncores = NR_CPUS; + } + + for (i = 0; i < ncores; i++) + set_cpu_possible(i, true); +} + +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + unsigned int ncores = num_possible_cpus(); + unsigned int cpu = smp_processor_id(); + int i; + + smp_store_cpu_info(cpu); + + /* are we trying to boot more cores than exist? */ + if (max_cpus > ncores) + max_cpus = ncores; + + /* + * Initialise the present map, which describes the set of CPUs + * actually populated at the present time. + */ + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); + + /* + * Initialise the SCU if there are more than one CPU and let + * them know where to start. + */ + if (max_cpus > 1) { + /* + * Enable the local timer or broadcast device for the + * boot CPU, but only if we have more than one CPU. + */ + percpu_timer_setup(); + + scu_enable(scu_base_addr()); + + /* + * Write the address of secondary startup into the + * system-wide flags register. The boot monitor waits + * until it receives a soft interrupt, and then the + * secondary CPU branches to this address. + */ + __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_INFORM0); + } +} diff --git a/arch/arm/mach-s5pv310/setup-i2c0.c b/arch/arm/mach-s5pv310/setup-i2c0.c new file mode 100644 index 000000000000..436712807383 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c0.c @@ -0,0 +1,28 @@ +/* + * linux/arch/arm/mach-s5pv310/setup-i2c0.c + * + * Copyright (c) 2009-2010 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. +*/ + +struct platform_device; /* don't need the contents */ + +#include <linux/gpio.h> +#include <plat/iic.h> +#include <plat/gpio-cfg.h> + +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); +} diff --git a/arch/arm/mach-s5pv310/setup-i2c1.c b/arch/arm/mach-s5pv310/setup-i2c1.c new file mode 100644 index 000000000000..1ecd5bc35b5a --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c1.c @@ -0,0 +1,25 @@ +/* + * linux/arch/arm/mach-s5pv310/setup-i2c1.c + * + * Copyright (C) 2010 Samsung Electronics Co., Ltd. + * + * I2C1 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_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); +} diff --git a/arch/arm/mach-s5pv310/setup-i2c2.c b/arch/arm/mach-s5pv310/setup-i2c2.c new file mode 100644 index 000000000000..4c0d8def660a --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c2.c @@ -0,0 +1,25 @@ +/* + * linux/arch/arm/mach-s5pv310/setup-i2c2.c + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * + * I2C2 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_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); +} diff --git a/arch/arm/mach-s5pv310/time.c b/arch/arm/mach-s5pv310/time.c new file mode 100644 index 000000000000..01b012ad1bfd --- /dev/null +++ b/arch/arm/mach-s5pv310/time.c @@ -0,0 +1,287 @@ +/* linux/arch/arm/mach-s5pv310/time.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5PV310 (and compatible) HRT support + * PWM 2/4 is used for this feature + * + * 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/sched.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/clockchips.h> +#include <linux/platform_device.h> + +#include <asm/smp_twd.h> + +#include <mach/map.h> +#include <plat/regs-timer.h> +#include <asm/mach/time.h> + +static unsigned long clock_count_per_tick; + +static struct clk *tin2; +static struct clk *tin4; +static struct clk *tdiv2; +static struct clk *tdiv4; +static struct clk *timerclk; + +static void s5pv310_pwm_stop(unsigned int pwm_id) +{ + unsigned long tcon; + + tcon = __raw_readl(S3C2410_TCON); + + switch (pwm_id) { + case 2: + tcon &= ~S3C2410_TCON_T2START; + break; + case 4: + tcon &= ~S3C2410_TCON_T4START; + break; + default: + break; + } + __raw_writel(tcon, S3C2410_TCON); +} + +static void s5pv310_pwm_init(unsigned int pwm_id, unsigned long tcnt) +{ + unsigned long tcon; + + tcon = __raw_readl(S3C2410_TCON); + + /* timers reload after counting zero, so reduce the count by 1 */ + tcnt--; + + /* ensure timer is stopped... */ + switch (pwm_id) { + case 2: + tcon &= ~(0xf<<12); + tcon |= S3C2410_TCON_T2MANUALUPD; + + __raw_writel(tcnt, S3C2410_TCNTB(2)); + __raw_writel(tcnt, S3C2410_TCMPB(2)); + __raw_writel(tcon, S3C2410_TCON); + + break; + case 4: + tcon &= ~(7<<20); + tcon |= S3C2410_TCON_T4MANUALUPD; + + __raw_writel(tcnt, S3C2410_TCNTB(4)); + __raw_writel(tcnt, S3C2410_TCMPB(4)); + __raw_writel(tcon, S3C2410_TCON); + + break; + default: + break; + } +} + +static inline void s5pv310_pwm_start(unsigned int pwm_id, bool periodic) +{ + unsigned long tcon; + + tcon = __raw_readl(S3C2410_TCON); + + switch (pwm_id) { + case 2: + tcon |= S3C2410_TCON_T2START; + tcon &= ~S3C2410_TCON_T2MANUALUPD; + + if (periodic) + tcon |= S3C2410_TCON_T2RELOAD; + else + tcon &= ~S3C2410_TCON_T2RELOAD; + break; + case 4: + tcon |= S3C2410_TCON_T4START; + tcon &= ~S3C2410_TCON_T4MANUALUPD; + + if (periodic) + tcon |= S3C2410_TCON_T4RELOAD; + else + tcon &= ~S3C2410_TCON_T4RELOAD; + break; + default: + break; + } + __raw_writel(tcon, S3C2410_TCON); +} + +static int s5pv310_pwm_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + s5pv310_pwm_init(2, cycles); + s5pv310_pwm_start(2, 0); + return 0; +} + +static void s5pv310_pwm_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + s5pv310_pwm_stop(2); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + s5pv310_pwm_init(2, clock_count_per_tick); + s5pv310_pwm_start(2, 1); + break; + case CLOCK_EVT_MODE_ONESHOT: + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + break; + } +} + +static struct clock_event_device pwm_event_device = { + .name = "pwm_timer2", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .shift = 32, + .set_next_event = s5pv310_pwm_set_next_event, + .set_mode = s5pv310_pwm_set_mode, +}; + +irqreturn_t s5pv310_clock_event_isr(int irq, void *dev_id) +{ + struct clock_event_device *evt = &pwm_event_device; + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction s5pv310_clock_event_irq = { + .name = "pwm_timer2_irq", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = s5pv310_clock_event_isr, +}; + +static void __init s5pv310_clockevent_init(void) +{ + unsigned long pclk; + unsigned long clock_rate; + struct clk *tscaler; + + pclk = clk_get_rate(timerclk); + + /* configure clock tick */ + + tscaler = clk_get_parent(tdiv2); + + clk_set_rate(tscaler, pclk / 2); + clk_set_rate(tdiv2, pclk / 2); + clk_set_parent(tin2, tdiv2); + + clock_rate = clk_get_rate(tin2); + + clock_count_per_tick = clock_rate / HZ; + + pwm_event_device.mult = + div_sc(clock_rate, NSEC_PER_SEC, pwm_event_device.shift); + pwm_event_device.max_delta_ns = + clockevent_delta2ns(-1, &pwm_event_device); + pwm_event_device.min_delta_ns = + clockevent_delta2ns(1, &pwm_event_device); + + pwm_event_device.cpumask = cpumask_of(0); + clockevents_register_device(&pwm_event_device); + + setup_irq(IRQ_TIMER2, &s5pv310_clock_event_irq); +} + +static cycle_t s5pv310_pwm4_read(struct clocksource *cs) +{ + return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40)); +} + +struct clocksource pwm_clocksource = { + .name = "pwm_timer4", + .rating = 250, + .read = s5pv310_pwm4_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 20, + .flags = CLOCK_SOURCE_IS_CONTINUOUS , +}; + +static void __init s5pv310_clocksource_init(void) +{ + unsigned long pclk; + unsigned long clock_rate; + + pclk = clk_get_rate(timerclk); + + clk_set_rate(tdiv4, pclk / 2); + clk_set_parent(tin4, tdiv4); + + clock_rate = clk_get_rate(tin4); + + s5pv310_pwm_init(4, ~0); + s5pv310_pwm_start(4, 1); + + pwm_clocksource.mult = + clocksource_khz2mult(clock_rate/1000, pwm_clocksource.shift); + + if (clocksource_register(&pwm_clocksource)) + panic("%s: can't register clocksource\n", pwm_clocksource.name); +} + +static void __init s5pv310_timer_resources(void) +{ + struct platform_device tmpdev; + + tmpdev.dev.bus = &platform_bus_type; + + timerclk = clk_get(NULL, "timers"); + if (IS_ERR(timerclk)) + panic("failed to get timers clock for system timer"); + + clk_enable(timerclk); + + tmpdev.id = 2; + tin2 = clk_get(&tmpdev.dev, "pwm-tin"); + if (IS_ERR(tin2)) + panic("failed to get pwm-tin2 clock for system timer"); + + tdiv2 = clk_get(&tmpdev.dev, "pwm-tdiv"); + if (IS_ERR(tdiv2)) + panic("failed to get pwm-tdiv2 clock for system timer"); + clk_enable(tin2); + + tmpdev.id = 4; + tin4 = clk_get(&tmpdev.dev, "pwm-tin"); + if (IS_ERR(tin4)) + panic("failed to get pwm-tin4 clock for system timer"); + + tdiv4 = clk_get(&tmpdev.dev, "pwm-tdiv"); + if (IS_ERR(tdiv4)) + panic("failed to get pwm-tdiv4 clock for system timer"); + + clk_enable(tin4); +} + +static void __init s5pv310_timer_init(void) +{ +#ifdef CONFIG_LOCAL_TIMERS + twd_base = S5P_VA_TWD; +#endif + + s5pv310_timer_resources(); + s5pv310_clockevent_init(); + s5pv310_clocksource_init(); +} + +struct sys_timer s5pv310_timer = { + .init = s5pv310_timer_init, +}; diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 101105e52610..9ca76bfe471c 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -782,7 +782,8 @@ config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \ - ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 + ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \ + ARCH_S5PV310 default y select OUTER_CACHE select OUTER_CACHE_SYNC diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 11d6a1bbd90d..907ac6312a1d 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -7,9 +7,10 @@ config PLAT_S5P bool - depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210) + depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310) default y - select ARM_VIC + select ARM_VIC if !ARCH_S5PV310 + select ARM_GIC if ARCH_S5PV310 select NO_IOPORT select ARCH_REQUIRE_GPIOLIB select S3C_GPIO_TRACK diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 8e18b5123dd7..b2e029673950 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -12,6 +12,7 @@ obj- := # Core files +obj-y += dev-pmu.o obj-y += dev-uart.o obj-y += cpu.o obj-y += clock.o diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c index 75cb8c37ca2c..b07a078fd284 100644 --- a/arch/arm/plat-s5p/cpu.c +++ b/arch/arm/plat-s5p/cpu.c @@ -21,6 +21,7 @@ #include <plat/s5p6442.h> #include <plat/s5pc100.h> #include <plat/s5pv210.h> +#include <plat/s5pv310.h> /* table of supported CPUs */ @@ -28,6 +29,7 @@ static const char name_s5p6440[] = "S5P6440"; static const char name_s5p6442[] = "S5P6442"; static const char name_s5pc100[] = "S5PC100"; static const char name_s5pv210[] = "S5PV210/S5PC110"; +static const char name_s5pv310[] = "S5PV310"; static struct cpu_table cpu_ids[] __initdata = { { @@ -62,6 +64,14 @@ static struct cpu_table cpu_ids[] __initdata = { .init_uarts = s5pv210_init_uarts, .init = s5pv210_init, .name = name_s5pv210, + }, { + .idcode = 0x43200000, + .idmask = 0xfffff000, + .map_io = s5pv310_map_io, + .init_clocks = s5pv310_init_clocks, + .init_uarts = s5pv310_init_uarts, + .init = s5pv310_init, + .name = name_s5pv310, }, }; @@ -81,8 +91,9 @@ static struct map_desc s5p_iodesc[] __initdata = { }, { .virtual = (unsigned long)S3C_VA_UART, .pfn = __phys_to_pfn(S3C_PA_UART), - .length = SZ_4K, + .length = SZ_512K, .type = MT_DEVICE, +#ifdef CONFIG_ARM_VIC }, { .virtual = (unsigned long)VA_VIC0, .pfn = __phys_to_pfn(S5P_PA_VIC0), @@ -93,6 +104,7 @@ static struct map_desc s5p_iodesc[] __initdata = { .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), @@ -103,6 +115,11 @@ static struct map_desc s5p_iodesc[] __initdata = { .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, + .type = MT_DEVICE, }, }; diff --git a/arch/arm/plat-s5p/dev-pmu.c b/arch/arm/plat-s5p/dev-pmu.c new file mode 100644 index 000000000000..a08576da72b0 --- /dev/null +++ b/arch/arm/plat-s5p/dev-pmu.c @@ -0,0 +1,36 @@ +/* + * linux/arch/arm/plat-s5p/dev-pmu.c + * + * Copyright (C) 2010 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim <jy0922.shim@samsung.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/platform_device.h> +#include <asm/pmu.h> +#include <mach/irqs.h> + +static struct resource s5p_pmu_resource = { + .start = IRQ_PMU, + .end = IRQ_PMU, + .flags = IORESOURCE_IRQ, +}; + +struct platform_device s5p_device_pmu = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = 1, + .resource = &s5p_pmu_resource, +}; + +static int __init s5p_pmu_init(void) +{ + platform_device_register(&s5p_device_pmu); + return 0; +} +arch_initcall(s5p_pmu_init); diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h index 14828521f70c..54e9fb9d315e 100644 --- a/arch/arm/plat-s5p/include/plat/map-s5p.h +++ b/arch/arm/plat-s5p/include/plat/map-s5p.h @@ -18,12 +18,27 @@ #define S5P_VA_SYSTIMER S3C_ADDR(0x01200000) #define S5P_VA_SROMC S3C_ADDR(0x01100000) -#define S5P_VA_UART0 (S3C_VA_UART + 0x0) -#define S5P_VA_UART1 (S3C_VA_UART + 0x400) -#define S5P_VA_UART2 (S3C_VA_UART + 0x800) -#define S5P_VA_UART3 (S3C_VA_UART + 0xC00) +#define S5P_VA_COMBINER_BASE S3C_ADDR(0x00600000) +#define S5P_VA_COMBINER(x) (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10) +#define S5P_VA_COREPERI_BASE S3C_ADDR(0x00800000) +#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_UART(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) +#define S5P_VA_UART0 S5P_VA_UART(0) +#define S5P_VA_UART1 S5P_VA_UART(1) +#define S5P_VA_UART2 S5P_VA_UART(2) +#define S5P_VA_UART3 S5P_VA_UART(3) + +#ifndef S3C_UART_OFFSET #define S3C_UART_OFFSET (0x400) +#endif #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) #define VA_VIC0 VA_VIC(0) diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h index 7db322726bc2..4e8fe08cb70d 100644 --- a/arch/arm/plat-s5p/include/plat/pll.h +++ b/arch/arm/plat-s5p/include/plat/pll.h @@ -46,6 +46,47 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con, return (unsigned long)fvco; } +#define PLL46XX_KDIV_MASK (0xFFFF) +#define PLL46XX_MDIV_MASK (0x1FF) +#define PLL46XX_PDIV_MASK (0x3F) +#define PLL46XX_SDIV_MASK (0x7) +#define PLL46XX_MDIV_SHIFT (16) +#define PLL46XX_PDIV_SHIFT (8) +#define PLL46XX_SDIV_SHIFT (0) + +enum pll46xx_type_t { + pll_4600, + pll_4650, +}; + +static inline unsigned long s5p_get_pll46xx(unsigned long baseclk, + u32 pll_con0, u32 pll_con1, + enum pll46xx_type_t pll_type) +{ + unsigned long result; + u32 mdiv, pdiv, sdiv, kdiv; + u64 tmp; + + mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK; + pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK; + sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK; + kdiv = pll_con1 & PLL46XX_KDIV_MASK; + + tmp = baseclk; + + if (pll_type == pll_4600) { + tmp *= (mdiv << 16) + kdiv; + do_div(tmp, (pdiv << sdiv)); + result = tmp >> 16; + } else { + tmp *= (mdiv << 10) + kdiv; + do_div(tmp, (pdiv << sdiv)); + result = tmp >> 10; + } + + return result; +} + #define PLL90XX_MDIV_MASK (0xFF) #define PLL90XX_PDIV_MASK (0x3F) #define PLL90XX_SDIV_MASK (0x7) diff --git a/arch/arm/plat-s5p/include/plat/reset.h b/arch/arm/plat-s5p/include/plat/reset.h new file mode 100644 index 000000000000..335e97812eed --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/reset.h @@ -0,0 +1,16 @@ +/* linux/arch/arm/plat-s5p/include/plat/reset.h + * + * 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. +*/ + +#ifndef __ASM_PLAT_S5P_RESET_H +#define __ASM_PLAT_S5P_RESET_H __FILE__ + +extern void (*s5p_reset_hook)(void); + +#endif /* __ASM_PLAT_S5P_RESET_H */ diff --git a/arch/arm/plat-s5p/include/plat/s5pv310.h b/arch/arm/plat-s5p/include/plat/s5pv310.h new file mode 100644 index 000000000000..769c991ceb37 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/s5pv310.h @@ -0,0 +1,34 @@ +/* linux/arch/arm/plat-s5p/include/plat/s5pv310.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Header file for s5pv310 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 S5PV310 related SoCs */ + +extern void s5pv310_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); +extern void s5pv310_register_clocks(void); +extern void s5pv310_setup_clocks(void); + +#ifdef CONFIG_CPU_S5PV310 + +extern int s5pv310_init(void); +extern void s5pv310_init_irq(void); +extern void s5pv310_map_io(void); +extern void s5pv310_init_clocks(int xtal); +extern struct sys_timer s5pv310_timer; + +#define s5pv310_init_uarts s5pv310_common_init_uarts + +#else +#define s5pv310_init_clocks NULL +#define s5pv310_init_uarts NULL +#define s5pv310_map_io NULL +#define s5pv310_init NULL +#endif diff --git a/arch/arm/plat-s5p/include/plat/system-reset.h b/arch/arm/plat-s5p/include/plat/system-reset.h new file mode 100644 index 000000000000..f307f34e6422 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/system-reset.h @@ -0,0 +1,31 @@ +/* linux/arch/arm/plat-s5p/include/plat/system-reset.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Based on arch/arm/mach-s3c2410/include/mach/system-reset.h + * + * S5P - System define for arch_reset() + * + * 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 <plat/watchdog-reset.h> + +void (*s5p_reset_hook)(void); + +static void arch_reset(char mode, const char *cmd) +{ + /* SWRESET support in s5p_reset_hook() */ + + if (s5p_reset_hook) + s5p_reset_hook(); + + /* Perform reset using Watchdog reset + * if there is no s5p_reset_hook() + */ + + arch_wdt_reset(); +} diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c index 25e1eb6de59e..5560b12035d1 100644 --- a/arch/arm/plat-s5p/irq.c +++ b/arch/arm/plat-s5p/irq.c @@ -56,11 +56,13 @@ static struct s3c_uart_irq uart_irqs[] = { void __init s5p_init_irq(u32 *vic, u32 num_vic) { +#ifdef CONFIG_ARM_VIC int irq; /* initialize the VICs */ for (irq = 0; irq < num_vic; irq++) vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0); +#endif s3c_init_vic_timer_irq(IRQ_TIMER0_VIC, IRQ_TIMER0); s3c_init_vic_timer_irq(IRQ_TIMER1_VIC, IRQ_TIMER1); diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 8594fe73b6d1..4d8ff923207a 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -12,7 +12,7 @@ obj- := # Objects we always build independent of SoC choice obj-y += init.o -obj-y += time.o +obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET) += time.o obj-y += clock.o obj-y += pwm-clock.o obj-y += gpio.o diff --git a/arch/arm/plat-samsung/include/plat/keypad-core.h b/arch/arm/plat-samsung/include/plat/keypad-core.h new file mode 100644 index 000000000000..d513e1b3a31e --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/keypad-core.h @@ -0,0 +1,31 @@ +/* + * linux/arch/arm/plat-samsung/include/plat/keypad-core.h + * + * Copyright (C) 2010 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim <jy0922.shim@samsung.com> + * + * Samsung keypad controller core function + * + * 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. + * + */ + +#ifndef __ASM_ARCH_KEYPAD_CORE_H +#define __ASM_ARCH_KEYPAD_CORE_H + +/* These function are only for use with the core support code, such as + * the cpu specific initialisation code + */ + +/* re-define device name depending on support. */ +static inline void samsung_keypad_setname(char *name) +{ +#ifdef CONFIG_SAMSUNG_DEV_KEYPAD + samsung_device_keypad.name = name; +#endif +} + +#endif /* __ASM_ARCH_KEYPAD_CORE_H */ diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h index a6eba8496b24..788837e99cb3 100644 --- a/arch/arm/plat-samsung/include/plat/regs-serial.h +++ b/arch/arm/plat-samsung/include/plat/regs-serial.h @@ -259,6 +259,8 @@ struct s3c2410_uartcfg { unsigned short flags; upf_t uart_flags; /* default uart flags */ + unsigned int has_fracval; + unsigned long ucon; /* value of ucon for port */ unsigned long ulcon; /* value of ulcon for port */ unsigned long ufcon; /* value of ufcon for port */ diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h index 44018111a981..30844c263d03 100644 --- a/arch/arm/plat-samsung/include/plat/sdhci.h +++ b/arch/arm/plat-samsung/include/plat/sdhci.h @@ -109,6 +109,7 @@ extern void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *, int w); 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); /* S3C64XX SDHCI setup */ @@ -270,10 +271,20 @@ static inline void s5pv210_default_sdhci2(void) #endif } +static inline void s5pv210_default_sdhci3(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC3 + s3c_hsmmc3_def_platdata.clocks = s5pv210_hsmmc_clksrcs; + s3c_hsmmc3_def_platdata.cfg_gpio = s5pv210_setup_sdhci3_cfg_gpio; + s3c_hsmmc3_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card; +#endif +} + #else static inline void s5pv210_default_sdhci0(void) { } static inline void s5pv210_default_sdhci1(void) { } static inline void s5pv210_default_sdhci2(void) { } +static inline void s5pv210_default_sdhci3(void) { } #endif /* CONFIG_S5PV210_SETUP_SDHCI */ diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 8b23165bc5dc..aa220108cece 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -544,8 +544,8 @@ config SERIAL_S3C6400 config SERIAL_S5PV210 tristate "Samsung S5PV210 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442) - select SERIAL_SAMSUNG_UARTS_4 if CPU_S5PV210 + depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_S5PV310) + select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_S5PV310) default y help Serial port support for Samsung's S5P Family of SoC's diff --git a/drivers/serial/s5pv210.c b/drivers/serial/s5pv210.c index 4a789e5361a4..6ebccd70a707 100644 --- a/drivers/serial/s5pv210.c +++ b/drivers/serial/s5pv210.c @@ -28,8 +28,12 @@ static int s5pv210_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *clk) { + struct s3c2410_uartcfg *cfg = port->dev->platform_data; unsigned long ucon = rd_regl(port, S3C2410_UCON); + if ((cfg->clocks_size) == 1) + return 0; + if (strcmp(clk->name, "pclk") == 0) ucon &= ~S5PV210_UCON_CLKMASK; else if (strcmp(clk->name, "uclk1") == 0) @@ -47,10 +51,14 @@ static int s5pv210_serial_setsource(struct uart_port *port, static int s5pv210_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *clk) { + struct s3c2410_uartcfg *cfg = port->dev->platform_data; u32 ucon = rd_regl(port, S3C2410_UCON); clk->divisor = 1; + if ((cfg->clocks_size) == 1) + return 0; + switch (ucon & S5PV210_UCON_CLKMASK) { case S5PV210_UCON_PCLK: clk->name = "pclk"; diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index a9d6c5626a0a..b1156ba8ad14 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -705,8 +705,13 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, if (ourport->info->has_divslot) { unsigned int div = ourport->baudclk_rate / baud; - udivslot = udivslot_table[div & 15]; - dbg("udivslot = %04x (div %d)\n", udivslot, div & 15); + if (cfg->has_fracval) { + udivslot = (div & 15); + dbg("fracval = %04x\n", udivslot); + } else { + udivslot = udivslot_table[div & 15]; + dbg("udivslot = %04x (div %d)\n", udivslot, div & 15); + } } switch (termios->c_cflag & CSIZE) { |