Merge branch 'heads/soc2' into boards2-base

This commit is contained in:
Simon Horman 2013-10-08 09:31:20 +09:00
commit 63862f14bd
34 changed files with 1260 additions and 146 deletions

View file

@ -0,0 +1,36 @@
/*
* Device Tree Source for the r7s72100 SoC
*
* Copyright (C) 2013 Renesas Solutions Corp.
*
* 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.
*/
/ {
compatible = "renesas,r7s72100";
interrupt-parent = <&gic>;
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
};
};
gic: interrupt-controller@e8201000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
#address-cells = <0>;
interrupt-controller;
reg = <0xe8201000 0x1000>,
<0xe8202000 0x1000>;
};
};

View file

@ -113,6 +113,12 @@ config ARCH_EMEV2
select ARM_GIC
select CPU_V7
config ARCH_R7S72100
bool "RZ/A1H (R7S72100)"
select ARM_GIC
select CPU_V7
select SH_CLK_CPG
comment "SH-Mobile Board Type"
config MACH_APE6EVM

View file

@ -15,8 +15,10 @@ obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o
obj-$(CONFIG_ARCH_R8A7778) += setup-r8a7778.o
obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o
obj-$(CONFIG_ARCH_R8A7790) += setup-r8a7790.o
obj-$(CONFIG_ARCH_R8A7791) += setup-r8a7791.o
obj-$(CONFIG_ARCH_R8A7790) += setup-r8a7790.o setup-rcar-gen2.o
obj-$(CONFIG_ARCH_R8A7791) += setup-r8a7791.o setup-rcar-gen2.o
obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o
obj-$(CONFIG_ARCH_R7S72100) += setup-r7s72100.o
# Clock objects
ifndef CONFIG_COMMON_CLK
@ -30,12 +32,15 @@ obj-$(CONFIG_ARCH_R8A7779) += clock-r8a7779.o
obj-$(CONFIG_ARCH_R8A7790) += clock-r8a7790.o
obj-$(CONFIG_ARCH_R8A7791) += clock-r8a7791.o
obj-$(CONFIG_ARCH_EMEV2) += clock-emev2.o
obj-$(CONFIG_ARCH_R7S72100) += clock-r7s72100.o
endif
# SMP objects
smp-y := platsmp.o headsmp.o
smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o platsmp-scu.o
smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o platsmp-scu.o
smp-$(CONFIG_ARCH_R8A7790) += smp-r8a7790.o platsmp-apmu.o
smp-$(CONFIG_ARCH_R8A7791) += smp-r8a7791.o platsmp-apmu.o
smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
# IRQ objects

View file

@ -57,7 +57,7 @@ static const char *ape6evm_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(APE6EVM_DT, "ape6evm")
.init_early = r8a73a4_init_delay,
.init_early = r8a73a4_init_early,
.init_machine = ape6evm_add_standard_devices,
.dt_compat = ape6evm_boards_compat_dt,
MACHINE_END

View file

@ -279,7 +279,7 @@ static const char *ape6evm_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(APE6EVM_DT, "ape6evm")
.init_early = r8a73a4_init_delay,
.init_early = r8a73a4_init_early,
.init_machine = ape6evm_add_standard_devices,
.dt_compat = ape6evm_boards_compat_dt,
MACHINE_END

View file

@ -38,8 +38,9 @@ static const char *lager_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(LAGER_DT, "lager")
.init_early = r8a7790_init_delay,
.smp = smp_ops(r8a7790_smp_ops),
.init_early = r8a7790_init_early,
.init_time = rcar_gen2_timer_init,
.init_machine = lager_add_standard_devices,
.init_time = r8a7790_timer_init,
.dt_compat = lager_boards_compat_dt,
MACHINE_END

View file

@ -229,8 +229,9 @@ static const char *lager_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(LAGER_DT, "lager")
.init_early = r8a7790_init_delay,
.init_time = r8a7790_timer_init,
.smp = smp_ops(r8a7790_smp_ops),
.init_early = r8a7790_init_early,
.init_time = rcar_gen2_timer_init,
.init_machine = lager_add_standard_devices,
.dt_compat = lager_boards_compat_dt,
MACHINE_END

View file

@ -0,0 +1,202 @@
/*
* r7a72100 clock framework support
*
* Copyright (C) 2013 Renesas Solutions Corp.
* Copyright (C) 2012 Phil Edworthy
* Copyright (C) 2011 Magnus Damm
*
* 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; version 2 of the License.
*
* 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.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
#include <mach/common.h>
#include <mach/r7s72100.h>
/* registers */
#define FRQCR 0xfcfe0010
#define FRQCR2 0xfcfe0014
#define STBCR3 0xfcfe0420
#define STBCR4 0xfcfe0424
#define PLL_RATE 30
static struct clk_mapping cpg_mapping = {
.phys = 0xfcfe0000,
.len = 0x1000,
};
/* Fixed 32 KHz root clock for RTC */
static struct clk r_clk = {
.rate = 32768,
};
/*
* Default rate for the root input clock, reset this with clk_set_rate()
* from the platform code.
*/
static struct clk extal_clk = {
.rate = 13330000,
.mapping = &cpg_mapping,
};
static unsigned long pll_recalc(struct clk *clk)
{
return clk->parent->rate * PLL_RATE;
}
static struct sh_clk_ops pll_clk_ops = {
.recalc = pll_recalc,
};
static struct clk pll_clk = {
.ops = &pll_clk_ops,
.parent = &extal_clk,
.flags = CLK_ENABLE_ON_INIT,
};
static unsigned long bus_recalc(struct clk *clk)
{
return clk->parent->rate * 2 / 3;
}
static struct sh_clk_ops bus_clk_ops = {
.recalc = bus_recalc,
};
static struct clk bus_clk = {
.ops = &bus_clk_ops,
.parent = &pll_clk,
.flags = CLK_ENABLE_ON_INIT,
};
static unsigned long peripheral0_recalc(struct clk *clk)
{
return clk->parent->rate / 12;
}
static struct sh_clk_ops peripheral0_clk_ops = {
.recalc = peripheral0_recalc,
};
static struct clk peripheral0_clk = {
.ops = &peripheral0_clk_ops,
.parent = &pll_clk,
.flags = CLK_ENABLE_ON_INIT,
};
static unsigned long peripheral1_recalc(struct clk *clk)
{
return clk->parent->rate / 6;
}
static struct sh_clk_ops peripheral1_clk_ops = {
.recalc = peripheral1_recalc,
};
static struct clk peripheral1_clk = {
.ops = &peripheral1_clk_ops,
.parent = &pll_clk,
.flags = CLK_ENABLE_ON_INIT,
};
struct clk *main_clks[] = {
&r_clk,
&extal_clk,
&pll_clk,
&bus_clk,
&peripheral0_clk,
&peripheral1_clk,
};
static int div2[] = { 1, 3, 0, 3 }; /* 1, 2/3, reserve, 1/3 */
static int multipliers[] = { 1, 2, 1, 1 };
static struct clk_div_mult_table div4_div_mult_table = {
.divisors = div2,
.nr_divisors = ARRAY_SIZE(div2),
.multipliers = multipliers,
.nr_multipliers = ARRAY_SIZE(multipliers),
};
static struct clk_div4_table div4_table = {
.div_mult_table = &div4_div_mult_table,
};
enum { DIV4_I,
DIV4_NR };
#define DIV4(_reg, _bit, _mask, _flags) \
SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
/* The mask field specifies the div2 entries that are valid */
struct clk div4_clks[DIV4_NR] = {
[DIV4_I] = DIV4(FRQCR, 8, 0xB, CLK_ENABLE_REG_16BIT
| CLK_ENABLE_ON_INIT),
};
enum { MSTP47, MSTP46, MSTP45, MSTP44, MSTP43, MSTP42, MSTP41, MSTP40,
MSTP33, MSTP_NR };
static struct clk mstp_clks[MSTP_NR] = {
[MSTP47] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 7, 0), /* SCIF0 */
[MSTP46] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 6, 0), /* SCIF1 */
[MSTP45] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 5, 0), /* SCIF2 */
[MSTP44] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 4, 0), /* SCIF3 */
[MSTP43] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 3, 0), /* SCIF4 */
[MSTP42] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 2, 0), /* SCIF5 */
[MSTP41] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 1, 0), /* SCIF6 */
[MSTP40] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 0, 0), /* SCIF7 */
[MSTP33] = SH_CLK_MSTP8(&peripheral0_clk, STBCR3, 3, 0), /* MTU2 */
};
static struct clk_lookup lookups[] = {
/* main clocks */
CLKDEV_CON_ID("rclk", &r_clk),
CLKDEV_CON_ID("extal", &extal_clk),
CLKDEV_CON_ID("pll_clk", &pll_clk),
CLKDEV_CON_ID("peripheral_clk", &peripheral1_clk),
/* DIV4 clocks */
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
/* MSTP clocks */
CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP47]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP46]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP45]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP44]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP43]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]),
CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]),
};
void __init r7s72100_clock_init(void)
{
int k, ret = 0;
for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
ret = clk_register(main_clks[k]);
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
if (!ret)
ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
if (!ret)
ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
if (!ret)
shmobile_clk_init();
else
panic("failed to setup rza1 clocks\n");
}

View file

@ -504,7 +504,7 @@ static struct clk div6_clks[DIV6_NR] = {
/* MSTP */
enum {
MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203,
MSTP218, MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203,
MSTP329, MSTP323, MSTP318, MSTP317, MSTP316,
MSTP315, MSTP314, MSTP313, MSTP312, MSTP305, MSTP300,
MSTP411, MSTP410, MSTP409,
@ -519,6 +519,7 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_MP], SMSTPCR2, 7, 0), /* SCIFB1 */
[MSTP216] = SH_CLK_MSTP32(&div6_clks[DIV6_MP], SMSTPCR2, 16, 0), /* SCIFB2 */
[MSTP217] = SH_CLK_MSTP32(&div6_clks[DIV6_MP], SMSTPCR2, 17, 0), /* SCIFB3 */
[MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC */
[MSTP300] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 0, 0), /* IIC2 */
[MSTP305] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC1],SMSTPCR3, 5, 0), /* MMCIF1 */
[MSTP312] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI2],SMSTPCR3, 12, 0), /* SDHI2 */
@ -578,6 +579,8 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]),
CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP217]),
CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
CLKDEV_DEV_ID("e6700020.dma-controller", &mstp_clks[MSTP218]),
CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
CLKDEV_DEV_ID("e6520000.i2c", &mstp_clks[MSTP300]),
CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),

View file

@ -52,6 +52,7 @@
#define SMSTPCR5 0xe6150144
#define SMSTPCR7 0xe615014c
#define SMSTPCR8 0xe6150990
#define SMSTPCR9 0xe6150994
#define SDCKCR 0xE6150074
#define SD2CKCR 0xE6150078
@ -181,6 +182,7 @@ static struct clk div6_clks[DIV6_NR] = {
/* MSTP */
enum {
MSTP931, MSTP930, MSTP929, MSTP928,
MSTP813,
MSTP726, MSTP725, MSTP724, MSTP723, MSTP722, MSTP721, MSTP720,
MSTP717, MSTP716,
@ -192,6 +194,10 @@ enum {
};
static struct clk mstp_clks[MSTP_NR] = {
[MSTP931] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 31, 0), /* I2C0 */
[MSTP930] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 30, 0), /* I2C1 */
[MSTP929] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 29, 0), /* I2C2 */
[MSTP928] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 28, 0), /* I2C3 */
[MSTP813] = SH_CLK_MSTP32(&p_clk, SMSTPCR8, 13, 0), /* Ether */
[MSTP726] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 26, 0), /* LVDS0 */
[MSTP725] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 25, 0), /* LVDS1 */
@ -271,6 +277,10 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]),
CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]),
CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]),
CLKDEV_DEV_ID("e6508000.i2c", &mstp_clks[MSTP931]),
CLKDEV_DEV_ID("e6518000.i2c", &mstp_clks[MSTP930]),
CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP929]),
CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP928]),
CLKDEV_DEV_ID("r8a7790-ether", &mstp_clks[MSTP813]),
CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
CLKDEV_DEV_ID("ee200000.mmcif", &mstp_clks[MSTP315]),
@ -300,7 +310,7 @@ static struct clk_lookup lookups[] = {
void __init r8a7790_clock_init(void)
{
u32 mode = r8a7790_read_mode_pins();
u32 mode = rcar_gen2_read_mode_pins();
int k, ret = 0;
switch (mode & (MD(14) | MD(13))) {

View file

@ -40,6 +40,9 @@ shmobile_boot_fn:
.globl shmobile_boot_arg
shmobile_boot_arg:
2: .space 4
.globl shmobile_boot_size
shmobile_boot_size:
.long . - shmobile_boot_vector
/*
* Per-CPU SMP boot function/argument selection code based on MPIDR

View file

@ -9,16 +9,23 @@ extern void shmobile_setup_console(void);
extern void shmobile_boot_vector(void);
extern unsigned long shmobile_boot_fn;
extern unsigned long shmobile_boot_arg;
extern unsigned long shmobile_boot_size;
extern void shmobile_smp_boot(void);
extern void shmobile_smp_sleep(void);
extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
unsigned long arg);
extern int shmobile_smp_cpu_disable(unsigned int cpu);
extern void shmobile_invalidate_start(void);
extern void shmobile_boot_scu(void);
extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
extern int shmobile_smp_scu_boot_secondary(unsigned int cpu,
struct task_struct *idle);
extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus);
extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
struct task_struct *idle);
extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
extern void shmobile_invalidate_start(void);
struct clk;
extern int shmobile_clk_init(void);
extern void shmobile_handle_irq_intc(struct pt_regs *);
@ -39,7 +46,6 @@ static inline int shmobile_cpuidle_init(void) { return 0; }
#endif
extern void __iomem *shmobile_scu_base;
extern void shmobile_smp_init_cpus(unsigned int ncores);
static inline void __init shmobile_init_late(void)
{

View file

@ -0,0 +1,8 @@
#ifndef __ASM_R7S72100_H__
#define __ASM_R7S72100_H__
void r7s72100_add_dt_devices(void);
void r7s72100_clock_init(void);
void r7s72100_init_early(void);
#endif /* __ASM_R7S72100_H__ */

View file

@ -1,10 +1,19 @@
#ifndef __ASM_R8A73A4_H__
#define __ASM_R8A73A4_H__
/* DMA slave IDs */
enum {
SHDMA_SLAVE_INVALID,
SHDMA_SLAVE_MMCIF0_TX,
SHDMA_SLAVE_MMCIF0_RX,
SHDMA_SLAVE_MMCIF1_TX,
SHDMA_SLAVE_MMCIF1_RX,
};
void r8a73a4_add_standard_devices(void);
void r8a73a4_add_dt_devices(void);
void r8a73a4_clock_init(void);
void r8a73a4_pinmux_init(void);
void r8a73a4_init_delay(void);
void r8a73a4_init_early(void);
#endif /* __ASM_R8A73A4_H__ */

View file

@ -1,6 +1,7 @@
/*
* Copyright (C) 2013 Renesas Solutions Corp.
* Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
* Copyright (C) 2013 Cogent Embedded, Inc.
*
* 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
@ -21,6 +22,13 @@
#include <linux/sh_eth.h>
#include <linux/platform_data/camera-rcar.h>
/* HPB-DMA slave IDs */
enum {
HPBDMA_SLAVE_DUMMY,
HPBDMA_SLAVE_SDHI0_TX,
HPBDMA_SLAVE_SDHI0_RX,
};
extern void r8a7778_add_standard_devices(void);
extern void r8a7778_add_standard_devices_dt(void);
extern void r8a7778_add_ether_device(struct sh_eth_plat_data *pdata);
@ -33,6 +41,7 @@ extern void r8a7778_init_delay(void);
extern void r8a7778_init_irq_dt(void);
extern void r8a7778_clock_init(void);
extern void r8a7778_init_irq_extpin(int irlm);
extern void r8a7778_init_irq_extpin_dt(int irlm);
extern void r8a7778_pinmux_init(void);
extern int r8a7778_usb_phy_power(bool enable);

View file

@ -6,6 +6,13 @@
#include <linux/sh_eth.h>
#include <linux/platform_data/camera-rcar.h>
/* HPB-DMA slave IDs */
enum {
HPBDMA_SLAVE_DUMMY,
HPBDMA_SLAVE_SDHI0_TX,
HPBDMA_SLAVE_SDHI0_RX,
};
struct platform_device;
struct r8a7779_pm_ch {
@ -26,6 +33,7 @@ static inline struct r8a7779_pm_ch *to_r8a7779_ch(struct generic_pm_domain *d)
extern void r8a7779_init_delay(void);
extern void r8a7779_init_irq_extpin(int irlm);
extern void r8a7779_init_irq_extpin_dt(int irlm);
extern void r8a7779_init_irq_dt(void);
extern void r8a7779_map_io(void);
extern void r8a7779_earlytimer_init(void);

View file

@ -1,14 +1,13 @@
#ifndef __ASM_R8A7790_H__
#define __ASM_R8A7790_H__
#include <mach/rcar-gen2.h>
void r8a7790_add_standard_devices(void);
void r8a7790_add_dt_devices(void);
void r8a7790_clock_init(void);
void r8a7790_pinmux_init(void);
void r8a7790_init_delay(void);
void r8a7790_timer_init(void);
#define MD(nr) BIT(nr)
u32 r8a7790_read_mode_pins(void);
void r8a7790_init_early(void);
extern struct smp_operations r8a7790_smp_ops;
#endif /* __ASM_R8A7790_H__ */

View file

@ -1,8 +1,10 @@
#ifndef __ASM_R8A7791_H__
#define __ASM_R8A7791_H__
void r8a7791_add_standard_devices(void);
void r8a7791_add_dt_devices(void);
void r8a7791_clock_init(void);
void r8a7791_init_early(void);
extern struct smp_operations r8a7791_smp_ops;
#endif /* __ASM_R8A7791_H__ */

View file

@ -0,0 +1,8 @@
#ifndef __ASM_RCAR_GEN2_H__
#define __ASM_RCAR_GEN2_H__
void rcar_gen2_timer_init(void);
#define MD(nr) BIT(nr)
u32 rcar_gen2_read_mode_pins(void);
#endif /* __ASM_RCAR_GEN2_H__ */

View file

@ -0,0 +1,195 @@
/*
* SMP support for SoCs with APMU
*
* Copyright (C) 2013 Magnus Damm
*
* 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/delay.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/of_address.h>
#include <linux/smp.h>
#include <asm/cacheflush.h>
#include <asm/cp15.h>
#include <asm/smp_plat.h>
#include <mach/common.h>
static struct {
void __iomem *iomem;
int bit;
} apmu_cpus[CONFIG_NR_CPUS];
#define WUPCR_OFFS 0x10
#define PSTR_OFFS 0x40
#define CPUNCR_OFFS(n) (0x100 + (0x10 * (n)))
static int apmu_power_on(void __iomem *p, int bit)
{
/* request power on */
writel_relaxed(BIT(bit), p + WUPCR_OFFS);
/* wait for APMU to finish */
while (readl_relaxed(p + WUPCR_OFFS) != 0)
;
return 0;
}
static int apmu_power_off(void __iomem *p, int bit)
{
/* request Core Standby for next WFI */
writel_relaxed(3, p + CPUNCR_OFFS(bit));
return 0;
}
static int apmu_power_off_poll(void __iomem *p, int bit)
{
int k;
for (k = 0; k < 1000; k++) {
if (((readl_relaxed(p + PSTR_OFFS) >> (bit * 4)) & 0x03) == 3)
return 1;
mdelay(1);
}
return 0;
}
static int apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu))
{
void __iomem *p = apmu_cpus[cpu].iomem;
return p ? fn(p, apmu_cpus[cpu].bit) : -EINVAL;
}
static void apmu_init_cpu(struct resource *res, int cpu, int bit)
{
if (apmu_cpus[cpu].iomem)
return;
apmu_cpus[cpu].iomem = ioremap_nocache(res->start, resource_size(res));
apmu_cpus[cpu].bit = bit;
pr_debug("apmu ioremap %d %d 0x%08x 0x%08x\n", cpu, bit,
res->start, resource_size(res));
}
static struct {
struct resource iomem;
int cpus[4];
} apmu_config[] = {
{
.iomem = DEFINE_RES_MEM(0xe6152000, 0x88),
.cpus = { 0, 1, 2, 3 },
},
{
.iomem = DEFINE_RES_MEM(0xe6151000, 0x88),
.cpus = { 0x100, 0x101, 0x102, 0x103 },
}
};
static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit))
{
u32 id;
int k;
int bit, index;
bool is_allowed;
for (k = 0; k < ARRAY_SIZE(apmu_config); k++) {
/* only enable the cluster that includes the boot CPU */
is_allowed = false;
for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
id = apmu_config[k].cpus[bit];
if (id >= 0) {
if (id == cpu_logical_map(0))
is_allowed = true;
}
}
if (!is_allowed)
continue;
for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
id = apmu_config[k].cpus[bit];
if (id >= 0) {
index = get_logical_index(id);
if (index >= 0)
fn(&apmu_config[k].iomem, index, bit);
}
}
}
}
void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus)
{
/* install boot code shared by all CPUs */
shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
shmobile_boot_arg = MPIDR_HWID_BITMASK;
/* perform per-cpu setup */
apmu_parse_cfg(apmu_init_cpu);
}
int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
/* For this particular CPU register boot vector */
shmobile_smp_hook(cpu, virt_to_phys(shmobile_invalidate_start), 0);
return apmu_wrap(cpu, apmu_power_on);
}
#ifdef CONFIG_HOTPLUG_CPU
/* nicked from arch/arm/mach-exynos/hotplug.c */
static inline void cpu_enter_lowpower_a15(void)
{
unsigned int v;
asm volatile(
" mrc p15, 0, %0, c1, c0, 0\n"
" bic %0, %0, %1\n"
" mcr p15, 0, %0, c1, c0, 0\n"
: "=&r" (v)
: "Ir" (CR_C)
: "cc");
flush_cache_louis();
asm volatile(
/*
* Turn off coherency
*/
" mrc p15, 0, %0, c1, c0, 1\n"
" bic %0, %0, %1\n"
" mcr p15, 0, %0, c1, c0, 1\n"
: "=&r" (v)
: "Ir" (0x40)
: "cc");
isb();
dsb();
}
void shmobile_smp_apmu_cpu_die(unsigned int cpu)
{
/* For this particular CPU deregister boot vector */
shmobile_smp_hook(cpu, 0, 0);
/* Select next sleep mode using the APMU */
apmu_wrap(cpu, apmu_power_off);
/* Do ARM specific CPU shutdown */
cpu_enter_lowpower_a15();
/* jump to shared mach-shmobile sleep / reset code */
shmobile_smp_sleep();
}
int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
{
return apmu_wrap(cpu, apmu_power_off_poll);
}
#endif

View file

@ -7,6 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/cpu.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
@ -16,6 +17,26 @@
#include <asm/smp_scu.h>
#include <mach/common.h>
static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (long)hcpu;
switch (action) {
case CPU_UP_PREPARE:
/* For this particular CPU register SCU SMP boot vector */
shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
(unsigned long)shmobile_scu_base);
break;
};
return NOTIFY_OK;
}
static struct notifier_block shmobile_smp_scu_notifier = {
.notifier_call = shmobile_smp_scu_notifier_call,
};
void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
{
/* install boot code shared by all CPUs */
@ -25,14 +46,9 @@ void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
/* enable SCU and cache coherency on booting CPU */
scu_enable(shmobile_scu_base);
scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
}
int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
/* For this particular CPU register SCU boot vector */
shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
(unsigned long)shmobile_scu_base);
return 0;
/* Use CPU notifier for reset vector control */
register_cpu_notifier(&shmobile_smp_scu_notifier);
}
#ifdef CONFIG_HOTPLUG_CPU

View file

@ -11,25 +11,10 @@
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/smp.h>
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include <mach/common.h>
void __init shmobile_smp_init_cpus(unsigned int ncores)
{
unsigned int i;
if (ncores > nr_cpu_ids) {
pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
ncores, nr_cpu_ids);
ncores = nr_cpu_ids;
}
for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
}
extern unsigned long shmobile_smp_fn[];
extern unsigned long shmobile_smp_arg[];
extern unsigned long shmobile_smp_mpidr[];
@ -44,3 +29,10 @@ void shmobile_smp_hook(unsigned int cpu, unsigned long fn, unsigned long arg)
shmobile_smp_arg[cpu] = arg;
flush_cache_all();
}
#ifdef CONFIG_HOTPLUG_CPU
int shmobile_smp_cpu_disable(unsigned int cpu)
{
return 0; /* Hotplug of any CPU is supported */
}
#endif

View file

@ -0,0 +1,88 @@
/*
* r7s72100 processor support
*
* Copyright (C) 2013 Renesas Solutions Corp.
* Copyright (C) 2013 Magnus Damm
*
* 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; version 2 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/of_platform.h>
#include <linux/serial_sci.h>
#include <mach/common.h>
#include <mach/irqs.h>
#include <mach/r7s72100.h>
#include <asm/mach/arch.h>
#define SCIF_DATA(index, baseaddr, irq) \
[index] = { \
.type = PORT_SCIF, \
.regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE, \
.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \
.scbrr_algo_id = SCBRR_ALGO_2, \
.scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE | \
SCSCR_REIE, \
.mapbase = baseaddr, \
.irqs = { irq + 1, irq + 2, irq + 3, irq }, \
}
enum { SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7 };
static const struct plat_sci_port scif[] __initconst = {
SCIF_DATA(SCIF0, 0xe8007000, gic_iid(221)), /* SCIF0 */
SCIF_DATA(SCIF1, 0xe8007800, gic_iid(225)), /* SCIF1 */
SCIF_DATA(SCIF2, 0xe8008000, gic_iid(229)), /* SCIF2 */
SCIF_DATA(SCIF3, 0xe8008800, gic_iid(233)), /* SCIF3 */
SCIF_DATA(SCIF4, 0xe8009000, gic_iid(237)), /* SCIF4 */
SCIF_DATA(SCIF5, 0xe8009800, gic_iid(241)), /* SCIF5 */
SCIF_DATA(SCIF6, 0xe800a000, gic_iid(245)), /* SCIF6 */
SCIF_DATA(SCIF7, 0xe800a800, gic_iid(249)), /* SCIF7 */
};
static inline void r7s72100_register_scif(int idx)
{
platform_device_register_data(&platform_bus, "sh-sci", idx, &scif[idx],
sizeof(struct plat_sci_port));
}
void __init r7s72100_add_dt_devices(void)
{
r7s72100_register_scif(SCIF0);
r7s72100_register_scif(SCIF1);
r7s72100_register_scif(SCIF2);
r7s72100_register_scif(SCIF3);
r7s72100_register_scif(SCIF4);
r7s72100_register_scif(SCIF5);
r7s72100_register_scif(SCIF6);
r7s72100_register_scif(SCIF7);
}
void __init r7s72100_init_early(void)
{
shmobile_setup_delay(400, 1, 3); /* Cortex-A9 @ 400MHz */
}
#ifdef CONFIG_USE_OF
static const char *r7s72100_boards_compat_dt[] __initdata = {
"renesas,r7s72100",
NULL,
};
DT_MACHINE_START(R7S72100_DT, "Generic R7S72100 (Flattened Device Tree)")
.init_early = r7s72100_init_early,
.dt_compat = r7s72100_boards_compat_dt,
MACHINE_END
#endif /* CONFIG_USE_OF */

View file

@ -22,8 +22,10 @@
#include <linux/of_platform.h>
#include <linux/platform_data/irq-renesas-irqc.h>
#include <linux/serial_sci.h>
#include <linux/sh_dma.h>
#include <linux/sh_timer.h>
#include <mach/common.h>
#include <mach/dma-register.h>
#include <mach/irqs.h>
#include <mach/r8a73a4.h>
#include <asm/mach/arch.h>
@ -199,15 +201,104 @@ void __init r8a73a4_add_dt_devices(void)
r8a7790_register_cmt(10);
}
/* DMA */
static const struct sh_dmae_slave_config dma_slaves[] = {
{
.slave_id = SHDMA_SLAVE_MMCIF0_TX,
.addr = 0xee200034,
.chcr = CHCR_TX(XMIT_SZ_32BIT),
.mid_rid = 0xd1,
}, {
.slave_id = SHDMA_SLAVE_MMCIF0_RX,
.addr = 0xee200034,
.chcr = CHCR_RX(XMIT_SZ_32BIT),
.mid_rid = 0xd2,
}, {
.slave_id = SHDMA_SLAVE_MMCIF1_TX,
.addr = 0xee220034,
.chcr = CHCR_TX(XMIT_SZ_32BIT),
.mid_rid = 0xe1,
}, {
.slave_id = SHDMA_SLAVE_MMCIF1_RX,
.addr = 0xee220034,
.chcr = CHCR_RX(XMIT_SZ_32BIT),
.mid_rid = 0xe2,
},
};
#define DMAE_CHANNEL(a, b) \
{ \
.offset = (a) - 0x20, \
.dmars = (a) - 0x20 + 0x40, \
.chclr_bit = (b), \
.chclr_offset = 0x80 - 0x20, \
}
static const struct sh_dmae_channel dma_channels[] = {
DMAE_CHANNEL(0x8000, 0),
DMAE_CHANNEL(0x8080, 1),
DMAE_CHANNEL(0x8100, 2),
DMAE_CHANNEL(0x8180, 3),
DMAE_CHANNEL(0x8200, 4),
DMAE_CHANNEL(0x8280, 5),
DMAE_CHANNEL(0x8300, 6),
DMAE_CHANNEL(0x8380, 7),
DMAE_CHANNEL(0x8400, 8),
DMAE_CHANNEL(0x8480, 9),
DMAE_CHANNEL(0x8500, 10),
DMAE_CHANNEL(0x8580, 11),
DMAE_CHANNEL(0x8600, 12),
DMAE_CHANNEL(0x8680, 13),
DMAE_CHANNEL(0x8700, 14),
DMAE_CHANNEL(0x8780, 15),
DMAE_CHANNEL(0x8800, 16),
DMAE_CHANNEL(0x8880, 17),
DMAE_CHANNEL(0x8900, 18),
DMAE_CHANNEL(0x8980, 19),
};
static const struct sh_dmae_pdata dma_pdata = {
.slave = dma_slaves,
.slave_num = ARRAY_SIZE(dma_slaves),
.channel = dma_channels,
.channel_num = ARRAY_SIZE(dma_channels),
.ts_low_shift = TS_LOW_SHIFT,
.ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT,
.ts_high_shift = TS_HI_SHIFT,
.ts_high_mask = TS_HI_BIT << TS_HI_SHIFT,
.ts_shift = dma_ts_shift,
.ts_shift_num = ARRAY_SIZE(dma_ts_shift),
.dmaor_init = DMAOR_DME,
.chclr_present = 1,
.chclr_bitwise = 1,
};
static struct resource dma_resources[] = {
DEFINE_RES_MEM(0xe6700020, 0x89e0),
DEFINE_RES_IRQ_NAMED(gic_spi(220), "error_irq"),
{
/* IRQ for channels 0-19 */
.start = gic_spi(200),
.end = gic_spi(219),
.flags = IORESOURCE_IRQ,
},
};
#define r8a73a4_register_dmac() \
platform_device_register_resndata(&platform_bus, "sh-dma-engine", 0, \
dma_resources, ARRAY_SIZE(dma_resources), \
&dma_pdata, sizeof(dma_pdata))
void __init r8a73a4_add_standard_devices(void)
{
r8a73a4_add_dt_devices();
r8a73a4_register_irqc(0);
r8a73a4_register_irqc(1);
r8a73a4_register_thermal();
r8a73a4_register_dmac();
}
void __init r8a73a4_init_delay(void)
void __init r8a73a4_init_early(void)
{
#ifndef CONFIG_ARM_ARCH_TIMER
shmobile_setup_delay(1500, 2, 4); /* Cortex-A15 @ 1500MHz */
@ -222,7 +313,7 @@ static const char *r8a73a4_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
.init_early = r8a73a4_init_delay,
.init_early = r8a73a4_init_early,
.dt_compat = r8a73a4_boards_compat_dt,
MACHINE_END
#endif /* CONFIG_USE_OF */

View file

@ -24,6 +24,7 @@
#include <linux/irqchip/arm-gic.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_data/dma-rcar-hpbdma.h>
#include <linux/platform_data/gpio-rcar.h>
#include <linux/platform_data/irq-renesas-intc-irqpin.h>
#include <linux/platform_device.h>
@ -356,6 +357,88 @@ void __init r8a7778_add_dt_devices(void)
r8a7778_register_tmu(1);
}
/* HPB-DMA */
/* Asynchronous mode register (ASYNCMDR) bits */
#define HPB_DMAE_ASYNCMDR_ASMD22_MASK BIT(2) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD22_SINGLE BIT(2) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD22_MULTI 0 /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD21_MASK BIT(1) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD21_SINGLE BIT(1) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD21_MULTI 0 /* SDHI0 */
static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = {
{
.id = HPBDMA_SLAVE_SDHI0_TX,
.addr = 0xffe4c000 + 0x30,
.dcr = HPB_DMAE_DCR_SPDS_16BIT |
HPB_DMAE_DCR_DMDL |
HPB_DMAE_DCR_DPDS_16BIT,
.rstr = HPB_DMAE_ASYNCRSTR_ASRST21 |
HPB_DMAE_ASYNCRSTR_ASRST22 |
HPB_DMAE_ASYNCRSTR_ASRST23,
.mdr = HPB_DMAE_ASYNCMDR_ASMD21_MULTI,
.mdm = HPB_DMAE_ASYNCMDR_ASMD21_MASK,
.port = 0x0D0C,
.flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
.dma_ch = 21,
}, {
.id = HPBDMA_SLAVE_SDHI0_RX,
.addr = 0xffe4c000 + 0x30,
.dcr = HPB_DMAE_DCR_SMDL |
HPB_DMAE_DCR_SPDS_16BIT |
HPB_DMAE_DCR_DPDS_16BIT,
.rstr = HPB_DMAE_ASYNCRSTR_ASRST21 |
HPB_DMAE_ASYNCRSTR_ASRST22 |
HPB_DMAE_ASYNCRSTR_ASRST23,
.mdr = HPB_DMAE_ASYNCMDR_ASMD22_MULTI,
.mdm = HPB_DMAE_ASYNCMDR_ASMD22_MASK,
.port = 0x0D0C,
.flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
.dma_ch = 22,
},
};
static const struct hpb_dmae_channel hpb_dmae_channels[] = {
HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_TX), /* ch. 21 */
HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_RX), /* ch. 22 */
};
static struct hpb_dmae_pdata dma_platform_data __initdata = {
.slaves = hpb_dmae_slaves,
.num_slaves = ARRAY_SIZE(hpb_dmae_slaves),
.channels = hpb_dmae_channels,
.num_channels = ARRAY_SIZE(hpb_dmae_channels),
.ts_shift = {
[XMIT_SZ_8BIT] = 0,
[XMIT_SZ_16BIT] = 1,
[XMIT_SZ_32BIT] = 2,
},
.num_hw_channels = 39,
};
static struct resource hpb_dmae_resources[] __initdata = {
/* Channel registers */
DEFINE_RES_MEM(0xffc08000, 0x1000),
/* Common registers */
DEFINE_RES_MEM(0xffc09000, 0x170),
/* Asynchronous reset registers */
DEFINE_RES_MEM(0xffc00300, 4),
/* Asynchronous mode registers */
DEFINE_RES_MEM(0xffc00400, 4),
/* IRQ for DMA channels */
DEFINE_RES_NAMED(gic_iid(0x7b), 5, NULL, IORESOURCE_IRQ),
};
static void __init r8a7778_register_hpb_dmae(void)
{
platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
hpb_dmae_resources,
ARRAY_SIZE(hpb_dmae_resources),
&dma_platform_data,
sizeof(dma_platform_data));
}
void __init r8a7778_add_standard_devices(void)
{
r8a7778_add_dt_devices();
@ -366,6 +449,8 @@ void __init r8a7778_add_standard_devices(void)
r8a7778_register_hspi(0);
r8a7778_register_hspi(1);
r8a7778_register_hspi(2);
r8a7778_register_hpb_dmae();
}
void __init r8a7778_init_late(void)
@ -391,7 +476,7 @@ static struct resource irqpin_resources[] __initdata = {
DEFINE_RES_IRQ(gic_iid(0x3e)), /* IRQ3 */
};
void __init r8a7778_init_irq_extpin(int irlm)
void __init r8a7778_init_irq_extpin_dt(int irlm)
{
void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
unsigned long tmp;
@ -409,7 +494,11 @@ void __init r8a7778_init_irq_extpin(int irlm)
tmp |= (1 << 21); /* LVLMODE = 1 */
iowrite32(tmp, icr0);
iounmap(icr0);
}
void __init r8a7778_init_irq_extpin(int irlm)
{
r8a7778_init_irq_extpin_dt(irlm);
if (irlm)
platform_device_register_resndata(
&platform_bus, "renesas_intc_irqpin", -1,

View file

@ -25,6 +25,7 @@
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/of_platform.h>
#include <linux/platform_data/dma-rcar-hpbdma.h>
#include <linux/platform_data/gpio-rcar.h>
#include <linux/platform_data/irq-renesas-intc-irqpin.h>
#include <linux/platform_device.h>
@ -97,7 +98,7 @@ static struct resource irqpin0_resources[] __initdata = {
DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
};
void __init r8a7779_init_irq_extpin(int irlm)
void __init r8a7779_init_irq_extpin_dt(int irlm)
{
void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
u32 tmp;
@ -115,7 +116,11 @@ void __init r8a7779_init_irq_extpin(int irlm)
tmp |= (1 << 21); /* LVLMODE = 1 */
iowrite32(tmp, icr0);
iounmap(icr0);
}
void __init r8a7779_init_irq_extpin(int irlm)
{
r8a7779_init_irq_extpin_dt(irlm);
if (irlm)
platform_device_register_resndata(
&platform_bus, "renesas_intc_irqpin", -1,
@ -632,6 +637,158 @@ static struct platform_device_info *vin_info_table[] __initdata = {
&vin3_info,
};
/* HPB-DMA */
/* Asynchronous mode register bits */
#define HPB_DMAE_ASYNCMDR_ASMD43_MASK BIT(23) /* MMC1 */
#define HPB_DMAE_ASYNCMDR_ASMD43_SINGLE BIT(23) /* MMC1 */
#define HPB_DMAE_ASYNCMDR_ASMD43_MULTI 0 /* MMC1 */
#define HPB_DMAE_ASYNCMDR_ASBTMD43_MASK BIT(22) /* MMC1 */
#define HPB_DMAE_ASYNCMDR_ASBTMD43_BURST BIT(22) /* MMC1 */
#define HPB_DMAE_ASYNCMDR_ASBTMD43_NBURST 0 /* MMC1 */
#define HPB_DMAE_ASYNCMDR_ASMD24_MASK BIT(21) /* MMC0 */
#define HPB_DMAE_ASYNCMDR_ASMD24_SINGLE BIT(21) /* MMC0 */
#define HPB_DMAE_ASYNCMDR_ASMD24_MULTI 0 /* MMC0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD24_MASK BIT(20) /* MMC0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD24_BURST BIT(20) /* MMC0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD24_NBURST 0 /* MMC0 */
#define HPB_DMAE_ASYNCMDR_ASMD41_MASK BIT(19) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASMD41_SINGLE BIT(19) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASMD41_MULTI 0 /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASBTMD41_MASK BIT(18) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASBTMD41_BURST BIT(18) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASBTMD41_NBURST 0 /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASMD40_MASK BIT(17) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASMD40_SINGLE BIT(17) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASMD40_MULTI 0 /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASBTMD40_MASK BIT(16) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASBTMD40_BURST BIT(16) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASBTMD40_NBURST 0 /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASMD39_MASK BIT(15) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASMD39_SINGLE BIT(15) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASMD39_MULTI 0 /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASBTMD39_MASK BIT(14) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASBTMD39_BURST BIT(14) /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASBTMD39_NBURST 0 /* SDHI3 */
#define HPB_DMAE_ASYNCMDR_ASMD27_MASK BIT(13) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASMD27_SINGLE BIT(13) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASMD27_MULTI 0 /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASBTMD27_MASK BIT(12) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASBTMD27_BURST BIT(12) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASBTMD27_NBURST 0 /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASMD26_MASK BIT(11) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASMD26_SINGLE BIT(11) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASMD26_MULTI 0 /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASBTMD26_MASK BIT(10) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASBTMD26_BURST BIT(10) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASBTMD26_NBURST 0 /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASMD25_MASK BIT(9) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASMD25_SINGLE BIT(9) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASMD25_MULTI 0 /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASBTMD25_MASK BIT(8) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASBTMD25_BURST BIT(8) /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASBTMD25_NBURST 0 /* SDHI2 */
#define HPB_DMAE_ASYNCMDR_ASMD23_MASK BIT(7) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD23_SINGLE BIT(7) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD23_MULTI 0 /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD23_MASK BIT(6) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD23_BURST BIT(6) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD23_NBURST 0 /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD22_MASK BIT(5) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD22_SINGLE BIT(5) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD22_MULTI 0 /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD22_MASK BIT(4) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD22_BURST BIT(4) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD22_NBURST 0 /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD21_MASK BIT(3) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD21_SINGLE BIT(3) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD21_MULTI 0 /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD21_MASK BIT(2) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD21_BURST BIT(2) /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASBTMD21_NBURST 0 /* SDHI0 */
#define HPB_DMAE_ASYNCMDR_ASMD20_MASK BIT(1) /* SDHI1 */
#define HPB_DMAE_ASYNCMDR_ASMD20_SINGLE BIT(1) /* SDHI1 */
#define HPB_DMAE_ASYNCMDR_ASMD20_MULTI 0 /* SDHI1 */
#define HPB_DMAE_ASYNCMDR_ASBTMD20_MASK BIT(0) /* SDHI1 */
#define HPB_DMAE_ASYNCMDR_ASBTMD20_BURST BIT(0) /* SDHI1 */
#define HPB_DMAE_ASYNCMDR_ASBTMD20_NBURST 0 /* SDHI1 */
static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = {
{
.id = HPBDMA_SLAVE_SDHI0_TX,
.addr = 0xffe4c000 + 0x30,
.dcr = HPB_DMAE_DCR_SPDS_16BIT |
HPB_DMAE_DCR_DMDL |
HPB_DMAE_DCR_DPDS_16BIT,
.rstr = HPB_DMAE_ASYNCRSTR_ASRST21 |
HPB_DMAE_ASYNCRSTR_ASRST22 |
HPB_DMAE_ASYNCRSTR_ASRST23,
.mdr = HPB_DMAE_ASYNCMDR_ASMD21_SINGLE |
HPB_DMAE_ASYNCMDR_ASBTMD21_NBURST,
.mdm = HPB_DMAE_ASYNCMDR_ASMD21_MASK |
HPB_DMAE_ASYNCMDR_ASBTMD21_MASK,
.port = 0x0D0C,
.flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
.dma_ch = 21,
}, {
.id = HPBDMA_SLAVE_SDHI0_RX,
.addr = 0xffe4c000 + 0x30,
.dcr = HPB_DMAE_DCR_SMDL |
HPB_DMAE_DCR_SPDS_16BIT |
HPB_DMAE_DCR_DPDS_16BIT,
.rstr = HPB_DMAE_ASYNCRSTR_ASRST21 |
HPB_DMAE_ASYNCRSTR_ASRST22 |
HPB_DMAE_ASYNCRSTR_ASRST23,
.mdr = HPB_DMAE_ASYNCMDR_ASMD22_SINGLE |
HPB_DMAE_ASYNCMDR_ASBTMD22_NBURST,
.mdm = HPB_DMAE_ASYNCMDR_ASMD22_MASK |
HPB_DMAE_ASYNCMDR_ASBTMD22_MASK,
.port = 0x0D0C,
.flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
.dma_ch = 22,
},
};
static const struct hpb_dmae_channel hpb_dmae_channels[] = {
HPB_DMAE_CHANNEL(0x93, HPBDMA_SLAVE_SDHI0_TX), /* ch. 21 */
HPB_DMAE_CHANNEL(0x93, HPBDMA_SLAVE_SDHI0_RX), /* ch. 22 */
};
static struct hpb_dmae_pdata dma_platform_data __initdata = {
.slaves = hpb_dmae_slaves,
.num_slaves = ARRAY_SIZE(hpb_dmae_slaves),
.channels = hpb_dmae_channels,
.num_channels = ARRAY_SIZE(hpb_dmae_channels),
.ts_shift = {
[XMIT_SZ_8BIT] = 0,
[XMIT_SZ_16BIT] = 1,
[XMIT_SZ_32BIT] = 2,
},
.num_hw_channels = 44,
};
static struct resource hpb_dmae_resources[] __initdata = {
/* Channel registers */
DEFINE_RES_MEM(0xffc08000, 0x1000),
/* Common registers */
DEFINE_RES_MEM(0xffc09000, 0x170),
/* Asynchronous reset registers */
DEFINE_RES_MEM(0xffc00300, 4),
/* Asynchronous mode registers */
DEFINE_RES_MEM(0xffc00400, 4),
/* IRQ for DMA channels */
DEFINE_RES_NAMED(gic_iid(0x8e), 12, NULL, IORESOURCE_IRQ),
};
static void __init r8a7779_register_hpb_dmae(void)
{
platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
hpb_dmae_resources,
ARRAY_SIZE(hpb_dmae_resources),
&dma_platform_data,
sizeof(dma_platform_data));
}
static struct platform_device *r8a7779_devices_dt[] __initdata = {
&scif0_device,
&scif1_device,
@ -665,6 +822,7 @@ void __init r8a7779_add_standard_devices(void)
ARRAY_SIZE(r8a7779_devices_dt));
platform_add_devices(r8a7779_standard_devices,
ARRAY_SIZE(r8a7779_standard_devices));
r8a7779_register_hpb_dmae();
}
void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata)

View file

@ -18,7 +18,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/clocksource.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/of_platform.h>
@ -31,17 +30,18 @@
#include <mach/r8a7790.h>
#include <asm/mach/arch.h>
static struct resource pfc_resources[] __initdata = {
static const struct resource pfc_resources[] __initconst = {
DEFINE_RES_MEM(0xe6060000, 0x250),
};
#define R8A7790_GPIO(idx) \
static struct resource r8a7790_gpio##idx##_resources[] __initdata = { \
static const struct resource r8a7790_gpio##idx##_resources[] __initconst = { \
DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50), \
DEFINE_RES_IRQ(gic_spi(4 + (idx))), \
}; \
\
static struct gpio_rcar_config r8a7790_gpio##idx##_platform_data __initdata = { \
static const struct gpio_rcar_config \
r8a7790_gpio##idx##_platform_data __initconst = { \
.gpio_base = 32 * (idx), \
.irq_base = 0, \
.number_of_pins = 32, \
@ -112,7 +112,7 @@ void __init r8a7790_pinmux_init(void)
enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1,
HSCIF0, HSCIF1 };
static struct plat_sci_port scif[] __initdata = {
static const struct plat_sci_port scif[] __initconst = {
SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
@ -131,11 +131,11 @@ static inline void r8a7790_register_scif(int idx)
sizeof(struct plat_sci_port));
}
static struct renesas_irqc_config irqc0_data __initdata = {
static const struct renesas_irqc_config irqc0_data __initconst = {
.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
};
static struct resource irqc0_resources[] __initdata = {
static const struct resource irqc0_resources[] __initconst = {
DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */
DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */
DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */
@ -150,7 +150,7 @@ static struct resource irqc0_resources[] __initdata = {
&irqc##idx##_data, \
sizeof(struct renesas_irqc_config))
static struct resource thermal_resources[] __initdata = {
static const struct resource thermal_resources[] __initconst = {
DEFINE_RES_MEM(0xe61f0000, 0x14),
DEFINE_RES_MEM(0xe61f0100, 0x38),
DEFINE_RES_IRQ(gic_spi(69)),
@ -161,13 +161,13 @@ static struct resource thermal_resources[] __initdata = {
thermal_resources, \
ARRAY_SIZE(thermal_resources))
static struct sh_timer_config cmt00_platform_data __initdata = {
static const struct sh_timer_config cmt00_platform_data __initconst = {
.name = "CMT00",
.timer_bit = 0,
.clockevent_rating = 80,
};
static struct resource cmt00_resources[] __initdata = {
static const struct resource cmt00_resources[] __initconst = {
DEFINE_RES_MEM(0xffca0510, 0x0c),
DEFINE_RES_MEM(0xffca0500, 0x04),
DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
@ -202,72 +202,7 @@ void __init r8a7790_add_standard_devices(void)
r8a7790_register_thermal();
}
#define MODEMR 0xe6160060
u32 __init r8a7790_read_mode_pins(void)
{
void __iomem *modemr = ioremap_nocache(MODEMR, 4);
u32 mode;
BUG_ON(!modemr);
mode = ioread32(modemr);
iounmap(modemr);
return mode;
}
#define CNTCR 0
#define CNTFID0 0x20
void __init r8a7790_timer_init(void)
{
#ifdef CONFIG_ARM_ARCH_TIMER
u32 mode = r8a7790_read_mode_pins();
void __iomem *base;
int extal_mhz = 0;
u32 freq;
/* At Linux boot time the r8a7790 arch timer comes up
* with the counter disabled. Moreover, it may also report
* a potentially incorrect fixed 13 MHz frequency. To be
* correct these registers need to be updated to use the
* frequency EXTAL / 2 which can be determined by the MD pins.
*/
switch (mode & (MD(14) | MD(13))) {
case 0:
extal_mhz = 15;
break;
case MD(13):
extal_mhz = 20;
break;
case MD(14):
extal_mhz = 26;
break;
case MD(13) | MD(14):
extal_mhz = 30;
break;
}
/* The arch timer frequency equals EXTAL / 2 */
freq = extal_mhz * (1000000 / 2);
/* Remap "armgcnt address map" space */
base = ioremap(0xe6080000, PAGE_SIZE);
/* Update registers with correct frequency */
iowrite32(freq, base + CNTFID0);
asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
/* make sure arch timer is started by setting bit 0 of CNTCR */
iowrite32(1, base + CNTCR);
iounmap(base);
#endif /* CONFIG_ARM_ARCH_TIMER */
clocksource_of_init();
}
void __init r8a7790_init_delay(void)
void __init r8a7790_init_early(void)
{
#ifndef CONFIG_ARM_ARCH_TIMER
shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
@ -276,14 +211,15 @@ void __init r8a7790_init_delay(void)
#ifdef CONFIG_USE_OF
static const char *r8a7790_boards_compat_dt[] __initdata = {
static const char * const r8a7790_boards_compat_dt[] __initconst = {
"renesas,r8a7790",
NULL,
};
DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
.init_early = r8a7790_init_delay,
.init_time = r8a7790_timer_init,
.smp = smp_ops(r8a7790_smp_ops),
.init_early = r8a7790_init_early,
.init_time = rcar_gen2_timer_init,
.dt_compat = r8a7790_boards_compat_dt,
MACHINE_END
#endif /* CONFIG_USE_OF */

View file

@ -22,11 +22,13 @@
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/of_platform.h>
#include <linux/platform_data/irq-renesas-irqc.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
#include <mach/common.h>
#include <mach/irqs.h>
#include <mach/r8a7791.h>
#include <mach/rcar-gen2.h>
#include <asm/mach/arch.h>
#define SCIF_COMMON(scif_type, baseaddr, irq) \
@ -109,6 +111,31 @@ static const struct resource cmt00_resources[] __initconst = {
&cmt##idx##_platform_data, \
sizeof(struct sh_timer_config))
static struct renesas_irqc_config irqc0_data = {
.irq_base = irq_pin(0), /* IRQ0 -> IRQ9 */
};
static struct resource irqc0_resources[] = {
DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */
DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */
DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */
DEFINE_RES_IRQ(gic_spi(2)), /* IRQ2 */
DEFINE_RES_IRQ(gic_spi(3)), /* IRQ3 */
DEFINE_RES_IRQ(gic_spi(12)), /* IRQ4 */
DEFINE_RES_IRQ(gic_spi(13)), /* IRQ5 */
DEFINE_RES_IRQ(gic_spi(14)), /* IRQ6 */
DEFINE_RES_IRQ(gic_spi(15)), /* IRQ7 */
DEFINE_RES_IRQ(gic_spi(16)), /* IRQ8 */
DEFINE_RES_IRQ(gic_spi(17)), /* IRQ9 */
};
#define r8a7791_register_irqc(idx) \
platform_device_register_resndata(&platform_bus, "renesas_irqc", \
idx, irqc##idx##_resources, \
ARRAY_SIZE(irqc##idx##_resources), \
&irqc##idx##_data, \
sizeof(struct renesas_irqc_config))
void __init r8a7791_add_dt_devices(void)
{
r8a7791_register_scif(SCIFA0);
@ -129,6 +156,12 @@ void __init r8a7791_add_dt_devices(void)
r8a7791_register_cmt(00);
}
void __init r8a7791_add_standard_devices(void)
{
r8a7791_add_dt_devices();
r8a7791_register_irqc(0);
}
void __init r8a7791_init_early(void)
{
#ifndef CONFIG_ARM_ARCH_TIMER
@ -143,7 +176,9 @@ static const char *r8a7791_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(R8A7791_DT, "Generic R8A7791 (Flattened Device Tree)")
.smp = smp_ops(r8a7791_smp_ops),
.init_early = r8a7791_init_early,
.init_time = rcar_gen2_timer_init,
.dt_compat = r8a7791_boards_compat_dt,
MACHINE_END
#endif /* CONFIG_USE_OF */

View file

@ -0,0 +1,91 @@
/*
* R-Car Generation 2 support
*
* Copyright (C) 2013 Renesas Solutions Corp.
* Copyright (C) 2013 Magnus Damm
*
* 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; version 2 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/clocksource.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <mach/common.h>
#include <mach/rcar-gen2.h>
#include <asm/mach/arch.h>
#define MODEMR 0xe6160060
u32 __init rcar_gen2_read_mode_pins(void)
{
void __iomem *modemr = ioremap_nocache(MODEMR, 4);
u32 mode;
BUG_ON(!modemr);
mode = ioread32(modemr);
iounmap(modemr);
return mode;
}
#define CNTCR 0
#define CNTFID0 0x20
void __init rcar_gen2_timer_init(void)
{
#ifdef CONFIG_ARM_ARCH_TIMER
u32 mode = rcar_gen2_read_mode_pins();
void __iomem *base;
int extal_mhz = 0;
u32 freq;
/* At Linux boot time the r8a7790 arch timer comes up
* with the counter disabled. Moreover, it may also report
* a potentially incorrect fixed 13 MHz frequency. To be
* correct these registers need to be updated to use the
* frequency EXTAL / 2 which can be determined by the MD pins.
*/
switch (mode & (MD(14) | MD(13))) {
case 0:
extal_mhz = 15;
break;
case MD(13):
extal_mhz = 20;
break;
case MD(14):
extal_mhz = 26;
break;
case MD(13) | MD(14):
extal_mhz = 30;
break;
}
/* The arch timer frequency equals EXTAL / 2 */
freq = extal_mhz * (1000000 / 2);
/* Remap "armgcnt address map" space */
base = ioremap(0xe6080000, PAGE_SIZE);
/* Update registers with correct frequency */
iowrite32(freq, base + CNTFID0);
asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
/* make sure arch timer is started by setting bit 0 of CNTCR */
iowrite32(1, base + CNTCR);
iounmap(base);
#endif /* CONFIG_ARM_ARCH_TIMER */
clocksource_of_init();
}

View file

@ -34,12 +34,6 @@
static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
int ret;
ret = shmobile_smp_scu_boot_secondary(cpu, idle);
if (ret)
return ret;
arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu)));
return 0;
}

View file

@ -87,10 +87,6 @@ static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
unsigned int lcpu = cpu_logical_map(cpu);
int ret;
ret = shmobile_smp_scu_boot_secondary(cpu, idle);
if (ret)
return ret;
if (lcpu < ARRAY_SIZE(r8a7779_ch_cpu))
ch = r8a7779_ch_cpu[lcpu];

View file

@ -0,0 +1,67 @@
/*
* SMP support for r8a7790
*
* Copyright (C) 2012-2013 Renesas Solutions Corp.
* Copyright (C) 2012 Takashi Yoshii <takashi.yoshii.ze@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <asm/smp_plat.h>
#include <mach/common.h>
#define RST 0xe6160000
#define CA15BAR 0x0020
#define CA7BAR 0x0030
#define CA15RESCNT 0x0040
#define CA7RESCNT 0x0044
#define MERAM 0xe8080000
static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
{
void __iomem *p;
u32 bar;
/* let APMU code install data related to shmobile_boot_vector */
shmobile_smp_apmu_prepare_cpus(max_cpus);
/* MERAM for jump stub, because BAR requires 256KB aligned address */
p = ioremap_nocache(MERAM, shmobile_boot_size);
memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
iounmap(p);
/* setup reset vectors */
p = ioremap_nocache(RST, 0x63);
bar = (MERAM >> 8) & 0xfffffc00;
writel_relaxed(bar, p + CA15BAR);
writel_relaxed(bar, p + CA7BAR);
writel_relaxed(bar | 0x10, p + CA15BAR);
writel_relaxed(bar | 0x10, p + CA7BAR);
/* enable clocks to all CPUs */
writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
p + CA15RESCNT);
writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
p + CA7RESCNT);
iounmap(p);
}
struct smp_operations r8a7790_smp_ops __initdata = {
.smp_prepare_cpus = r8a7790_smp_prepare_cpus,
.smp_boot_secondary = shmobile_smp_apmu_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_disable = shmobile_smp_cpu_disable,
.cpu_die = shmobile_smp_apmu_cpu_die,
.cpu_kill = shmobile_smp_apmu_cpu_kill,
#endif
};

View file

@ -0,0 +1,62 @@
/*
* SMP support for r8a7791
*
* Copyright (C) 2013 Renesas Solutions Corp.
* Copyright (C) 2013 Magnus Damm
*
* 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; version 2 of the License.
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <asm/smp_plat.h>
#include <mach/common.h>
#include <mach/r8a7791.h>
#define RST 0xe6160000
#define CA15BAR 0x0020
#define CA15RESCNT 0x0040
#define RAM 0xe6300000
static void __init r8a7791_smp_prepare_cpus(unsigned int max_cpus)
{
void __iomem *p;
u32 bar;
/* let APMU code install data related to shmobile_boot_vector */
shmobile_smp_apmu_prepare_cpus(max_cpus);
/* RAM for jump stub, because BAR requires 256KB aligned address */
p = ioremap_nocache(RAM, shmobile_boot_size);
memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
iounmap(p);
/* setup reset vectors */
p = ioremap_nocache(RST, 0x63);
bar = (RAM >> 8) & 0xfffffc00;
writel_relaxed(bar, p + CA15BAR);
writel_relaxed(bar | 0x10, p + CA15BAR);
/* enable clocks to all CPUs */
writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
p + CA15RESCNT);
iounmap(p);
}
struct smp_operations r8a7791_smp_ops __initdata = {
.smp_prepare_cpus = r8a7791_smp_prepare_cpus,
.smp_boot_secondary = shmobile_smp_apmu_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_disable = shmobile_smp_cpu_disable,
.cpu_die = shmobile_smp_apmu_cpu_die,
.cpu_kill = shmobile_smp_apmu_cpu_kill,
#endif
};

View file

@ -46,11 +46,6 @@ void __init sh73a0_register_twd(void)
static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned int lcpu = cpu_logical_map(cpu);
int ret;
ret = shmobile_smp_scu_boot_secondary(cpu, idle);
if (ret)
return ret;
if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3)
__raw_writel(1 << lcpu, WUPCR); /* wake up */
@ -71,18 +66,11 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
shmobile_smp_scu_prepare_cpus(max_cpus);
}
#ifdef CONFIG_HOTPLUG_CPU
static int sh73a0_cpu_disable(unsigned int cpu)
{
return 0; /* CPU0 and CPU1 supported */
}
#endif /* CONFIG_HOTPLUG_CPU */
struct smp_operations sh73a0_smp_ops __initdata = {
.smp_prepare_cpus = sh73a0_smp_prepare_cpus,
.smp_boot_secondary = sh73a0_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_disable = sh73a0_cpu_disable,
.cpu_disable = shmobile_smp_cpu_disable,
.cpu_die = shmobile_smp_scu_cpu_die,
.cpu_kill = shmobile_smp_scu_cpu_kill,
#endif