2013-09-12 09:32:49 +09:00
/*
* R - Car Generation 2 support
*
* Copyright ( C ) 2013 Renesas Solutions Corp .
* Copyright ( C ) 2013 Magnus Damm
2014-09-12 10:52:05 +02:00
* Copyright ( C ) 2014 Ulrich Hecht
2013-09-12 09:32:49 +09:00
*
* 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 .
*/
2015-07-07 15:06:34 +02:00
# include <linux/clk-provider.h>
2013-09-12 09:32:49 +09:00
# include <linux/clocksource.h>
2014-06-09 21:38:45 +09:00
# include <linux/device.h>
# include <linux/dma-contiguous.h>
2013-09-12 09:32:49 +09:00
# include <linux/io.h>
# include <linux/kernel.h>
2015-01-21 14:01:37 +09:00
# include <linux/memblock.h>
2014-09-12 10:52:05 +02:00
# include <linux/of.h>
2014-06-09 21:38:45 +09:00
# include <linux/of_fdt.h>
2016-10-17 16:59:04 +03:00
# include <linux/of_platform.h>
2013-09-12 09:32:49 +09:00
# include <asm/mach/arch.h>
2014-06-17 16:47:37 +09:00
# include "common.h"
2014-06-17 16:48:01 +09:00
# include "rcar-gen2.h"
2013-09-12 09:32:49 +09: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 12:39:32 +02:00
static const struct of_device_id cpg_matches [ ] __initconst = {
{ . compatible = " renesas,rcar-gen2-cpg-clocks " , } ,
{ . compatible = " renesas,r8a7743-cpg-mssr " , . data = " extal " } ,
{ . 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 12:29:37 +02: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 12:39:32 +02:00
const struct of_device_id * match ;
2016-06-13 12:29:37 +02: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 12:39:32 +02:00
int idx = 0 ;
2016-06-13 12:29:37 +02: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 12:39:32 +02:00
cpg = of_find_matching_node_and_match ( NULL , cpg_matches , & match ) ;
2016-06-13 12:29:37 +02: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 12:39:32 +02:00
if ( match - > data )
idx = of_property_match_string ( cpg , " clock-names " , match - > data ) ;
extal = of_parse_phandle ( cpg , " clocks " , idx ) ;
2016-06-13 12:29:37 +02: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 09:32:49 +09:00
# define CNTCR 0
# define CNTFID0 0x20
void __init rcar_gen2_timer_init ( void )
{
2013-12-11 15:13:51 +01:00
# ifdef CONFIG_ARM_ARCH_TIMER
2013-09-12 09:32:49 +09:00
void __iomem * base ;
u32 freq ;
2017-07-18 15:30:15 +02:00
if ( of_machine_is_compatible ( " renesas,r8a7745 " ) | |
of_machine_is_compatible ( " renesas,r8a7792 " ) | |
2016-06-13 12:31:12 +02:00
of_machine_is_compatible ( " renesas,r8a7794 " ) ) {
2014-09-12 10:52:05 +02:00
freq = 260000000 / 8 ; /* ZS / 8 */
/* CNTVOFF has to be initialized either from non-secure
* Hypervisor mode or secure Monitor mode with SCR . NS = = 1.
* If TrustZone is enabled then it should be handled by the
* secure code .
*/
asm volatile (
" cps 0x16 \n "
" mrc p15, 0, r1, c1, c1, 0 \n "
" orr r0, r1, #1 \n "
" mcr p15, 0, r0, c1, c1, 0 \n "
" isb \n "
" mov r0, #0 \n "
" mcrr p15, 4, r0, r0, c14 \n "
" isb \n "
" mcr p15, 0, r1, c1, c1, 0 \n "
" isb \n "
" cps 0x13 \n "
: : : " r0 " , " r1 " ) ;
} 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 12:29:37 +02:00
* frequency EXTAL / 2.
2014-09-12 10:52:05 +02:00
*/
2016-06-13 12:29:37 +02:00
freq = get_extal_freq ( ) / 2 ;
2014-09-12 10:52:05 +02:00
}
2013-09-12 09:32:49 +09:00
/* Remap "armgcnt address map" space */
base = ioremap ( 0xe6080000 , PAGE_SIZE ) ;
2013-12-11 10:07:42 +00: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 09:32:49 +09:00
iounmap ( base ) ;
# endif /* CONFIG_ARM_ARCH_TIMER */
2015-07-07 15:06:34 +02:00
of_clk_init ( NULL ) ;
2017-05-26 17:40:46 +02:00
timer_probe ( ) ;
2013-09-12 09:32:49 +09:00
}
2014-06-12 10:42:22 +02: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 10:42:23 +02:00
u64 lpae_start = 1ULL < < 32 ;
2014-06-12 10:42:22 +02:00
/* We are scanning "memory" nodes only */
2014-06-12 10:42:24 +02:00
if ( type = = NULL | | strcmp ( type , " memory " ) )
2014-06-12 10:42:22 +02: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 , & reg ) ;
size = dt_mem_next_cell ( dt_root_size_cells , & reg ) ;
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 16:20:47 +01:00
if ( mrc . size & & memblock_is_region_memory ( mrc . base , mrc . size ) ) {
static struct cma * rcar_gen2_dma_contiguous ;
2014-06-12 10:42:22 +02:00
dma_contiguous_reserve_area ( mrc . size , mrc . base , 0 ,
2014-06-19 11:31:10 +02:00
& rcar_gen2_dma_contiguous , true ) ;
2016-01-28 16:20:47 +01:00
}
2014-06-12 10:42:22 +02:00
# endif
}
2016-10-17 16:59:04 +03:00
static const char * const rcar_gen2_boards_compat_dt [ ] __initconst = {
/*
* R8A7790 and R8A7791 can ' t be handled here as long as they need SMP
* initialization fallback .
*/
" renesas,r8a7792 " ,
" renesas,r8a7793 " ,
" renesas,r8a7794 " ,
NULL ,
} ;
DT_MACHINE_START ( RCAR_GEN2_DT , " Generic R-Car Gen2 (Flattened Device Tree) " )
. init_early = shmobile_init_delay ,
. 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 " ,
2016-11-05 00:49:55 +03:00
" renesas,r8a7745 " ,
2016-10-17 16:59:04 +03:00
NULL ,
} ;
DT_MACHINE_START ( RZ_G1_DT , " Generic RZ/G1 (Flattened Device Tree) " )
. init_early = shmobile_init_delay ,
. init_late = shmobile_init_late ,
. init_time = rcar_gen2_timer_init ,
. reserve = rcar_gen2_reserve ,
. dt_compat = rz_g1_boards_compat_dt ,
MACHINE_END