Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
32c70e40
Commit
32c70e40
authored
Sep 23, 2018
by
Jorge Ramirez-Ortiz
Committed by
ldts
Oct 17, 2018
Browse files
rcar_gen3: drivers: power controller
Signed-off-by:
ldts
<
jramirez@baylibre.com
>
parent
0a106e28
Changes
3
Hide whitespace changes
Inline
Side-by-side
drivers/renesas/rcar/pwrc/call_sram.S
0 → 100644
View file @
32c70e40
/*
*
Copyright
(
c
)
2018
,
Renesas
Electronics
Corporation
.
All
rights
reserved
.
*
*
SPDX
-
License
-
Identifier
:
BSD
-
3
-
Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include "rcar_def.h"
.
global
rcar_pwrc_switch_stack
.
global
rcar_pwrc_save_generic_timer
.
global
rcar_pwrc_restore_generic_timer
#define OFFSET_SP_X9_X10 (0x00)
#define OFFSET_CNTFID0 (0x10)
#define OFFSET_CNTPCT_EL0 (0x18)
#define OFFSET_TIMER_COUNT (0x20)
/*
*
x0
:
jump
address
,
*
x1
:
stack
address
,
*
x2
:
arg
,
*
x3
:
stack
address
(
temporary
)
*/
func
rcar_pwrc_switch_stack
/
*
lr
to
stack
*/
stp
x29
,
x30
,
[
sp
,#-
16
]
/
*
change
stack
pointer
*/
mov
x3
,
sp
mov
sp
,
x1
/
*
save
stack
pointer
*/
sub
sp
,
sp
,
#
16
stp
x0
,
x3
,
[
sp
]
/
*
data
synchronization
barrier
*/
dsb
sy
/
*
jump
to
code
*/
mov
x1
,
x0
mov
x0
,
x2
blr
x1
/
*
load
stack
pointer
*/
ldp
x0
,
x2
,
[
sp
,#
0
]
/
*
change
stack
pointer
*/
mov
sp
,
x2
/
*
return
*/
ldp
x29
,
x30
,
[
sp
,#-
16
]
ret
endfunc
rcar_pwrc_switch_stack
/*
x0
:
stack
pointer
base
address
*/
func
rcar_pwrc_save_generic_timer
stp
x9
,
x10
,
[
x0
,
#
OFFSET_SP_X9_X10
]
/
*
save
CNTFID0
and
cntpct_el0
*/
mov_imm
x10
,
(
RCAR_CNTC_BASE
+
CNTFID_OFF
)
ldr
x9
,
[
x10
]
mrs
x10
,
cntpct_el0
stp
x9
,
x10
,
[
x0
,
#
OFFSET_CNTFID0
]
ldp
x9
,
x10
,
[
x0
,
#
OFFSET_SP_X9_X10
]
ret
endfunc
rcar_pwrc_save_generic_timer
/*
x0
:
Stack
pointer
base
address
*/
func
rcar_pwrc_restore_generic_timer
stp
x9
,
x10
,
[
x0
,
#
OFFSET_SP_X9_X10
]
/
*
restore
CNTFID0
and
cntpct_el0
*/
ldr
x10
,
[
x0
,
#
OFFSET_CNTFID0
]
mov_imm
x9
,
(
RCAR_CNTC_BASE
+
CNTFID_OFF
)
str
x10
,
[
x9
]
ldp
x9
,
x10
,
[
x0
,
#
OFFSET_CNTPCT_EL0
]
add
x9
,
x9
,
x10
str
x9
,
[
x0
,
#
OFFSET_TIMER_COUNT
]
ldp
x9
,
x10
,
[
x0
,
#
OFFSET_SP_X9_X10
]
ret
endfunc
rcar_pwrc_restore_generic_timer
drivers/renesas/rcar/pwrc/pwrc.c
0 → 100644
View file @
32c70e40
/*
* Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
#include <bakery_lock.h>
#include <debug.h>
#include <mmio.h>
#include <string.h>
#include <xlat_tables_v2.h>
#include "iic_dvfs.h"
#include "rcar_def.h"
#include "rcar_private.h"
#include "pwrc.h"
/*
* Someday there will be a generic power controller api. At the moment each
* platform has its own pwrc so just exporting functions should be acceptable.
*/
RCAR_INSTANTIATE_LOCK
#define WUP_IRQ_SHIFT (0U)
#define WUP_FIQ_SHIFT (8U)
#define WUP_CSD_SHIFT (16U)
#define BIT_SOFTRESET (1U<<15)
#define BIT_CA53_SCU (1U<<21)
#define BIT_CA57_SCU (1U<<12)
#define REQ_RESUME (1U<<1)
#define REQ_OFF (1U<<0)
#define STATUS_PWRUP (1U<<4)
#define STATUS_PWRDOWN (1U<<0)
#define STATE_CA57_CPU (27U)
#define STATE_CA53_CPU (22U)
#define MODE_L2_DOWN (0x00000002U)
#define CPU_PWR_OFF (0x00000003U)
#define RCAR_PSTR_MASK (0x00000003U)
#define ST_ALL_STANDBY (0x00003333U)
/* Suspend to ram */
#define DBSC4_REG_BASE (0xE6790000U)
#define DBSC4_REG_DBSYSCNT0 (DBSC4_REG_BASE + 0x0100U)
#define DBSC4_REG_DBACEN (DBSC4_REG_BASE + 0x0200U)
#define DBSC4_REG_DBCMD (DBSC4_REG_BASE + 0x0208U)
#define DBSC4_REG_DBRFEN (DBSC4_REG_BASE + 0x0204U)
#define DBSC4_REG_DBWAIT (DBSC4_REG_BASE + 0x0210U)
#define DBSC4_REG_DBCALCNF (DBSC4_REG_BASE + 0x0424U)
#define DBSC4_REG_DBPDLK0 (DBSC4_REG_BASE + 0x0620U)
#define DBSC4_REG_DBPDRGA0 (DBSC4_REG_BASE + 0x0624U)
#define DBSC4_REG_DBPDRGD0 (DBSC4_REG_BASE + 0x0628U)
#define DBSC4_REG_DBCAM0CTRL0 (DBSC4_REG_BASE + 0x0940U)
#define DBSC4_REG_DBCAM0STAT0 (DBSC4_REG_BASE + 0x0980U)
#define DBSC4_REG_DBCAM1STAT0 (DBSC4_REG_BASE + 0x0990U)
#define DBSC4_REG_DBCAM2STAT0 (DBSC4_REG_BASE + 0x09A0U)
#define DBSC4_REG_DBCAM3STAT0 (DBSC4_REG_BASE + 0x09B0U)
#define DBSC4_BIT_DBACEN_ACCEN ((uint32_t)(1U << 0))
#define DBSC4_BIT_DBRFEN_ARFEN ((uint32_t)(1U << 0))
#define DBSC4_BIT_DBCAMxSTAT0 (0x00000001U)
#define DBSC4_SET_DBCMD_OPC_PRE (0x04000000U)
#define DBSC4_SET_DBCMD_OPC_SR (0x0A000000U)
#define DBSC4_SET_DBCMD_OPC_PD (0x08000000U)
#define DBSC4_SET_DBCMD_OPC_MRW (0x0E000000U)
#define DBSC4_SET_DBCMD_CH_ALL (0x00800000U)
#define DBSC4_SET_DBCMD_RANK_ALL (0x00040000U)
#define DBSC4_SET_DBCMD_ARG_ALL (0x00000010U)
#define DBSC4_SET_DBCMD_ARG_ENTER (0x00000000U)
#define DBSC4_SET_DBCMD_ARG_MRW_ODTC (0x00000B00U)
#define DBSC4_SET_DBSYSCNT0_WRITE_ENABLE (0x00001234U)
#define DBSC4_SET_DBSYSCNT0_WRITE_DISABLE (0x00000000U)
#define DBSC4_SET_DBPDLK0_PHY_ACCESS (0x0000A55AU)
#define DBSC4_SET_DBPDRGA0_ACIOCR0 (0x0000001AU)
#define DBSC4_SET_DBPDRGD0_ACIOCR0 (0x33C03C11U)
#define DBSC4_SET_DBPDRGA0_DXCCR (0x00000020U)
#define DBSC4_SET_DBPDRGD0_DXCCR (0x00181006U)
#define DBSC4_SET_DBPDRGA0_PGCR1 (0x00000003U)
#define DBSC4_SET_DBPDRGD0_PGCR1 (0x0380C600U)
#define DBSC4_SET_DBPDRGA0_ACIOCR1 (0x0000001BU)
#define DBSC4_SET_DBPDRGD0_ACIOCR1 (0xAAAAAAAAU)
#define DBSC4_SET_DBPDRGA0_ACIOCR3 (0x0000001DU)
#define DBSC4_SET_DBPDRGD0_ACIOCR3 (0xAAAAAAAAU)
#define DBSC4_SET_DBPDRGA0_ACIOCR5 (0x0000001FU)
#define DBSC4_SET_DBPDRGD0_ACIOCR5 (0x000000AAU)
#define DBSC4_SET_DBPDRGA0_DX0GCR2 (0x000000A2U)
#define DBSC4_SET_DBPDRGD0_DX0GCR2 (0xAAAA0000U)
#define DBSC4_SET_DBPDRGA0_DX1GCR2 (0x000000C2U)
#define DBSC4_SET_DBPDRGD0_DX1GCR2 (0xAAAA0000U)
#define DBSC4_SET_DBPDRGA0_DX2GCR2 (0x000000E2U)
#define DBSC4_SET_DBPDRGD0_DX2GCR2 (0xAAAA0000U)
#define DBSC4_SET_DBPDRGA0_DX3GCR2 (0x00000102U)
#define DBSC4_SET_DBPDRGD0_DX3GCR2 (0xAAAA0000U)
#define DBSC4_SET_DBPDRGA0_ZQCR (0x00000090U)
#define DBSC4_SET_DBPDRGD0_ZQCR_MD19_0 (0x04058904U)
#define DBSC4_SET_DBPDRGD0_ZQCR_MD19_1 (0x04058A04U)
#define DBSC4_SET_DBPDRGA0_DX0GCR0 (0x000000A0U)
#define DBSC4_SET_DBPDRGD0_DX0GCR0 (0x7C0002E5U)
#define DBSC4_SET_DBPDRGA0_DX1GCR0 (0x000000C0U)
#define DBSC4_SET_DBPDRGD0_DX1GCR0 (0x7C0002E5U)
#define DBSC4_SET_DBPDRGA0_DX2GCR0 (0x000000E0U)
#define DBSC4_SET_DBPDRGD0_DX2GCR0 (0x7C0002E5U)
#define DBSC4_SET_DBPDRGA0_DX3GCR0 (0x00000100U)
#define DBSC4_SET_DBPDRGD0_DX3GCR0 (0x7C0002E5U)
#define DBSC4_SET_DBPDRGA0_DX0GCR1 (0x000000A1U)
#define DBSC4_SET_DBPDRGD0_DX0GCR1 (0x55550000U)
#define DBSC4_SET_DBPDRGA0_DX1GCR1 (0x000000C1U)
#define DBSC4_SET_DBPDRGD0_DX1GCR1 (0x55550000U)
#define DBSC4_SET_DBPDRGA0_DX2GCR1 (0x000000E1U)
#define DBSC4_SET_DBPDRGD0_DX2GCR1 (0x55550000U)
#define DBSC4_SET_DBPDRGA0_DX3GCR1 (0x00000101U)
#define DBSC4_SET_DBPDRGD0_DX3GCR1 (0x55550000U)
#define DBSC4_SET_DBPDRGA0_DX0GCR3 (0x000000A3U)
#define DBSC4_SET_DBPDRGD0_DX0GCR3 (0x00008484U)
#define DBSC4_SET_DBPDRGA0_DX1GCR3 (0x000000C3U)
#define DBSC4_SET_DBPDRGD0_DX1GCR3 (0x00008484U)
#define DBSC4_SET_DBPDRGA0_DX2GCR3 (0x000000E3U)
#define DBSC4_SET_DBPDRGD0_DX2GCR3 (0x00008484U)
#define DBSC4_SET_DBPDRGA0_DX3GCR3 (0x00000103U)
#define DBSC4_SET_DBPDRGD0_DX3GCR3 (0x00008484U)
#define RST_BASE (0xE6160000U)
#define RST_MODEMR (RST_BASE + 0x0060U)
#define RST_MODEMR_BIT0 (0x00000001U)
#define RCAR_CONV_MICROSEC (1000000U)
#if PMIC_ROHM_BD9571
#define BIT_BKUP_CTRL_OUT ((uint8_t)(1U << 4))
#define PMIC_BKUP_MODE_CNT (0x20U)
#define PMIC_QLLM_CNT (0x27U)
#define PMIC_RETRY_MAX (100U)
#endif
#define SCTLR_EL3_M_BIT ((uint32_t)1U << 0)
#define RCAR_CA53CPU_NUM_MAX (4U)
#define RCAR_CA57CPU_NUM_MAX (4U)
#define IS_A53A57(c) ((c) == RCAR_CLUSTER_A53A57)
#define IS_CA57(c) ((c) == RCAR_CLUSTER_CA57)
#define IS_CA53(c) ((c) == RCAR_CLUSTER_CA53)
#ifndef __ASSEMBLY__
IMPORT_SYM
(
unsigned
long
,
__system_ram_start__
,
SYSTEM_RAM_START
);
IMPORT_SYM
(
unsigned
long
,
__system_ram_end__
,
SYSTEM_RAM_END
);
IMPORT_SYM
(
unsigned
long
,
__SRAM_COPY_START__
,
SRAM_COPY_START
);
#endif
#if RCAR_SYSTEM_SUSPEND
static
void
__attribute__
((
section
(
".system_ram"
)))
rcar_pwrc_micro_delay
(
uint64_t
micro_sec
)
{
uint64_t
freq
,
base
,
val
;
uint64_t
wait_time
=
0
;
freq
=
read_cntfrq_el0
();
base
=
read_cntpct_el0
();
while
(
micro_sec
>
wait_time
)
{
val
=
read_cntpct_el0
()
-
base
;
wait_time
=
val
*
RCAR_CONV_MICROSEC
/
freq
;
}
}
#endif
uint32_t
rcar_pwrc_status
(
uint64_t
mpidr
)
{
uint32_t
ret
=
0
;
uint64_t
cm
,
cpu
;
uint32_t
reg
;
uint32_t
c
;
rcar_lock_get
();
c
=
rcar_pwrc_get_cluster
();
cm
=
mpidr
&
MPIDR_CLUSTER_MASK
;
if
(
!
IS_A53A57
(
c
)
&&
cm
!=
0
)
{
ret
=
RCAR_INVALID
;
goto
done
;
}
reg
=
mmio_read_32
(
RCAR_PRR
);
cpu
=
mpidr
&
MPIDR_CPU_MASK
;
if
(
IS_CA53
(
c
))
if
(
reg
&
(
1
<<
(
STATE_CA53_CPU
+
cpu
)))
ret
=
RCAR_INVALID
;
if
(
IS_CA57
(
c
))
if
(
reg
&
(
1
<<
(
STATE_CA57_CPU
+
cpu
)))
ret
=
RCAR_INVALID
;
done:
rcar_lock_release
();
return
ret
;
}
static
void
scu_power_up
(
uint64_t
mpidr
)
{
uintptr_t
reg_pwrsr
,
reg_cpumcr
,
reg_pwron
,
reg_pwrer
;
uint32_t
c
,
sysc_reg_bit
;
c
=
rcar_pwrc_get_mpidr_cluster
(
mpidr
);
reg_cpumcr
=
IS_CA57
(
c
)
?
RCAR_CA57CPUCMCR
:
RCAR_CA53CPUCMCR
;
sysc_reg_bit
=
IS_CA57
(
c
)
?
BIT_CA57_SCU
:
BIT_CA53_SCU
;
reg_pwron
=
IS_CA57
(
c
)
?
RCAR_PWRONCR5
:
RCAR_PWRONCR3
;
reg_pwrer
=
IS_CA57
(
c
)
?
RCAR_PWRER5
:
RCAR_PWRER3
;
reg_pwrsr
=
IS_CA57
(
c
)
?
RCAR_PWRSR5
:
RCAR_PWRSR3
;
if
((
mmio_read_32
(
reg_pwrsr
)
&
STATUS_PWRDOWN
)
==
0
)
return
;
if
(
mmio_read_32
(
reg_cpumcr
)
!=
0
)
mmio_write_32
(
reg_cpumcr
,
0
);
mmio_setbits_32
(
RCAR_SYSCIER
,
sysc_reg_bit
);
mmio_setbits_32
(
RCAR_SYSCIMR
,
sysc_reg_bit
);
do
{
while
((
mmio_read_32
(
RCAR_SYSCSR
)
&
REQ_RESUME
)
==
0
)
;
mmio_write_32
(
reg_pwron
,
1
);
}
while
(
mmio_read_32
(
reg_pwrer
)
&
1
);
while
((
mmio_read_32
(
RCAR_SYSCISR
)
&
sysc_reg_bit
)
==
0
)
;
mmio_write_32
(
RCAR_SYSCISR
,
sysc_reg_bit
);
while
((
mmio_read_32
(
reg_pwrsr
)
&
STATUS_PWRUP
)
==
0
)
;
}
void
rcar_pwrc_cpuon
(
uint64_t
mpidr
)
{
uint32_t
res_data
,
on_data
;
uintptr_t
res_reg
,
on_reg
;
uint32_t
limit
,
c
;
uint64_t
cpu
;
rcar_lock_get
();
c
=
rcar_pwrc_get_mpidr_cluster
(
mpidr
);
res_reg
=
IS_CA53
(
c
)
?
RCAR_CA53RESCNT
:
RCAR_CA57RESCNT
;
on_reg
=
IS_CA53
(
c
)
?
RCAR_CA53WUPCR
:
RCAR_CA57WUPCR
;
limit
=
IS_CA53
(
c
)
?
0x5A5A0000
:
0xA5A50000
;
res_data
=
mmio_read_32
(
res_reg
)
|
limit
;
scu_power_up
(
mpidr
);
cpu
=
mpidr
&
MPIDR_CPU_MASK
;
on_data
=
1
<<
cpu
;
mmio_write_32
(
RCAR_CPGWPR
,
~
on_data
);
mmio_write_32
(
on_reg
,
on_data
);
mmio_write_32
(
res_reg
,
res_data
&
(
~
(
1
<<
(
3
-
cpu
))));
rcar_lock_release
();
}
void
rcar_pwrc_cpuoff
(
uint64_t
mpidr
)
{
uint32_t
c
;
uintptr_t
reg
;
uint64_t
cpu
;
rcar_lock_get
();
cpu
=
mpidr
&
MPIDR_CPU_MASK
;
c
=
rcar_pwrc_get_mpidr_cluster
(
mpidr
);
reg
=
IS_CA53
(
c
)
?
RCAR_CA53CPU0CR
:
RCAR_CA57CPU0CR
;
if
(
read_mpidr_el1
()
!=
mpidr
)
panic
();
mmio_write_32
(
RCAR_CPGWPR
,
~
CPU_PWR_OFF
);
mmio_write_32
(
reg
+
cpu
*
0x0010
,
CPU_PWR_OFF
);
rcar_lock_release
();
}
void
rcar_pwrc_enable_interrupt_wakeup
(
uint64_t
mpidr
)
{
uint32_t
c
,
shift_irq
,
shift_fiq
;
uintptr_t
reg
;
uint64_t
cpu
;
rcar_lock_get
();
cpu
=
mpidr
&
MPIDR_CPU_MASK
;
c
=
rcar_pwrc_get_mpidr_cluster
(
mpidr
);
reg
=
IS_CA53
(
c
)
?
RCAR_WUPMSKCA53
:
RCAR_WUPMSKCA57
;
shift_irq
=
WUP_IRQ_SHIFT
+
cpu
;
shift_fiq
=
WUP_FIQ_SHIFT
+
cpu
;
mmio_write_32
(
reg
,
~
((
uint32_t
)
1
<<
shift_irq
)
&
~
((
uint32_t
)
1
<<
shift_fiq
));
rcar_lock_release
();
}
void
rcar_pwrc_disable_interrupt_wakeup
(
uint64_t
mpidr
)
{
uint32_t
c
,
shift_irq
,
shift_fiq
;
uintptr_t
reg
;
uint64_t
cpu
;
rcar_lock_get
();
cpu
=
mpidr
&
MPIDR_CPU_MASK
;
c
=
rcar_pwrc_get_mpidr_cluster
(
mpidr
);
reg
=
IS_CA53
(
c
)
?
RCAR_WUPMSKCA53
:
RCAR_WUPMSKCA57
;
shift_irq
=
WUP_IRQ_SHIFT
+
cpu
;
shift_fiq
=
WUP_FIQ_SHIFT
+
cpu
;
mmio_write_32
(
reg
,
((
uint32_t
)
1
<<
shift_irq
)
|
((
uint32_t
)
1
<<
shift_fiq
));
rcar_lock_release
();
}
void
rcar_pwrc_clusteroff
(
uint64_t
mpidr
)
{
uint32_t
c
,
product
,
cut
,
reg
;
uintptr_t
dst
;
rcar_lock_get
();
reg
=
mmio_read_32
(
RCAR_PRR
);
product
=
reg
&
RCAR_PRODUCT_MASK
;
cut
=
reg
&
RCAR_CUT_MASK
;
c
=
rcar_pwrc_get_mpidr_cluster
(
mpidr
);
dst
=
IS_CA53
(
c
)
?
RCAR_CA53CPUCMCR
:
RCAR_CA57CPUCMCR
;
if
(
RCAR_PRODUCT_M3
==
product
&&
cut
<=
RCAR_M3_CUT_VER11
)
goto
done
;
if
(
RCAR_PRODUCT_H3
==
product
&&
cut
<=
RCAR_CUT_VER20
)
goto
done
;
/* all of the CPUs in the cluster is in the CoreStandby mode */
mmio_write_32
(
dst
,
MODE_L2_DOWN
);
done:
rcar_lock_release
();
}
#if !PMIC_ROHM_BD9571
void
rcar_pwrc_system_reset
(
void
)
{
mmio_write_32
(
RCAR_SRESCR
,
0x5AA50000U
|
BIT_SOFTRESET
);
}
#endif
/* PMIC_ROHM_BD9571 */
#define RST_CA53_CPU0_BARH (0xE6160080U)
#define RST_CA53_CPU0_BARL (0xE6160084U)
#define RST_CA57_CPU0_BARH (0xE61600C0U)
#define RST_CA57_CPU0_BARL (0xE61600C4U)
void
rcar_pwrc_setup
(
void
)
{
uintptr_t
rst_barh
;
uintptr_t
rst_barl
;
uint32_t
i
,
j
;
uint64_t
reset
=
(
uint64_t
)
(
&
plat_secondary_reset
)
&
0xFFFFFFFF
;
const
uint32_t
cluster
[
PLATFORM_CLUSTER_COUNT
]
=
{
RCAR_CLUSTER_CA53
,
RCAR_CLUSTER_CA57
};
const
uintptr_t
reg_barh
[
PLATFORM_CLUSTER_COUNT
]
=
{
RST_CA53_CPU0_BARH
,
RST_CA57_CPU0_BARH
};
const
uintptr_t
reg_barl
[
PLATFORM_CLUSTER_COUNT
]
=
{
RST_CA53_CPU0_BARL
,
RST_CA57_CPU0_BARL
};
for
(
i
=
0
;
i
<
PLATFORM_CLUSTER_COUNT
;
i
++
)
{
rst_barh
=
reg_barh
[
i
];
rst_barl
=
reg_barl
[
i
];
for
(
j
=
0
;
j
<
rcar_pwrc_get_cpu_num
(
cluster
[
i
]);
j
++
)
{
mmio_write_32
(
rst_barh
,
0
);
mmio_write_32
(
rst_barl
,
(
uint32_t
)
reset
);
rst_barh
+=
0x10
;
rst_barl
+=
0x10
;
}
}
rcar_lock_init
();
}
#if RCAR_SYSTEM_SUSPEND
#define DBCAM_FLUSH(__bit) \
do { \
; \
} while (!(mmio_read_32(DBSC4_REG_DBCAM##__bit##STAT0) & DBSC4_BIT_DBCAMxSTAT0))
static
void
__attribute__
((
section
(
".system_ram"
)))
rcar_pwrc_set_self_refresh
(
void
)
{
uint32_t
reg
=
mmio_read_32
(
RCAR_PRR
);
uint32_t
cut
,
product
;
product
=
reg
&
RCAR_PRODUCT_MASK
;
cut
=
reg
&
RCAR_CUT_MASK
;
if
(
product
==
RCAR_PRODUCT_M3
)
goto
self_refresh
;
if
(
product
==
RCAR_PRODUCT_H3
&&
cut
<
RCAR_CUT_VER20
)
goto
self_refresh
;
mmio_write_32
(
DBSC4_REG_DBSYSCNT0
,
DBSC4_SET_DBSYSCNT0_WRITE_ENABLE
);
self_refresh:
/* Set the Self-Refresh mode */
mmio_write_32
(
DBSC4_REG_DBACEN
,
0
);
if
(
product
==
RCAR_PRODUCT_H3
&&
cut
<
RCAR_CUT_VER20
)
rcar_pwrc_micro_delay
(
100
);
else
if
(
product
==
RCAR_PRODUCT_H3
)
{
mmio_write_32
(
DBSC4_REG_DBCAM0CTRL0
,
1
);
DBCAM_FLUSH
(
0
);
DBCAM_FLUSH
(
1
);
DBCAM_FLUSH
(
2
);
DBCAM_FLUSH
(
3
);
mmio_write_32
(
DBSC4_REG_DBCAM0CTRL0
,
0
);
}
else
if
(
product
==
RCAR_PRODUCT_M3
)
{
mmio_write_32
(
DBSC4_REG_DBCAM0CTRL0
,
1
);
DBCAM_FLUSH
(
0
);
DBCAM_FLUSH
(
1
);
mmio_write_32
(
DBSC4_REG_DBCAM0CTRL0
,
0
);
}
else
{
mmio_write_32
(
DBSC4_REG_DBCAM0CTRL0
,
1
);
DBCAM_FLUSH
(
0
);
mmio_write_32
(
DBSC4_REG_DBCAM0CTRL0
,
0
);
}
/* Set the SDRAM calibration configuration register */
mmio_write_32
(
DBSC4_REG_DBCALCNF
,
0
);
reg
=
DBSC4_SET_DBCMD_OPC_PRE
|
DBSC4_SET_DBCMD_CH_ALL
|
DBSC4_SET_DBCMD_RANK_ALL
|
DBSC4_SET_DBCMD_ARG_ALL
;
mmio_write_32
(
DBSC4_REG_DBCMD
,
reg
);
while
(
mmio_read_32
(
DBSC4_REG_DBWAIT
))
;
/* Self-Refresh entry command */
reg
=
DBSC4_SET_DBCMD_OPC_SR
|
DBSC4_SET_DBCMD_CH_ALL
|
DBSC4_SET_DBCMD_RANK_ALL
|
DBSC4_SET_DBCMD_ARG_ENTER
;
mmio_write_32
(
DBSC4_REG_DBCMD
,
reg
);
while
(
mmio_read_32
(
DBSC4_REG_DBWAIT
))
;
/* Mode Register Write command. (ODT disabled) */
reg
=
DBSC4_SET_DBCMD_OPC_MRW
|
DBSC4_SET_DBCMD_CH_ALL
|
DBSC4_SET_DBCMD_RANK_ALL
|
DBSC4_SET_DBCMD_ARG_MRW_ODTC
;
mmio_write_32
(
DBSC4_REG_DBCMD
,
reg
);
while
(
mmio_read_32
(
DBSC4_REG_DBWAIT
))
;
/* Power Down entry command */
reg
=
DBSC4_SET_DBCMD_OPC_PD
|
DBSC4_SET_DBCMD_CH_ALL
|
DBSC4_SET_DBCMD_RANK_ALL
|
DBSC4_SET_DBCMD_ARG_ENTER
;
mmio_write_32
(
DBSC4_REG_DBCMD
,
reg
);
while
(
mmio_read_32
(
DBSC4_REG_DBWAIT
))
;
/* Set the auto-refresh enable register */
mmio_write_32
(
DBSC4_REG_DBRFEN
,
0U
);
rcar_pwrc_micro_delay
(
1U
);
if
(
product
==
RCAR_PRODUCT_M3
)
return
;
if
(
product
==
RCAR_PRODUCT_H3
&&
cut
<
RCAR_CUT_VER20
)
return
;
mmio_write_32
(
DBSC4_REG_DBSYSCNT0
,
DBSC4_SET_DBSYSCNT0_WRITE_DISABLE
);
}
static
void
__attribute__
((
section
(
".system_ram"
)))
rcar_pwrc_set_self_refresh_e3
(
void
)
{
uint32_t
ddr_md
;
uint32_t
reg
;
ddr_md
=
(
mmio_read_32
(
RST_MODEMR
)
>>
19
)
&
RST_MODEMR_BIT0
;
/* Write enable */
mmio_write_32
(
DBSC4_REG_DBSYSCNT0
,
DBSC4_SET_DBSYSCNT0_WRITE_ENABLE
);
mmio_write_32
(
DBSC4_REG_DBACEN
,
0
);
DBCAM_FLUSH
(
0
);
reg
=
DBSC4_SET_DBCMD_OPC_PRE
|
DBSC4_SET_DBCMD_CH_ALL
|
DBSC4_SET_DBCMD_RANK_ALL
|
DBSC4_SET_DBCMD_ARG_ALL
;
mmio_write_32
(
DBSC4_REG_DBCMD
,
reg
);
while
(
mmio_read_32
(
DBSC4_REG_DBWAIT
))
;
reg
=
DBSC4_SET_DBCMD_OPC_SR
|
DBSC4_SET_DBCMD_CH_ALL
|
DBSC4_SET_DBCMD_RANK_ALL
|
DBSC4_SET_DBCMD_ARG_ENTER
;
mmio_write_32
(
DBSC4_REG_DBCMD
,
reg
);
while
(
mmio_read_32
(
DBSC4_REG_DBWAIT
))
;
/* Set the auto-refresh enable register */
/* Set the ARFEN bit to 0 in the DBRFEN */
mmio_write_32
(
DBSC4_REG_DBRFEN
,
0
);
mmio_write_32
(
DBSC4_REG_DBPDLK0
,
DBSC4_SET_DBPDLK0_PHY_ACCESS
);
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_ACIOCR0
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_ACIOCR0
);
/* DDR_DXCCR */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DXCCR
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DXCCR
);
/* DDR_PGCR1 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_PGCR1
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_PGCR1
);
/* DDR_ACIOCR1 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_ACIOCR1
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_ACIOCR1
);
/* DDR_ACIOCR3 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_ACIOCR3
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_ACIOCR3
);
/* DDR_ACIOCR5 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_ACIOCR5
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_ACIOCR5
);
/* DDR_DX0GCR2 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX0GCR2
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX0GCR2
);
/* DDR_DX1GCR2 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX1GCR2
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX1GCR2
);
/* DDR_DX2GCR2 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX2GCR2
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX2GCR2
);
/* DDR_DX3GCR2 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX3GCR2
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX3GCR2
);
/* DDR_ZQCR */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_ZQCR
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
ddr_md
==
0
?
DBSC4_SET_DBPDRGD0_ZQCR_MD19_0
:
DBSC4_SET_DBPDRGD0_ZQCR_MD19_1
);
/* DDR_DX0GCR0 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX0GCR0
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX0GCR0
);
/* DDR_DX1GCR0 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX1GCR0
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX1GCR0
);
/* DDR_DX2GCR0 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX2GCR0
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX2GCR0
);
/* DDR_DX3GCR0 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX3GCR0
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX3GCR0
);
/* DDR_DX0GCR1 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX0GCR1
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX0GCR1
);
/* DDR_DX1GCR1 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX1GCR1
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX1GCR1
);
/* DDR_DX2GCR1 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX2GCR1
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX2GCR1
);
/* DDR_DX3GCR1 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX3GCR1
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX3GCR1
);
/* DDR_DX0GCR3 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX0GCR3
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX0GCR3
);
/* DDR_DX1GCR3 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX1GCR3
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX1GCR3
);
/* DDR_DX2GCR3 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX2GCR3
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX2GCR3
);
/* DDR_DX3GCR3 */
mmio_write_32
(
DBSC4_REG_DBPDRGA0
,
DBSC4_SET_DBPDRGA0_DX3GCR3
);
mmio_write_32
(
DBSC4_REG_DBPDRGD0
,
DBSC4_SET_DBPDRGD0_DX3GCR3
);
/* Write disable */
mmio_write_32
(
DBSC4_REG_DBSYSCNT0
,
DBSC4_SET_DBSYSCNT0_WRITE_DISABLE
);
}
void
__attribute__
((
section
(
".system_ram"
)))
__attribute__
((
noinline
))
rcar_pwrc_go_suspend_to_ram
(
void
)
{
#if PMIC_ROHM_BD9571
int32_t
rc
=
-
1
,
qllm
=
-
1
;
uint8_t
mode
;
uint32_t
i
;
#endif
uint32_t
reg
,
product
;
reg
=
mmio_read_32
(
RCAR_PRR
);
product
=
reg
&
RCAR_PRODUCT_MASK
;
if
(
product
!=
RCAR_PRODUCT_E3
)
rcar_pwrc_set_self_refresh
();
else
rcar_pwrc_set_self_refresh_e3
();
#if PMIC_ROHM_BD9571
/* Set QLLM Cnt Disable */
for
(
i
=
0
;
(
i
<
PMIC_RETRY_MAX
)
&&
(
qllm
!=
0
);
i
++
)
qllm
=
rcar_iic_dvfs_send
(
PMIC
,
PMIC_QLLM_CNT
,
0
);
/* Set trigger of power down to PMIV */
for
(
i
=
0
;
(
i
<
PMIC_RETRY_MAX
)
&&
(
rc
!=
0
)
&&
(
qllm
==
0
);
i
++
)
{
rc
=
rcar_iic_dvfs_receive
(
PMIC
,
PMIC_BKUP_MODE_CNT
,
&
mode
);
if
(
rc
==
0
)
{
mode
|=
BIT_BKUP_CTRL_OUT
;
rc
=
rcar_iic_dvfs_send
(
PMIC
,
PMIC_BKUP_MODE_CNT
,
mode
);
}
}
#endif
wfi
();
while
(
1
)
;
}
void
rcar_pwrc_set_suspend_to_ram
(
void
)
{
uintptr_t
jump
=
(
uintptr_t
)
&
rcar_pwrc_go_suspend_to_ram
;
uintptr_t
stack
=
(
uintptr_t
)
(
DEVICE_SRAM_STACK_BASE
+
DEVICE_SRAM_STACK_SIZE
);
uint32_t
sctlr
;
rcar_pwrc_code_copy_to_system_ram
();
rcar_pwrc_save_generic_timer
(
rcar_stack_generic_timer
);
/* disable MMU */
sctlr
=
(
uint32_t
)
read_sctlr_el3
();
sctlr
&=
(
uint32_t
)
~
SCTLR_EL3_M_BIT
;
write_sctlr_el3
((
uint64_t
)
sctlr
);
rcar_pwrc_switch_stack
(
jump
,
stack
,
NULL
);
}
void
rcar_pwrc_init_suspend_to_ram
(
void
)
{
#if PMIC_ROHM_BD9571
uint8_t
mode
;
#endif
rcar_pwrc_code_copy_to_system_ram
();
#if PMIC_ROHM_BD9571
if
(
rcar_iic_dvfs_receive
(
PMIC
,
PMIC_BKUP_MODE_CNT
,
&
mode
))
panic
();
mode
&=
(
uint8_t
)
(
~
BIT_BKUP_CTRL_OUT
);
if
(
rcar_iic_dvfs_send
(
PMIC
,
PMIC_BKUP_MODE_CNT
,
mode
))
panic
();
#endif
}
void
rcar_pwrc_suspend_to_ram
(
void
)
{
#if RCAR_SYSTEM_RESET_KEEPON_DDR
int32_t
error
;
rcar_pwrc_code_copy_to_system_ram
();
error
=
rcar_iic_dvfs_send
(
PMIC
,
REG_KEEP10
,
0
);
if
(
error
)
{
ERROR
(
"Failed send KEEP10 init ret=%d
\n
"
,
error
);
return
;
}
#endif
rcar_pwrc_set_suspend_to_ram
();
}
#endif
void
rcar_pwrc_code_copy_to_system_ram
(
void
)
{
int
ret
__attribute__
((
unused
));
/* in assert */
uint32_t
attr
;
struct
device_sram_t
{
uintptr_t
base
;
size_t
len
;
}
sram
=
{
.
base
=
(
uintptr_t
)
DEVICE_SRAM_BASE
,
.
len
=
DEVICE_SRAM_SIZE
,
};
struct
ddr_code_t
{
void
*
base
;
size_t
len
;
}
code
=
{
.
base
=
(
void
*
)
SRAM_COPY_START
,
.
len
=
SYSTEM_RAM_END
-
SYSTEM_RAM_START
,
};
attr
=
MT_MEMORY
|
MT_RW
|
MT_SECURE
|
MT_EXECUTE_NEVER
;
ret
=
xlat_change_mem_attributes
(
sram
.
base
,
sram
.
len
,
attr
);
assert
(
ret
==
0
);
memcpy
((
void
*
)
sram
.
base
,
code
.
base
,
code
.
len
);
flush_dcache_range
((
uint64_t
)
sram
.
base
,
code
.
len
);
/* Invalidate instruction cache */
plat_invalidate_icache
();
dsb
();
isb
();
attr
=
MT_MEMORY
|
MT_RO
|
MT_SECURE
|
MT_EXECUTE
;
ret
=
xlat_change_mem_attributes
(
sram
.
base
,
sram
.
len
,
attr
);
assert
(
ret
==
0
);
}
uint32_t
rcar_pwrc_get_cluster
(
void
)
{
uint32_t
reg
;
reg
=
mmio_read_32
(
RCAR_PRR
);
if
(
reg
&
(
1
<<
(
STATE_CA53_CPU
+
RCAR_CA53CPU_NUM_MAX
)))
return
RCAR_CLUSTER_CA57
;
if
(
reg
&
(
1
<<
(
STATE_CA57_CPU
+
RCAR_CA57CPU_NUM_MAX
)))
return
RCAR_CLUSTER_CA53
;
return
RCAR_CLUSTER_A53A57
;
}
uint32_t
rcar_pwrc_get_mpidr_cluster
(
uint64_t
mpidr
)
{
uint32_t
c
=
rcar_pwrc_get_cluster
();
if
(
IS_A53A57
(
c
))
{
if
(
mpidr
&
MPIDR_CLUSTER_MASK
)
return
RCAR_CLUSTER_CA53
;
return
RCAR_CLUSTER_CA57
;
}
return
c
;
}
uint32_t
rcar_pwrc_get_cpu_num
(
uint32_t
c
)
{
uint32_t
reg
=
mmio_read_32
(
RCAR_PRR
);
uint32_t
count
=
0
,
i
;
if
(
IS_A53A57
(
c
)
||
IS_CA53
(
c
))
{
if
(
reg
&
(
1
<<
(
STATE_CA53_CPU
+
RCAR_CA53CPU_NUM_MAX
)))
goto
count_ca57
;
for
(
i
=
0
;
i
<
RCAR_CA53CPU_NUM_MAX
;
i
++
)
{
if
(
reg
&
(
1
<<
(
STATE_CA53_CPU
+
i
)))
continue
;
count
++
;
}
}
count_ca57:
if
(
IS_A53A57
(
c
)
||
IS_CA57
(
c
))
{
if
(
reg
&
(
1
<<
(
STATE_CA57_CPU
+
RCAR_CA57CPU_NUM_MAX
)))
goto
done
;
for
(
i
=
0
;
i
<
RCAR_CA57CPU_NUM_MAX
;
i
++
)
{
if
(
reg
&
(
1
<<
(
STATE_CA57_CPU
+
i
)))
continue
;
count
++
;
}
}
done:
return
count
;
}
drivers/renesas/rcar/pwrc/pwrc.h
0 → 100644
View file @
32c70e40
/*
* Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef RCAR_PWRC_H__
#define RCAR_PWRC_H__
#define PPOFFR_OFF 0x0
#define PPONR_OFF 0x4
#define PCOFFR_OFF 0x8
#define PWKUPR_OFF 0xc
#define PSYSR_OFF 0x10
#define PWKUPR_WEN (1ull << 31)
#define PSYSR_AFF_L2 (1 << 31)
#define PSYSR_AFF_L1 (1 << 30)
#define PSYSR_AFF_L0 (1 << 29)
#define PSYSR_WEN (1 << 28)
#define PSYSR_PC (1 << 27)
#define PSYSR_PP (1 << 26)
#define PSYSR_WK_SHIFT (24)
#define PSYSR_WK_MASK (0x3)
#define PSYSR_WK(x) (((x) >> PSYSR_WK_SHIFT) & PSYSR_WK_MASK)
#define WKUP_COLD 0x0
#define WKUP_RESET 0x1
#define WKUP_PPONR 0x2
#define WKUP_GICREQ 0x3
#define RCAR_INVALID (0xffffffffU)
#define PSYSR_INVALID 0xffffffff
#define RCAR_CLUSTER_A53A57 (0U)
#define RCAR_CLUSTER_CA53 (1U)
#define RCAR_CLUSTER_CA57 (2U)
#ifndef __ASSEMBLY__
void
rcar_pwrc_disable_interrupt_wakeup
(
uint64_t
mpidr
);
void
rcar_pwrc_enable_interrupt_wakeup
(
uint64_t
mpidr
);
void
rcar_pwrc_clusteroff
(
uint64_t
mpidr
);
void
rcar_pwrc_cpuoff
(
uint64_t
mpidr
);
void
rcar_pwrc_cpuon
(
uint64_t
mpidr
);
void
rcar_pwrc_setup
(
void
);
uint32_t
rcar_pwrc_get_cpu_wkr
(
uint64_t
mpidr
);
uint32_t
rcar_pwrc_status
(
uint64_t
mpidr
);
uint32_t
rcar_pwrc_get_cluster
(
void
);
uint32_t
rcar_pwrc_get_mpidr_cluster
(
uint64_t
mpidr
);
uint32_t
rcar_pwrc_get_cpu_num
(
uint32_t
cluster_type
);
void
plat_secondary_reset
(
void
);
void
rcar_pwrc_code_copy_to_system_ram
(
void
);
#if !PMIC_ROHM_BD9571
void
rcar_pwrc_system_reset
(
void
);
#endif
#if RCAR_SYSTEM_SUSPEND
void
rcar_pwrc_go_suspend_to_ram
(
void
);
void
rcar_pwrc_set_suspend_to_ram
(
void
);
void
rcar_pwrc_init_suspend_to_ram
(
void
);
void
rcar_pwrc_suspend_to_ram
(
void
);
#endif
extern
void
rcar_pwrc_save_generic_timer
(
uint64_t
*
rcar_stack_generic_timer
);
extern
uint32_t
rcar_pwrc_switch_stack
(
uintptr_t
jump
,
uintptr_t
stack
,
void
*
arg
);
extern
uint64_t
rcar_stack_generic_timer
[
5
];
#endif
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment