dect
/
linux-2.6
Archived
13
0
Fork 0

ARM: arm-soc: SoC updates, take 2

This is the second batch of SoC updates for the 3.8 merge window,
 containing parts that had dependencies on earlier branches such that we
 couldn't include them with the first branch.
 
 These are general updates for Samsung Exynos, Renesas/shmobile and a
 topic branch that adds SMP support to Altera's socfpga platform.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJQy5gxAAoJEIwa5zzehBx3ab0P/1SSJYLNcn8rieIALLZaSH17
 lxVwyv/OMLmRual0eVjXN+mcNuAc05gemLUSNSrdFPrHhEGSqFz8x0C/A6o3Ovw/
 OxNNX3rQiZP86vKRVmT/did7yEkMmleKng19uOyBXN2p7f6lh01Y5NFTVE1dWiZG
 TJPEgWI9mrarUMarL90fBu7AlXPNJwfG0opmT5QWuZmcLlaRXFTqFU2U08e5rPp5
 9yrTn3fQCDx+eT7qUBiZfuH6sesMnofYWDNJSvV/aPI4UYsEcK6KyJUL8LBuTLQ7
 9LHqsJNHLnlqxDsq6N/B0/pno2rhgdbkPPtl0c0xw35anHWW86IUgWgSCbu16LDZ
 uKDV31tIsx8yhsm8QkSKwzEjVnablhVYORGByVkNYBVSgMobdxBNFog6iX9NNQxJ
 3Z1K0i65YPffDoK7CJorIxcxyvBuBR/KueUFpzEK05xzJlvhPK2NQSY5Je0qEaA3
 tZYt0WfMtLC0huhLxEL/xNXuErqvj18kOSal3CHmg2LWVaKCFKNuY/B71yF7xaTc
 qN3RGJdb5Dyh49CCzXVBSAKJozc+pB8RauGnM//UQf49lmFzQ7oaQjxNjS3zQrjA
 3LsbJ8cDbwWVKb8yRvR8BtnJl81yE58D6R/gEPjH33v4jRPLUONLyyhVI57Rf0tV
 SFjd8wRlsFakOQ4qnG/B
 =77Ct
 -----END PGP SIGNATURE-----

Merge tag 'soc2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM Soc updates, take 2, from Olof Johansson:
 "This is the second batch of SoC updates for the 3.8 merge window,
  containing parts that had dependencies on earlier branches such that
  we couldn't include them with the first branch.

  These are general updates for Samsung Exynos, Renesas/shmobile and a
  topic branch that adds SMP support to Altera's socfpga platform."

Fix up conflicts mostly as per Olof.

* tag 'soc2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc:
  ARM: EXYNOS: Clock settings for SATA and SATA PHY
  ARM: EXYNOS: Add ARM down clock support
  ARM: EXYNOS: Fix i2c suspend/resume for legacy controller
  ARM: EXYNOS: Add aliases for i2c controller
  ARM: EXYNOS: Setup legacy i2c controller interrupts
  sh: clkfwk: fixup unsed variable warning
  Revert "ARM: shmobile: r8a7779: Replace modify_scu_cpu_psr with scu_power_mode"
  Revert "ARM: shmobile: sh73a0: Replace modify_scu_cpu_psr with scu_power_mode"
  Revert "ARM: shmobile: emev2: Replace modify_scu_cpu_psr with scu_power_mode"
  ARM: highbank: use common debug_ll_io_init
  ARM: shmobile: sh7372: sh7372_fsiXck_clk become non-global
  ARM: shmobile: sh7372: remove fsidivx clock
  ARM: socfpga: mark secondary_trampoline as cpuinit
  socfpga: map uart into virtual address space so that early_printk() works
  ARM: socfpga: fix build break for allyesconfig
  ARM: socfpga: Enable SMP for socfpga
  ARM: EXYNOS: Add dp clock support for EXYNOS5
  ARM: SAMSUNG: call clk_get_rate for debugfs rate files
  ARM: SAMSUNG: add clock_tree debugfs file in clock
This commit is contained in:
Linus Torvalds 2012-12-14 14:38:28 -08:00
commit 6a57d104c8
24 changed files with 544 additions and 37 deletions

View File

@ -0,0 +1,11 @@
Altera SOCFPGA Reset Manager
Required properties:
- compatible : "altr,rst-mgr"
- reg : Should contain 1 register ranges(address and length)
Example:
rstmgr@ffd05000 {
compatible = "altr,rst-mgr";
reg = <0xffd05000 0x1000>;
};

View File

@ -0,0 +1,11 @@
Altera SOCFPGA System Manager
Required properties:
- compatible : "altr,sys-mgr"
- reg : Should contain 1 register ranges(address and length)
Example:
sysmgr@ffd08000 {
compatible = "altr,sys-mgr";
reg = <0xffd08000 0x1000>;
};

View File

@ -35,6 +35,15 @@
mshc1 = &dwmmc_1;
mshc2 = &dwmmc_2;
mshc3 = &dwmmc_3;
i2c0 = &i2c_0;
i2c1 = &i2c_1;
i2c2 = &i2c_2;
i2c3 = &i2c_3;
i2c4 = &i2c_4;
i2c5 = &i2c_5;
i2c6 = &i2c_6;
i2c7 = &i2c_7;
i2c8 = &i2c_8;
};
gic:interrupt-controller@10481000 {
@ -119,7 +128,7 @@
reg = <0x12170000 0x1ff>;
};
i2c@12C60000 {
i2c_0: i2c@12C60000 {
compatible = "samsung,s3c2440-i2c";
reg = <0x12C60000 0x100>;
interrupts = <0 56 0>;
@ -127,7 +136,7 @@
#size-cells = <0>;
};
i2c@12C70000 {
i2c_1: i2c@12C70000 {
compatible = "samsung,s3c2440-i2c";
reg = <0x12C70000 0x100>;
interrupts = <0 57 0>;
@ -135,7 +144,7 @@
#size-cells = <0>;
};
i2c@12C80000 {
i2c_2: i2c@12C80000 {
compatible = "samsung,s3c2440-i2c";
reg = <0x12C80000 0x100>;
interrupts = <0 58 0>;
@ -143,7 +152,7 @@
#size-cells = <0>;
};
i2c@12C90000 {
i2c_3: i2c@12C90000 {
compatible = "samsung,s3c2440-i2c";
reg = <0x12C90000 0x100>;
interrupts = <0 59 0>;
@ -151,7 +160,7 @@
#size-cells = <0>;
};
i2c@12CA0000 {
i2c_4: i2c@12CA0000 {
compatible = "samsung,s3c2440-i2c";
reg = <0x12CA0000 0x100>;
interrupts = <0 60 0>;
@ -159,7 +168,7 @@
#size-cells = <0>;
};
i2c@12CB0000 {
i2c_5: i2c@12CB0000 {
compatible = "samsung,s3c2440-i2c";
reg = <0x12CB0000 0x100>;
interrupts = <0 61 0>;
@ -167,7 +176,7 @@
#size-cells = <0>;
};
i2c@12CC0000 {
i2c_6: i2c@12CC0000 {
compatible = "samsung,s3c2440-i2c";
reg = <0x12CC0000 0x100>;
interrupts = <0 62 0>;
@ -175,7 +184,7 @@
#size-cells = <0>;
};
i2c@12CD0000 {
i2c_7: i2c@12CD0000 {
compatible = "samsung,s3c2440-i2c";
reg = <0x12CD0000 0x100>;
interrupts = <0 63 0>;
@ -183,7 +192,7 @@
#size-cells = <0>;
};
i2c@12CE0000 {
i2c_8: i2c@12CE0000 {
compatible = "samsung,s3c2440-hdmiphy-i2c";
reg = <0x12CE0000 0x1000>;
interrupts = <0 64 0>;

View File

@ -143,5 +143,15 @@
reg-shift = <2>;
reg-io-width = <4>;
};
rstmgr@ffd05000 {
compatible = "altr,rst-mgr";
reg = <0xffd05000 0x1000>;
};
sysmgr@ffd08000 {
compatible = "altr,sys-mgr";
reg = <0xffd08000 0x4000>;
};
};
};

View File

@ -18,9 +18,10 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_ARCH_SOCFPGA=y
CONFIG_MACH_SOCFPGA_CYCLONE5=y
CONFIG_ARM_THUMBEE=y
# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
# CONFIG_CACHE_L2X0 is not set
CONFIG_HIGH_RES_TIMERS=y
CONFIG_VMSPLIT_2G=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_AEABI=y
CONFIG_ZBOOT_ROM_TEXT=0x0

View File

@ -80,6 +80,8 @@ static struct sleep_save exynos5_clock_save[] = {
SAVE_ITEM(EXYNOS5_VPLL_CON0),
SAVE_ITEM(EXYNOS5_VPLL_CON1),
SAVE_ITEM(EXYNOS5_VPLL_CON2),
SAVE_ITEM(EXYNOS5_PWR_CTRL1),
SAVE_ITEM(EXYNOS5_PWR_CTRL2),
};
#endif
@ -661,15 +663,20 @@ static struct clk exynos5_init_clocks_off[] = {
.ctrlbit = (1 << 15),
}, {
.name = "sata",
.devname = "ahci",
.devname = "exynos5-sata",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "sata_phy",
.name = "sata-phy",
.devname = "exynos5-sata-phy",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 24),
}, {
.name = "sata_phy_i2c",
.name = "i2c",
.devname = "exynos5-sata-phy-i2c",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 25),
}, {
@ -692,6 +699,11 @@ static struct clk exynos5_init_clocks_off[] = {
.devname = "exynos5-mixer",
.enable = exynos5_clk_ip_disp1_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "dp",
.devname = "exynos-dp",
.enable = exynos5_clk_ip_disp1_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "jpeg",
.enable = exynos5_clk_ip_gen_ctrl,
@ -1239,6 +1251,16 @@ static struct clksrc_clk exynos5_clksrcs[] = {
.sources = &exynos5_clkset_aclk,
.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
}, {
.clk = {
.name = "sclk_sata",
.devname = "exynos5-sata",
.enable = exynos5_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 24),
},
.sources = &exynos5_clkset_aclk,
.reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 24, .size = 1 },
.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS0, .shift = 20, .size = 4 },
}, {
.clk = {
.name = "sclk_gscl_wrap",

View File

@ -21,6 +21,7 @@
#include <asm/suspend.h>
#include <asm/unified.h>
#include <asm/cpuidle.h>
#include <mach/regs-clock.h>
#include <mach/regs-pmu.h>
#include <mach/pmu.h>
@ -157,12 +158,47 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
return exynos4_enter_core0_aftr(dev, drv, new_index);
}
static void __init exynos5_core_down_clk(void)
{
unsigned int tmp;
/*
* Enable arm clock down (in idle) and set arm divider
* ratios in WFI/WFE state.
*/
tmp = PWR_CTRL1_CORE2_DOWN_RATIO | \
PWR_CTRL1_CORE1_DOWN_RATIO | \
PWR_CTRL1_DIV2_DOWN_EN | \
PWR_CTRL1_DIV1_DOWN_EN | \
PWR_CTRL1_USE_CORE1_WFE | \
PWR_CTRL1_USE_CORE0_WFE | \
PWR_CTRL1_USE_CORE1_WFI | \
PWR_CTRL1_USE_CORE0_WFI;
__raw_writel(tmp, EXYNOS5_PWR_CTRL1);
/*
* Enable arm clock up (on exiting idle). Set arm divider
* ratios when not in idle along with the standby duration
* ratios.
*/
tmp = PWR_CTRL2_DIV2_UP_EN | \
PWR_CTRL2_DIV1_UP_EN | \
PWR_CTRL2_DUR_STANDBY2_VAL | \
PWR_CTRL2_DUR_STANDBY1_VAL | \
PWR_CTRL2_CORE2_UP_RATIO | \
PWR_CTRL2_CORE1_UP_RATIO;
__raw_writel(tmp, EXYNOS5_PWR_CTRL2);
}
static int __init exynos4_init_cpuidle(void)
{
int i, max_cpuidle_state, cpu_id;
struct cpuidle_device *device;
struct cpuidle_driver *drv = &exynos4_idle_driver;
if (soc_is_exynos5250())
exynos5_core_down_clk();
/* Setup cpuidle driver */
drv->state_count = (sizeof(exynos4_cpuidle_set) /
sizeof(struct cpuidle_state));

View File

@ -267,6 +267,9 @@
#define EXYNOS5_CLKDIV_STATCPU0 EXYNOS_CLKREG(0x00600)
#define EXYNOS5_CLKDIV_STATCPU1 EXYNOS_CLKREG(0x00604)
#define EXYNOS5_PWR_CTRL1 EXYNOS_CLKREG(0x01020)
#define EXYNOS5_PWR_CTRL2 EXYNOS_CLKREG(0x01024)
#define EXYNOS5_MPLL_CON0 EXYNOS_CLKREG(0x04100)
#define EXYNOS5_CLKSRC_CORE1 EXYNOS_CLKREG(0x04204)
@ -344,6 +347,22 @@
#define EXYNOS5_EPLLCON0_LOCKED_SHIFT (29)
#define PWR_CTRL1_CORE2_DOWN_RATIO (7 << 28)
#define PWR_CTRL1_CORE1_DOWN_RATIO (7 << 16)
#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9)
#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8)
#define PWR_CTRL1_USE_CORE1_WFE (1 << 5)
#define PWR_CTRL1_USE_CORE0_WFE (1 << 4)
#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
#define PWR_CTRL2_DIV2_UP_EN (1 << 25)
#define PWR_CTRL2_DIV1_UP_EN (1 << 24)
#define PWR_CTRL2_DUR_STANDBY2_VAL (1 << 16)
#define PWR_CTRL2_DUR_STANDBY1_VAL (1 << 8)
#define PWR_CTRL2_CORE2_UP_RATIO (1 << 4)
#define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
/* Compatibility defines and inclusion */
#include <mach/regs-pmu.h>

View File

@ -15,6 +15,7 @@
#include <mach/map.h>
#define S5P_PMUREG(x) (S5P_VA_PMU + (x))
#define S5P_SYSREG(x) (S3C_VA_SYS + (x))
#define S5P_CENTRAL_SEQ_CONFIGURATION S5P_PMUREG(0x0200)
@ -231,6 +232,8 @@
/* For EXYNOS5 */
#define EXYNOS5_SYS_I2C_CFG S5P_SYSREG(0x0234)
#define EXYNOS5_AUTO_WDTRESET_DISABLE S5P_PMUREG(0x0408)
#define EXYNOS5_MASK_WDTRESET_REQUEST S5P_PMUREG(0x040C)

View File

@ -13,11 +13,12 @@
#include <linux/of_fdt.h>
#include <linux/serial_core.h>
#include <linux/memblock.h>
#include <linux/of_fdt.h>
#include <linux/io.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
#include <mach/map.h>
#include <mach/regs-pmu.h>
#include <plat/cpu.h>
#include <plat/regs-serial.h>
@ -124,6 +125,28 @@ static void __init exynos5_dt_map_io(void)
static void __init exynos5_dt_machine_init(void)
{
struct device_node *i2c_np;
const char *i2c_compat = "samsung,s3c2440-i2c";
unsigned int tmp;
/*
* Exynos5's legacy i2c controller and new high speed i2c
* controller have muxed interrupt sources. By default the
* interrupts for 4-channel HS-I2C controller are enabled.
* If node for first four channels of legacy i2c controller
* are available then re-configure the interrupts via the
* system register.
*/
for_each_compatible_node(i2c_np, NULL, i2c_compat) {
if (of_device_is_available(i2c_np)) {
if (of_alias_get_id(i2c_np, "i2c") < 4) {
tmp = readl(EXYNOS5_SYS_I2C_CFG);
writel(tmp & ~(0x1 << of_alias_get_id(i2c_np, "i2c")),
EXYNOS5_SYS_I2C_CFG);
}
}
}
if (of_machine_is_compatible("samsung,exynos5250"))
of_platform_populate(NULL, of_default_bus_match_table,
exynos5250_auxdata_lookup, NULL);

View File

@ -62,6 +62,10 @@ static struct sleep_save exynos4_vpll_save[] = {
SAVE_ITEM(EXYNOS4_VPLL_CON1),
};
static struct sleep_save exynos5_sys_save[] = {
SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
};
static struct sleep_save exynos_core_save[] = {
/* SROM side */
SAVE_ITEM(S5P_SROM_BW),
@ -101,6 +105,7 @@ static void exynos_pm_prepare(void)
s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
} else {
s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
/* Disable USE_RETENTION of JPEG_MEM_OPTION */
tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
@ -304,6 +309,10 @@ static void exynos_pm_resume(void)
__raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
__raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
if (soc_is_exynos5250())
s3c_pm_do_restore(exynos5_sys_save,
ARRAY_SIZE(exynos5_sys_save));
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
if (!soc_is_exynos5250()) {

View File

@ -295,10 +295,10 @@ struct clk sh7372_pllc2_clk = {
};
/* External input clock (pin name: FSIACK/FSIBCK ) */
struct clk sh7372_fsiack_clk = {
static struct clk fsiack_clk = {
};
struct clk sh7372_fsibck_clk = {
static struct clk fsibck_clk = {
};
static struct clk *main_clks[] = {
@ -314,8 +314,8 @@ static struct clk *main_clks[] = {
&pllc1_clk,
&pllc1_div2_clk,
&sh7372_pllc2_clk,
&sh7372_fsiack_clk,
&sh7372_fsibck_clk,
&fsiack_clk,
&fsibck_clk,
};
static void div4_kick(struct clk *clk)
@ -399,14 +399,14 @@ static struct clk *hdmi_parent[] = {
static struct clk *fsiackcr_parent[] = {
[0] = &pllc1_div2_clk,
[1] = &sh7372_pllc2_clk,
[2] = &sh7372_fsiack_clk, /* external input for FSI A */
[2] = &fsiack_clk, /* external input for FSI A */
[3] = NULL, /* setting prohibited */
};
static struct clk *fsibckcr_parent[] = {
[0] = &pllc1_div2_clk,
[1] = &sh7372_pllc2_clk,
[2] = &sh7372_fsibck_clk, /* external input for FSI B */
[2] = &fsibck_clk, /* external input for FSI B */
[3] = NULL, /* setting prohibited */
};
@ -507,8 +507,8 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
CLKDEV_CON_ID("pllc2_clk", &sh7372_pllc2_clk),
CLKDEV_CON_ID("fsidiva", &fsidivs[FSIDIV_A]),
CLKDEV_CON_ID("fsidivb", &fsidivs[FSIDIV_B]),
CLKDEV_CON_ID("fsiack", &fsiack_clk),
CLKDEV_CON_ID("fsibck", &fsibck_clk),
/* DIV4 clocks */
CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
@ -606,8 +606,8 @@ static struct clk_lookup lookups[] = {
CLKDEV_ICK_ID("spu2", "sh_fsi2", &mstp_clks[MSTP223]),
CLKDEV_ICK_ID("diva", "sh_fsi2", &fsidivs[FSIDIV_A]),
CLKDEV_ICK_ID("divb", "sh_fsi2", &fsidivs[FSIDIV_B]),
CLKDEV_ICK_ID("xcka", "sh_fsi2", &sh7372_fsiack_clk),
CLKDEV_ICK_ID("xckb", "sh_fsi2", &sh7372_fsibck_clk),
CLKDEV_ICK_ID("xcka", "sh_fsi2", &fsiack_clk),
CLKDEV_ICK_ID("xckb", "sh_fsi2", &fsibck_clk),
};
void __init sh7372_clock_init(void)

View File

@ -477,8 +477,6 @@ extern struct clk sh7372_extal2_clk;
extern struct clk sh7372_dv_clki_clk;
extern struct clk sh7372_dv_clki_div2_clk;
extern struct clk sh7372_pllc2_clk;
extern struct clk sh7372_fsiack_clk;
extern struct clk sh7372_fsibck_clk;
extern void sh7372_intcs_suspend(void);
extern void sh7372_intcs_resume(void);

View File

@ -32,8 +32,24 @@
#define EMEV2_SCU_BASE 0x1e000000
static DEFINE_SPINLOCK(scu_lock);
static void __iomem *scu_base;
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
{
unsigned long tmp;
/* we assume this code is running on a different cpu
* than the one that is changing coherency setting */
spin_lock(&scu_lock);
tmp = readl(scu_base + 8);
tmp &= ~clr;
tmp |= set;
writel(tmp, scu_base + 8);
spin_unlock(&scu_lock);
}
static unsigned int __init emev2_get_core_count(void)
{
if (!scu_base) {
@ -79,7 +95,7 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *
cpu = cpu_logical_map(cpu);
/* enable cache coherency */
scu_power_mode(scu_base, 0);
modify_scu_cpu_psr(0, 3 << (cpu * 8));
/* Tell ROM loader about our vector (in headsmp.S) */
emev2_set_boot_vector(__pa(shmobile_secondary_vector));
@ -90,10 +106,12 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *
static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
{
int cpu = cpu_logical_map(0);
scu_enable(scu_base);
/* enable cache coherency on CPU0 */
scu_power_mode(scu_base, 0);
modify_scu_cpu_psr(0, 3 << (cpu * 8));
}
static void __init emev2_smp_init_cpus(void)

View File

@ -61,6 +61,9 @@ static void __iomem *scu_base_addr(void)
return (void __iomem *)0xf0000000;
}
static DEFINE_SPINLOCK(scu_lock);
static unsigned long tmp;
#ifdef CONFIG_HAVE_ARM_TWD
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
@ -70,6 +73,20 @@ void __init r8a7779_register_twd(void)
}
#endif
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
{
void __iomem *scu_base = scu_base_addr();
spin_lock(&scu_lock);
tmp = __raw_readl(scu_base + 8);
tmp &= ~clr;
tmp |= set;
spin_unlock(&scu_lock);
/* disable cache coherency after releasing the lock */
__raw_writel(tmp, scu_base + 8);
}
static unsigned int __init r8a7779_get_core_count(void)
{
void __iomem *scu_base = scu_base_addr();
@ -85,7 +102,7 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
cpu = cpu_logical_map(cpu);
/* disable cache coherency */
scu_power_mode(scu_base_addr(), 3);
modify_scu_cpu_psr(3 << (cpu * 8), 0);
if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
ch = r8a7779_ch_cpu[cpu];
@ -128,7 +145,7 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
cpu = cpu_logical_map(cpu);
/* enable cache coherency */
scu_power_mode(scu_base_addr(), 0);
modify_scu_cpu_psr(0, 3 << (cpu * 8));
if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
ch = r8a7779_ch_cpu[cpu];
@ -141,13 +158,15 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
{
int cpu = cpu_logical_map(0);
scu_enable(scu_base_addr());
/* Map the reset vector (in headsmp.S) */
__raw_writel(__pa(shmobile_secondary_vector), AVECR);
/* enable cache coherency on CPU0 */
scu_power_mode(scu_base_addr(), 0);
modify_scu_cpu_psr(0, 3 << (cpu * 8));
r8a7779_pm_init();

View File

@ -41,6 +41,9 @@ static void __iomem *scu_base_addr(void)
return (void __iomem *)0xf0000000;
}
static DEFINE_SPINLOCK(scu_lock);
static unsigned long tmp;
#ifdef CONFIG_HAVE_ARM_TWD
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
void __init sh73a0_register_twd(void)
@ -49,6 +52,20 @@ void __init sh73a0_register_twd(void)
}
#endif
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
{
void __iomem *scu_base = scu_base_addr();
spin_lock(&scu_lock);
tmp = __raw_readl(scu_base + 8);
tmp &= ~clr;
tmp |= set;
spin_unlock(&scu_lock);
/* disable cache coherency after releasing the lock */
__raw_writel(tmp, scu_base + 8);
}
static unsigned int __init sh73a0_get_core_count(void)
{
void __iomem *scu_base = scu_base_addr();
@ -66,7 +83,7 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
cpu = cpu_logical_map(cpu);
/* enable cache coherency */
scu_power_mode(scu_base_addr(), 0);
modify_scu_cpu_psr(0, 3 << (cpu * 8));
if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3)
__raw_writel(1 << cpu, WUPCR); /* wake up */
@ -78,6 +95,8 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
{
int cpu = cpu_logical_map(0);
scu_enable(scu_base_addr());
/* Map the reset vector (in headsmp.S) */
@ -85,7 +104,7 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
__raw_writel(__pa(shmobile_secondary_vector), SBAR);
/* enable cache coherency on CPU0 */
scu_power_mode(scu_base_addr(), 0);
modify_scu_cpu_psr(0, 3 << (cpu * 8));
}
static void __init sh73a0_smp_init_cpus(void)

View File

@ -12,5 +12,6 @@ config ARCH_SOCFPGA
select GENERIC_CLOCKEVENTS
select GPIO_PL061 if GPIOLIB
select HAVE_ARM_SCU
select HAVE_SMP
select SPARSE_IRQ
select USE_OF

View File

@ -3,3 +3,4 @@
#
obj-y := socfpga.o
obj-$(CONFIG_SMP) += headsmp.o platsmp.o

View File

@ -0,0 +1,34 @@
/*
* Copyright 2012 Pavel Machek <pavel@denx.de>
* Copyright (C) 2012 Altera Corporation
*
* 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
*/
#ifndef __MACH_CORE_H
#define __MACH_CORE_H
extern void secondary_startup(void);
extern void __iomem *socfpga_scu_base_addr;
extern void socfpga_init_clocks(void);
extern void socfpga_sysmgr_init(void);
extern struct smp_operations socfpga_smp_ops;
extern char secondary_trampoline, secondary_trampoline_end;
#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
#endif

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2003 ARM Limited
* Copyright (c) u-boot contributors
* Copyright (c) 2012 Pavel Machek <pavel@denx.de>
*
* 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>
__CPUINIT
.arch armv7-a
#define CPU1_START_ADDR 0xffd08010
ENTRY(secondary_trampoline)
movw r0, #:lower16:CPU1_START_ADDR
movt r0, #:upper16:CPU1_START_ADDR
ldr r1, [r0]
bx r1
ENTRY(secondary_trampoline_end)

View File

@ -0,0 +1,116 @@
/*
* Copyright 2010-2011 Calxeda, Inc.
* Copyright 2012 Pavel Machek <pavel@denx.de>
* Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
* Copyright (C) 2012 Altera Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
#include <asm/smp_scu.h>
#include <asm/smp_plat.h>
#include "core.h"
extern void __iomem *sys_manager_base_addr;
extern void __iomem *rst_manager_base_addr;
static void __cpuinit socfpga_secondary_init(unsigned int cpu)
{
/*
* 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_secondary_init(0);
}
static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
__raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
flush_cache_all();
smp_wmb();
outer_clean_range(0, trampoline_size);
/* This will release CPU #1 out of reset.*/
__raw_writel(0, rst_manager_base_addr + 0x10);
return 0;
}
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system.
*/
static void __init socfpga_smp_init_cpus(void)
{
unsigned int i, ncores;
ncores = scu_get_core_count(socfpga_scu_base_addr);
for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
/* sanity check */
if (ncores > num_possible_cpus()) {
pr_warn("socfpga: no. of cores (%d) greater than configured"
"maximum of %d - clipping\n", ncores, num_possible_cpus());
ncores = num_possible_cpus();
}
for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
set_smp_cross_call(gic_raise_softirq);
}
static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
{
scu_enable(socfpga_scu_base_addr);
}
/*
* platform-specific code to shutdown a CPU
*
* Called with IRQs disabled
*/
static void socfpga_cpu_die(unsigned int cpu)
{
cpu_do_idle();
/* We should have never returned from idle */
panic("cpu %d unexpectedly exit from shutdown\n", cpu);
}
struct smp_operations socfpga_smp_ops __initdata = {
.smp_init_cpus = socfpga_smp_init_cpus,
.smp_prepare_cpus = socfpga_smp_prepare_cpus,
.smp_secondary_init = socfpga_secondary_init,
.smp_boot_secondary = socfpga_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = socfpga_cpu_die,
#endif
};

View File

@ -15,23 +15,73 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/dw_apb_timer.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/gic.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
extern void socfpga_init_clocks(void);
#include "core.h"
void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
void __iomem *sys_manager_base_addr;
void __iomem *rst_manager_base_addr;
static struct map_desc scu_io_desc __initdata = {
.virtual = SOCFPGA_SCU_VIRT_BASE,
.pfn = 0, /* run-time */
.length = SZ_8K,
.type = MT_DEVICE,
};
static struct map_desc uart_io_desc __initdata = {
.virtual = 0xfec02000,
.pfn = __phys_to_pfn(0xffc02000),
.length = SZ_8K,
.type = MT_DEVICE,
};
static void __init socfpga_scu_map_io(void)
{
unsigned long base;
/* Get SCU base */
asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
scu_io_desc.pfn = __phys_to_pfn(base);
iotable_init(&scu_io_desc, 1);
}
static void __init socfpga_map_io(void)
{
socfpga_scu_map_io();
iotable_init(&uart_io_desc, 1);
early_printk("Early printk initialized\n");
}
const static struct of_device_id irq_match[] = {
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
{}
};
void __init socfpga_sysmgr_init(void)
{
struct device_node *np;
np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
sys_manager_base_addr = of_iomap(np, 0);
np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
rst_manager_base_addr = of_iomap(np, 0);
}
static void __init gic_init_irq(void)
{
of_irq_init(irq_match);
socfpga_sysmgr_init();
}
static void socfpga_cyclone5_restart(char mode, const char *cmd)
@ -53,6 +103,8 @@ static const char *altera_dt_match[] = {
};
DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
.smp = smp_ops(socfpga_smp_ops),
.map_io = socfpga_map_io,
.init_irq = gic_init_irq,
.handle_irq = gic_handle_irq,
.timer = &dw_apb_timer,

View File

@ -389,6 +389,72 @@ int __init s3c24xx_register_baseclocks(unsigned long xtal)
static struct dentry *clk_debugfs_root;
static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
{
struct clk *child;
const char *state;
char buf[255] = { 0 };
int n = 0;
if (c->name)
n = snprintf(buf, sizeof(buf) - 1, "%s", c->name);
if (c->devname)
n += snprintf(buf + n, sizeof(buf) - 1 - n, ":%s", c->devname);
state = (c->usage > 0) ? "on" : "off";
seq_printf(s, "%*s%-*s %-6s %-3d %-10lu\n",
level * 3 + 1, "",
50 - level * 3, buf,
state, c->usage, clk_get_rate(c));
list_for_each_entry(child, &clocks, list) {
if (child->parent != c)
continue;
clock_tree_show_one(s, child, level + 1);
}
}
static int clock_tree_show(struct seq_file *s, void *data)
{
struct clk *c;
unsigned long flags;
seq_printf(s, " clock state ref rate\n");
seq_printf(s, "----------------------------------------------------\n");
spin_lock_irqsave(&clocks_lock, flags);
list_for_each_entry(c, &clocks, list)
if (c->parent == NULL)
clock_tree_show_one(s, c, 0);
spin_unlock_irqrestore(&clocks_lock, flags);
return 0;
}
static int clock_tree_open(struct inode *inode, struct file *file)
{
return single_open(file, clock_tree_show, inode->i_private);
}
static const struct file_operations clock_tree_fops = {
.open = clock_tree_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int clock_rate_show(void *data, u64 *val)
{
struct clk *c = data;
*val = clk_get_rate(c);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_rate_show, NULL, "%llu\n");
static int clk_debugfs_register_one(struct clk *c)
{
int err;
@ -411,7 +477,7 @@ static int clk_debugfs_register_one(struct clk *c)
goto err_out;
}
d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
d = debugfs_create_file("rate", S_IRUGO, c->dent, c, &clock_rate_fops);
if (!d) {
err = -ENOMEM;
goto err_out;
@ -446,13 +512,18 @@ static int __init clk_debugfs_init(void)
{
struct clk *c;
struct dentry *d;
int err;
int err = -ENOMEM;
d = debugfs_create_dir("clock", NULL);
if (!d)
return -ENOMEM;
clk_debugfs_root = d;
d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
&clock_tree_fops);
if (!d)
goto err_out;
list_for_each_entry(c, &clocks, list) {
err = clk_debugfs_register(c);
if (err)

View File

@ -401,7 +401,6 @@ static int fsidiv_enable(struct clk *clk)
static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
{
u32 val;
int idx;
idx = (clk->parent->rate / rate) & 0xffff;