2018-09-07 01:43:23 +00:00
// SPDX-License-Identifier: GPL-2.0
2015-03-16 14:48:43 +09:00
/*
* R - Car Generation 2 Power management support
*
* Copyright ( C ) 2013 - 2015 Renesas Electronics Corporation
* Copyright ( C ) 2011 Renesas Solutions Corp .
* Copyright ( C ) 2011 Magnus Damm
*/
# include <linux/kernel.h>
2017-07-04 17:41:36 +02:00
# include <linux/ioport.h>
2015-03-16 14:48:43 +09:00
# include <linux/of.h>
2017-07-04 17:41:36 +02:00
# include <linux/of_address.h>
2015-03-16 14:48:43 +09:00
# include <linux/smp.h>
# include <asm/io.h>
2018-02-12 17:44:19 +00:00
# include <asm/cputype.h>
2015-03-16 14:48:43 +09:00
# include "common.h"
# include "rcar-gen2.h"
/* RST */
# define RST 0xe6160000
2017-01-25 10:02:13 +01:00
# define CA15BAR 0x0020 /* CA15 Boot Address Register */
# define CA7BAR 0x0030 /* CA7 Boot Address Register */
# define CA15RESCNT 0x0040 /* CA15 Reset Control Register */
# define CA7RESCNT 0x0044 /* CA7 Reset Control Register */
/* SYS Boot Address Register */
# define SBAR_BAREN BIT(4) /* SBAR is valid */
/* Reset Control Registers */
# define CA15RESCNT_CODE 0xa5a50000
# define CA15RESCNT_CPUS 0xf /* CPU0-3 */
# define CA7RESCNT_CODE 0x5a5a0000
# define CA7RESCNT_CPUS 0xf /* CPU0-3 */
2015-03-16 14:48:43 +09:00
/* On-chip RAM */
2016-05-17 17:15:33 +02:00
# define ICRAM1 0xe63c0000 /* Inter Connect RAM1 (4 KiB) */
2015-03-16 14:48:43 +09:00
2017-01-25 10:02:13 +01:00
static inline u32 phys_to_sbar ( phys_addr_t addr )
{
return ( addr > > 8 ) & 0xfffffc00 ;
}
2015-03-16 14:48:43 +09:00
void __init rcar_gen2_pm_init ( void )
{
void __iomem * p ;
u32 bar ;
static int once ;
2018-08-27 09:42:49 -05:00
struct device_node * np ;
2015-03-16 14:48:43 +09:00
bool has_a7 = false ;
bool has_a15 = false ;
2017-07-04 17:41:36 +02:00
struct resource res ;
int error ;
2015-03-16 14:48:43 +09:00
if ( once + + )
return ;
2018-08-27 09:42:49 -05:00
for_each_of_cpu_node ( np ) {
2015-03-16 14:48:43 +09:00
if ( of_device_is_compatible ( np , " arm,cortex-a15 " ) )
has_a15 = true ;
else if ( of_device_is_compatible ( np , " arm,cortex-a7 " ) )
has_a7 = true ;
}
2017-07-04 17:41:36 +02:00
np = of_find_compatible_node ( NULL , NULL , " renesas,smp-sram " ) ;
if ( ! np ) {
/* No smp-sram in DT, fall back to hardcoded address */
res = ( struct resource ) DEFINE_RES_MEM ( ICRAM1 ,
shmobile_boot_size ) ;
goto map ;
}
error = of_address_to_resource ( np , 0 , & res ) ;
2019-03-01 16:56:49 +08:00
of_node_put ( np ) ;
2017-07-04 17:41:36 +02:00
if ( error ) {
pr_err ( " Failed to get smp-sram address: %d \n " , error ) ;
return ;
}
map :
2015-03-16 14:48:43 +09:00
/* RAM for jump stub, because BAR requires 256KB aligned address */
2017-07-04 17:41:36 +02:00
if ( res . start & ( 256 * 1024 - 1 ) | |
resource_size ( & res ) < shmobile_boot_size ) {
pr_err ( " Invalid smp-sram region \n " ) ;
return ;
}
p = ioremap ( res . start , resource_size ( & res ) ) ;
if ( ! p )
return ;
2018-02-12 17:44:19 +00:00
/*
* 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 ) ;
}
2015-03-16 14:48:43 +09:00
iounmap ( p ) ;
/* setup reset vectors */
2020-01-06 09:43:50 +01:00
p = ioremap ( RST , 0x63 ) ;
2017-07-04 17:41:36 +02:00
bar = phys_to_sbar ( res . start ) ;
2015-03-16 14:48:43 +09:00
if ( has_a15 ) {
writel_relaxed ( bar , p + CA15BAR ) ;
2017-01-25 10:02:13 +01:00
writel_relaxed ( bar | SBAR_BAREN , p + CA15BAR ) ;
2015-03-16 14:48:43 +09:00
/* de-assert reset for CA15 CPUs */
2017-01-25 10:02:13 +01:00
writel_relaxed ( ( readl_relaxed ( p + CA15RESCNT ) &
~ CA15RESCNT_CPUS ) | CA15RESCNT_CODE ,
p + CA15RESCNT ) ;
2015-03-16 14:48:43 +09:00
}
if ( has_a7 ) {
writel_relaxed ( bar , p + CA7BAR ) ;
2017-01-25 10:02:13 +01:00
writel_relaxed ( bar | SBAR_BAREN , p + CA7BAR ) ;
2015-03-16 14:48:43 +09:00
/* de-assert reset for CA7 CPUs */
2017-01-25 10:02:13 +01:00
writel_relaxed ( ( readl_relaxed ( p + CA7RESCNT ) &
~ CA7RESCNT_CPUS ) | CA7RESCNT_CODE ,
p + CA7RESCNT ) ;
2015-03-16 14:48:43 +09:00
}
iounmap ( p ) ;
shmobile_smp_apmu_suspend_init ( ) ;
}