summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r--arch/arm/mach-shmobile/common.h4
-rw-r--r--arch/arm/mach-shmobile/headsmp.S55
-rw-r--r--arch/arm/mach-shmobile/platsmp-apmu.c1
-rw-r--r--arch/arm/mach-shmobile/pm-rcar-gen2.c15
-rw-r--r--arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c25
5 files changed, 89 insertions, 11 deletions
diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h
index a8fa4f7..43c1ac69 100644
--- a/arch/arm/mach-shmobile/common.h
+++ b/arch/arm/mach-shmobile/common.h
@@ -7,6 +7,10 @@ extern void shmobile_init_delay(void);
extern void shmobile_boot_vector(void);
extern unsigned long shmobile_boot_fn;
extern unsigned long shmobile_boot_size;
+extern void shmobile_boot_vector_gen2(void);
+extern unsigned long shmobile_boot_fn_gen2;
+extern unsigned long shmobile_boot_cpu_gen2;
+extern unsigned long shmobile_boot_size_gen2;
extern void shmobile_smp_boot(void);
extern void shmobile_smp_sleep(void);
extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
index 32e0bf6..cef8e8c 100644
--- a/arch/arm/mach-shmobile/headsmp.S
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -16,6 +16,11 @@
#include <asm/assembler.h>
#include <asm/memory.h>
+#define SCTLR_MMU 0x01
+#define BOOTROM_ADDRESS 0xE6340000
+#define RWTCSRA_ADDRESS 0xE6020004
+#define RWTCSRA_WOVF 0x10
+
/*
* Reset vector for secondary CPUs.
* This will be mapped at address 0 by SBAR register.
@@ -37,6 +42,56 @@ shmobile_boot_fn:
shmobile_boot_size:
.long . - shmobile_boot_vector
+#ifdef CONFIG_ARCH_RCAR_GEN2
+/*
+ * Reset vector for R-Car Gen2 and RZ/G1 secondary CPUs.
+ * This will be mapped at address 0 by SBAR register.
+ */
+ENTRY(shmobile_boot_vector_gen2)
+ mrc p15, 0, r0, c0, c0, 5 @ r0 = MPIDR
+ ldr r1, shmobile_boot_cpu_gen2
+ cmp r0, r1
+ bne shmobile_smp_continue_gen2
+
+ mrc p15, 0, r1, c1, c0, 0 @ r1 = SCTLR
+ and r0, r1, #SCTLR_MMU
+ cmp r0, #SCTLR_MMU
+ beq shmobile_smp_continue_gen2
+
+ ldr r0, rwtcsra
+ mov r1, #0
+ ldrb r1, [r0]
+ and r0, r1, #RWTCSRA_WOVF
+ cmp r0, #RWTCSRA_WOVF
+ bne shmobile_smp_continue_gen2
+
+ ldr r0, bootrom
+ bx r0
+
+shmobile_smp_continue_gen2:
+ ldr r1, shmobile_boot_fn_gen2
+ bx r1
+
+ENDPROC(shmobile_boot_vector_gen2)
+
+ .align 4
+rwtcsra:
+ .word RWTCSRA_ADDRESS
+bootrom:
+ .word BOOTROM_ADDRESS
+ .globl shmobile_boot_cpu_gen2
+shmobile_boot_cpu_gen2:
+ .word 0x00000000
+
+ .align 2
+ .globl shmobile_boot_fn_gen2
+shmobile_boot_fn_gen2:
+ .space 4
+ .globl shmobile_boot_size_gen2
+shmobile_boot_size_gen2:
+ .long . - shmobile_boot_vector_gen2
+#endif /* CONFIG_ARCH_RCAR_GEN2 */
+
/*
* Per-CPU SMP boot function/argument selection code based on MPIDR
*/
diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c
index 4422b61..ba732ef 100644
--- a/arch/arm/mach-shmobile/platsmp-apmu.c
+++ b/arch/arm/mach-shmobile/platsmp-apmu.c
@@ -191,6 +191,7 @@ static void __init shmobile_smp_apmu_setup_boot(void)
{
/* install boot code shared by all CPUs */
shmobile_boot_fn = __pa_symbol(shmobile_smp_boot);
+ shmobile_boot_fn_gen2 = shmobile_boot_fn;
}
void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
diff --git a/arch/arm/mach-shmobile/pm-rcar-gen2.c b/arch/arm/mach-shmobile/pm-rcar-gen2.c
index e5f215c..5a798b4 100644
--- a/arch/arm/mach-shmobile/pm-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/pm-rcar-gen2.c
@@ -17,6 +17,7 @@
#include <linux/smp.h>
#include <linux/soc/renesas/rcar-sysc.h>
#include <asm/io.h>
+#include <asm/cputype.h>
#include "common.h"
#include "rcar-gen2.h"
@@ -37,7 +38,6 @@
#define CA7RESCNT_CODE 0x5a5a0000
#define CA7RESCNT_CPUS 0xf /* CPU0-3 */
-
/* On-chip RAM */
#define ICRAM1 0xe63c0000 /* Inter Connect RAM1 (4 KiB) */
@@ -119,8 +119,17 @@ map:
p = ioremap(res.start, resource_size(&res));
if (!p)
return;
-
- memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+ /*
+ * install the reset vector, use the largest version if we have enough
+ * memory available
+ */
+ if (resource_size(&res) >= shmobile_boot_size_gen2) {
+ shmobile_boot_cpu_gen2 = read_cpuid_mpidr();
+ memcpy_toio(p, shmobile_boot_vector_gen2,
+ shmobile_boot_size_gen2);
+ } else {
+ memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+ }
iounmap(p);
/* setup reset vectors */
diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
index 44438f3..93f628a 100644
--- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
@@ -1,9 +1,9 @@
/*
* R-Car Generation 2 da9063/da9210 regulator quirk
*
- * The r8a7790/lager and r8a7791/koelsch development boards have da9063 and
- * da9210 regulators. Both regulators have their interrupt request lines tied
- * to the same interrupt pin (IRQ2) on the SoC.
+ * Certain Gen2 development boards have an da9063 and one or more da9210
+ * regulators. All of these regulators have their interrupt request lines
+ * tied to the same interrupt pin (IRQ2) on the SoC.
*
* After cold boot or da9063-induced restart, both the da9063 and da9210 seem
* to assert their interrupt request lines. Hence as soon as one driver
@@ -50,7 +50,7 @@ static void __iomem *irqc;
static u8 da9063_irq_clr[] = { DA9063_REG_IRQ_MASK_A, 0xff, 0xff, 0xff, 0xff };
static u8 da9210_irq_clr[] = { DA9210_REG_MASK_A, 0xff, 0xff };
-static struct i2c_msg da9xxx_msgs[2] = {
+static struct i2c_msg da9xxx_msgs[3] = {
{
.addr = 0x58,
.len = ARRAY_SIZE(da9063_irq_clr),
@@ -59,6 +59,10 @@ static struct i2c_msg da9xxx_msgs[2] = {
.addr = 0x68,
.len = ARRAY_SIZE(da9210_irq_clr),
.buf = da9210_irq_clr,
+ }, {
+ .addr = 0x70,
+ .len = ARRAY_SIZE(da9210_irq_clr),
+ .buf = da9210_irq_clr,
},
};
@@ -85,12 +89,16 @@ static int regulator_quirk_notify(struct notifier_block *nb,
dev_dbg(dev, "Detected %s\n", client->name);
if ((client->addr == 0x58 && !strcmp(client->name, "da9063")) ||
- (client->addr == 0x68 && !strcmp(client->name, "da9210"))) {
- int ret;
+ (client->addr == 0x68 && !strcmp(client->name, "da9210")) ||
+ (client->addr == 0x70 && !strcmp(client->name, "da9210"))) {
+ int ret, len;
+
+ /* There are two DA9210 on Stout, one on the other boards. */
+ len = of_machine_is_compatible("renesas,stout") ? 3 : 2;
dev_info(&client->dev, "clearing da9063/da9210 interrupts\n");
- ret = i2c_transfer(client->adapter, da9xxx_msgs, ARRAY_SIZE(da9xxx_msgs));
- if (ret != ARRAY_SIZE(da9xxx_msgs))
+ ret = i2c_transfer(client->adapter, da9xxx_msgs, len);
+ if (ret != len)
dev_err(&client->dev, "i2c error %d\n", ret);
}
@@ -118,6 +126,7 @@ static int __init rcar_gen2_regulator_quirk(void)
if (!of_machine_is_compatible("renesas,koelsch") &&
!of_machine_is_compatible("renesas,lager") &&
+ !of_machine_is_compatible("renesas,stout") &&
!of_machine_is_compatible("renesas,gose"))
return -ENODEV;
OpenPOWER on IntegriCloud