summaryrefslogtreecommitdiff
path: root/arch/arm/mach-s5pv210
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-s5pv210')
-rw-r--r--arch/arm/mach-s5pv210/Kconfig37
-rw-r--r--arch/arm/mach-s5pv210/Makefile3
-rw-r--r--arch/arm/mach-s5pv210/clock.c207
-rw-r--r--arch/arm/mach-s5pv210/cpu.c15
-rw-r--r--arch/arm/mach-s5pv210/cpufreq.c484
-rw-r--r--arch/arm/mach-s5pv210/dev-audio.c86
-rw-r--r--arch/arm/mach-s5pv210/dev-spi.c19
-rw-r--r--arch/arm/mach-s5pv210/dma.c4
-rw-r--r--arch/arm/mach-s5pv210/gpiolib.c14
-rw-r--r--arch/arm/mach-s5pv210/include/mach/irqs.h12
-rw-r--r--arch/arm/mach-s5pv210/include/mach/map.h12
-rw-r--r--arch/arm/mach-s5pv210/include/mach/pm-core.h43
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-clock.h39
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-gpio.h7
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-sys.h19
-rw-r--r--arch/arm/mach-s5pv210/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-s5pv210/mach-aquila.c169
-rw-r--r--arch/arm/mach-s5pv210/mach-goni.c381
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkc110.c4
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkv210.c4
-rw-r--r--arch/arm/mach-s5pv210/mach-torbreck.c131
-rw-r--r--arch/arm/mach-s5pv210/pm.c166
-rw-r--r--arch/arm/mach-s5pv210/setup-fb-24bpp.c34
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c0.c6
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c1.c6
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c2.c6
-rw-r--r--arch/arm/mach-s5pv210/setup-ide.c49
-rw-r--r--arch/arm/mach-s5pv210/setup-keypad.c14
-rw-r--r--arch/arm/mach-s5pv210/setup-sdhci-gpio.c57
-rw-r--r--arch/arm/mach-s5pv210/sleep.S170
30 files changed, 1986 insertions, 214 deletions
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 5315fec3db8..862f239a0fd 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -11,9 +11,9 @@ if ARCH_S5PV210
config CPU_S5PV210
bool
- select PLAT_S5P
select S3C_PL330_DMA
select S5P_EXT_INT
+ select S5PV210_PM if PM
help
Enable S5PV210 CPU support
@@ -58,7 +58,6 @@ menu "S5PC110 Machines"
config MACH_AQUILA
bool "Aquila"
select CPU_S5PV210
- select ARCH_SPARSEMEM_ENABLE
select S3C_DEV_FB
select S5P_DEV_FIMC0
select S5P_DEV_FIMC1
@@ -75,7 +74,7 @@ config MACH_AQUILA
config MACH_GONI
bool "GONI"
select CPU_S5PV210
- select ARCH_SPARSEMEM_ENABLE
+ select S5P_GPIO_INT
select S3C_DEV_FB
select S5P_DEV_FIMC0
select S5P_DEV_FIMC1
@@ -83,8 +82,15 @@ config MACH_GONI
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
+ select S3C_DEV_I2C1
+ select S3C_DEV_I2C2
+ select S3C_DEV_USB_HSOTG
select S5P_DEV_ONENAND
+ select SAMSUNG_DEV_KEYPAD
select S5PV210_SETUP_FB_24BPP
+ select S5PV210_SETUP_I2C1
+ select S5PV210_SETUP_I2C2
+ select S5PV210_SETUP_KEYPAD
select S5PV210_SETUP_SDHCI
help
Machine support for Samsung GONI board
@@ -93,7 +99,6 @@ config MACH_GONI
config MACH_SMDKC110
bool "SMDKC110"
select CPU_S5PV210
- select ARCH_SPARSEMEM_ENABLE
select S3C_DEV_I2C1
select S3C_DEV_I2C2
select S3C_DEV_RTC
@@ -113,7 +118,6 @@ menu "S5PV210 Machines"
config MACH_SMDKV210
bool "SMDKV210"
select CPU_S5PV210
- select ARCH_SPARSEMEM_ENABLE
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
@@ -134,6 +138,29 @@ config MACH_SMDKV210
help
Machine support for Samsung SMDKV210
+config MACH_TORBRECK
+ bool "Torbreck"
+ select CPU_S5PV210
+ select ARCH_SPARSEMEM_ENABLE
+ select S3C_DEV_HSMMC
+ select S3C_DEV_HSMMC1
+ select S3C_DEV_HSMMC2
+ select S3C_DEV_HSMMC3
+ select S3C_DEV_I2C1
+ select S3C_DEV_I2C2
+ select S3C_DEV_RTC
+ select S3C_DEV_WDT
+ select S5PV210_SETUP_I2C1
+ select S5PV210_SETUP_I2C2
+ select S5PV210_SETUP_SDHCI
+ help
+ Machine support for aESOP Torbreck
+
endmenu
+config S5PV210_PM
+ bool
+ help
+ Power Management code common to S5PV210
+
endif
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 70454891240..ff1a0db57a2 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -14,6 +14,8 @@ obj- :=
obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o gpiolib.o
obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o
+obj-$(CONFIG_S5PV210_PM) += pm.o sleep.o
+obj-$(CONFIG_CPU_FREQ) += cpufreq.o
# machine support
@@ -21,6 +23,7 @@ obj-$(CONFIG_MACH_AQUILA) += mach-aquila.o
obj-$(CONFIG_MACH_SMDKV210) += mach-smdkv210.o
obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o
obj-$(CONFIG_MACH_GONI) += mach-goni.o
+obj-$(CONFIG_MACH_TORBRECK) += mach-torbreck.o
# device support
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index d562670e1b0..019c3a69b0e 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -31,6 +31,8 @@
#include <plat/clock-clksrc.h>
#include <plat/s5pv210.h>
+static unsigned long xtal;
+
static struct clksrc_clk clk_mout_apll = {
.clk = {
.name = "mout_apll",
@@ -259,6 +261,36 @@ static struct clksrc_clk clk_sclk_vpll = {
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
};
+static struct clk *clkset_moutdmc0src_list[] = {
+ [0] = &clk_sclk_a2m.clk,
+ [1] = &clk_mout_mpll.clk,
+ [2] = NULL,
+ [3] = NULL,
+};
+
+static struct clksrc_sources clkset_moutdmc0src = {
+ .sources = clkset_moutdmc0src_list,
+ .nr_sources = ARRAY_SIZE(clkset_moutdmc0src_list),
+};
+
+static struct clksrc_clk clk_mout_dmc0 = {
+ .clk = {
+ .name = "mout_dmc0",
+ .id = -1,
+ },
+ .sources = &clkset_moutdmc0src,
+ .reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
+};
+
+static struct clksrc_clk clk_sclk_dmc0 = {
+ .clk = {
+ .name = "sclk_dmc0",
+ .id = -1,
+ .parent = &clk_mout_dmc0.clk,
+ },
+ .reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
+};
+
static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 2;
@@ -268,8 +300,29 @@ static struct clk_ops clk_hclk_imem_ops = {
.get_rate = s5pv210_clk_imem_get_rate,
};
+static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk *clk)
+{
+ return s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
+}
+
+static struct clk_ops clk_fout_apll_ops = {
+ .get_rate = s5pv210_clk_fout_apll_get_rate,
+};
+
static struct clk init_clocks_disable[] = {
{
+ .name = "pdma",
+ .id = 0,
+ .parent = &clk_hclk_psys.clk,
+ .enable = s5pv210_clk_ip0_ctrl,
+ .ctrlbit = (1 << 3),
+ }, {
+ .name = "pdma",
+ .id = 1,
+ .parent = &clk_hclk_psys.clk,
+ .enable = s5pv210_clk_ip0_ctrl,
+ .ctrlbit = (1 << 4),
+ }, {
.name = "rot",
.id = -1,
.parent = &clk_hclk_dsys.clk,
@@ -431,6 +484,12 @@ static struct clk init_clocks_disable[] = {
.parent = &clk_p,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 6),
+ }, {
+ .name = "spdif",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1 << 0),
},
};
@@ -660,6 +719,53 @@ static struct clksrc_sources clkset_sclk_spdif = {
.nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list),
};
+static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk *pclk;
+ int ret;
+
+ pclk = clk_get_parent(clk);
+ if (IS_ERR(pclk))
+ return -EINVAL;
+
+ ret = pclk->ops->set_rate(pclk, rate);
+ clk_put(pclk);
+
+ return ret;
+}
+
+static unsigned long s5pv210_spdif_get_rate(struct clk *clk)
+{
+ struct clk *pclk;
+ int rate;
+
+ pclk = clk_get_parent(clk);
+ if (IS_ERR(pclk))
+ return -EINVAL;
+
+ rate = pclk->ops->get_rate(clk);
+ clk_put(pclk);
+
+ return rate;
+}
+
+static struct clk_ops s5pv210_sclk_spdif_ops = {
+ .set_rate = s5pv210_spdif_set_rate,
+ .get_rate = s5pv210_spdif_get_rate,
+};
+
+static struct clksrc_clk clk_sclk_spdif = {
+ .clk = {
+ .name = "sclk_spdif",
+ .id = -1,
+ .enable = s5pv210_clk_mask0_ctrl,
+ .ctrlbit = (1 << 27),
+ .ops = &s5pv210_sclk_spdif_ops,
+ },
+ .sources = &clkset_sclk_spdif,
+ .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
+};
+
static struct clk *clkset_group2_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_xusbxti,
@@ -744,15 +850,6 @@ static struct clksrc_clk clksrcs[] = {
.sources = &clkset_sclk_mixer,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
}, {
- .clk = {
- .name = "sclk_spdif",
- .id = -1,
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 27),
- },
- .sources = &clkset_sclk_spdif,
- .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
- }, {
.clk = {
.name = "sclk_fimc",
.id = 0,
@@ -953,12 +1050,93 @@ static struct clksrc_clk *sysclks[] = {
&clk_sclk_dac,
&clk_sclk_pixel,
&clk_sclk_hdmi,
+ &clk_mout_dmc0,
+ &clk_sclk_dmc0,
+ &clk_sclk_audio0,
+ &clk_sclk_audio1,
+ &clk_sclk_audio2,
+ &clk_sclk_spdif,
+};
+
+static u32 epll_div[][6] = {
+ { 48000000, 0, 48, 3, 3, 0 },
+ { 96000000, 0, 48, 3, 2, 0 },
+ { 144000000, 1, 72, 3, 2, 0 },
+ { 192000000, 0, 48, 3, 1, 0 },
+ { 288000000, 1, 72, 3, 1, 0 },
+ { 32750000, 1, 65, 3, 4, 35127 },
+ { 32768000, 1, 65, 3, 4, 35127 },
+ { 45158400, 0, 45, 3, 3, 10355 },
+ { 45000000, 0, 45, 3, 3, 10355 },
+ { 45158000, 0, 45, 3, 3, 10355 },
+ { 49125000, 0, 49, 3, 3, 9961 },
+ { 49152000, 0, 49, 3, 3, 9961 },
+ { 67737600, 1, 67, 3, 3, 48366 },
+ { 67738000, 1, 67, 3, 3, 48366 },
+ { 73800000, 1, 73, 3, 3, 47710 },
+ { 73728000, 1, 73, 3, 3, 47710 },
+ { 36000000, 1, 32, 3, 4, 0 },
+ { 60000000, 1, 60, 3, 3, 0 },
+ { 72000000, 1, 72, 3, 3, 0 },
+ { 80000000, 1, 80, 3, 3, 0 },
+ { 84000000, 0, 42, 3, 2, 0 },
+ { 50000000, 0, 50, 3, 3, 0 },
+};
+
+static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int epll_con, epll_con_k;
+ unsigned int i;
+
+ /* Return if nothing changed */
+ if (clk->rate == rate)
+ return 0;
+
+ epll_con = __raw_readl(S5P_EPLL_CON);
+ epll_con_k = __raw_readl(S5P_EPLL_CON1);
+
+ epll_con_k &= ~PLL46XX_KDIV_MASK;
+ epll_con &= ~(1 << 27 |
+ PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |
+ PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |
+ PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+ for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
+ if (epll_div[i][0] == rate) {
+ epll_con_k |= epll_div[i][5] << 0;
+ epll_con |= (epll_div[i][1] << 27 |
+ epll_div[i][2] << PLL46XX_MDIV_SHIFT |
+ epll_div[i][3] << PLL46XX_PDIV_SHIFT |
+ epll_div[i][4] << PLL46XX_SDIV_SHIFT);
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(epll_div)) {
+ printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ __raw_writel(epll_con, S5P_EPLL_CON);
+ __raw_writel(epll_con_k, S5P_EPLL_CON1);
+
+ printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
+ clk->rate, rate);
+
+ clk->rate = rate;
+
+ return 0;
+}
+
+static struct clk_ops s5pv210_epll_ops = {
+ .set_rate = s5pv210_epll_set_rate,
+ .get_rate = s5p_epll_get_rate,
};
void __init_or_cpufreq s5pv210_setup_clocks(void)
{
struct clk *xtal_clk;
- unsigned long xtal;
unsigned long vpllsrc;
unsigned long armclk;
unsigned long hclk_msys;
@@ -974,6 +1152,10 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
unsigned int ptr;
u32 clkdiv0, clkdiv1;
+ /* Set functions for clk_fout_epll */
+ clk_fout_epll.enable = s5p_epll_enable;
+ clk_fout_epll.ops = &s5pv210_epll_ops;
+
printk(KERN_DEBUG "%s: registering clocks\n", __func__);
clkdiv0 = __raw_readl(S5P_CLK_DIV0);
@@ -992,11 +1174,12 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
- epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500);
+ epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON),
+ __raw_readl(S5P_EPLL_CON1), pll_4600);
vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502);
- clk_fout_apll.rate = apll;
+ clk_fout_apll.ops = &clk_fout_apll_ops;
clk_fout_mpll.rate = mpll;
clk_fout_epll.rate = epll;
clk_fout_vpll.rate = vpll;
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 2f16bfc0a11..8eb480e201b 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -85,6 +85,21 @@ static struct map_desc s5pv210_iodesc[] __initdata = {
.pfn = __phys_to_pfn(S5PV210_PA_SROMC),
.length = SZ_4K,
.type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_DMC0,
+ .pfn = __phys_to_pfn(S5PV210_PA_DMC0),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_DMC1,
+ .pfn = __phys_to_pfn(S5PV210_PA_DMC1),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S3C_VA_USB_HSPHY,
+ .pfn =__phys_to_pfn(S5PV210_PA_HSPHY),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
}
};
diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c
new file mode 100644
index 00000000000..a6f22920a2c
--- /dev/null
+++ b/arch/arm/mach-s5pv210/cpufreq.c
@@ -0,0 +1,484 @@
+/* linux/arch/arm/mach-s5pv210/cpufreq.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * CPU frequency scaling for S5PC110/S5PV210
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/cpufreq.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+static struct clk *cpu_clk;
+static struct clk *dmc0_clk;
+static struct clk *dmc1_clk;
+static struct cpufreq_freqs freqs;
+
+/* APLL M,P,S values for 1G/800Mhz */
+#define APLL_VAL_1000 ((1 << 31) | (125 << 16) | (3 << 8) | 1)
+#define APLL_VAL_800 ((1 << 31) | (100 << 16) | (3 << 8) | 1)
+
+/*
+ * DRAM configurations to calculate refresh counter for changing
+ * frequency of memory.
+ */
+struct dram_conf {
+ unsigned long freq; /* HZ */
+ unsigned long refresh; /* DRAM refresh counter * 1000 */
+};
+
+/* DRAM configuration (DMC0 and DMC1) */
+static struct dram_conf s5pv210_dram_conf[2];
+
+enum perf_level {
+ L0, L1, L2, L3, L4,
+};
+
+enum s5pv210_mem_type {
+ LPDDR = 0x1,
+ LPDDR2 = 0x2,
+ DDR2 = 0x4,
+};
+
+enum s5pv210_dmc_port {
+ DMC0 = 0,
+ DMC1,
+};
+
+static struct cpufreq_frequency_table s5pv210_freq_table[] = {
+ {L0, 1000*1000},
+ {L1, 800*1000},
+ {L2, 400*1000},
+ {L3, 200*1000},
+ {L4, 100*1000},
+ {0, CPUFREQ_TABLE_END},
+};
+
+static u32 clkdiv_val[5][11] = {
+ /*
+ * Clock divider value for following
+ * { APLL, A2M, HCLK_MSYS, PCLK_MSYS,
+ * HCLK_DSYS, PCLK_DSYS, HCLK_PSYS, PCLK_PSYS,
+ * ONEDRAM, MFC, G3D }
+ */
+
+ /* L0 : [1000/200/100][166/83][133/66][200/200] */
+ {0, 4, 4, 1, 3, 1, 4, 1, 3, 0, 0},
+
+ /* L1 : [800/200/100][166/83][133/66][200/200] */
+ {0, 3, 3, 1, 3, 1, 4, 1, 3, 0, 0},
+
+ /* L2 : [400/200/100][166/83][133/66][200/200] */
+ {1, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
+
+ /* L3 : [200/200/100][166/83][133/66][200/200] */
+ {3, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
+
+ /* L4 : [100/100/100][83/83][66/66][100/100] */
+ {7, 7, 0, 0, 7, 0, 9, 0, 7, 0, 0},
+};
+
+/*
+ * This function set DRAM refresh counter
+ * accoriding to operating frequency of DRAM
+ * ch: DMC port number 0 or 1
+ * freq: Operating frequency of DRAM(KHz)
+ */
+static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
+{
+ unsigned long tmp, tmp1;
+ void __iomem *reg = NULL;
+
+ if (ch == DMC0)
+ reg = (S5P_VA_DMC0 + 0x30);
+ else if (ch == DMC1)
+ reg = (S5P_VA_DMC1 + 0x30);
+ else
+ printk(KERN_ERR "Cannot find DMC port\n");
+
+ /* Find current DRAM frequency */
+ tmp = s5pv210_dram_conf[ch].freq;
+
+ do_div(tmp, freq);
+
+ tmp1 = s5pv210_dram_conf[ch].refresh;
+
+ do_div(tmp1, tmp);
+
+ __raw_writel(tmp1, reg);
+}
+
+int s5pv210_verify_speed(struct cpufreq_policy *policy)
+{
+ if (policy->cpu)
+ return -EINVAL;
+
+ return cpufreq_frequency_table_verify(policy, s5pv210_freq_table);
+}
+
+unsigned int s5pv210_getspeed(unsigned int cpu)
+{
+ if (cpu)
+ return 0;
+
+ return clk_get_rate(cpu_clk) / 1000;
+}
+
+static int s5pv210_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned long reg;
+ unsigned int index, priv_index;
+ unsigned int pll_changing = 0;
+ unsigned int bus_speed_changing = 0;
+
+ freqs.old = s5pv210_getspeed(0);
+
+ if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
+ target_freq, relation, &index))
+ return -EINVAL;
+
+ freqs.new = s5pv210_freq_table[index].frequency;
+ freqs.cpu = 0;
+
+ if (freqs.new == freqs.old)
+ return 0;
+
+ /* Finding current running level index */
+ if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
+ freqs.old, relation, &priv_index))
+ return -EINVAL;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ if (freqs.new > freqs.old) {
+ /* Voltage up: will be implemented */
+ }
+
+ /* Check if there need to change PLL */
+ if ((index == L0) || (priv_index == L0))
+ pll_changing = 1;
+
+ /* Check if there need to change System bus clock */
+ if ((index == L4) || (priv_index == L4))
+ bus_speed_changing = 1;
+
+ if (bus_speed_changing) {
+ /*
+ * Reconfigure DRAM refresh counter value for minimum
+ * temporary clock while changing divider.
+ * expected clock is 83Mhz : 7.8usec/(1/83Mhz) = 0x287
+ */
+ if (pll_changing)
+ s5pv210_set_refresh(DMC1, 83000);
+ else
+ s5pv210_set_refresh(DMC1, 100000);
+
+ s5pv210_set_refresh(DMC0, 83000);
+ }
+
+ /*
+ * APLL should be changed in this level
+ * APLL -> MPLL(for stable transition) -> APLL
+ * Some clock source's clock API are not prepared.
+ * Do not use clock API in below code.
+ */
+ if (pll_changing) {
+ /*
+ * 1. Temporary Change divider for MFC and G3D
+ * SCLKA2M(200/1=200)->(200/4=50)Mhz
+ */
+ reg = __raw_readl(S5P_CLK_DIV2);
+ reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
+ reg |= (3 << S5P_CLKDIV2_G3D_SHIFT) |
+ (3 << S5P_CLKDIV2_MFC_SHIFT);
+ __raw_writel(reg, S5P_CLK_DIV2);
+
+ /* For MFC, G3D dividing */
+ do {
+ reg = __raw_readl(S5P_CLKDIV_STAT0);
+ } while (reg & ((1 << 16) | (1 << 17)));
+
+ /*
+ * 2. Change SCLKA2M(200Mhz)to SCLKMPLL in MFC_MUX, G3D MUX
+ * (200/4=50)->(667/4=166)Mhz
+ */
+ reg = __raw_readl(S5P_CLK_SRC2);
+ reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
+ reg |= (1 << S5P_CLKSRC2_G3D_SHIFT) |
+ (1 << S5P_CLKSRC2_MFC_SHIFT);
+ __raw_writel(reg, S5P_CLK_SRC2);
+
+ do {
+ reg = __raw_readl(S5P_CLKMUX_STAT1);
+ } while (reg & ((1 << 7) | (1 << 3)));
+
+ /*
+ * 3. DMC1 refresh count for 133Mhz if (index == L4) is
+ * true refresh counter is already programed in upper
+ * code. 0x287@83Mhz
+ */
+ if (!bus_speed_changing)
+ s5pv210_set_refresh(DMC1, 133000);
+
+ /* 4. SCLKAPLL -> SCLKMPLL */
+ reg = __raw_readl(S5P_CLK_SRC0);
+ reg &= ~(S5P_CLKSRC0_MUX200_MASK);
+ reg |= (0x1 << S5P_CLKSRC0_MUX200_SHIFT);
+ __raw_writel(reg, S5P_CLK_SRC0);
+
+ do {
+ reg = __raw_readl(S5P_CLKMUX_STAT0);
+ } while (reg & (0x1 << 18));
+
+ }
+
+ /* Change divider */
+ reg = __raw_readl(S5P_CLK_DIV0);
+
+ reg &= ~(S5P_CLKDIV0_APLL_MASK | S5P_CLKDIV0_A2M_MASK |
+ S5P_CLKDIV0_HCLK200_MASK | S5P_CLKDIV0_PCLK100_MASK |
+ S5P_CLKDIV0_HCLK166_MASK | S5P_CLKDIV0_PCLK83_MASK |
+ S5P_CLKDIV0_HCLK133_MASK | S5P_CLKDIV0_PCLK66_MASK);
+
+ reg |= ((clkdiv_val[index][0] << S5P_CLKDIV0_APLL_SHIFT) |
+ (clkdiv_val[index][1] << S5P_CLKDIV0_A2M_SHIFT) |
+ (clkdiv_val[index][2] << S5P_CLKDIV0_HCLK200_SHIFT) |
+ (clkdiv_val[index][3] << S5P_CLKDIV0_PCLK100_SHIFT) |
+ (clkdiv_val[index][4] << S5P_CLKDIV0_HCLK166_SHIFT) |
+ (clkdiv_val[index][5] << S5P_CLKDIV0_PCLK83_SHIFT) |
+ (clkdiv_val[index][6] << S5P_CLKDIV0_HCLK133_SHIFT) |
+ (clkdiv_val[index][7] << S5P_CLKDIV0_PCLK66_SHIFT));
+
+ __raw_writel(reg, S5P_CLK_DIV0);
+
+ do {
+ reg = __raw_readl(S5P_CLKDIV_STAT0);
+ } while (reg & 0xff);
+
+ /* ARM MCS value changed */
+ reg = __raw_readl(S5P_ARM_MCS_CON);
+ reg &= ~0x3;
+ if (index >= L3)
+ reg |= 0x3;
+ else
+ reg |= 0x1;
+
+ __raw_writel(reg, S5P_ARM_MCS_CON);
+
+ if (pll_changing) {
+ /* 5. Set Lock time = 30us*24Mhz = 0x2cf */
+ __raw_writel(0x2cf, S5P_APLL_LOCK);
+
+ /*
+ * 6. Turn on APLL
+ * 6-1. Set PMS values
+ * 6-2. Wait untile the PLL is locked
+ */
+ if (index == L0)
+ __raw_writel(APLL_VAL_1000, S5P_APLL_CON);
+ else
+ __raw_writel(APLL_VAL_800, S5P_APLL_CON);
+
+ do {
+ reg = __raw_readl(S5P_APLL_CON);
+ } while (!(reg & (0x1 << 29)));
+
+ /*
+ * 7. Change souce clock from SCLKMPLL(667Mhz)
+ * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX
+ * (667/4=166)->(200/4=50)Mhz
+ */
+ reg = __raw_readl(S5P_CLK_SRC2);
+ reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
+ reg |= (0 << S5P_CLKSRC2_G3D_SHIFT) |
+ (0 << S5P_CLKSRC2_MFC_SHIFT);
+ __raw_writel(reg, S5P_CLK_SRC2);
+
+ do {
+ reg = __raw_readl(S5P_CLKMUX_STAT1);
+ } while (reg & ((1 << 7) | (1 << 3)));
+
+ /*
+ * 8. Change divider for MFC and G3D
+ * (200/4=50)->(200/1=200)Mhz
+ */
+ reg = __raw_readl(S5P_CLK_DIV2);
+ reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
+ reg |= (clkdiv_val[index][10] << S5P_CLKDIV2_G3D_SHIFT) |
+ (clkdiv_val[index][9] << S5P_CLKDIV2_MFC_SHIFT);
+ __raw_writel(reg, S5P_CLK_DIV2);
+
+ /* For MFC, G3D dividing */
+ do {
+ reg = __raw_readl(S5P_CLKDIV_STAT0);
+ } while (reg & ((1 << 16) | (1 << 17)));
+
+ /* 9. Change MPLL to APLL in MSYS_MUX */
+ reg = __raw_readl(S5P_CLK_SRC0);
+ reg &= ~(S5P_CLKSRC0_MUX200_MASK);
+ reg |= (0x0 << S5P_CLKSRC0_MUX200_SHIFT);
+ __raw_writel(reg, S5P_CLK_SRC0);
+
+ do {
+ reg = __raw_readl(S5P_CLKMUX_STAT0);
+ } while (reg & (0x1 << 18));
+
+ /*
+ * 10. DMC1 refresh counter
+ * L4 : DMC1 = 100Mhz 7.8us/(1/100) = 0x30c
+ * Others : DMC1 = 200Mhz 7.8us/(1/200) = 0x618
+ */
+ if (!bus_speed_changing)
+ s5pv210_set_refresh(DMC1, 200000);
+ }
+
+ /*
+ * L4 level need to change memory bus speed, hence onedram clock divier
+ * and memory refresh parameter should be changed
+ */
+ if (bus_speed_changing) {
+ reg = __raw_readl(S5P_CLK_DIV6);
+ reg &= ~S5P_CLKDIV6_ONEDRAM_MASK;
+ reg |= (clkdiv_val[index][8] << S5P_CLKDIV6_ONEDRAM_SHIFT);
+ __raw_writel(reg, S5P_CLK_DIV6);
+
+ do {
+ reg = __raw_readl(S5P_CLKDIV_STAT1);
+ } while (reg & (1 << 15));
+
+ /* Reconfigure DRAM refresh counter value */
+ if (index != L4) {
+ /*
+ * DMC0 : 166Mhz
+ * DMC1 : 200Mhz
+ */
+ s5pv210_set_refresh(DMC0, 166000);
+ s5pv210_set_refresh(DMC1, 200000);
+ } else {
+ /*
+ * DMC0 : 83Mhz
+ * DMC1 : 100Mhz
+ */
+ s5pv210_set_refresh(DMC0, 83000);
+ s5pv210_set_refresh(DMC1, 100000);
+ }
+ }
+
+ if (freqs.new < freqs.old) {
+ /* Voltage down: will be implemented */
+ }
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ printk(KERN_DEBUG "Perf changed[L%d]\n", index);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy,
+ pm_message_t pmsg)
+{
+ return 0;
+}
+
+static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy)
+{
+ return 0;
+}
+#endif
+
+static int check_mem_type(void __iomem *dmc_reg)
+{
+ unsigned long val;
+
+ val = __raw_readl(dmc_reg + 0x4);
+ val = (val & (0xf << 8));
+
+ return val >> 8;
+}
+
+static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
+{
+ unsigned long mem_type;
+
+ cpu_clk = clk_get(NULL, "armclk");
+ if (IS_ERR(cpu_clk))
+ return PTR_ERR(cpu_clk);
+
+ dmc0_clk = clk_get(NULL, "sclk_dmc0");
+ if (IS_ERR(dmc0_clk)) {
+ clk_put(cpu_clk);
+ return PTR_ERR(dmc0_clk);
+ }
+
+ dmc1_clk = clk_get(NULL, "hclk_msys");
+ if (IS_ERR(dmc1_clk)) {
+ clk_put(dmc0_clk);
+ clk_put(cpu_clk);
+ return PTR_ERR(dmc1_clk);
+ }
+
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ /*
+ * check_mem_type : This driver only support LPDDR & LPDDR2.
+ * other memory type is not supported.
+ */
+ mem_type = check_mem_type(S5P_VA_DMC0);
+
+ if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
+ printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
+ return -EINVAL;
+ }
+
+ /* Find current refresh counter and frequency each DMC */
+ s5pv210_dram_conf[0].refresh = (__raw_readl(S5P_VA_DMC0 + 0x30) * 1000);
+ s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk);
+
+ s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
+ s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
+
+ policy->cur = policy->min = policy->max = s5pv210_getspeed(0);
+
+ cpufreq_frequency_table_get_attr(s5pv210_freq_table, policy->cpu);
+
+ policy->cpuinfo.transition_latency = 40000;
+
+ return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
+}
+
+static struct cpufreq_driver s5pv210_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = s5pv210_verify_speed,
+ .target = s5pv210_target,
+ .get = s5pv210_getspeed,
+ .init = s5pv210_cpu_init,
+ .name = "s5pv210",
+#ifdef CONFIG_PM
+ .suspend = s5pv210_cpufreq_suspend,
+ .resume = s5pv210_cpufreq_resume,
+#endif
+};
+
+static int __init s5pv210_cpufreq_init(void)
+{
+ return cpufreq_register_driver(&s5pv210_driver);
+}
+
+late_initcall(s5pv210_cpufreq_init);
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c
index 21dc6cf955c..1303fcb12b5 100644
--- a/arch/arm/mach-s5pv210/dev-audio.c
+++ b/arch/arm/mach-s5pv210/dev-audio.c
@@ -24,29 +24,15 @@ static int s5pv210_cfg_i2s(struct platform_device *pdev)
/* configure GPIO for i2s port */
switch (pdev->id) {
case 1:
- s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(2));
break;
case 2:
- s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(4));
- s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(4));
- s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(4));
- s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(4));
- s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(4));
+ s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(4));
break;
case -1:
- s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPI(5), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPI(6), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin_range(S5PV210_GPI(0), 7, S3C_GPIO_SFN(2));
break;
default:
@@ -151,25 +137,13 @@ static int s5pv210_pcm_cfg_gpio(struct platform_device *pdev)
{
switch (pdev->id) {
case 0:
- s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(3));
- s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(3));
- s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(3));
- s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(3));
- s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(3));
+ s3c_gpio_cfgpin_range(S5PV210_GPI(0), 5, S3C_GPIO_SFN(3));
break;
case 1:
- s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(3));
- s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(3));
- s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(3));
- s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(3));
- s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(3));
+ s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(3));
break;
case 2:
- s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(2));
break;
default:
printk(KERN_DEBUG "Invalid PCM Controller number!");
@@ -271,13 +245,7 @@ struct platform_device s5pv210_device_pcm2 = {
static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev)
{
- s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(4));
- s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(4));
- s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(4));
- s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(4));
- s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(4));
-
- return 0;
+ return s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(4));
}
static struct resource s5pv210_ac97_resource[] = {
@@ -325,3 +293,43 @@ struct platform_device s5pv210_device_ac97 = {
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
+
+/* S/PDIF Controller platform_device */
+
+static int s5pv210_spdif_cfg_gpio(struct platform_device *pdev)
+{
+ s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 2, S3C_GPIO_SFN(3));
+
+ return 0;
+}
+
+static struct resource s5pv210_spdif_resource[] = {
+ [0] = {
+ .start = S5PV210_PA_SPDIF,
+ .end = S5PV210_PA_SPDIF + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DMACH_SPDIF,
+ .end = DMACH_SPDIF,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct s3c_audio_pdata samsung_spdif_pdata = {
+ .cfg_gpio = s5pv210_spdif_cfg_gpio,
+};
+
+static u64 s5pv210_spdif_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5pv210_device_spdif = {
+ .name = "samsung-spdif",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5pv210_spdif_resource),
+ .resource = s5pv210_spdif_resource,
+ .dev = {
+ .platform_data = &samsung_spdif_pdata,
+ .dma_mask = &s5pv210_spdif_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
diff --git a/arch/arm/mach-s5pv210/dev-spi.c b/arch/arm/mach-s5pv210/dev-spi.c
index 826cdbc43e2..e3249a47e3b 100644
--- a/arch/arm/mach-s5pv210/dev-spi.c
+++ b/arch/arm/mach-s5pv210/dev-spi.c
@@ -35,23 +35,15 @@ static char *spi_src_clks[] = {
*/
static int s5pv210_spi_cfg_gpio(struct platform_device *pdev)
{
+ unsigned int base;
+
switch (pdev->id) {
case 0:
- s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPB(1), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPB(2), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_UP);
- s3c_gpio_setpull(S5PV210_GPB(1), S3C_GPIO_PULL_UP);
- s3c_gpio_setpull(S5PV210_GPB(2), S3C_GPIO_PULL_UP);
+ base = S5PV210_GPB(0);
break;
case 1:
- s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPB(5), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5PV210_GPB(6), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP);
- s3c_gpio_setpull(S5PV210_GPB(5), S3C_GPIO_PULL_UP);
- s3c_gpio_setpull(S5PV210_GPB(6), S3C_GPIO_PULL_UP);
+ base = S5PV210_GPB(4);
break;
default:
@@ -59,6 +51,9 @@ static int s5pv210_spi_cfg_gpio(struct platform_device *pdev)
return -EINVAL;
}
+ s3c_gpio_cfgall_range(base, 3,
+ S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+
return 0;
}
diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c
index 778ad5fe231..497d3439a14 100644
--- a/arch/arm/mach-s5pv210/dma.c
+++ b/arch/arm/mach-s5pv210/dma.c
@@ -82,7 +82,7 @@ static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
static struct platform_device s5pv210_device_pdma0 = {
.name = "s3c-pl330",
- .id = 1,
+ .id = 0,
.num_resources = ARRAY_SIZE(s5pv210_pdma0_resource),
.resource = s5pv210_pdma0_resource,
.dev = {
@@ -144,7 +144,7 @@ static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
static struct platform_device s5pv210_device_pdma1 = {
.name = "s3c-pl330",
- .id = 2,
+ .id = 1,
.num_resources = ARRAY_SIZE(s5pv210_pdma1_resource),
.resource = s5pv210_pdma1_resource,
.dev = {
diff --git a/arch/arm/mach-s5pv210/gpiolib.c b/arch/arm/mach-s5pv210/gpiolib.c
index 0d459112d03..ab673effd76 100644
--- a/arch/arm/mach-s5pv210/gpiolib.c
+++ b/arch/arm/mach-s5pv210/gpiolib.c
@@ -150,6 +150,7 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
.label = "GPG3",
},
}, {
+ .config = &gpio_cfg_noint,
.chip = {
.base = S5PV210_GPI(0),
.ngpio = S5PV210_GPIO_I_NR,
@@ -223,34 +224,42 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
}, {
.base = (S5P_VA_GPIO + 0xC00),
.config = &gpio_cfg_noint,
+ .irq_base = IRQ_EINT(0),
.chip = {
.base = S5PV210_GPH0(0),
.ngpio = S5PV210_GPIO_H0_NR,
.label = "GPH0",
+ .to_irq = samsung_gpiolib_to_irq,
},
}, {
.base = (S5P_VA_GPIO + 0xC20),
.config = &gpio_cfg_noint,
+ .irq_base = IRQ_EINT(8),
.chip = {
.base = S5PV210_GPH1(0),
.ngpio = S5PV210_GPIO_H1_NR,
.label = "GPH1",
+ .to_irq = samsung_gpiolib_to_irq,
},
}, {
.base = (S5P_VA_GPIO + 0xC40),
.config = &gpio_cfg_noint,
+ .irq_base = IRQ_EINT(16),
.chip = {
.base = S5PV210_GPH2(0),
.ngpio = S5PV210_GPIO_H2_NR,
.label = "GPH2",
+ .to_irq = samsung_gpiolib_to_irq,
},
}, {
.base = (S5P_VA_GPIO + 0xC60),
.config = &gpio_cfg_noint,
+ .irq_base = IRQ_EINT(24),
.chip = {
.base = S5PV210_GPH3(0),
.ngpio = S5PV210_GPIO_H3_NR,
.label = "GPH3",
+ .to_irq = samsung_gpiolib_to_irq,
},
},
};
@@ -259,11 +268,14 @@ static __init int s5pv210_gpiolib_init(void)
{
struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
+ int gpioint_group = 0;
int i = 0;
for (i = 0; i < nr_chips; i++, chip++) {
- if (chip->config == NULL)
+ if (chip->config == NULL) {
chip->config = &gpio_cfg;
+ chip->group = gpioint_group++;
+ }
if (chip->base == NULL)
chip->base = S5PV210_BANK_BASE(i);
}
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
index e1c020e5a49..119b95fdc3c 100644
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -55,8 +55,8 @@
#define IRQ_SPI1 S5P_IRQ_VIC1(16)
#define IRQ_SPI2 S5P_IRQ_VIC1(17)
#define IRQ_IRDA S5P_IRQ_VIC1(18)
-#define IRQ_CAN0 S5P_IRQ_VIC1(19)
-#define IRQ_CAN1 S5P_IRQ_VIC1(20)
+#define IRQ_IIC2 S5P_IRQ_VIC1(19)
+#define IRQ_IIC3 S5P_IRQ_VIC1(20)
#define IRQ_HSIRX S5P_IRQ_VIC1(21)
#define IRQ_HSITX S5P_IRQ_VIC1(22)
#define IRQ_UHOST S5P_IRQ_VIC1(23)
@@ -109,7 +109,7 @@
#define IRQ_IPC S5P_IRQ_VIC3(0)
#define IRQ_HOSTIF S5P_IRQ_VIC3(1)
-#define IRQ_MMC3 S5P_IRQ_VIC3(2)
+#define IRQ_HSMMC3 S5P_IRQ_VIC3(2)
#define IRQ_CEC S5P_IRQ_VIC3(3)
#define IRQ_TSI S5P_IRQ_VIC3(4)
#define IRQ_MDNIE0 S5P_IRQ_VIC3(5)
@@ -121,8 +121,12 @@
#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0))
#define S5P_EINT_BASE2 (IRQ_VIC_END + 1)
+/* GPIO interrupt */
+#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1)
+#define S5P_GPIOINT_GROUP_MAXNR 22
+
/* Set the default NR_IRQS */
-#define NR_IRQS (IRQ_EINT(31) + 1)
+#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
/* Compatibility */
#define IRQ_LCD_FIFO IRQ_LCD0
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index bd9afd52466..861d7fe11fc 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -57,6 +57,8 @@
#define S5P_SZ_UART SZ_256
+#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+
#define S5PV210_PA_SROMC (0xE8000000)
#define S5PV210_PA_CFCON (0xE8200000)
@@ -73,6 +75,9 @@
#define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000))
+#define S5PV210_PA_HSOTG (0xEC000000)
+#define S5PV210_PA_HSPHY (0xEC100000)
+
#define S5PV210_PA_VIC0 (0xF2000000)
#define S5PV210_PA_VIC1 (0xF2100000)
#define S5PV210_PA_VIC2 (0xF2200000)
@@ -81,6 +86,9 @@
#define S5PV210_PA_SDRAM (0x20000000)
#define S5P_PA_SDRAM S5PV210_PA_SDRAM
+/* S/PDIF */
+#define S5PV210_PA_SPDIF 0xE1100000
+
/* I2S */
#define S5PV210_PA_IIS0 0xEEE30000
#define S5PV210_PA_IIS1 0xE2100000
@@ -96,6 +104,9 @@
#define S5PV210_PA_ADC (0xE1700000)
+#define S5PV210_PA_DMC0 (0xF0000000)
+#define S5PV210_PA_DMC1 (0xF1400000)
+
/* compatibiltiy defines. */
#define S3C_PA_UART S5PV210_PA_UART
#define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0)
@@ -108,6 +119,7 @@
#define S3C_PA_FB S5PV210_PA_FB
#define S3C_PA_RTC S5PV210_PA_RTC
#define S3C_PA_WDT S5PV210_PA_WATCHDOG
+#define S3C_PA_USB_HSOTG S5PV210_PA_HSOTG
#define S5P_PA_FIMC0 S5PV210_PA_FIMC0
#define S5P_PA_FIMC1 S5PV210_PA_FIMC1
#define S5P_PA_FIMC2 S5PV210_PA_FIMC2
diff --git a/arch/arm/mach-s5pv210/include/mach/pm-core.h b/arch/arm/mach-s5pv210/include/mach/pm-core.h
new file mode 100644
index 00000000000..e8d394f8b05
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/pm-core.h
@@ -0,0 +1,43 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/pm-core.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h,
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S5PV210 - PM core support for arch/arm/plat-s5p/pm.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+ /* nothing here yet */
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+ __raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK);
+ __raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+ /* nothing here yet */
+}
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+ /* nothing here yet */
+}
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+ struct pm_uart_save *save)
+{
+ /* nothing here yet */
+}
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
index 499aef73747..ebaabe021af 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
@@ -25,6 +25,7 @@
#define S5P_APLL_CON S5P_CLKREG(0x100)
#define S5P_MPLL_CON S5P_CLKREG(0x108)
#define S5P_EPLL_CON S5P_CLKREG(0x110)
+#define S5P_EPLL_CON1 S5P_CLKREG(0x114)
#define S5P_VPLL_CON S5P_CLKREG(0x120)
#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
@@ -67,11 +68,28 @@
#define S5P_CLKGATE_BUS1 S5P_CLKREG(0x488)
#define S5P_CLK_OUT S5P_CLKREG(0x500)
+/* DIV/MUX STATUS */
+#define S5P_CLKDIV_STAT0 S5P_CLKREG(0x1000)
+#define S5P_CLKDIV_STAT1 S5P_CLKREG(0x1004)
+#define S5P_CLKMUX_STAT0 S5P_CLKREG(0x1100)
+#define S5P_CLKMUX_STAT1 S5P_CLKREG(0x1104)
+
/* CLKSRC0 */
-#define S5P_CLKSRC0_MUX200_MASK (0x1<<16)
+#define S5P_CLKSRC0_MUX200_SHIFT (16)
+#define S5P_CLKSRC0_MUX200_MASK (0x1 << S5P_CLKSRC0_MUX200_SHIFT)
#define S5P_CLKSRC0_MUX166_MASK (0x1<<20)
#define S5P_CLKSRC0_MUX133_MASK (0x1<<24)
+/* CLKSRC2 */
+#define S5P_CLKSRC2_G3D_SHIFT (0)
+#define S5P_CLKSRC2_G3D_MASK (0x3 << S5P_CLKSRC2_G3D_SHIFT)
+#define S5P_CLKSRC2_MFC_SHIFT (4)
+#define S5P_CLKSRC2_MFC_MASK (0x3 << S5P_CLKSRC2_MFC_SHIFT)
+
+/* CLKSRC6*/
+#define S5P_CLKSRC6_ONEDRAM_SHIFT (24)
+#define S5P_CLKSRC6_ONEDRAM_MASK (0x3 << S5P_CLKSRC6_ONEDRAM_SHIFT)
+
/* CLKDIV0 */
#define S5P_CLKDIV0_APLL_SHIFT (0)
#define S5P_CLKDIV0_APLL_MASK (0x7 << S5P_CLKDIV0_APLL_SHIFT)
@@ -90,12 +108,24 @@
#define S5P_CLKDIV0_PCLK66_SHIFT (28)
#define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT)
+/* CLKDIV2 */
+#define S5P_CLKDIV2_G3D_SHIFT (0)
+#define S5P_CLKDIV2_G3D_MASK (0xF << S5P_CLKDIV2_G3D_SHIFT)
+#define S5P_CLKDIV2_MFC_SHIFT (4)
+#define S5P_CLKDIV2_MFC_MASK (0xF << S5P_CLKDIV2_MFC_SHIFT)
+
+/* CLKDIV6 */
+#define S5P_CLKDIV6_ONEDRAM_SHIFT (28)
+#define S5P_CLKDIV6_ONEDRAM_MASK (0xF << S5P_CLKDIV6_ONEDRAM_SHIFT)
+
#define S5P_SWRESET S5P_CLKREG(0x2000)
+#define S5P_ARM_MCS_CON S5P_CLKREG(0x6100)
+
/* Registers related to power management */
#define S5P_PWR_CFG S5P_CLKREG(0xC000)
#define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0xC004)
-#define S5P_WAKEUP_MASK S5P_CLKREG(0xC008)
+#define S5P_WAKEUP_MASK S5P_CLKREG(0xC008)
#define S5P_PWR_MODE S5P_CLKREG(0xC00C)
#define S5P_NORMAL_CFG S5P_CLKREG(0xC010)
#define S5P_IDLE_CFG S5P_CLKREG(0xC020)
@@ -159,8 +189,11 @@
#define S5P_SLEEP_CFG_USBOSC_EN (1 << 1)
/* OTHERS Resgister */
+#define S5P_OTHERS_RET_IO (1 << 31)
+#define S5P_OTHERS_RET_CF (1 << 30)
+#define S5P_OTHERS_RET_MMC (1 << 29)
+#define S5P_OTHERS_RET_UART (1 << 28)
#define S5P_OTHERS_USB_SIG_MASK (1 << 16)
-#define S5P_OTHERS_MIPI_DPHY_EN (1 << 28)
/* MIPI */
#define S5P_MIPI_DPHY_EN (3)
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
index 49e029b4978..de0c8997607 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
@@ -31,13 +31,6 @@
#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7))
-/* values for S5P_EXTINT0 */
-#define S5P_EXTINT_LOWLEV (0x00)
-#define S5P_EXTINT_HILEV (0x01)
-#define S5P_EXTINT_FALLEDGE (0x02)
-#define S5P_EXTINT_RISEEDGE (0x03)
-#define S5P_EXTINT_BOTHEDGE (0x04)
-
#define EINT_MODE S3C_GPIO_SFN(0xf)
#define EINT_GPIO_0(x) S5PV210_GPH0(x)
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-sys.h b/arch/arm/mach-s5pv210/include/mach/regs-sys.h
new file mode 100644
index 00000000000..26691d39d0f
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-sys.h
@@ -0,0 +1,19 @@
+/* arch/arm/mach-s5pv210/include/mach/regs-sys.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5PV210 - System registers definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S5PV210_USB_PHY_CON (S3C_VA_SYS + 0xE80C)
+#define S5PV210_USB_PHY0_EN (1 << 0)
+#define S5PV210_USB_PHY1_EN (1 << 1)
+
+/* compatibility defines for s3c-hsotg driver */
+#define S3C64XX_OTHERS S5PV210_USB_PHY_CON
+#define S3C64XX_OTHERS_USBMASK S5PV210_USB_PHY0_EN
diff --git a/arch/arm/mach-s5pv210/include/mach/vmalloc.h b/arch/arm/mach-s5pv210/include/mach/vmalloc.h
index df9a2880832..a6c659d68a5 100644
--- a/arch/arm/mach-s5pv210/include/mach/vmalloc.h
+++ b/arch/arm/mach-s5pv210/include/mach/vmalloc.h
@@ -17,6 +17,6 @@
#ifndef __ASM_ARCH_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H __FILE__
-#define VMALLOC_END (0xE0000000UL)
+#define VMALLOC_END 0xF6000000UL
#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 00883087363..28677caf361 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -16,6 +16,8 @@
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/mfd/max8998.h>
+#include <linux/mfd/wm8994/pdata.h>
+#include <linux/regulator/fixed.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/gpio.h>
@@ -379,6 +381,119 @@ static struct max8998_platform_data aquila_max8998_pdata = {
};
#endif
+static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
+ {
+ .dev_name = "5-001a",
+ .supply = "DBVDD",
+ }, {
+ .dev_name = "5-001a",
+ .supply = "AVDD2",
+ }, {
+ .dev_name = "5-001a",
+ .supply = "CPVDD",
+ },
+};
+
+static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
+ {
+ .dev_name = "5-001a",
+ .supply = "SPKVDD1",
+ }, {
+ .dev_name = "5-001a",
+ .supply = "SPKVDD2",
+ },
+};
+
+static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
+ .constraints = {
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies),
+ .consumer_supplies = wm8994_fixed_voltage0_supplies,
+};
+
+static struct regulator_init_data wm8994_fixed_voltage1_init_data = {
+ .constraints = {
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies),
+ .consumer_supplies = wm8994_fixed_voltage1_supplies,
+};
+
+static struct fixed_voltage_config wm8994_fixed_voltage0_config = {
+ .supply_name = "VCC_1.8V_PDA",
+ .microvolts = 1800000,
+ .gpio = -EINVAL,
+ .init_data = &wm8994_fixed_voltage0_init_data,
+};
+
+static struct fixed_voltage_config wm8994_fixed_voltage1_config = {
+ .supply_name = "V_BAT",
+ .microvolts = 3700000,
+ .gpio = -EINVAL,
+ .init_data = &wm8994_fixed_voltage1_init_data,
+};
+
+static struct platform_device wm8994_fixed_voltage0 = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &wm8994_fixed_voltage0_config,
+ },
+};
+
+static struct platform_device wm8994_fixed_voltage1 = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &wm8994_fixed_voltage1_config,
+ },
+};
+
+static struct regulator_consumer_supply wm8994_avdd1_supply = {
+ .dev_name = "5-001a",
+ .supply = "AVDD1",
+};
+
+static struct regulator_consumer_supply wm8994_dcvdd_supply = {
+ .dev_name = "5-001a",
+ .supply = "DCVDD",
+};
+
+static struct regulator_init_data wm8994_ldo1_data = {
+ .constraints = {
+ .name = "AVDD1_3.0V",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &wm8994_avdd1_supply,
+};
+
+static struct regulator_init_data wm8994_ldo2_data = {
+ .constraints = {
+ .name = "DCVDD_1.0V",
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &wm8994_dcvdd_supply,
+};
+
+static struct wm8994_pdata wm8994_platform_data = {
+ /* configure gpio1 function: 0x0001(Logic level input/output) */
+ .gpio_defaults[0] = 0x0001,
+ /* configure gpio3/4/5/7 function for AIF2 voice */
+ .gpio_defaults[2] = 0x8100,
+ .gpio_defaults[3] = 0x8100,
+ .gpio_defaults[4] = 0x8100,
+ .gpio_defaults[6] = 0x0100,
+ /* configure gpio8/9/10/11 function for AIF3 BT */
+ .gpio_defaults[7] = 0x8100,
+ .gpio_defaults[8] = 0x0100,
+ .gpio_defaults[9] = 0x0100,
+ .gpio_defaults[10] = 0x0100,
+ .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */
+ .ldo[1] = { 0, NULL, &wm8994_ldo2_data },
+};
+
/* GPIO I2C PMIC */
#define AP_I2C_GPIO_PMIC_BUS_4 4
static struct i2c_gpio_platform_data aquila_i2c_gpio_pmic_data = {
@@ -404,6 +519,29 @@ static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = {
#endif
};
+/* GPIO I2C AP 1.8V */
+#define AP_I2C_GPIO_BUS_5 5
+static struct i2c_gpio_platform_data aquila_i2c_gpio5_data = {
+ .sda_pin = S5PV210_MP05(3), /* XM0ADDR_11 */
+ .scl_pin = S5PV210_MP05(2), /* XM0ADDR_10 */
+};
+
+static struct platform_device aquila_i2c_gpio5 = {
+ .name = "i2c-gpio",
+ .id = AP_I2C_GPIO_BUS_5,
+ .dev = {
+ .platform_data = &aquila_i2c_gpio5_data,
+ },
+};
+
+static struct i2c_board_info i2c_gpio5_devs[] __initdata = {
+ {
+ /* CS/ADDR = low 0x34 (FYI: high = 0x36) */
+ I2C_BOARD_INFO("wm8994", 0x1a),
+ .platform_data = &wm8994_platform_data,
+ },
+};
+
/* PMIC Power button */
static struct gpio_keys_button aquila_gpio_keys_table[] = {
{
@@ -475,6 +613,7 @@ static void aquila_setup_sdhci(void)
static struct platform_device *aquila_devices[] __initdata = {
&aquila_i2c_gpio_pmic,
+ &aquila_i2c_gpio5,
&aquila_device_gpiokeys,
&s3c_device_fb,
&s5p_device_onenand,
@@ -484,8 +623,33 @@ static struct platform_device *aquila_devices[] __initdata = {
&s5p_device_fimc0,
&s5p_device_fimc1,
&s5p_device_fimc2,
+ &s5pv210_device_iis0,
+ &wm8994_fixed_voltage0,
+ &wm8994_fixed_voltage1,
};
+static void __init aquila_sound_init(void)
+{
+ unsigned int gpio;
+
+ /* CODEC_XTAL_EN
+ *
+ * The Aquila board have a oscillator which provide main clock
+ * to WM8994 codec. The oscillator provide 24MHz clock to WM8994
+ * clock. Set gpio setting of "CODEC_XTAL_EN" to enable a oscillator.
+ * */
+ gpio = S5PV210_GPH3(2); /* XEINT_26 */
+ gpio_request(gpio, "CODEC_XTAL_EN");
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+ /* Ths main clock of WM8994 codec uses the output of CLKOUT pin.
+ * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS)
+ * because it needs 24MHz clock to operate WM8994 codec.
+ */
+ __raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS);
+}
+
static void __init aquila_map_io(void)
{
s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -506,6 +670,11 @@ static void __init aquila_machine_init(void)
s3c_fimc_setname(1, "s5p-fimc");
s3c_fimc_setname(2, "s5p-fimc");
+ /* SOUND */
+ aquila_sound_init();
+ i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs,
+ ARRAY_SIZE(i2c_gpio5_devs));
+
/* FB */
s3c_fb_set_platdata(&aquila_lcd_pdata);
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index d9ecf57fc2a..b1dcf964a76 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -15,7 +15,13 @@
#include <linux/fb.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
+#include <linux/i2c/qt602240_ts.h>
#include <linux/mfd/max8998.h>
+#include <linux/mfd/wm8994/pdata.h>
+#include <linux/regulator/fixed.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/lcd.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/gpio.h>
@@ -35,7 +41,10 @@
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/fb.h>
+#include <plat/iic.h>
+#include <plat/keypad.h>
#include <plat/sdhci.h>
+#include <plat/clock.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -87,13 +96,12 @@ static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = {
/* Frame Buffer */
static struct s3c_fb_pd_win goni_fb_win0 = {
.win_mode = {
- .pixclock = 1000000000000ULL / ((16+16+2+480)*(28+3+2+800)*55),
.left_margin = 16,
.right_margin = 16,
- .upper_margin = 3,
+ .upper_margin = 2,
.lower_margin = 28,
.hsync_len = 2,
- .vsync_len = 2,
+ .vsync_len = 1,
.xres = 480,
.yres = 800,
.refresh = 55,
@@ -111,9 +119,160 @@ static struct s3c_fb_platdata goni_lcd_pdata __initdata = {
.setup_gpio = s5pv210_fb_gpio_setup_24bpp,
};
+static int lcd_power_on(struct lcd_device *ld, int enable)
+{
+ return 1;
+}
+
+static int reset_lcd(struct lcd_device *ld)
+{
+ static unsigned int first = 1;
+ int reset_gpio = -1;
+
+ reset_gpio = S5PV210_MP05(5);
+
+ if (first) {
+ gpio_request(reset_gpio, "MLCD_RST");
+ first = 0;
+ }
+
+ gpio_direction_output(reset_gpio, 1);
+ return 1;
+}
+
+static struct lcd_platform_data goni_lcd_platform_data = {
+ .reset = reset_lcd,
+ .power_on = lcd_power_on,
+ .lcd_enabled = 0,
+ .reset_delay = 120, /* 120ms */
+ .power_on_delay = 25, /* 25ms */
+ .power_off_delay = 200, /* 200ms */
+};
+
+#define LCD_BUS_NUM 3
+static struct spi_board_info spi_board_info[] __initdata = {
+ {
+ .modalias = "s6e63m0",
+ .platform_data = &goni_lcd_platform_data,
+ .max_speed_hz = 1200000,
+ .bus_num = LCD_BUS_NUM,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ .controller_data = (void *)S5PV210_MP01(1), /* DISPLAY_CS */
+ },
+};
+
+static struct spi_gpio_platform_data lcd_spi_gpio_data = {
+ .sck = S5PV210_MP04(1), /* DISPLAY_CLK */
+ .mosi = S5PV210_MP04(3), /* DISPLAY_SI */
+ .miso = SPI_GPIO_NO_MISO,
+ .num_chipselect = 1,
+};
+
+static struct platform_device goni_spi_gpio = {
+ .name = "spi_gpio",
+ .id = LCD_BUS_NUM,
+ .dev = {
+ .parent = &s3c_device_fb.dev,
+ .platform_data = &lcd_spi_gpio_data,
+ },
+};
+
+/* KEYPAD */
+static uint32_t keymap[] __initdata = {
+ /* KEY(row, col, keycode) */
+ KEY(0, 1, KEY_MENU), /* Send */
+ KEY(0, 2, KEY_BACK), /* End */
+ KEY(1, 1, KEY_CONFIG), /* Half shot */
+ KEY(1, 2, KEY_VOLUMEUP),
+ KEY(2, 1, KEY_CAMERA), /* Full shot */
+ KEY(2, 2, KEY_VOLUMEDOWN),
+};
+
+static struct matrix_keymap_data keymap_data __initdata = {
+ .keymap = keymap,
+ .keymap_size = ARRAY_SIZE(keymap),
+};
+
+static struct samsung_keypad_platdata keypad_data __initdata = {
+ .keymap_data = &keymap_data,
+ .rows = 3,
+ .cols = 3,
+};
+
+/* Radio */
+static struct i2c_board_info i2c1_devs[] __initdata = {
+ {
+ I2C_BOARD_INFO("si470x", 0x10),
+ },
+};
+
+static void __init goni_radio_init(void)
+{
+ int gpio;
+
+ gpio = S5PV210_GPJ2(4); /* XMSMDATA_4 */
+ gpio_request(gpio, "FM_INT");
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+ i2c1_devs[0].irq = gpio_to_irq(gpio);
+
+ gpio = S5PV210_GPJ2(5); /* XMSMDATA_5 */
+ gpio_request(gpio, "FM_RST");
+ gpio_direction_output(gpio, 1);
+}
+
+/* TSP */
+static struct qt602240_platform_data qt602240_platform_data = {
+ .x_line = 17,
+ .y_line = 11,
+ .x_size = 800,
+ .y_size = 480,
+ .blen = 0x21,
+ .threshold = 0x28,
+ .voltage = 2800000, /* 2.8V */
+ .orient = QT602240_DIAGONAL,
+};
+
+static struct s3c2410_platform_i2c i2c2_data __initdata = {
+ .flags = 0,
+ .bus_num = 2,
+ .slave_addr = 0x10,
+ .frequency = 400 * 1000,
+ .sda_delay = 100,
+};
+
+static struct i2c_board_info i2c2_devs[] __initdata = {
+ {
+ I2C_BOARD_INFO("qt602240_ts", 0x4a),
+ .platform_data = &qt602240_platform_data,
+ },
+};
+
+static void __init goni_tsp_init(void)
+{
+ int gpio;
+
+ gpio = S5PV210_GPJ1(3); /* XMSMADDR_11 */
+ gpio_request(gpio, "TSP_LDO_ON");
+ gpio_direction_output(gpio, 1);
+ gpio_export(gpio, 0);
+
+ gpio = S5PV210_GPJ0(5); /* XMSMADDR_5 */
+ gpio_request(gpio, "TSP_INT");
+
+ s5p_register_gpio_interrupt(gpio);
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+ i2c2_devs[0].irq = gpio_to_irq(gpio);
+}
+
/* MAX8998 regulators */
#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
+static struct regulator_consumer_supply goni_ldo5_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
+};
+
static struct regulator_init_data goni_ldo2_data = {
.constraints = {
.name = "VALIVE_1.1V",
@@ -153,6 +312,8 @@ static struct regulator_init_data goni_ldo5_data = {
.max_uV = 2800000,
.apply_uV = 1,
},
+ .num_consumer_supplies = ARRAY_SIZE(goni_ldo5_consumers),
+ .consumer_supplies = goni_ldo5_consumers,
};
static struct regulator_init_data goni_ldo6_data = {
@@ -360,6 +521,119 @@ static struct max8998_platform_data goni_max8998_pdata = {
};
#endif
+static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
+ {
+ .dev_name = "5-001a",
+ .supply = "DBVDD",
+ }, {
+ .dev_name = "5-001a",
+ .supply = "AVDD2",
+ }, {
+ .dev_name = "5-001a",
+ .supply = "CPVDD",
+ },
+};
+
+static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
+ {
+ .dev_name = "5-001a",
+ .supply = "SPKVDD1",
+ }, {
+ .dev_name = "5-001a",
+ .supply = "SPKVDD2",
+ },
+};
+
+static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
+ .constraints = {
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies),
+ .consumer_supplies = wm8994_fixed_voltage0_supplies,
+};
+
+static struct regulator_init_data wm8994_fixed_voltage1_init_data = {
+ .constraints = {
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies),
+ .consumer_supplies = wm8994_fixed_voltage1_supplies,
+};
+
+static struct fixed_voltage_config wm8994_fixed_voltage0_config = {
+ .supply_name = "VCC_1.8V_PDA",
+ .microvolts = 1800000,
+ .gpio = -EINVAL,
+ .init_data = &wm8994_fixed_voltage0_init_data,
+};
+
+static struct fixed_voltage_config wm8994_fixed_voltage1_config = {
+ .supply_name = "V_BAT",
+ .microvolts = 3700000,
+ .gpio = -EINVAL,
+ .init_data = &wm8994_fixed_voltage1_init_data,
+};
+
+static struct platform_device wm8994_fixed_voltage0 = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &wm8994_fixed_voltage0_config,
+ },
+};
+
+static struct platform_device wm8994_fixed_voltage1 = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &wm8994_fixed_voltage1_config,
+ },
+};
+
+static struct regulator_consumer_supply wm8994_avdd1_supply = {
+ .dev_name = "5-001a",
+ .supply = "AVDD1",
+};
+
+static struct regulator_consumer_supply wm8994_dcvdd_supply = {
+ .dev_name = "5-001a",
+ .supply = "DCVDD",
+};
+
+static struct regulator_init_data wm8994_ldo1_data = {
+ .constraints = {
+ .name = "AVDD1_3.0V",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &wm8994_avdd1_supply,
+};
+
+static struct regulator_init_data wm8994_ldo2_data = {
+ .constraints = {
+ .name = "DCVDD_1.0V",
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &wm8994_dcvdd_supply,
+};
+
+static struct wm8994_pdata wm8994_platform_data = {
+ /* configure gpio1 function: 0x0001(Logic level input/output) */
+ .gpio_defaults[0] = 0x0001,
+ /* configure gpio3/4/5/7 function for AIF2 voice */
+ .gpio_defaults[2] = 0x8100,
+ .gpio_defaults[3] = 0x8100,
+ .gpio_defaults[4] = 0x8100,
+ .gpio_defaults[6] = 0x0100,
+ /* configure gpio8/9/10/11 function for AIF3 BT */
+ .gpio_defaults[7] = 0x8100,
+ .gpio_defaults[8] = 0x0100,
+ .gpio_defaults[9] = 0x0100,
+ .gpio_defaults[10] = 0x0100,
+ .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */
+ .ldo[1] = { 0, NULL, &wm8994_ldo2_data },
+};
+
/* GPIO I2C PMIC */
#define AP_I2C_GPIO_PMIC_BUS_4 4
static struct i2c_gpio_platform_data goni_i2c_gpio_pmic_data = {
@@ -385,6 +659,29 @@ static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = {
#endif
};
+/* GPIO I2C AP 1.8V */
+#define AP_I2C_GPIO_BUS_5 5
+static struct i2c_gpio_platform_data goni_i2c_gpio5_data = {
+ .sda_pin = S5PV210_MP05(3), /* XM0ADDR_11 */
+ .scl_pin = S5PV210_MP05(2), /* XM0ADDR_10 */
+};
+
+static struct platform_device goni_i2c_gpio5 = {
+ .name = "i2c-gpio",
+ .id = AP_I2C_GPIO_BUS_5,
+ .dev = {
+ .platform_data = &goni_i2c_gpio5_data,
+ },
+};
+
+static struct i2c_board_info i2c_gpio5_devs[] __initdata = {
+ {
+ /* CS/ADDR = low 0x34 (FYI: high = 0x36) */
+ I2C_BOARD_INFO("wm8994", 0x1a),
+ .platform_data = &wm8994_platform_data,
+ },
+};
+
/* PMIC Power button */
static struct gpio_keys_button goni_gpio_keys_table[] = {
{
@@ -444,11 +741,37 @@ static struct s3c_sdhci_platdata goni_hsmmc2_data __initdata = {
.ext_cd_gpio_invert = 1,
};
+static struct regulator_consumer_supply mmc2_supplies[] = {
+ REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
+};
+
+static struct regulator_init_data mmc2_fixed_voltage_init_data = {
+ .constraints = {
+ .name = "V_TF_2.8V",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(mmc2_supplies),
+ .consumer_supplies = mmc2_supplies,
+};
+
+static struct fixed_voltage_config mmc2_fixed_voltage_config = {
+ .supply_name = "EXT_FLASH_EN",
+ .microvolts = 2800000,
+ .gpio = GONI_EXT_FLASH_EN,
+ .enable_high = true,
+ .init_data = &mmc2_fixed_voltage_init_data,
+};
+
+static struct platform_device mmc2_fixed_voltage = {
+ .name = "reg-fixed-voltage",
+ .id = 2,
+ .dev = {
+ .platform_data = &mmc2_fixed_voltage_config,
+ },
+};
+
static void goni_setup_sdhci(void)
{
- gpio_request(GONI_EXT_FLASH_EN, "FLASH_EN");
- gpio_direction_output(GONI_EXT_FLASH_EN, 1);
-
s3c_sdhci0_set_platdata(&goni_hsmmc0_data);
s3c_sdhci1_set_platdata(&goni_hsmmc1_data);
s3c_sdhci2_set_platdata(&goni_hsmmc2_data);
@@ -457,7 +780,10 @@ static void goni_setup_sdhci(void)
static struct platform_device *goni_devices[] __initdata = {
&s3c_device_fb,
&s5p_device_onenand,
+ &goni_spi_gpio,
&goni_i2c_gpio_pmic,
+ &goni_i2c_gpio5,
+ &mmc2_fixed_voltage,
&goni_device_gpiokeys,
&s5p_device_fimc0,
&s5p_device_fimc1,
@@ -465,8 +791,24 @@ static struct platform_device *goni_devices[] __initdata = {
&s3c_device_hsmmc0,
&s3c_device_hsmmc1,
&s3c_device_hsmmc2,
+ &s5pv210_device_iis0,
+ &s3c_device_usb_hsotg,
+ &samsung_device_keypad,
+ &s3c_device_i2c1,
+ &s3c_device_i2c2,
+ &wm8994_fixed_voltage0,
+ &wm8994_fixed_voltage1,
};
+static void __init goni_sound_init(void)
+{
+ /* Ths main clock of WM8994 codec uses the output of CLKOUT pin.
+ * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS)
+ * because it needs 24MHz clock to operate WM8994 codec.
+ */
+ __raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS);
+}
+
static void __init goni_map_io(void)
{
s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -476,6 +818,20 @@ static void __init goni_map_io(void)
static void __init goni_machine_init(void)
{
+ /* Radio: call before I2C 1 registeration */
+ goni_radio_init();
+
+ /* I2C1 */
+ s3c_i2c1_set_platdata(NULL);
+ i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+
+ /* TSP: call before I2C 2 registeration */
+ goni_tsp_init();
+
+ /* I2C2 */
+ s3c_i2c2_set_platdata(&i2c2_data);
+ i2c_register_board_info(2, i2c2_devs, ARRAY_SIZE(i2c2_devs));
+
/* PMIC */
goni_pmic_init();
i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs,
@@ -483,9 +839,22 @@ static void __init goni_machine_init(void)
/* SDHCI */
goni_setup_sdhci();
+ /* SOUND */
+ goni_sound_init();
+ i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs,
+ ARRAY_SIZE(i2c_gpio5_devs));
+
/* FB */
s3c_fb_set_platdata(&goni_lcd_pdata);
+ /* SPI */
+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
+ /* KEYPAD */
+ samsung_keypad_set_platdata(&keypad_data);
+
+ clk_xusbxti.rate = 24000000;
+
platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices));
}
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index cea9bca79d8..0ad7924fe62 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -28,6 +28,7 @@
#include <plat/cpu.h>
#include <plat/ata.h>
#include <plat/iic.h>
+#include <plat/pm.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define SMDKC110_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -81,6 +82,7 @@ static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = {
static struct platform_device *smdkc110_devices[] __initdata = {
&s5pv210_device_iis0,
&s5pv210_device_ac97,
+ &s5pv210_device_spdif,
&s3c_device_cfcon,
&s3c_device_i2c0,
&s3c_device_i2c1,
@@ -110,6 +112,8 @@ static void __init smdkc110_map_io(void)
static void __init smdkc110_machine_init(void)
{
+ s3c_pm_init();
+
s3c_i2c0_set_platdata(NULL);
s3c_i2c1_set_platdata(NULL);
s3c_i2c2_set_platdata(NULL);
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 83189ae9da9..bcd7a5d5340 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -31,6 +31,7 @@
#include <plat/ata.h>
#include <plat/iic.h>
#include <plat/keypad.h>
+#include <plat/pm.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define SMDKV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -103,6 +104,7 @@ static struct samsung_keypad_platdata smdkv210_keypad_data __initdata = {
static struct platform_device *smdkv210_devices[] __initdata = {
&s5pv210_device_iis0,
&s5pv210_device_ac97,
+ &s5pv210_device_spdif,
&s3c_device_adc,
&s3c_device_cfcon,
&s3c_device_hsmmc0,
@@ -145,6 +147,8 @@ static void __init smdkv210_map_io(void)
static void __init smdkv210_machine_init(void)
{
+ s3c_pm_init();
+
samsung_keypad_set_platdata(&smdkv210_keypad_data);
s3c24xx_ts_set_platdata(&s3c_ts_platform);
diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c
new file mode 100644
index 00000000000..043c938806b
--- /dev/null
+++ b/arch/arm/mach-s5pv210/mach-torbreck.c
@@ -0,0 +1,131 @@
+/* linux/arch/arm/mach-s5pv210/mach-torbreck.c
+ *
+ * Copyright (c) 2010 aESOP Community
+ * http://www.aesop.or.kr/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/regs-serial.h>
+#include <plat/s5pv210.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/iic.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define TORBRECK_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
+ S3C2410_UCON_RXILEVEL | \
+ S3C2410_UCON_TXIRQMODE | \
+ S3C2410_UCON_RXIRQMODE | \
+ S3C2410_UCON_RXFIFO_TOI | \
+ S3C2443_UCON_RXERR_IRQEN)
+
+#define TORBRECK_ULCON_DEFAULT S3C2410_LCON_CS8
+
+#define TORBRECK_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
+ S5PV210_UFCON_TXTRIG4 | \
+ S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg torbreck_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = TORBRECK_UCON_DEFAULT,
+ .ulcon = TORBRECK_ULCON_DEFAULT,
+ .ufcon = TORBRECK_UFCON_DEFAULT,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = TORBRECK_UCON_DEFAULT,
+ .ulcon = TORBRECK_ULCON_DEFAULT,
+ .ufcon = TORBRECK_UFCON_DEFAULT,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = TORBRECK_UCON_DEFAULT,
+ .ulcon = TORBRECK_ULCON_DEFAULT,
+ .ufcon = TORBRECK_UFCON_DEFAULT,
+ },
+ [3] = {
+ .hwport = 3,
+ .flags = 0,
+ .ucon = TORBRECK_UCON_DEFAULT,
+ .ulcon = TORBRECK_ULCON_DEFAULT,
+ .ufcon = TORBRECK_UFCON_DEFAULT,
+ },
+};
+
+static struct platform_device *torbreck_devices[] __initdata = {
+ &s5pv210_device_iis0,
+ &s3c_device_cfcon,
+ &s3c_device_hsmmc0,
+ &s3c_device_hsmmc1,
+ &s3c_device_hsmmc2,
+ &s3c_device_hsmmc3,
+ &s3c_device_i2c0,
+ &s3c_device_i2c1,
+ &s3c_device_i2c2,
+ &s3c_device_rtc,
+ &s3c_device_wdt,
+};
+
+static struct i2c_board_info torbreck_i2c_devs0[] __initdata = {
+ /* To Be Updated */
+};
+
+static struct i2c_board_info torbreck_i2c_devs1[] __initdata = {
+ /* To Be Updated */
+};
+
+static struct i2c_board_info torbreck_i2c_devs2[] __initdata = {
+ /* To Be Updated */
+};
+
+static void __init torbreck_map_io(void)
+{
+ s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+ s3c24xx_init_clocks(24000000);
+ s3c24xx_init_uarts(torbreck_uartcfgs, ARRAY_SIZE(torbreck_uartcfgs));
+}
+
+static void __init torbreck_machine_init(void)
+{
+ s3c_i2c0_set_platdata(NULL);
+ s3c_i2c1_set_platdata(NULL);
+ s3c_i2c2_set_platdata(NULL);
+ i2c_register_board_info(0, torbreck_i2c_devs0,
+ ARRAY_SIZE(torbreck_i2c_devs0));
+ i2c_register_board_info(1, torbreck_i2c_devs1,
+ ARRAY_SIZE(torbreck_i2c_devs1));
+ i2c_register_board_info(2, torbreck_i2c_devs2,
+ ARRAY_SIZE(torbreck_i2c_devs2));
+
+ platform_add_devices(torbreck_devices, ARRAY_SIZE(torbreck_devices));
+}
+
+MACHINE_START(TORBRECK, "TORBRECK")
+ /* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */
+ .boot_params = S5P_PA_SDRAM + 0x100,
+ .init_irq = s5pv210_init_irq,
+ .map_io = torbreck_map_io,
+ .init_machine = torbreck_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c
new file mode 100644
index 00000000000..549d7924fd4
--- /dev/null
+++ b/arch/arm/mach-s5pv210/pm.c
@@ -0,0 +1,166 @@
+/* linux/arch/arm/mach-s5pv210/pm.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5PV210 - Power Management support
+ *
+ * Based on arch/arm/mach-s3c2410/pm.c
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/io.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/regs-timer.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-clock.h>
+
+static struct sleep_save s5pv210_core_save[] = {
+ /* Clock source */
+ SAVE_ITEM(S5P_CLK_SRC0),
+ SAVE_ITEM(S5P_CLK_SRC1),
+ SAVE_ITEM(S5P_CLK_SRC2),
+ SAVE_ITEM(S5P_CLK_SRC3),
+ SAVE_ITEM(S5P_CLK_SRC4),
+ SAVE_ITEM(S5P_CLK_SRC5),
+ SAVE_ITEM(S5P_CLK_SRC6),
+
+ /* Clock source Mask */
+ SAVE_ITEM(S5P_CLK_SRC_MASK0),
+ SAVE_ITEM(S5P_CLK_SRC_MASK1),
+
+ /* Clock Divider */
+ SAVE_ITEM(S5P_CLK_DIV0),
+ SAVE_ITEM(S5P_CLK_DIV1),
+ SAVE_ITEM(S5P_CLK_DIV2),
+ SAVE_ITEM(S5P_CLK_DIV3),
+ SAVE_ITEM(S5P_CLK_DIV4),
+ SAVE_ITEM(S5P_CLK_DIV5),
+ SAVE_ITEM(S5P_CLK_DIV6),
+ SAVE_ITEM(S5P_CLK_DIV7),
+
+ /* Clock Main Gate */
+ SAVE_ITEM(S5P_CLKGATE_MAIN0),
+ SAVE_ITEM(S5P_CLKGATE_MAIN1),
+ SAVE_ITEM(S5P_CLKGATE_MAIN2),
+
+ /* Clock source Peri Gate */
+ SAVE_ITEM(S5P_CLKGATE_PERI0),
+ SAVE_ITEM(S5P_CLKGATE_PERI1),
+
+ /* Clock source SCLK Gate */
+ SAVE_ITEM(S5P_CLKGATE_SCLK0),
+ SAVE_ITEM(S5P_CLKGATE_SCLK1),
+
+ /* Clock IP Clock gate */
+ SAVE_ITEM(S5P_CLKGATE_IP0),
+ SAVE_ITEM(S5P_CLKGATE_IP1),
+ SAVE_ITEM(S5P_CLKGATE_IP2),
+ SAVE_ITEM(S5P_CLKGATE_IP3),
+ SAVE_ITEM(S5P_CLKGATE_IP4),
+
+ /* Clock Blcok and Bus gate */
+ SAVE_ITEM(S5P_CLKGATE_BLOCK),
+ SAVE_ITEM(S5P_CLKGATE_BUS0),
+
+ /* Clock ETC */
+ SAVE_ITEM(S5P_CLK_OUT),
+ SAVE_ITEM(S5P_MDNIE_SEL),
+
+ /* PWM Register */
+ SAVE_ITEM(S3C2410_TCFG0),
+ SAVE_ITEM(S3C2410_TCFG1),
+ SAVE_ITEM(S3C64XX_TINT_CSTAT),
+ SAVE_ITEM(S3C2410_TCON),
+ SAVE_ITEM(S3C2410_TCNTB(0)),
+ SAVE_ITEM(S3C2410_TCMPB(0)),
+ SAVE_ITEM(S3C2410_TCNTO(0)),
+};
+
+void s5pv210_cpu_suspend(void)
+{
+ unsigned long tmp;
+
+ /* issue the standby signal into the pm unit. Note, we
+ * issue a write-buffer drain just in case */
+
+ tmp = 0;
+
+ asm("b 1f\n\t"
+ ".align 5\n\t"
+ "1:\n\t"
+ "mcr p15, 0, %0, c7, c10, 5\n\t"
+ "mcr p15, 0, %0, c7, c10, 4\n\t"
+ "wfi" : : "r" (tmp));
+
+ /* we should never get past here */
+ panic("sleep resumed to originator?");
+}
+
+static void s5pv210_pm_prepare(void)
+{
+ unsigned int tmp;
+
+ /* ensure at least INFORM0 has the resume address */
+ __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
+
+ tmp = __raw_readl(S5P_SLEEP_CFG);
+ tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN);
+ __raw_writel(tmp, S5P_SLEEP_CFG);
+
+ /* WFI for SLEEP mode configuration by SYSCON */
+ tmp = __raw_readl(S5P_PWR_CFG);
+ tmp &= S5P_CFG_WFI_CLEAN;
+ tmp |= S5P_CFG_WFI_SLEEP;
+ __raw_writel(tmp, S5P_PWR_CFG);
+
+ /* SYSCON interrupt handling disable */
+ tmp = __raw_readl(S5P_OTHERS);
+ tmp |= S5P_OTHER_SYSC_INTOFF;
+ __raw_writel(tmp, S5P_OTHERS);
+
+ s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
+}
+
+static int s5pv210_pm_add(struct sys_device *sysdev)
+{
+ pm_cpu_prep = s5pv210_pm_prepare;
+ pm_cpu_sleep = s5pv210_cpu_suspend;
+
+ return 0;
+}
+
+static int s5pv210_pm_resume(struct sys_device *dev)
+{
+ u32 tmp;
+
+ tmp = __raw_readl(S5P_OTHERS);
+ tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF |\
+ S5P_OTHERS_RET_MMC | S5P_OTHERS_RET_UART);
+ __raw_writel(tmp , S5P_OTHERS);
+
+ s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
+
+ return 0;
+}
+
+static struct sysdev_driver s5pv210_pm_driver = {
+ .add = s5pv210_pm_add,
+ .resume = s5pv210_pm_resume,
+};
+
+static __init int s5pv210_pm_drvinit(void)
+{
+ return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver);
+}
+arch_initcall(s5pv210_pm_drvinit);
diff --git a/arch/arm/mach-s5pv210/setup-fb-24bpp.c b/arch/arm/mach-s5pv210/setup-fb-24bpp.c
index 928cf1f125f..e932ebfac56 100644
--- a/arch/arm/mach-s5pv210/setup-fb-24bpp.c
+++ b/arch/arm/mach-s5pv210/setup-fb-24bpp.c
@@ -21,33 +21,21 @@
#include <mach/regs-clock.h>
#include <plat/gpio-cfg.h>
-void s5pv210_fb_gpio_setup_24bpp(void)
+static void s5pv210_fb_cfg_gpios(unsigned int base, unsigned int nr)
{
- unsigned int gpio = 0;
-
- for (gpio = S5PV210_GPF0(0); gpio <= S5PV210_GPF0(7); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
- }
+ s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2));
- for (gpio = S5PV210_GPF1(0); gpio <= S5PV210_GPF1(7); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
- }
+ for (; nr > 0; nr--, base++)
+ s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
+}
- for (gpio = S5PV210_GPF2(0); gpio <= S5PV210_GPF2(7); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
- }
- for (gpio = S5PV210_GPF3(0); gpio <= S5PV210_GPF3(3); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
- }
+void s5pv210_fb_gpio_setup_24bpp(void)
+{
+ s5pv210_fb_cfg_gpios(S5PV210_GPF0(0), 8);
+ s5pv210_fb_cfg_gpios(S5PV210_GPF1(0), 8);
+ s5pv210_fb_cfg_gpios(S5PV210_GPF2(0), 8);
+ s5pv210_fb_cfg_gpios(S5PV210_GPF3(0), 4);
/* Set DISPLAY_CONTROL register for Display path selection.
*
diff --git a/arch/arm/mach-s5pv210/setup-i2c0.c b/arch/arm/mach-s5pv210/setup-i2c0.c
index d38f7cb7e66..0f1cc3a1c1e 100644
--- a/arch/arm/mach-s5pv210/setup-i2c0.c
+++ b/arch/arm/mach-s5pv210/setup-i2c0.c
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */
void s3c_i2c0_cfg_gpio(struct platform_device *dev)
{
- s3c_gpio_cfgpin(S5PV210_GPD1(0), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PV210_GPD1(0), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPD1(1), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PV210_GPD1(1), S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgall_range(S5PV210_GPD1(0), 2,
+ S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
}
diff --git a/arch/arm/mach-s5pv210/setup-i2c1.c b/arch/arm/mach-s5pv210/setup-i2c1.c
index 148bb7857d8..f61365a34c5 100644
--- a/arch/arm/mach-s5pv210/setup-i2c1.c
+++ b/arch/arm/mach-s5pv210/setup-i2c1.c
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */
void s3c_i2c1_cfg_gpio(struct platform_device *dev)
{
- s3c_gpio_cfgpin(S5PV210_GPD1(2), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PV210_GPD1(2), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPD1(3), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PV210_GPD1(3), S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgall_range(S5PV210_GPD1(2), 2,
+ S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
}
diff --git a/arch/arm/mach-s5pv210/setup-i2c2.c b/arch/arm/mach-s5pv210/setup-i2c2.c
index 2396cb8c373..2f91b5cefbc 100644
--- a/arch/arm/mach-s5pv210/setup-i2c2.c
+++ b/arch/arm/mach-s5pv210/setup-i2c2.c
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */
void s3c_i2c2_cfg_gpio(struct platform_device *dev)
{
- s3c_gpio_cfgpin(S5PV210_GPD1(4), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PV210_GPD1(4), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPD1(5), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PV210_GPD1(5), S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgall_range(S5PV210_GPD1(4), 2,
+ S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
}
diff --git a/arch/arm/mach-s5pv210/setup-ide.c b/arch/arm/mach-s5pv210/setup-ide.c
index b558b1cc8d6..ea123d546bd 100644
--- a/arch/arm/mach-s5pv210/setup-ide.c
+++ b/arch/arm/mach-s5pv210/setup-ide.c
@@ -15,36 +15,25 @@
#include <plat/gpio-cfg.h>
+static void s5pv210_ide_cfg_gpios(unsigned int base, unsigned int nr)
+{
+ s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4));
+
+ for (; nr > 0; nr--, base++)
+ s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
+}
+
void s5pv210_ide_setup_gpio(void)
{
- unsigned int gpio = 0;
-
- for (gpio = S5PV210_GPJ0(0); gpio <= S5PV210_GPJ0(7); gpio++) {
- /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST,
- CF_DMACK */
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
- }
-
- for (gpio = S5PV210_GPJ2(0); gpio <= S5PV210_GPJ2(7); gpio++) {
- /*CF_Data[0 - 7] */
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
- }
-
- for (gpio = S5PV210_GPJ3(0); gpio <= S5PV210_GPJ3(7); gpio++) {
- /* CF_Data[8 - 15] */
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
- }
-
- for (gpio = S5PV210_GPJ4(0); gpio <= S5PV210_GPJ4(3); gpio++) {
- /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
- }
+ /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */
+ s5pv210_ide_cfg_gpios(S5PV210_GPJ0(0), 8);
+
+ /* CF_Data[0 - 7] */
+ s5pv210_ide_cfg_gpios(S5PV210_GPJ2(0), 8);
+
+ /* CF_Data[8 - 15] */
+ s5pv210_ide_cfg_gpios(S5PV210_GPJ3(0), 8);
+
+ /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
+ s5pv210_ide_cfg_gpios(S5PV210_GPJ4(0), 4);
}
diff --git a/arch/arm/mach-s5pv210/setup-keypad.c b/arch/arm/mach-s5pv210/setup-keypad.c
index 37b2790aafc..c56420a52f4 100644
--- a/arch/arm/mach-s5pv210/setup-keypad.c
+++ b/arch/arm/mach-s5pv210/setup-keypad.c
@@ -16,19 +16,9 @@
void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
{
- unsigned int gpio, end;
-
/* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */
- end = S5PV210_GPH3(rows);
- for (gpio = S5PV210_GPH3(0); gpio < end; gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPH3(0), rows, S3C_GPIO_SFN(3));
/* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */
- end = S5PV210_GPH2(cols);
- for (gpio = S5PV210_GPH2(0); gpio < end; gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPH2(0), cols, S3C_GPIO_SFN(3));
}
diff --git a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
index b18587b1ec5..746777d56df 100644
--- a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
+++ b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
@@ -26,26 +26,17 @@
void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
- unsigned int gpio;
/* Set all the necessary GPG0/GPG1 pins to special-function 2 */
- for (gpio = S5PV210_GPG0(0); gpio < S5PV210_GPG0(2); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPG0(0), 2, S3C_GPIO_SFN(2));
+
switch (width) {
case 8:
/* GPG1[3:6] special-funtion 3 */
- for (gpio = S5PV210_GPG1(3); gpio <= S5PV210_GPG1(6); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(3));
case 4:
/* GPG0[3:6] special-funtion 2 */
- for (gpio = S5PV210_GPG0(3); gpio <= S5PV210_GPG0(6); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPG0(3), 4, S3C_GPIO_SFN(2));
default:
break;
}
@@ -59,19 +50,12 @@ void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
- unsigned int gpio;
/* Set all the necessary GPG1[0:1] pins to special-function 2 */
- for (gpio = S5PV210_GPG1(0); gpio < S5PV210_GPG1(2); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPG1(0), 2, S3C_GPIO_SFN(2));
/* Data pin GPG1[3:6] to special-function 2 */
- for (gpio = S5PV210_GPG1(3); gpio <= S5PV210_GPG1(6); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(2));
if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP);
@@ -82,27 +66,17 @@ void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
- unsigned int gpio;
/* Set all the necessary GPG2[0:1] pins to special-function 2 */
- for (gpio = S5PV210_GPG2(0); gpio < S5PV210_GPG2(2); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPG2(0), 2, S3C_GPIO_SFN(2));
switch (width) {
case 8:
/* Data pin GPG3[3:6] to special-function 3 */
- for (gpio = S5PV210_GPG3(3); gpio <= S5PV210_GPG3(6); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(3));
case 4:
/* Data pin GPG2[3:6] to special-function 2 */
- for (gpio = S5PV210_GPG2(3); gpio <= S5PV210_GPG2(6); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPG2(3), 4, S3C_GPIO_SFN(2));
default:
break;
}
@@ -116,19 +90,12 @@ void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
- unsigned int gpio;
- /* Set all the necessary GPG3[0:2] pins to special-function 2 */
- for (gpio = S5PV210_GPG3(0); gpio < S5PV210_GPG3(2); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ /* Set all the necessary GPG3[0:1] pins to special-function 2 */
+ s3c_gpio_cfgrange_nopull(S5PV210_GPG3(0), 2, S3C_GPIO_SFN(2));
/* Data pin GPG3[3:6] to special-function 2 */
- for (gpio = S5PV210_GPG3(3); gpio <= S5PV210_GPG3(6); gpio++) {
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
- }
+ s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(2));
if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_setpull(S5PV210_GPG3(2), S3C_GPIO_PULL_UP);
diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S
new file mode 100644
index 00000000000..d4d222b716b
--- /dev/null
+++ b/arch/arm/mach-s5pv210/sleep.S
@@ -0,0 +1,170 @@
+/* linux/arch/arm/plat-s5p/sleep.S
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5PV210 power Manager (Suspend-To-RAM) support
+ * Based on S3C2410 sleep code by:
+ * Ben Dooks, (c) 2004 Simtec Electronics
+ *
+ * Based on PXA/SA1100 sleep code by:
+ * Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ * Cliff Brake, (c) 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/memory.h>
+
+ .text
+
+ /* s3c_cpu_save
+ *
+ * entry:
+ * r0 = save address (virtual addr of s3c_sleep_save_phys)
+ */
+
+ENTRY(s3c_cpu_save)
+
+ stmfd sp!, { r3 - r12, lr }
+
+ mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
+ mrc p15, 0, r5, c3, c0, 0 @ Domain ID
+ mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
+ mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
+ mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control
+ mrc p15, 0, r9, c1, c0, 0 @ Control register
+ mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
+ mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls
+ mrc p15, 0, r12, c10, c2, 0 @ Read PRRR
+ mrc p15, 0, r3, c10, c2, 1 @ READ NMRR
+
+ stmia r0, { r3 - r13 }
+
+ bl s3c_pm_cb_flushcache
+
+ ldr r0, =pm_cpu_sleep
+ ldr r0, [ r0 ]
+ mov pc, r0
+
+resume_with_mmu:
+ /*
+ * After MMU is turned on, restore the previous MMU table.
+ */
+ ldr r9 , =(PAGE_OFFSET - PHYS_OFFSET)
+ add r4, r4, r9
+ str r12, [r4]
+
+ ldmfd sp!, { r3 - r12, pc }
+
+ .ltorg
+
+ .data
+
+ .global s3c_sleep_save_phys
+s3c_sleep_save_phys:
+ .word 0
+
+ /* sleep magic, to allow the bootloader to check for an valid
+ * image to resume to. Must be the first word before the
+ * s3c_cpu_resume entry.
+ */
+
+ .word 0x2bedf00d
+
+ /* s3c_cpu_resume
+ *
+ * resume code entry for bootloader to call
+ *
+ * we must put this code here in the data segment as we have no
+ * other way of restoring the stack pointer after sleep, and we
+ * must not write to the code segment (code is read-only)
+ */
+
+ENTRY(s3c_cpu_resume)
+ mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+ msr cpsr_c, r0
+
+ mov r1, #0
+ mcr p15, 0, r1, c8, c7, 0 @ invalidate TLBs
+ mcr p15, 0, r1, c7, c5, 0 @ invalidate I Cache
+
+ ldr r0, s3c_sleep_save_phys @ address of restore block
+ ldmia r0, { r3 - r13 }
+
+ mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
+ mcr p15, 0, r5, c3, c0, 0 @ Domain ID
+
+ mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control
+ mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
+ mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
+
+ mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register
+
+ mov r0, #0
+ mcr p15, 0, r0, c8, c7, 0 @ Invalidate I & D TLB
+
+ mov r0, #0 @ restore copro access
+ mcr p15, 0, r11, c1, c0, 2 @ Co-processor access
+ mcr p15, 0, r0, c7, c5, 4
+
+ mcr p15, 0, r12, c10, c2, 0 @ write PRRR
+ mcr p15, 0, r3, c10, c2, 1 @ write NMRR
+
+ /*
+ * In Cortex-A8, when MMU is turned on, the pipeline is flushed.
+ * And there are no valid entries in the MMU table at this point.
+ * So before turning on the MMU, the MMU entry for the DRAM address
+ * range is added. After the MMU is turned on, the other entries
+ * in the MMU table will be restored.
+ */
+
+ /* r6 = Translation Table BASE0 */
+ mov r4, r6
+ mov r4, r4, LSR #14
+ mov r4, r4, LSL #14
+
+ /* Load address for adding to MMU table list */
+ ldr r11, =0xE010F000 @ INFORM0 reg.
+ ldr r10, [r11, #0]
+ mov r10, r10, LSR #18
+ bic r10, r10, #0x3
+ orr r4, r4, r10
+
+ /* Calculate MMU table entry */
+ mov r10, r10, LSL #18
+ ldr r5, =0x40E
+ orr r10, r10, r5
+
+ /* Back up originally data */
+ ldr r12, [r4]
+
+ /* Add calculated MMU table entry into MMU table list */
+ str r10, [r4]
+
+ ldr r2, =resume_with_mmu
+ mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc
+
+ nop
+ nop
+ nop
+ nop
+ nop @ second-to-last before mmu
+
+ mov pc, r2 @ go back to virtual address
+
+ .ltorg