2018-06-14 04:56:06 +03:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2013-09-12 04:32:49 +04:00
|
|
|
/*
|
|
|
|
* R-Car Generation 2 support
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 Renesas Solutions Corp.
|
|
|
|
* Copyright (C) 2013 Magnus Damm
|
2014-09-12 12:52:05 +04:00
|
|
|
* Copyright (C) 2014 Ulrich Hecht
|
2013-09-12 04:32:49 +04:00
|
|
|
*/
|
|
|
|
|
2015-07-07 16:06:34 +03:00
|
|
|
#include <linux/clk-provider.h>
|
2013-09-12 04:32:49 +04:00
|
|
|
#include <linux/clocksource.h>
|
2014-06-09 16:38:45 +04:00
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/dma-contiguous.h>
|
2013-09-12 04:32:49 +04:00
|
|
|
#include <linux/io.h>
|
|
|
|
#include <linux/kernel.h>
|
2015-01-21 08:01:37 +03:00
|
|
|
#include <linux/memblock.h>
|
2014-09-12 12:52:05 +04:00
|
|
|
#include <linux/of.h>
|
2014-06-09 16:38:45 +04:00
|
|
|
#include <linux/of_fdt.h>
|
2016-10-17 16:59:04 +03:00
|
|
|
#include <linux/of_platform.h>
|
2019-05-29 19:05:00 +03:00
|
|
|
#include <linux/psci.h>
|
2013-09-12 04:32:49 +04:00
|
|
|
#include <asm/mach/arch.h>
|
2018-05-04 22:05:45 +03:00
|
|
|
#include <asm/secure_cntvoff.h>
|
2014-06-17 11:47:37 +04:00
|
|
|
#include "common.h"
|
2014-06-17 11:48:01 +04:00
|
|
|
#include "rcar-gen2.h"
|
2013-09-12 04:32:49 +04:00
|
|
|
|
ARM: shmobile: rcar-gen2: Add support for CPG/MSSR bindings
When using the new CPG/MSSR bindings, there is no longer a
"renesas,rcar-gen2-cpg-clocks" node, and the code to obtain the external
clock crystal frequency falls back to a default of 20 MHz.
While this is correct for all upstream R-Car Gen2 and RZ/G1 boards, this
is not necessarily the case for out-of-tree third party boards.
Add support for finding the external clock crystal oscillator on RZ/G1M,
and on R-Car H2, M2-W, and M2-N using the new CPG/MSSR bindings, through
the corresponding "renesas,r8a77xx-cpg-mssr" nodes.
Note that this is not needed on R-Car V2H and E2, and on RZ/G1E, as on
those SoCs the arch_timer and generic counter clock is derived from the
ZS clock instead.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
2017-07-12 13:39:32 +03:00
|
|
|
static const struct of_device_id cpg_matches[] __initconst = {
|
|
|
|
{ .compatible = "renesas,r8a7743-cpg-mssr", .data = "extal" },
|
2018-09-11 13:12:50 +03:00
|
|
|
{ .compatible = "renesas,r8a7744-cpg-mssr", .data = "extal" },
|
ARM: shmobile: rcar-gen2: Add support for CPG/MSSR bindings
When using the new CPG/MSSR bindings, there is no longer a
"renesas,rcar-gen2-cpg-clocks" node, and the code to obtain the external
clock crystal frequency falls back to a default of 20 MHz.
While this is correct for all upstream R-Car Gen2 and RZ/G1 boards, this
is not necessarily the case for out-of-tree third party boards.
Add support for finding the external clock crystal oscillator on RZ/G1M,
and on R-Car H2, M2-W, and M2-N using the new CPG/MSSR bindings, through
the corresponding "renesas,r8a77xx-cpg-mssr" nodes.
Note that this is not needed on R-Car V2H and E2, and on RZ/G1E, as on
those SoCs the arch_timer and generic counter clock is derived from the
ZS clock instead.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
2017-07-12 13:39:32 +03:00
|
|
|
{ .compatible = "renesas,r8a7790-cpg-mssr", .data = "extal" },
|
|
|
|
{ .compatible = "renesas,r8a7791-cpg-mssr", .data = "extal" },
|
|
|
|
{ .compatible = "renesas,r8a7793-cpg-mssr", .data = "extal" },
|
|
|
|
{ /* sentinel */ }
|
|
|
|
};
|
|
|
|
|
2016-06-13 13:29:37 +03:00
|
|
|
static unsigned int __init get_extal_freq(void)
|
|
|
|
{
|
ARM: shmobile: rcar-gen2: Add support for CPG/MSSR bindings
When using the new CPG/MSSR bindings, there is no longer a
"renesas,rcar-gen2-cpg-clocks" node, and the code to obtain the external
clock crystal frequency falls back to a default of 20 MHz.
While this is correct for all upstream R-Car Gen2 and RZ/G1 boards, this
is not necessarily the case for out-of-tree third party boards.
Add support for finding the external clock crystal oscillator on RZ/G1M,
and on R-Car H2, M2-W, and M2-N using the new CPG/MSSR bindings, through
the corresponding "renesas,r8a77xx-cpg-mssr" nodes.
Note that this is not needed on R-Car V2H and E2, and on RZ/G1E, as on
those SoCs the arch_timer and generic counter clock is derived from the
ZS clock instead.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
2017-07-12 13:39:32 +03:00
|
|
|
const struct of_device_id *match;
|
2016-06-13 13:29:37 +03:00
|
|
|
struct device_node *cpg, *extal;
|
|
|
|
u32 freq = 20000000;
|
ARM: shmobile: rcar-gen2: Add support for CPG/MSSR bindings
When using the new CPG/MSSR bindings, there is no longer a
"renesas,rcar-gen2-cpg-clocks" node, and the code to obtain the external
clock crystal frequency falls back to a default of 20 MHz.
While this is correct for all upstream R-Car Gen2 and RZ/G1 boards, this
is not necessarily the case for out-of-tree third party boards.
Add support for finding the external clock crystal oscillator on RZ/G1M,
and on R-Car H2, M2-W, and M2-N using the new CPG/MSSR bindings, through
the corresponding "renesas,r8a77xx-cpg-mssr" nodes.
Note that this is not needed on R-Car V2H and E2, and on RZ/G1E, as on
those SoCs the arch_timer and generic counter clock is derived from the
ZS clock instead.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
2017-07-12 13:39:32 +03:00
|
|
|
int idx = 0;
|
2016-06-13 13:29:37 +03:00
|
|
|
|
ARM: shmobile: rcar-gen2: Add support for CPG/MSSR bindings
When using the new CPG/MSSR bindings, there is no longer a
"renesas,rcar-gen2-cpg-clocks" node, and the code to obtain the external
clock crystal frequency falls back to a default of 20 MHz.
While this is correct for all upstream R-Car Gen2 and RZ/G1 boards, this
is not necessarily the case for out-of-tree third party boards.
Add support for finding the external clock crystal oscillator on RZ/G1M,
and on R-Car H2, M2-W, and M2-N using the new CPG/MSSR bindings, through
the corresponding "renesas,r8a77xx-cpg-mssr" nodes.
Note that this is not needed on R-Car V2H and E2, and on RZ/G1E, as on
those SoCs the arch_timer and generic counter clock is derived from the
ZS clock instead.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
2017-07-12 13:39:32 +03:00
|
|
|
cpg = of_find_matching_node_and_match(NULL, cpg_matches, &match);
|
2016-06-13 13:29:37 +03:00
|
|
|
if (!cpg)
|
|
|
|
return freq;
|
|
|
|
|
ARM: shmobile: rcar-gen2: Add support for CPG/MSSR bindings
When using the new CPG/MSSR bindings, there is no longer a
"renesas,rcar-gen2-cpg-clocks" node, and the code to obtain the external
clock crystal frequency falls back to a default of 20 MHz.
While this is correct for all upstream R-Car Gen2 and RZ/G1 boards, this
is not necessarily the case for out-of-tree third party boards.
Add support for finding the external clock crystal oscillator on RZ/G1M,
and on R-Car H2, M2-W, and M2-N using the new CPG/MSSR bindings, through
the corresponding "renesas,r8a77xx-cpg-mssr" nodes.
Note that this is not needed on R-Car V2H and E2, and on RZ/G1E, as on
those SoCs the arch_timer and generic counter clock is derived from the
ZS clock instead.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
2017-07-12 13:39:32 +03:00
|
|
|
if (match->data)
|
|
|
|
idx = of_property_match_string(cpg, "clock-names", match->data);
|
|
|
|
extal = of_parse_phandle(cpg, "clocks", idx);
|
2016-06-13 13:29:37 +03:00
|
|
|
of_node_put(cpg);
|
|
|
|
if (!extal)
|
|
|
|
return freq;
|
|
|
|
|
|
|
|
of_property_read_u32(extal, "clock-frequency", &freq);
|
|
|
|
of_node_put(extal);
|
|
|
|
return freq;
|
|
|
|
}
|
|
|
|
|
2013-09-12 04:32:49 +04:00
|
|
|
#define CNTCR 0
|
|
|
|
#define CNTFID0 0x20
|
|
|
|
|
|
|
|
void __init rcar_gen2_timer_init(void)
|
|
|
|
{
|
2019-05-29 19:05:00 +03:00
|
|
|
bool need_update = true;
|
2013-09-12 04:32:49 +04:00
|
|
|
void __iomem *base;
|
|
|
|
u32 freq;
|
|
|
|
|
2019-05-29 19:05:00 +03:00
|
|
|
/*
|
|
|
|
* If PSCI is available then most likely we are running on PSCI-enabled
|
|
|
|
* U-Boot which, we assume, has already taken care of resetting CNTVOFF
|
|
|
|
* and updating counter module before switching to non-secure mode
|
|
|
|
* and we don't need to.
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_ARM_PSCI_FW
|
|
|
|
if (psci_ops.cpu_on)
|
|
|
|
need_update = false;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (need_update == false)
|
|
|
|
goto skip_update;
|
|
|
|
|
2018-05-04 22:05:45 +03:00
|
|
|
secure_cntvoff_init();
|
ARM: shmobile: rcar-gen2: Make sure CNTVOFF is initialized on CA7/15
On Cortex-A7, the arch timer CNTVOFF register is uninitialized.
Ideally it should be initialized by the boot loader, but it isn't.
For the boot CPU, CNTVOFF is initialized by Linux since commit
9ce3fa6816c2fb59 ("ARM: shmobile: rcar-gen2: Add CA7 arch_timer
initialization for r8a7794").
For secondary CPU cores, no such initialization is done.
Hence when enabling SMP on r8a7794, the kernel log is spammed with:
WARNING: Underflow in clocksource 'arch_sys_counter' observed, time update ignored.
Please report this, consider using a different clocksource, if possible.
Your kernel is probably still fine.
As Marc Zyngier pointed out that Cortex-A15 and Cortex-A7 are similar with
respect to CNTVOFF, we have been very lucky this just worked on R-Car
Gen2 SoCs with Cortex-A15 cores.
To fix this:
- Move the existing inline asm code to initialize CNTVOFF to an
assembler source file (adding comments and replacing hardcoded
constants by definitions in the process), so it can be reused,
- Perform the initialization of CNTVOFF on the boot CPU (Cortex-A15 or
Cortex-A7) on all R-Car Gen2 and RZ/G1 parts,
- Wrap the standard secondary_startup() routine inside a routine which
initializes CNTVOFF.
Based on patches by Hisashi Nakamura in the BSP.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Tested-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
2017-09-01 11:37:45 +03:00
|
|
|
|
2017-07-18 16:30:15 +03:00
|
|
|
if (of_machine_is_compatible("renesas,r8a7745") ||
|
2018-03-28 22:26:13 +03:00
|
|
|
of_machine_is_compatible("renesas,r8a77470") ||
|
2017-07-18 16:30:15 +03:00
|
|
|
of_machine_is_compatible("renesas,r8a7792") ||
|
2016-06-13 13:31:12 +03:00
|
|
|
of_machine_is_compatible("renesas,r8a7794")) {
|
2014-09-12 12:52:05 +04:00
|
|
|
freq = 260000000 / 8; /* ZS / 8 */
|
|
|
|
} else {
|
|
|
|
/* 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
|
2016-06-13 13:29:37 +03:00
|
|
|
* frequency EXTAL / 2.
|
2014-09-12 12:52:05 +04:00
|
|
|
*/
|
2016-06-13 13:29:37 +03:00
|
|
|
freq = get_extal_freq() / 2;
|
2014-09-12 12:52:05 +04:00
|
|
|
}
|
2013-09-12 04:32:49 +04:00
|
|
|
|
|
|
|
/* Remap "armgcnt address map" space */
|
|
|
|
base = ioremap(0xe6080000, PAGE_SIZE);
|
|
|
|
|
2013-12-11 14:07:42 +04:00
|
|
|
/*
|
|
|
|
* Update the timer if it is either not running, or is not at the
|
|
|
|
* right frequency. The timer is only configurable in secure mode
|
|
|
|
* so this avoids an abort if the loader started the timer and
|
|
|
|
* entered the kernel in non-secure mode.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((ioread32(base + CNTCR) & 1) == 0 ||
|
|
|
|
ioread32(base + CNTFID0) != freq) {
|
|
|
|
/* 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);
|
|
|
|
}
|
2013-09-12 04:32:49 +04:00
|
|
|
|
|
|
|
iounmap(base);
|
|
|
|
|
2019-05-29 19:05:00 +03:00
|
|
|
skip_update:
|
2015-07-07 16:06:34 +03:00
|
|
|
of_clk_init(NULL);
|
2017-05-26 18:40:46 +03:00
|
|
|
timer_probe();
|
2013-09-12 04:32:49 +04:00
|
|
|
}
|
2014-06-12 12:42:22 +04:00
|
|
|
|
|
|
|
struct memory_reserve_config {
|
|
|
|
u64 reserved;
|
|
|
|
u64 base, size;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __init rcar_gen2_scan_mem(unsigned long node, const char *uname,
|
|
|
|
int depth, void *data)
|
|
|
|
{
|
|
|
|
const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
|
|
|
|
const __be32 *reg, *endp;
|
|
|
|
int l;
|
|
|
|
struct memory_reserve_config *mrc = data;
|
2014-06-12 12:42:23 +04:00
|
|
|
u64 lpae_start = 1ULL << 32;
|
2014-06-12 12:42:22 +04:00
|
|
|
|
|
|
|
/* We are scanning "memory" nodes only */
|
2014-06-12 12:42:24 +04:00
|
|
|
if (type == NULL || strcmp(type, "memory"))
|
2014-06-12 12:42:22 +04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
|
|
|
|
if (reg == NULL)
|
|
|
|
reg = of_get_flat_dt_prop(node, "reg", &l);
|
|
|
|
if (reg == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
endp = reg + (l / sizeof(__be32));
|
|
|
|
while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
|
|
|
|
u64 base, size;
|
|
|
|
|
|
|
|
base = dt_mem_next_cell(dt_root_addr_cells, ®);
|
|
|
|
size = dt_mem_next_cell(dt_root_size_cells, ®);
|
|
|
|
|
|
|
|
if (base >= lpae_start)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((base + size) >= lpae_start)
|
|
|
|
size = lpae_start - base;
|
|
|
|
|
|
|
|
if (size < mrc->reserved)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (base < mrc->base)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* keep the area at top near the 32-bit legacy limit */
|
|
|
|
mrc->base = base + size - mrc->reserved;
|
|
|
|
mrc->size = mrc->reserved;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void __init rcar_gen2_reserve(void)
|
|
|
|
{
|
|
|
|
struct memory_reserve_config mrc;
|
|
|
|
|
|
|
|
/* reserve 256 MiB at the top of the physical legacy 32-bit space */
|
|
|
|
memset(&mrc, 0, sizeof(mrc));
|
|
|
|
mrc.reserved = SZ_256M;
|
|
|
|
|
|
|
|
of_scan_flat_dt(rcar_gen2_scan_mem, &mrc);
|
|
|
|
#ifdef CONFIG_DMA_CMA
|
2016-01-28 18:20:47 +03:00
|
|
|
if (mrc.size && memblock_is_region_memory(mrc.base, mrc.size)) {
|
|
|
|
static struct cma *rcar_gen2_dma_contiguous;
|
|
|
|
|
2014-06-12 12:42:22 +04:00
|
|
|
dma_contiguous_reserve_area(mrc.size, mrc.base, 0,
|
2014-06-19 13:31:10 +04:00
|
|
|
&rcar_gen2_dma_contiguous, true);
|
2016-01-28 18:20:47 +03:00
|
|
|
}
|
2014-06-12 12:42:22 +04:00
|
|
|
#endif
|
|
|
|
}
|
2016-10-17 16:59:04 +03:00
|
|
|
|
|
|
|
static const char * const rcar_gen2_boards_compat_dt[] __initconst = {
|
2018-05-18 15:48:51 +03:00
|
|
|
"renesas,r8a7790",
|
2018-05-18 15:48:53 +03:00
|
|
|
"renesas,r8a7791",
|
2016-10-17 16:59:04 +03:00
|
|
|
"renesas,r8a7792",
|
|
|
|
"renesas,r8a7793",
|
|
|
|
"renesas,r8a7794",
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
DT_MACHINE_START(RCAR_GEN2_DT, "Generic R-Car Gen2 (Flattened Device Tree)")
|
|
|
|
.init_late = shmobile_init_late,
|
|
|
|
.init_time = rcar_gen2_timer_init,
|
|
|
|
.reserve = rcar_gen2_reserve,
|
|
|
|
.dt_compat = rcar_gen2_boards_compat_dt,
|
|
|
|
MACHINE_END
|
|
|
|
|
|
|
|
static const char * const rz_g1_boards_compat_dt[] __initconst = {
|
|
|
|
"renesas,r8a7743",
|
2018-09-11 13:12:50 +03:00
|
|
|
"renesas,r8a7744",
|
2016-11-05 00:49:55 +03:00
|
|
|
"renesas,r8a7745",
|
2018-03-28 22:26:13 +03:00
|
|
|
"renesas,r8a77470",
|
2016-10-17 16:59:04 +03:00
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
DT_MACHINE_START(RZ_G1_DT, "Generic RZ/G1 (Flattened Device Tree)")
|
|
|
|
.init_late = shmobile_init_late,
|
|
|
|
.init_time = rcar_gen2_timer_init,
|
|
|
|
.reserve = rcar_gen2_reserve,
|
|
|
|
.dt_compat = rz_g1_boards_compat_dt,
|
|
|
|
MACHINE_END
|