Commit 6b8eda04 authored by Kukjin Kim's avatar Kukjin Kim

Merge branch 'next-s5pv310' into for-next

parents a639718b 516607d6
......@@ -704,6 +704,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
......@@ -904,6 +913,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"
......@@ -1100,10 +1111,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
......@@ -1172,9 +1184,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
......@@ -1186,7 +1199,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
......
......@@ -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
......
# 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
# 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
zreladdr-y := 0x40008000
params_phys-y := 0x40000100
/* 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();
}
/* 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);
}
/*
* 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
/* 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>
/* 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
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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);
}
/* 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);
}
}
/* 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);
}
/* 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
/* 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
/* 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);
}
}
/*
* 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);
}
/*
* 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);
}
/*
* 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);
}
/* 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,
};
......@@ -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
......
......@@ -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
......
......@@ -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),
......
......@@ -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)
......
......@@ -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)
......
/* 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
......@@ -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);
......
......@@ -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
......
......@@ -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 */
......
......@@ -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
......
......@@ -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";
......
......@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment