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
eb47f14d
Unverified
Commit
eb47f14d
authored
Nov 01, 2018
by
Antonio Niño Díaz
Committed by
GitHub
Nov 01, 2018
Browse files
Merge pull request #1623 from MISL-EBU-System-SW/a3700-support
Add support for Armada 3700 and COMPHY porting layer
parents
d03823d4
1e66bacb
Changes
58
Hide whitespace changes
Inline
Side-by-side
plat/marvell/a3700/a3700/mvebu_def.h
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#ifndef __MVEBU_DEF_H__
#define __MVEBU_DEF_H__
#include <a3700_plat_def.h>
#endif
/* __MVEBU_DEF_H__ */
plat/marvell/a3700/a3700/plat_bl31_setup.c
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#include <armada_common.h>
#include <dram_win.h>
#include <io_addr_dec.h>
#include <mmio.h>
#include <marvell_plat_priv.h>
#include <plat_marvell.h>
/* This routine does MPP initialization */
static
void
marvell_bl31_mpp_init
(
void
)
{
mmio_clrbits_32
(
MVEBU_NB_GPIO_SEL_REG
,
1
<<
MVEBU_GPIO_TW1_GPIO_EN_OFF
);
/* Set hidden GPIO setting for SPI.
* In north_bridge_pin_out_en_high register 13804,
* bit 28 is the one which enables CS, CLK pins to be
* output, need to set it to 1.
* The initial value of this bit is 1, but in UART boot mode
* initialization, this bit is disabled and the SPI CS and CLK pins
* are used for downloading image purpose; so after downloading,
* we should set this bit to 1 again to enable SPI CS and CLK pins.
* And anyway, this bit value should be 1 in all modes,
* so here we does not judge boot mode and set this bit to 1 always.
*/
mmio_setbits_32
(
MVEBU_NB_GPIO_OUTPUT_EN_HIGH_REG
,
1
<<
MVEBU_GPIO_NB_SPI_PIN_MODE_OFF
);
}
/* This function overruns the same function in marvell_bl31_setup.c */
void
bl31_plat_arch_setup
(
void
)
{
struct
dec_win_config
*
io_dec_map
;
uint32_t
dec_win_num
;
struct
dram_win_map
dram_wins_map
;
marvell_bl31_plat_arch_setup
();
/* MPP init */
marvell_bl31_mpp_init
();
/* initialize the timer for delay functionality */
plat_delay_timer_init
();
/* CPU address decoder windows initialization. */
cpu_wins_init
();
/* fetch CPU-DRAM window mapping information by reading
* CPU-DRAM decode windows (only the enabled ones)
*/
dram_win_map_build
(
&
dram_wins_map
);
/* Get IO address decoder windows */
if
(
marvell_get_io_dec_win_conf
(
&
io_dec_map
,
&
dec_win_num
))
{
printf
(
"No IO address decoder windows configurations found!
\n
"
);
return
;
}
/* IO address decoder init */
if
(
init_io_addr_dec
(
&
dram_wins_map
,
io_dec_map
,
dec_win_num
))
{
printf
(
"IO address decoder windows initialization failed!
\n
"
);
return
;
}
}
plat/marvell/a3700/a3700/platform.mk
0 → 100644
View file @
eb47f14d
#
# Copyright (C) 2018 Marvell International Ltd.
#
# SPDX-License-Identifier: BSD-3-Clause
# https://spdx.org/licenses
#
include
plat/marvell/a3700/common/a3700_common.mk
include
plat/marvell/common/marvell_common.mk
plat/marvell/a3700/common/a3700_common.mk
0 → 100644
View file @
eb47f14d
#
# Copyright (C) 2018 Marvell International Ltd.
#
# SPDX-License-Identifier: BSD-3-Clause
# https://spdx.org/licenses
#
MARVELL_PLAT_BASE
:=
plat/marvell
MARVELL_PLAT_INCLUDE_BASE
:=
include/plat/marvell
PLAT_FAMILY
:=
a3700
PLAT_FAMILY_BASE
:=
$(MARVELL_PLAT_BASE)
/
$(PLAT_FAMILY)
PLAT_INCLUDE_BASE
:=
$(MARVELL_PLAT_INCLUDE_BASE)
/
$(PLAT_FAMILY)
PLAT_COMMON_BASE
:=
$(PLAT_FAMILY_BASE)
/common
MARVELL_DRV_BASE
:=
drivers/marvell
MARVELL_COMMON_BASE
:=
$(MARVELL_PLAT_BASE)
/common
include
$(MARVELL_PLAT_BASE)/marvell.mk
#*********** A3700 *************
DOIMAGEPATH
:=
$(WTP)
DOIMAGETOOL
:=
$(DOIMAGEPATH)
/wtptp/linux/tbb_linux
ifeq
($(MARVELL_SECURE_BOOT),1)
DOIMAGE_CFG
:=
$(DOIMAGEPATH)
/atf-tim.txt
IMAGESPATH
:=
$(DOIMAGEPATH)
/tim/trusted
TIMNCFG
:=
$(DOIMAGEPATH)
/atf-timN.txt
TIMNSIG
:=
$(IMAGESPATH)
/timnsign.txt
TIM2IMGARGS
:=
-i
$(DOIMAGE_CFG)
-n
$(TIMNCFG)
TIMN_IMAGE
:=
$$
(
grep
"Image Filename:"
-m
1
$(TIMNCFG)
|
cut
-c
17-
)
else
#MARVELL_SECURE_BOOT
DOIMAGE_CFG
:=
$(DOIMAGEPATH)
/atf-ntim.txt
IMAGESPATH
:=
$(DOIMAGEPATH)
/tim/untrusted
TIM2IMGARGS
:=
-i
$(DOIMAGE_CFG)
endif
#MARVELL_SECURE_BOOT
TIMBUILD
:=
$(DOIMAGEPATH)
/script/buildtim.sh
TIM2IMG
:=
$(DOIMAGEPATH)
/script/tim2img.pl
# WTMI_IMG is used to specify the customized RTOS image running over
# Service CPU (CM3 processor). By the default, it points to a
# baremetal binary of fuse programming in A3700_utils.
WTMI_IMG
:=
$(DOIMAGEPATH)
/wtmi/fuse/build/fuse.bin
# WTMI_SYSINIT_IMG is used for the system early initialization,
# such as AVS settings, clock-tree setup and dynamic DDR PHY training.
# After the initialization is done, this image will be wiped out
# from the memory and CM3 will continue with RTOS image or other application.
WTMI_SYSINIT_IMG
:=
$(DOIMAGEPATH)
/wtmi/sys_init/build/sys_init.bin
# WTMI_MULTI_IMG is composed of CM3 RTOS image (WTMI_IMG)
# and sys-init image (WTMI_SYSINIT_IMG).
WTMI_MULTI_IMG
:=
$(DOIMAGEPATH)
/wtmi/build/wtmi.bin
WTMI_ENC_IMG
:=
$(DOIMAGEPATH)
/wtmi/build/wtmi-enc.bin
BUILD_UART
:=
uart-images
SRCPATH
:=
$(
dir
$(BL33)
)
CLOCKSPRESET
?=
CPU_800_DDR_800
DDR_TOPOLOGY
?=
0
BOOTDEV
?=
SPINOR
PARTNUM
?=
0
TIM_IMAGE
:=
$$
(
grep
"Image Filename:"
-m
1
$(DOIMAGE_CFG)
|
cut
-c
17-
)
TIMBLDARGS
:=
$(MARVELL_SECURE_BOOT)
$(BOOTDEV)
$(IMAGESPATH)
$(DOIMAGEPATH)
$(CLOCKSPRESET)
\
$(DDR_TOPOLOGY)
$(PARTNUM)
$(DEBUG)
$(DOIMAGE_CFG)
$(TIMNCFG)
$(TIMNSIG)
1
TIMBLDUARTARGS
:=
$(MARVELL_SECURE_BOOT)
UART
$(IMAGESPATH)
$(DOIMAGEPATH)
$(CLOCKSPRESET)
\
$(DDR_TOPOLOGY)
0 0
$(DOIMAGE_CFG)
$(TIMNCFG)
$(TIMNSIG)
0
DOIMAGE_FLAGS
:=
-r
$(DOIMAGE_CFG)
-v
-D
# GICV3
$(eval
$(call
add_define,CONFIG_GICV3))
# CCI-400
$(eval
$(call
add_define,USE_CCI))
MARVELL_GIC_SOURCES
:=
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v3/gicv3_main.c
\
drivers/arm/gic/v3/gicv3_helpers.c
\
drivers/arm/gic/v3/arm_gicv3_common.c
\
plat/common/plat_gicv3.c
\
drivers/arm/gic/v3/gic500.c
ATF_INCLUDES
:=
-Iinclude
/common/tbbr
\
-Iinclude
/drivers
PLAT_INCLUDES
:=
-I
$(PLAT_FAMILY_BASE)
/
$(PLAT)
\
-I
$(PLAT_COMMON_BASE)
/include
\
-I
$(PLAT_INCLUDE_BASE)
/common
\
-I
$(MARVELL_DRV_BASE)
/uart
\
-I
$(MARVELL_DRV_BASE)
\
-I
$/
drivers/arm/gic/common/
\
$(ATF_INCLUDES)
PLAT_BL_COMMON_SOURCES
:=
$(PLAT_COMMON_BASE)
/aarch64/a3700_common.c
\
drivers/console/aarch64/console.S
\
$(MARVELL_COMMON_BASE)
/marvell_cci.c
\
$(MARVELL_DRV_BASE)
/uart/a3700_console.S
BL1_SOURCES
+=
$(PLAT_COMMON_BASE)
/aarch64/plat_helpers.S
\
lib/cpus/aarch64/cortex_a53.S
BL31_PORTING_SOURCES
:=
$(PLAT_FAMILY_BASE)
/
$(PLAT)
/board/pm_src.c
MARVELL_DRV
:=
$(MARVELL_DRV_BASE)
/comphy/phy-comphy-3700.c
BL31_SOURCES
+=
lib/cpus/aarch64/cortex_a53.S
\
$(PLAT_COMMON_BASE)
/aarch64/plat_helpers.S
\
$(PLAT_COMMON_BASE)
/plat_pm.c
\
$(PLAT_COMMON_BASE)
/dram_win.c
\
$(PLAT_COMMON_BASE)
/io_addr_dec.c
\
$(PLAT_COMMON_BASE)
/marvell_plat_config.c
\
$(PLAT_FAMILY_BASE)
/
$(PLAT)
/plat_bl31_setup.c
\
$(MARVELL_COMMON_BASE)
/marvell_ddr_info.c
\
$(MARVELL_COMMON_BASE)
/marvell_gicv3.c
\
$(MARVELL_GIC_SOURCES)
\
drivers/arm/cci/cci.c
\
$(BL31_PORTING_SOURCES)
\
$(PLAT_COMMON_BASE)
/a3700_sip_svc.c
\
$(MARVELL_DRV)
mrvl_flash
:
${BUILD_PLAT}/${FIP_NAME} ${DOIMAGETOOL}
$(
shell
truncate
-s
%128K
${BUILD_PLAT}
/bl1.bin
)
$(
shell
cat
${BUILD_PLAT}
/bl1.bin
${BUILD_PLAT}
/
${FIP_NAME}
>
${BUILD_PLAT}
/
${BOOT_IMAGE}
)
$(
shell
truncate
-s
%4
${BUILD_PLAT}
/
${BOOT_IMAGE}
)
$(
shell
truncate
-s
%4
$(WTMI_IMG)
)
@
echo
@
echo
"Building uart images"
$(TIMBUILD)
$(TIMBLDUARTARGS)
@
sed
-i
's|WTMI_IMG|
$(WTMI_MULTI_IMG)
|1'
$(DOIMAGE_CFG)
@
sed
-i
's|BOOT_IMAGE|
$(BUILD_PLAT)
/
$(BOOT_IMAGE)
|1'
$(DOIMAGE_CFG)
ifeq
($(MARVELL_SECURE_BOOT),1)
@
sed
-i
's|WTMI_IMG|
$(WTMI_MULTI_IMG)
|1'
$(TIMNCFG)
@
sed
-i
's|BOOT_IMAGE|
$(BUILD_PLAT)
/
$(BOOT_IMAGE)
|1'
$(TIMNCFG)
endif
$(DOIMAGETOOL)
$(DOIMAGE_FLAGS)
@
if
[
-e
"
$(TIMNCFG)
"
]
;
then
$(DOIMAGETOOL)
-r
$(TIMNCFG)
;
fi
@
rm
-rf
$(BUILD_PLAT)
/
$(BUILD_UART)
*
@
mkdir
$(BUILD_PLAT)
/
$(BUILD_UART)
@
mv
-t
$(BUILD_PLAT)
/
$(BUILD_UART)
$(TIM_IMAGE)
$(DOIMAGE_CFG)
$(TIMN_IMAGE)
$(TIMNCFG)
@
find
.
-name
"*_h.*"
|xargs
cp
-ut
$(BUILD_PLAT)
/
$(BUILD_UART)
@
mv
$(
subst
.bin,_h.bin,
$(WTMI_MULTI_IMG)
)
$(BUILD_PLAT)
/
$(BUILD_UART)
/wtmi_h.bin
@
tar
czf
$(BUILD_PLAT)
/
$(BUILD_UART)
.tgz
-C
$(BUILD_PLAT)
./
$(BUILD_UART)
@
echo
@
echo
"Building flash image"
$(TIMBUILD)
$(TIMBLDARGS)
sed
-i
's|WTMI_IMG|
$(WTMI_MULTI_IMG)
|1'
$(DOIMAGE_CFG)
sed
-i
's|BOOT_IMAGE|
$(BUILD_PLAT)
/
$(BOOT_IMAGE)
|1'
$(DOIMAGE_CFG)
ifeq
($(MARVELL_SECURE_BOOT),1)
@
sed
-i
's|WTMI_IMG|
$(WTMI_MULTI_IMG)
|1'
$(TIMNCFG)
@
sed
-i
's|BOOT_IMAGE|
$(BUILD_PLAT)
/
$(BOOT_IMAGE)
|1'
$(TIMNCFG)
@
echo
-e
"
\n\t
=======================================================
\n
"
;
@
echo
-e
"
\t
Secure boot. Encrypting wtmi and boot-image
\n
"
;
@
echo
-e
"
\t
=======================================================
\n
"
;
@
truncate
-s
%16
$(WTMI_MULTI_IMG)
@
openssl enc
-aes-256-cbc
-e
-in
$(WTMI_MULTI_IMG)
\
-out
$(WTMI_ENC_IMG)
\
-K
`
cat
$(IMAGESPATH)
/aes-256.txt
`
-k
0
-nosalt
\
-iv
`
cat
$(IMAGESPATH)
/iv.txt
`
-p
@
truncate
-s
%16
$(BUILD_PLAT)
/
$(BOOT_IMAGE)
;
@
openssl enc
-aes-256-cbc
-e
-in
$(BUILD_PLAT)
/
$(BOOT_IMAGE)
\
-out
$(BUILD_PLAT)
/
$(BOOT_ENC_IMAGE)
\
-K
`
cat
$(IMAGESPATH)
/aes-256.txt
`
-k
0
-nosalt
\
-iv
`
cat
$(IMAGESPATH)
/iv.txt
`
-p
endif
$(DOIMAGETOOL)
$(DOIMAGE_FLAGS)
@
if
[
-e
"
$(TIMNCFG)
"
]
;
then
$(DOIMAGETOOL)
-r
$(TIMNCFG)
;
fi
@
if
[
"
$(MARVELL_SECURE_BOOT)
"
=
"1"
]
;
then
sed
-i
's|
$(WTMI_MULTI_IMG)
|
$(WTMI_ENC_IMG)
|1;s|
$(BOOT_IMAGE)
|
$(BOOT_ENC_IMAGE)
|1;'
$(TIMNCFG)
;
fi
$(TIM2IMG)
$(TIM2IMGARGS)
-o
$(BUILD_PLAT)
/
$(FLASH_IMAGE)
@
mv
-t
$(BUILD_PLAT)
$(TIM_IMAGE)
$(DOIMAGE_CFG)
$(TIMN_IMAGE)
$(TIMNCFG)
$(WTMI_IMG)
$(WTMI_SYSINIT_IMG)
$(WTMI_MULTI_IMG)
@
if
[
"
$(MARVELL_SECURE_BOOT)
"
=
"1"
]
;
then
mv
-t
$(BUILD_PLAT)
$(WTMI_ENC_IMG)
OtpHash.txt
;
fi
@
find
.
-name
"*.txt"
|
grep
-E
"CSK[[:alnum:]]_KeyHash.txt|Tim_msg.txt|TIMHash.txt"
| xargs
rm
-f
plat/marvell/a3700/common/a3700_sip_svc.c
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#include <debug.h>
#include <marvell_plat_priv.h>
#include <plat_marvell.h>
#include <runtime_svc.h>
#include <smccc.h>
#include "comphy/phy-comphy-3700.h"
/* Comphy related FID's */
#define MV_SIP_COMPHY_POWER_ON 0x82000001
#define MV_SIP_COMPHY_POWER_OFF 0x82000002
#define MV_SIP_COMPHY_PLL_LOCK 0x82000003
/* Miscellaneous FID's' */
#define MV_SIP_DRAM_SIZE 0x82000010
/* This macro is used to identify COMPHY related calls from SMC function ID */
#define is_comphy_fid(fid) \
((fid) >= MV_SIP_COMPHY_POWER_ON && (fid) <= MV_SIP_COMPHY_PLL_LOCK)
uintptr_t
mrvl_sip_smc_handler
(
uint32_t
smc_fid
,
u_register_t
x1
,
u_register_t
x2
,
u_register_t
x3
,
u_register_t
x4
,
void
*
cookie
,
void
*
handle
,
u_register_t
flags
)
{
u_register_t
ret
;
VERBOSE
(
"%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx
\n
"
,
__func__
,
smc_fid
,
x1
,
x2
);
if
(
is_comphy_fid
(
smc_fid
))
{
if
(
x1
>=
MAX_LANE_NR
)
{
ERROR
(
"%s: Wrong smc (0x%x) lane nr: %lx
\n
"
,
__func__
,
smc_fid
,
x2
);
SMC_RET1
(
handle
,
SMC_UNK
);
}
}
switch
(
smc_fid
)
{
/* Comphy related FID's */
case
MV_SIP_COMPHY_POWER_ON
:
/* x1: comphy_index, x2: comphy_mode */
ret
=
mvebu_3700_comphy_power_on
(
x1
,
x2
);
SMC_RET1
(
handle
,
ret
);
case
MV_SIP_COMPHY_POWER_OFF
:
/* x1: comphy_index, x2: comphy_mode */
ret
=
mvebu_3700_comphy_power_off
(
x1
,
x2
);
SMC_RET1
(
handle
,
ret
);
case
MV_SIP_COMPHY_PLL_LOCK
:
/* x1: comphy_index, x2: comphy_mode */
ret
=
mvebu_3700_comphy_is_pll_locked
(
x1
,
x2
);
SMC_RET1
(
handle
,
ret
);
/* Miscellaneous FID's' */
case
MV_SIP_DRAM_SIZE
:
/* x1: ap_base_addr */
ret
=
mvebu_get_dram_size
(
MVEBU_REGS_BASE
);
SMC_RET1
(
handle
,
ret
);
default:
ERROR
(
"%s: unhandled SMC (0x%x)
\n
"
,
__func__
,
smc_fid
);
SMC_RET1
(
handle
,
SMC_UNK
);
}
}
/* Define a runtime service descriptor for fast SMC calls */
DECLARE_RT_SVC
(
marvell_sip_svc
,
OEN_SIP_START
,
OEN_SIP_END
,
SMC_TYPE_FAST
,
NULL
,
mrvl_sip_smc_handler
);
plat/marvell/a3700/common/aarch64/a3700_common.c
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#include <plat_marvell.h>
/* MMU entry for internal (register) space access */
#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
DEVICE0_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
/*
* Table of regions for various BL stages to map using the MMU.
*/
#if IMAGE_BL1
const
mmap_region_t
plat_marvell_mmap
[]
=
{
MARVELL_MAP_SHARED_RAM
,
MAP_DEVICE0
,
{
0
}
};
#endif
#if IMAGE_BL2
const
mmap_region_t
plat_marvell_mmap
[]
=
{
MARVELL_MAP_SHARED_RAM
,
MAP_DEVICE0
,
MARVELL_MAP_DRAM
,
{
0
}
};
#endif
#if IMAGE_BL2U
const
mmap_region_t
plat_marvell_mmap
[]
=
{
MAP_DEVICE0
,
{
0
}
};
#endif
#if IMAGE_BL31
const
mmap_region_t
plat_marvell_mmap
[]
=
{
MARVELL_MAP_SHARED_RAM
,
MAP_DEVICE0
,
MARVELL_MAP_DRAM
,
{
0
}
};
#endif
#if IMAGE_BL32
const
mmap_region_t
plat_marvell_mmap
[]
=
{
MAP_DEVICE0
,
{
0
}
};
#endif
MARVELL_CASSERT_MMAP
;
plat/marvell/a3700/common/aarch64/plat_helpers.S
0 → 100644
View file @
eb47f14d
/*
*
Copyright
(
C
)
2018
Marvell
International
Ltd
.
*
*
SPDX
-
License
-
Identifier
:
BSD
-
3
-
Clause
*
https
:
//
spdx
.
org
/
licenses
*/
#include <asm_macros.S>
#include <platform_def.h>
.
globl
plat_secondary_cold_boot_setup
.
globl
plat_get_my_entrypoint
.
globl
plat_is_my_cpu_primary
/
*
-----------------------------------------------------
*
void
plat_secondary_cold_boot_setup
(
void
)
;
*
*
This
function
performs
any
platform
specific
actions
*
needed
for
a
secondary
cpu
after
a
cold
reset
.
Right
*
now
this
is
a
stub
function
.
*
-----------------------------------------------------
*/
func
plat_secondary_cold_boot_setup
mov
x0
,
#
0
ret
endfunc
plat_secondary_cold_boot_setup
/
*
---------------------------------------------------------------------
*
unsigned
long
plat_get_my_entrypoint
(
void
)
;
*
*
Main
job
of
this
routine
is
to
distinguish
between
cold
and
warm
boot
*
For
a
cold
boot
,
return
0
.
*
For
a
warm
boot
,
read
the
mailbox
and
return
the
address
it
contains
.
*
A
magic
number
is
placed
before
entrypoint
to
avoid
mistake
caused
by
*
uninitialized
mailbox
data
area
.
*
---------------------------------------------------------------------
*/
func
plat_get_my_entrypoint
/
*
Read
first
word
and
compare
it
with
magic
num
*/
mov_imm
x0
,
PLAT_MARVELL_MAILBOX_BASE
ldr
x1
,
[
x0
]
mov_imm
x2
,
PLAT_MARVELL_MAILBOX_MAGIC_NUM
cmp
x1
,
x2
/
*
If
compare
failed
,
return
0
,
i
.
e
.
cold
boot
*/
beq
entrypoint
mov
x0
,
#
0
ret
entrypoint
:
/
*
Second
word
contains
the
jump
address
*/
add
x0
,
x0
,
#
8
ldr
x0
,
[
x0
]
ret
endfunc
plat_get_my_entrypoint
/
*
-----------------------------------------------------
*
unsigned
int
plat_is_my_cpu_primary
(
void
)
;
*
*
Find
out
whether
the
current
cpu
is
the
primary
*
cpu
.
*
-----------------------------------------------------
*/
func
plat_is_my_cpu_primary
mrs
x0
,
mpidr_el1
and
x0
,
x0
,
#(
MPIDR_CLUSTER_MASK
|
MPIDR_CPU_MASK
)
cmp
x0
,
#
MVEBU_PRIMARY_CPU
cset
w0
,
eq
ret
endfunc
plat_is_my_cpu_primary
plat/marvell/a3700/common/dram_win.c
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#include <dram_win.h>
#include <marvell_plat_priv.h>
#include <mmio.h>
#include <mvebu.h>
#include <plat_marvell.h>
#include <string.h>
/* Armada 3700 has 5 configurable windows */
#define MV_CPU_WIN_NUM 5
#define CPU_WIN_DISABLED 0
#define CPU_WIN_ENABLED 1
/*
* There are 2 different cpu decode window configuration cases:
* - DRAM size is not over 2GB;
* - DRAM size is 4GB.
*/
enum
cpu_win_config_num
{
CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB
=
0
,
CPU_WIN_CONFIG_DRAM_4GB
,
CPU_WIN_CONFIG_MAX
};
enum
cpu_win_target
{
CPU_WIN_TARGET_DRAM
=
0
,
CPU_WIN_TARGET_INTERNAL_REG
,
CPU_WIN_TARGET_PCIE
,
CPU_WIN_TARGET_PCIE_OVER_MCI
,
CPU_WIN_TARGET_BOOT_ROM
,
CPU_WIN_TARGET_MCI_EXTERNAL
,
CPU_WIN_TARGET_RWTM_RAM
=
7
,
CPU_WIN_TARGET_CCI400_REG
};
struct
cpu_win_configuration
{
uint32_t
enabled
;
enum
cpu_win_target
target
;
uint64_t
base_addr
;
uint64_t
size
;
uint64_t
remap_addr
;
};
struct
cpu_win_configuration
mv_cpu_wins
[
CPU_WIN_CONFIG_MAX
][
MV_CPU_WIN_NUM
]
=
{
/*
* When total dram size is not over 2GB:
* DDR window 0 is configured in tim header, its size may be not 512MB,
* but the actual dram size, no need to configure it again;
* other cpu windows are kept as default.
*/
{
/* enabled
* target
* base
* size
* remap
*/
{
CPU_WIN_ENABLED
,
CPU_WIN_TARGET_DRAM
,
0x0
,
0x08000000
,
0x0
},
{
CPU_WIN_ENABLED
,
CPU_WIN_TARGET_MCI_EXTERNAL
,
0xe0000000
,
0x08000000
,
0xe0000000
},
{
CPU_WIN_ENABLED
,
CPU_WIN_TARGET_PCIE
,
0xe8000000
,
0x08000000
,
0xe8000000
},
{
CPU_WIN_ENABLED
,
CPU_WIN_TARGET_RWTM_RAM
,
0xf0000000
,
0x00020000
,
0x1fff0000
},
{
CPU_WIN_ENABLED
,
CPU_WIN_TARGET_PCIE_OVER_MCI
,
0x80000000
,
0x10000000
,
0x80000000
},
},
/*
* If total dram size is more than 2GB, now there is only one case - 4GB
* dram; we will use below cpu windows configurations:
* - Internal Regs, CCI-400, Boot Rom and PCIe windows are kept as
* default;
* - Use 4 CPU decode windows for DRAM, which cover 3.375GB DRAM;
* DDR window 0 is configured in tim header with 2GB size, no need to
* configure it again here;
*
* 0xFFFFFFFF ---> |-----------------------|
* | Boot ROM | 64KB
* 0xFFF00000 ---> +-----------------------+
* : :
* 0xF0000000 ---> |-----------------------|
* | PCIE | 128 MB
* 0xE8000000 ---> |-----------------------|
* | DDR window 3 | 128 MB
* 0xE0000000 ---> +-----------------------+
* : :
* 0xD8010000 ---> |-----------------------|
* | CCI Regs | 64 KB
* 0xD8000000 ---> +-----------------------+
* : :
* : :
* 0xD2000000 ---> +-----------------------+
* | Internal Regs | 32MB
* 0xD0000000 ---> |-----------------------|
* | DDR window 2 | 256 MB
* 0xC0000000 ---> |-----------------------|
* | |
* | DDR window 1 | 1 GB
* | |
* 0x80000000 ---> |-----------------------|
* | |
* | |
* | DDR window 0 | 2 GB
* | |
* | |
* 0x00000000 ---> +-----------------------+
*/
{
/* win_id
* target
* base
* size
* remap
*/
{
CPU_WIN_ENABLED
,
CPU_WIN_TARGET_DRAM
,
0x0
,
0x80000000
,
0x0
},
{
CPU_WIN_ENABLED
,
CPU_WIN_TARGET_DRAM
,
0x80000000
,
0x40000000
,
0x80000000
},
{
CPU_WIN_ENABLED
,
CPU_WIN_TARGET_DRAM
,
0xc0000000
,
0x10000000
,
0xc0000000
},
{
CPU_WIN_ENABLED
,
CPU_WIN_TARGET_DRAM
,
0xe0000000
,
0x08000000
,
0xe0000000
},
{
CPU_WIN_ENABLED
,
CPU_WIN_TARGET_PCIE
,
0xe8000000
,
0x08000000
,
0xe8000000
},
},
};
/*
* dram_win_map_build
*
* This function builds cpu dram windows mapping
* which includes base address and window size by
* reading cpu dram decode windows registers.
*
* @input: N/A
*
* @output:
* - win_map: cpu dram windows mapping
*
* @return: N/A
*/
void
dram_win_map_build
(
struct
dram_win_map
*
win_map
)
{
int32_t
win_id
;
struct
dram_win
*
win
;
uint32_t
base_reg
,
ctrl_reg
,
size_reg
,
enabled
,
target
;
memset
(
win_map
,
0
,
sizeof
(
struct
dram_win_map
));
for
(
win_id
=
0
;
win_id
<
DRAM_WIN_MAP_NUM_MAX
;
win_id
++
)
{
ctrl_reg
=
mmio_read_32
(
CPU_DEC_WIN_CTRL_REG
(
win_id
));
target
=
(
ctrl_reg
&
CPU_DEC_CR_WIN_TARGET_MASK
)
>>
CPU_DEC_CR_WIN_TARGET_OFFS
;
enabled
=
ctrl_reg
&
CPU_DEC_CR_WIN_ENABLE
;
/* Ignore invalid and non-dram windows*/
if
((
enabled
==
0
)
||
(
target
!=
DRAM_CPU_DEC_TARGET_NUM
))
continue
;
win
=
win_map
->
dram_windows
+
win_map
->
dram_win_num
;
base_reg
=
mmio_read_32
(
CPU_DEC_WIN_BASE_REG
(
win_id
));
size_reg
=
mmio_read_32
(
CPU_DEC_WIN_SIZE_REG
(
win_id
));
/* Base reg [15:0] corresponds to transaction address [39:16] */
win
->
base_addr
=
(
base_reg
&
CPU_DEC_BR_BASE_MASK
)
>>
CPU_DEC_BR_BASE_OFFS
;
win
->
base_addr
*=
CPU_DEC_CR_WIN_SIZE_ALIGNMENT
;
/*
* Size reg [15:0] is programmed from LSB to MSB as a sequence
* of 1s followed by a sequence of 0s and the number of 1s
* specifies the size of the window in 64 KB granularity,
* for example, a value of 00FFh specifies 256 x 64 KB = 16 MB
*/
win
->
win_size
=
(
size_reg
&
CPU_DEC_CR_WIN_SIZE_MASK
)
>>
CPU_DEC_CR_WIN_SIZE_OFFS
;
win
->
win_size
=
(
win
->
win_size
+
1
)
*
CPU_DEC_CR_WIN_SIZE_ALIGNMENT
;
win_map
->
dram_win_num
++
;
}
}
static
void
cpu_win_set
(
uint32_t
win_id
,
struct
cpu_win_configuration
*
win_cfg
)
{
uint32_t
base_reg
,
ctrl_reg
,
size_reg
,
remap_reg
;
/* Disable window */
ctrl_reg
=
mmio_read_32
(
CPU_DEC_WIN_CTRL_REG
(
win_id
));
ctrl_reg
&=
~
CPU_DEC_CR_WIN_ENABLE
;
mmio_write_32
(
CPU_DEC_WIN_CTRL_REG
(
win_id
),
ctrl_reg
);
/* For an disabled window, only disable it. */
if
(
!
win_cfg
->
enabled
)
return
;
/* Set Base Register */
base_reg
=
(
uint32_t
)(
win_cfg
->
base_addr
/
CPU_DEC_CR_WIN_SIZE_ALIGNMENT
);
base_reg
<<=
CPU_DEC_BR_BASE_OFFS
;
base_reg
&=
CPU_DEC_BR_BASE_MASK
;
mmio_write_32
(
CPU_DEC_WIN_BASE_REG
(
win_id
),
base_reg
);
/* Set Remap Register with the same value
* as the <Base> field in Base Register
*/
remap_reg
=
(
uint32_t
)(
win_cfg
->
remap_addr
/
CPU_DEC_CR_WIN_SIZE_ALIGNMENT
);
remap_reg
<<=
CPU_DEC_RLR_REMAP_LOW_OFFS
;
remap_reg
&=
CPU_DEC_RLR_REMAP_LOW_MASK
;
mmio_write_32
(
CPU_DEC_REMAP_LOW_REG
(
win_id
),
remap_reg
);
/* Set Size Register */
size_reg
=
(
win_cfg
->
size
/
CPU_DEC_CR_WIN_SIZE_ALIGNMENT
)
-
1
;
size_reg
<<=
CPU_DEC_CR_WIN_SIZE_OFFS
;
size_reg
&=
CPU_DEC_CR_WIN_SIZE_MASK
;
mmio_write_32
(
CPU_DEC_WIN_SIZE_REG
(
win_id
),
size_reg
);
/* Set Control Register - set target id and enable window */
ctrl_reg
&=
~
CPU_DEC_CR_WIN_TARGET_MASK
;
ctrl_reg
|=
(
win_cfg
->
target
<<
CPU_DEC_CR_WIN_TARGET_OFFS
);
ctrl_reg
|=
CPU_DEC_CR_WIN_ENABLE
;
mmio_write_32
(
CPU_DEC_WIN_CTRL_REG
(
win_id
),
ctrl_reg
);
}
void
cpu_wins_init
(
void
)
{
uint32_t
cfg_idx
,
win_id
;
if
(
mvebu_get_dram_size
(
MVEBU_REGS_BASE
)
<=
_2GB_
)
cfg_idx
=
CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB
;
else
cfg_idx
=
CPU_WIN_CONFIG_DRAM_4GB
;
/* Window 0 is configured always for DRAM in tim header
* already, no need to configure it again here
*/
for
(
win_id
=
1
;
win_id
<
MV_CPU_WIN_NUM
;
win_id
++
)
cpu_win_set
(
win_id
,
&
mv_cpu_wins
[
cfg_idx
][
win_id
]);
}
plat/marvell/a3700/common/include/a3700_plat_def.h
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#ifndef __A3700_PLAT_DEF_H__
#define __A3700_PLAT_DEF_H__
#include <marvell_def.h>
#define MVEBU_MAX_CPUS_PER_CLUSTER 2
#define MVEBU_PRIMARY_CPU 0x0
/*
* The counter on A3700 is always fed from reference 25M clock (XTAL).
* However minimal CPU counter prescaler is 2, so the counter
* frequency will be divided by 2, the number is 12.5M
*/
#define COUNTER_FREQUENCY 12500000
#define MVEBU_REGS_BASE 0xD0000000
/*****************************************************************************
* MVEBU memory map related constants
*****************************************************************************
*/
/* Aggregate of all devices in the first GB */
#define DEVICE0_BASE MVEBU_REGS_BASE
#define DEVICE0_SIZE 0x10000000
/*****************************************************************************
* GIC-500 & interrupt handling related constants
*****************************************************************************
*/
/* Base MVEBU compatible GIC memory map */
#define MVEBU_GICD_BASE 0x1D00000
#define MVEBU_GICR_BASE 0x1D40000
#define MVEBU_GICC_BASE 0x1D80000
/* CCI-400 */
#define MVEBU_CCI_BASE 0x8000000
/*****************************************************************************
* North and south bridge register base
*****************************************************************************
*/
#define MVEBU_NB_REGS_BASE (MVEBU_REGS_BASE + 0x13000)
#define MVEBU_SB_REGS_BASE (MVEBU_REGS_BASE + 0x18000)
/*****************************************************************************
* GPIO registers related constants
*****************************************************************************
*/
/* North and south bridge GPIO register base address */
#define MVEBU_NB_GPIO_REG_BASE (MVEBU_NB_REGS_BASE + 0x800)
#define MVEBU_NB_GPIO_IRQ_REG_BASE (MVEBU_NB_REGS_BASE + 0xC00)
#define MVEBU_SB_GPIO_REG_BASE (MVEBU_SB_REGS_BASE + 0x800)
#define MVEBU_SB_GPIO_IRQ_REG_BASE (MVEBU_SB_REGS_BASE + 0xC00)
#define MVEBU_NB_SB_IRQ_REG_BASE (MVEBU_REGS_BASE + 0x8A00)
/* North Bridge GPIO selection register */
#define MVEBU_NB_GPIO_SEL_REG (MVEBU_NB_GPIO_REG_BASE + 0x30)
#define MVEBU_NB_GPIO_OUTPUT_EN_HIGH_REG (MVEBU_NB_GPIO_REG_BASE + 0x04)
/* I2C1 GPIO Enable bit offset */
#define MVEBU_GPIO_TW1_GPIO_EN_OFF (10)
/* SPI pins mode bit offset */
#define MVEBU_GPIO_NB_SPI_PIN_MODE_OFF (28)
/*****************************************************************************
* DRAM registers related constants
*****************************************************************************
*/
#define MVEBU_DRAM_REG_BASE (MVEBU_REGS_BASE)
/*****************************************************************************
* SB wake-up registers related constants
*****************************************************************************
*/
#define MVEBU_SB_WAKEUP_REG_BASE (MVEBU_REGS_BASE + 0x19000)
/*****************************************************************************
* PMSU registers related constants
*****************************************************************************
*/
#define MVEBU_PMSU_REG_BASE (MVEBU_REGS_BASE + 0x14000)
/*****************************************************************************
* North Bridge Step-Down Registers
*****************************************************************************
*/
#define MVEBU_NB_STEP_DOWN_REG_BASE (MVEBU_REGS_BASE + 0x12800)
/*****************************************************************************
* DRAM CS memory map register base
*****************************************************************************
*/
#define MVEBU_CS_MMAP_REG_BASE (MVEBU_REGS_BASE + 0x200)
/*****************************************************************************
* CPU decoder window registers related constants
*****************************************************************************
*/
#define MVEBU_CPU_DEC_WIN_REG_BASE (MVEBU_REGS_BASE + 0xCF00)
/*****************************************************************************
* AVS registers related constants
*****************************************************************************
*/
#define MVEBU_AVS_REG_BASE (MVEBU_REGS_BASE + 0x11500)
/*****************************************************************************
* AVS registers related constants
*****************************************************************************
*/
#define MVEBU_COMPHY_REG_BASE (MVEBU_REGS_BASE + 0x18300)
#endif
/* __A3700_PLAT_DEF_H__ */
plat/marvell/a3700/common/include/a3700_pm.h
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2016 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#ifndef __A3700_PM_H__
#define __A3700_PM_H__
#include <stdint.h>
/* supported wake up sources */
enum
pm_wake_up_src_type
{
WAKE_UP_SRC_GPIO
,
/* FOLLOWING SRC NOT SUPPORTED YET */
WAKE_UP_SRC_TIMER
,
WAKE_UP_SRC_UART0
,
WAKE_UP_SRC_UART1
,
WAKE_UP_SRC_MAX
,
};
struct
pm_gpio_data
{
/*
* bank 0: North bridge GPIO
* bank 1: South bridge GPIO
*/
uint32_t
bank_num
;
uint32_t
gpio_num
;
};
union
pm_wake_up_src_data
{
struct
pm_gpio_data
gpio_data
;
/* delay in seconds */
uint32_t
timer_delay
;
};
struct
pm_wake_up_src
{
enum
pm_wake_up_src_type
wake_up_src_type
;
union
pm_wake_up_src_data
wake_up_data
;
};
struct
pm_wake_up_src_config
{
uint32_t
wake_up_src_num
;
struct
pm_wake_up_src
wake_up_src
[
WAKE_UP_SRC_MAX
];
};
struct
pm_wake_up_src_config
*
mv_wake_up_src_config_get
(
void
);
#endif
/* __A3700_PM_H__ */
plat/marvell/a3700/common/include/ddr_info.h
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#ifndef _DDR_INFO_H_
#define _DDR_INFO_H_
#define DRAM_MAX_IFACE 1
#define DRAM_CH0_MMAP_LOW_OFFSET 0x200
#endif
/* _DDR_INFO_H_ */
plat/marvell/a3700/common/include/dram_win.h
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#ifndef _DRAM_WIN_H_
#define _DRAM_WIN_H_
#include <bl_common.h>
#include <io_addr_dec.h>
void
dram_win_map_build
(
struct
dram_win_map
*
win_map
);
void
cpu_wins_init
(
void
);
#endif
/* _DRAM_WIN_H_ */
plat/marvell/a3700/common/include/io_addr_dec.h
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#ifndef _IO_ADDR_DEC_H_
#define _IO_ADDR_DEC_H_
#include <stdint.h>
/* There are 5 configurable cpu decoder windows. */
#define DRAM_WIN_MAP_NUM_MAX 5
/* Target number for dram in cpu decoder windows. */
#define DRAM_CPU_DEC_TARGET_NUM 0
/*
* Not all configurable decode windows could be used for dram, some units have
* to reserve one decode window for other unit they have to communicate with;
* for example, DMA engineer has 3 configurable windows, but only two could be
* for dram while the last one has to be for pcie, so for DMA, its max_dram_win
* is 2.
*/
struct
dec_win_config
{
uint32_t
dec_reg_base
;
/* IO address decoder register base address */
uint32_t
win_attr
;
/* IO address decoder windows attributes */
/* How many configurable dram decoder windows that this unit has; */
uint32_t
max_dram_win
;
/* The decoder windows number including remapping that this unit has */
uint32_t
max_remap
;
/* The offset between continuous decode windows
* within the same unit, typically 0x10
*/
uint32_t
win_offset
;
};
struct
dram_win
{
uintptr_t
base_addr
;
uintptr_t
win_size
;
};
struct
dram_win_map
{
int
dram_win_num
;
struct
dram_win
dram_windows
[
DRAM_WIN_MAP_NUM_MAX
];
};
/*
* init_io_addr_dec
*
* This function initializes io address decoder windows by
* cpu dram window mapping information
*
* @input: N/A
* - dram_wins_map: cpu dram windows mapping
* - io_dec_config: io address decoder windows configuration
* - io_unit_num: io address decoder unit number
* @output: N/A
*
* @return: 0 on success and others on failure
*/
int
init_io_addr_dec
(
struct
dram_win_map
*
dram_wins_map
,
struct
dec_win_config
*
io_dec_config
,
uint32_t
io_unit_num
);
#endif
/* _IO_ADDR_DEC_H_ */
plat/marvell/a3700/common/include/plat_macros.S
0 → 100644
View file @
eb47f14d
/*
*
Copyright
(
C
)
2018
Marvell
International
Ltd
.
*
*
SPDX
-
License
-
Identifier
:
BSD
-
3
-
Clause
*
https
:
//
spdx
.
org
/
licenses
*/
#ifndef __PLAT_MACROS_S__
#define __PLAT_MACROS_S__
#include <marvell_macros.S>
/*
---------------------------------------------
*
The
below
macro
prints
out
relevant
GIC
and
*
CCI
registers
registers
whenever
an
unhandled
*
exception
is
taken
in
BL31
.
*
---------------------------------------------
*/
.
macro
plat_crash_print_regs
mov_imm
x17
,
MVEBU_GICC_BASE
mov_imm
x16
,
MVEBU_GICD_BASE
marvell_print_gic_regs
print_cci_regs
.
endm
#endif /* __PLAT_MACROS_S__ */
plat/marvell/a3700/common/include/platform_def.h
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2016 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#ifndef __PLATFORM_DEF_H__
#define __PLATFORM_DEF_H__
#include <board_marvell_def.h>
#include <mvebu_def.h>
#ifndef __ASSEMBLY__
#include <stdio.h>
#endif
/* __ASSEMBLY__ */
/*
* Most platform porting definitions provided by included headers
*/
/*
* DRAM Memory layout:
* +-----------------------+
* : :
* : Linux :
* 0x04X00000-->+-----------------------+
* | BL3-3(u-boot) |>>}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
* |-----------------------| } |
* | BL3-[0,1, 2] | }---------------------------------> |
* |-----------------------| } || |
* | BL2 | }->FIP (loaded by || |
* |-----------------------| } BootROM to DRAM) || |
* | FIP_TOC | } || |
* 0x04120000-->|-----------------------| || |
* | BL1 (RO) | || |
* 0x04100000-->+-----------------------+ || |
* : : || |
* : Trusted SRAM section : \/ |
* 0x04040000-->+-----------------------+ Replaced by BL2 +----------------+ |
* | BL1 (RW) | <<<<<<<<<<<<<<<< | BL3-1 NOBITS | |
* 0x04037000-->|-----------------------| <<<<<<<<<<<<<<<< |----------------| |
* | | <<<<<<<<<<<<<<<< | BL3-1 PROGBITS | |
* 0x04023000-->|-----------------------| +----------------+ |
* | BL2 | |
* |-----------------------| |
* | | |
* 0x04001000-->|-----------------------| |
* | Shared | |
* 0x04000000-->+-----------------------+ |
* : : |
* : Linux : |
* : : |
* |-----------------------| |
* | | U-Boot(BL3-3) Loaded by BL2 |
* | U-Boot | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
* 0x00000000-->+-----------------------+
*
* Trusted SRAM section 0x4000000..0x4200000:
* ----------------------------------------
* SRAM_BASE = 0x4001000
* BL2_BASE = 0x4006000
* BL2_LIMIT = BL31_BASE
* BL31_BASE = 0x4023000 = (64MB + 256KB - 0x1D000)
* BL31_PROGBITS_LIMIT = BL1_RW_BASE
* BL1_RW_BASE = 0x4037000 = (64MB + 256KB - 0x9000)
* BL1_RW_LIMIT = BL31_LIMIT = 0x4040000
*
*
* PLAT_MARVELL_FIP_BASE = 0x4120000
*/
#define PLAT_MARVELL_ATF_BASE 0x4000000
#define PLAT_MARVELL_ATF_LOAD_ADDR \
(PLAT_MARVELL_ATF_BASE + 0x100000)
#define PLAT_MARVELL_FIP_BASE \
(PLAT_MARVELL_ATF_LOAD_ADDR + 0x20000)
#define PLAT_MARVELL_FIP_MAX_SIZE 0x4000000
#define PLAT_MARVELL_CLUSTER_CORE_COUNT 2
/* DRAM[2MB..66MB] is used as Trusted ROM */
#define PLAT_MARVELL_TRUSTED_ROM_BASE PLAT_MARVELL_ATF_LOAD_ADDR
/* 64 MB TODO: reduce this to minimum needed according to fip image size*/
#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x04000000
/* Reserve 16M for SCP (Secure PayLoad) Trusted DRAM */
#define PLAT_MARVELL_TRUSTED_DRAM_BASE 0x04400000
#define PLAT_MARVELL_TRUSTED_DRAM_SIZE 0x01000000
/* 16 MB */
/*
* PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
* plus a little space for growth.
*/
#define PLAT_MARVELL_MAX_BL1_RW_SIZE 0xA000
/*
* PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
* little space for growth.
*/
#define PLAT_MARVELL_MAX_BL2_SIZE 0xF000
/*
* PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
* little space for growth.
*/
#define PLAT_MARVEL_MAX_BL31_SIZE 0x5D000
#define PLAT_MARVELL_CPU_ENTRY_ADDR BL1_RO_BASE
/* GIC related definitions */
#define PLAT_MARVELL_GICD_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE)
#define PLAT_MARVELL_GICR_BASE (MVEBU_REGS_BASE + MVEBU_GICR_BASE)
#define PLAT_MARVELL_GICC_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE)
#define PLAT_MARVELL_G0_IRQ_PROPS(grp) \
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL)
#define PLAT_MARVELL_G1S_IRQ_PROPS(grp) \
INTR_PROP_DESC(MARVELL_IRQ_SEC_PHY_TIMER, \
GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL)
#define PLAT_MARVELL_SHARED_RAM_CACHED 1
/* CCI related constants */
#define PLAT_MARVELL_CCI_BASE (MVEBU_REGS_BASE + MVEBU_CCI_BASE)
#define PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX 3
#define PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX 4
/*
* Load address of BL3-3 for this platform port
*/
#define PLAT_MARVELL_NS_IMAGE_OFFSET 0x0
/* System Reference Clock*/
#define PLAT_REF_CLK_IN_HZ COUNTER_FREQUENCY
/*
* PL011 related constants
*/
#define PLAT_MARVELL_BOOT_UART_BASE (MVEBU_REGS_BASE + 0x12000)
#define PLAT_MARVELL_BOOT_UART_CLK_IN_HZ 25804800
#define PLAT_MARVELL_CRASH_UART_BASE PLAT_MARVELL_BOOT_UART_BASE
#define PLAT_MARVELL_CRASH_UART_CLK_IN_HZ PLAT_MARVELL_BOOT_UART_CLK_IN_HZ
#define PLAT_MARVELL_BL31_RUN_UART_BASE PLAT_MARVELL_BOOT_UART_BASE
#define PLAT_MARVELL_BL31_RUN_UART_CLK_IN_HZ PLAT_MARVELL_BOOT_UART_CLK_IN_HZ
/* Required platform porting definitions */
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
/* System timer related constants */
#define PLAT_MARVELL_NSTIMER_FRAME_ID 1
/* Mailbox base address */
#define PLAT_MARVELL_MAILBOX_BASE \
(MARVELL_TRUSTED_SRAM_BASE + 0x400)
#define PLAT_MARVELL_MAILBOX_SIZE 0x100
#define PLAT_MARVELL_MAILBOX_MAGIC_NUM 0x6D72766C
/* mrvl */
/* DRAM CS memory map registers related constants */
#define MVEBU_CS_MMAP_LOW(cs_num) \
(MVEBU_CS_MMAP_REG_BASE + (cs_num) * 0x8)
#define MVEBU_CS_MMAP_ENABLE 0x1
#define MVEBU_CS_MMAP_AREA_LEN_OFFS 16
#define MVEBU_CS_MMAP_AREA_LEN_MASK \
(0x1f << MVEBU_CS_MMAP_AREA_LEN_OFFS)
#define MVEBU_CS_MMAP_START_ADDR_LOW_OFFS 23
#define MVEBU_CS_MMAP_START_ADDR_LOW_MASK \
(0x1ff << MVEBU_CS_MMAP_START_ADDR_LOW_OFFS)
#define MVEBU_CS_MMAP_HIGH(cs_num) \
(MVEBU_CS_MMAP_REG_BASE + 0x4 + (cs_num) * 0x8)
/* DRAM max CS number */
#define MVEBU_MAX_CS_MMAP_NUM (2)
/* CPU decoder window related constants */
#define CPU_DEC_WIN_CTRL_REG(win_num) \
(MVEBU_CPU_DEC_WIN_REG_BASE + (win_num) * 0x10)
#define CPU_DEC_CR_WIN_ENABLE 0x1
#define CPU_DEC_CR_WIN_TARGET_OFFS 4
#define CPU_DEC_CR_WIN_TARGET_MASK \
(0xf << CPU_DEC_CR_WIN_TARGET_OFFS)
#define CPU_DEC_WIN_SIZE_REG(win_num) \
(MVEBU_CPU_DEC_WIN_REG_BASE + 0x4 + (win_num) * 0x10)
#define CPU_DEC_CR_WIN_SIZE_OFFS 0
#define CPU_DEC_CR_WIN_SIZE_MASK \
(0xffff << CPU_DEC_CR_WIN_SIZE_OFFS)
#define CPU_DEC_CR_WIN_SIZE_ALIGNMENT 0x10000
#define CPU_DEC_WIN_BASE_REG(win_num) \
(MVEBU_CPU_DEC_WIN_REG_BASE + 0x8 + (win_num) * 0x10)
#define CPU_DEC_BR_BASE_OFFS 0
#define CPU_DEC_BR_BASE_MASK \
(0xffff << CPU_DEC_BR_BASE_OFFS)
#define CPU_DEC_REMAP_LOW_REG(win_num) \
(MVEBU_CPU_DEC_WIN_REG_BASE + 0xC + (win_num) * 0x10)
#define CPU_DEC_RLR_REMAP_LOW_OFFS 0
#define CPU_DEC_RLR_REMAP_LOW_MASK \
(0xffff << CPU_DEC_BR_BASE_OFFS)
/* Securities */
#define IRQ_SEC_OS_TICK_INT MARVELL_IRQ_SEC_PHY_TIMER
#define TRUSTED_DRAM_BASE PLAT_MARVELL_TRUSTED_DRAM_BASE
#define TRUSTED_DRAM_SIZE PLAT_MARVELL_TRUSTED_DRAM_SIZE
#ifdef BL32
#define BL32_BASE TRUSTED_DRAM_BASE
#define BL32_LIMIT TRUSTED_DRAM_SIZE
#endif
#endif
/* __PLATFORM_DEF_H__ */
plat/marvell/a3700/common/io_addr_dec.c
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2016 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#include <debug.h>
#include <io_addr_dec.h>
#include <mmio.h>
#include <plat_marvell.h>
#define MVEBU_DEC_WIN_CTRL_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
(win) * (off))
#define MVEBU_DEC_WIN_BASE_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
(win) * (off) + 0x4)
#define MVEBU_DEC_WIN_REMAP_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
(win) * (off) + 0x8)
#define MVEBU_DEC_WIN_CTRL_SIZE_OFF (16)
#define MVEBU_DEC_WIN_ENABLE (0x1)
#define MVEBU_DEC_WIN_CTRL_ATTR_OFF (8)
#define MVEBU_DEC_WIN_CTRL_TARGET_OFF (4)
#define MVEBU_DEC_WIN_CTRL_EN_OFF (0)
#define MVEBU_DEC_WIN_BASE_OFF (16)
#define MVEBU_WIN_BASE_SIZE_ALIGNMENT (0x10000)
/* There are up to 14 IO unit which need address decode in Armada-3700 */
#define IO_UNIT_NUM_MAX (14)
#define MVEBU_MAX_ADDRSS_4GB (0x100000000ULL)
static
void
set_io_addr_dec_win
(
int
win_id
,
uintptr_t
base_addr
,
uintptr_t
win_size
,
struct
dec_win_config
*
dec_win
)
{
uint32_t
ctrl
=
0
;
uint32_t
base
=
0
;
/* set size */
ctrl
=
((
win_size
/
MVEBU_WIN_BASE_SIZE_ALIGNMENT
)
-
1
)
<<
MVEBU_DEC_WIN_CTRL_SIZE_OFF
;
/* set attr according to IO decode window */
ctrl
|=
dec_win
->
win_attr
<<
MVEBU_DEC_WIN_CTRL_ATTR_OFF
;
/* set target */
ctrl
|=
DRAM_CPU_DEC_TARGET_NUM
<<
MVEBU_DEC_WIN_CTRL_TARGET_OFF
;
/* set base */
base
=
(
base_addr
/
MVEBU_WIN_BASE_SIZE_ALIGNMENT
)
<<
MVEBU_DEC_WIN_BASE_OFF
;
/* set base address*/
mmio_write_32
(
MVEBU_DEC_WIN_BASE_REG
(
dec_win
->
dec_reg_base
,
win_id
,
dec_win
->
win_offset
),
base
);
/* set remap window, some unit does not have remap window */
if
(
win_id
<
dec_win
->
max_remap
)
mmio_write_32
(
MVEBU_DEC_WIN_REMAP_REG
(
dec_win
->
dec_reg_base
,
win_id
,
dec_win
->
win_offset
),
base
);
/* set control register */
mmio_write_32
(
MVEBU_DEC_WIN_CTRL_REG
(
dec_win
->
dec_reg_base
,
win_id
,
dec_win
->
win_offset
),
ctrl
);
/* enable the address decode window at last to make it effective */
ctrl
|=
MVEBU_DEC_WIN_ENABLE
<<
MVEBU_DEC_WIN_CTRL_EN_OFF
;
mmio_write_32
(
MVEBU_DEC_WIN_CTRL_REG
(
dec_win
->
dec_reg_base
,
win_id
,
dec_win
->
win_offset
),
ctrl
);
INFO
(
"set_io_addr_dec %d result: ctrl(0x%x) base(0x%x)"
,
win_id
,
mmio_read_32
(
MVEBU_DEC_WIN_CTRL_REG
(
dec_win
->
dec_reg_base
,
win_id
,
dec_win
->
win_offset
)),
mmio_read_32
(
MVEBU_DEC_WIN_BASE_REG
(
dec_win
->
dec_reg_base
,
win_id
,
dec_win
->
win_offset
)));
if
(
win_id
<
dec_win
->
max_remap
)
INFO
(
" remap(%x)
\n
"
,
mmio_read_32
(
MVEBU_DEC_WIN_REMAP_REG
(
dec_win
->
dec_reg_base
,
win_id
,
dec_win
->
win_offset
)));
else
INFO
(
"
\n
"
);
}
/* Set io decode window */
static
int
set_io_addr_dec
(
struct
dram_win_map
*
win_map
,
struct
dec_win_config
*
dec_win
)
{
struct
dram_win
*
win
;
int
id
;
/* disable all windows first */
for
(
id
=
0
;
id
<
dec_win
->
max_dram_win
;
id
++
)
mmio_write_32
(
MVEBU_DEC_WIN_CTRL_REG
(
dec_win
->
dec_reg_base
,
id
,
dec_win
->
win_offset
),
0
);
/* configure IO decode windows for DRAM, inheritate DRAM size,
* base and target from CPU-DRAM decode window and others
* from hard coded IO decode window settings array.
*/
if
(
win_map
->
dram_win_num
>
dec_win
->
max_dram_win
)
{
/*
* If cpu dram windows number exceeds the io decode windows
* max number, then fill the first io decode window
* with base(0) and size(4GB).
*/
set_io_addr_dec_win
(
0
,
0
,
MVEBU_MAX_ADDRSS_4GB
,
dec_win
);
return
0
;
}
for
(
id
=
0
;
id
<
win_map
->
dram_win_num
;
id
++
,
win
++
)
{
win
=
&
win_map
->
dram_windows
[
id
];
set_io_addr_dec_win
(
id
,
win
->
base_addr
,
win
->
win_size
,
dec_win
);
}
return
0
;
}
/*
* init_io_addr_dec
*
* This function initializes io address decoder windows by
* cpu dram window mapping information
*
* @input: N/A
* - dram_wins_map: cpu dram windows mapping
* - io_dec_config: io address decoder windows configuration
* - io_unit_num: io address decoder unit number
* @output: N/A
*
* @return: 0 on success and others on failure
*/
int
init_io_addr_dec
(
struct
dram_win_map
*
dram_wins_map
,
struct
dec_win_config
*
io_dec_config
,
uint32_t
io_unit_num
)
{
int32_t
index
;
struct
dec_win_config
*
io_dec_win
;
int32_t
ret
;
INFO
(
"Initializing IO address decode windows
\n
"
);
if
(
io_dec_config
==
NULL
||
io_unit_num
==
0
)
{
ERROR
(
"No IO address decoder windows configurations!
\n
"
);
return
-
1
;
}
if
(
io_unit_num
>
IO_UNIT_NUM_MAX
)
{
ERROR
(
"IO address decoder windows number %d is over max %d
\n
"
,
io_unit_num
,
IO_UNIT_NUM_MAX
);
return
-
1
;
}
if
(
dram_wins_map
==
NULL
)
{
ERROR
(
"No cpu dram decoder windows map!
\n
"
);
return
-
1
;
}
for
(
index
=
0
;
index
<
dram_wins_map
->
dram_win_num
;
index
++
)
INFO
(
"DRAM mapping %d base(0x%lx) size(0x%lx)
\n
"
,
index
,
dram_wins_map
->
dram_windows
[
index
].
base_addr
,
dram_wins_map
->
dram_windows
[
index
].
win_size
);
/* Set address decode window for each IO */
for
(
index
=
0
;
index
<
io_unit_num
;
index
++
)
{
io_dec_win
=
io_dec_config
+
index
;
ret
=
set_io_addr_dec
(
dram_wins_map
,
io_dec_win
);
if
(
ret
)
{
ERROR
(
"Failed to set IO address decode
\n
"
);
return
-
1
;
}
INFO
(
"Set IO decode window successfully, base(0x%x)"
,
io_dec_win
->
dec_reg_base
);
INFO
(
" win_attr(%x) max_dram_win(%d) max_remap(%d)"
,
io_dec_win
->
win_attr
,
io_dec_win
->
max_dram_win
,
io_dec_win
->
max_remap
);
INFO
(
" win_offset(%d)
\n
"
,
io_dec_win
->
win_offset
);
}
return
0
;
}
plat/marvell/a3700/common/marvell_plat_config.c
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#include <bl_common.h>
#include <io_addr_dec.h>
#include <mvebu_def.h>
struct
dec_win_config
io_dec_win_conf
[]
=
{
/* dec_reg_base win_attr max_dram_win max_remap win_offset */
{
0xc000
,
0x3d
,
2
,
0
,
0x08
},
/* USB */
{
0xc100
,
0x3d
,
3
,
0
,
0x10
},
/* USB3 */
{
0xc200
,
0x3d
,
2
,
0
,
0x10
},
/* DMA */
{
0xc300
,
0x3d
,
2
,
0
,
0x10
},
/* NETA0 */
{
0xc400
,
0x3d
,
2
,
0
,
0x10
},
/* NETA1 */
{
0xc500
,
0x3d
,
2
,
0
,
0x10
},
/* PCIe */
{
0xc800
,
0x3d
,
3
,
0
,
0x10
},
/* SATA */
{
0xca00
,
0x3d
,
3
,
0
,
0x08
},
/* SD */
{
0xcb00
,
0x3d
,
3
,
0
,
0x10
},
/* eMMC */
{
0xce00
,
0x3d
,
2
,
0
,
0x08
},
/* EIP97 */
};
int
marvell_get_io_dec_win_conf
(
struct
dec_win_config
**
win
,
uint32_t
*
size
)
{
*
win
=
io_dec_win_conf
;
*
size
=
sizeof
(
io_dec_win_conf
)
/
sizeof
(
struct
dec_win_config
);
return
0
;
}
plat/marvell/a3700/common/plat_pm.c
0 → 100644
View file @
eb47f14d
/*
* Copyright (C) 2018 Marvell International Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
* https://spdx.org/licenses
*/
#include <a3700_pm.h>
#include <arch_helpers.h>
#include <armada_common.h>
#include <debug.h>
#include <dram_win.h>
#include <io_addr_dec.h>
#include <mmio.h>
#include <mvebu.h>
#include <mvebu_def.h>
#include <marvell_plat_priv.h>
#include <platform.h>
#include <plat_marvell.h>
#include <psci.h>
#ifdef USE_CCI
#include <cci.h>
#endif
/* Warm reset register */
#define MVEBU_WARM_RESET_REG (MVEBU_NB_REGS_BASE + 0x840)
#define MVEBU_WARM_RESET_MAGIC 0x1D1E
/* North Bridge GPIO1 SEL register */
#define MVEBU_NB_GPIO1_SEL_REG (MVEBU_NB_REGS_BASE + 0x830)
#define MVEBU_NB_GPIO1_UART1_SEL BIT(19)
#define MVEBU_NB_GPIO1_GPIO_25_26_EN BIT(17)
#define MVEBU_NB_GPIO1_GPIO_19_EN BIT(14)
#define MVEBU_NB_GPIO1_GPIO_18_EN BIT(13)
/* CPU 1 reset register */
#define MVEBU_CPU_1_RESET_VECTOR (MVEBU_REGS_BASE + 0x14044)
#define MVEBU_CPU_1_RESET_REG (MVEBU_REGS_BASE + 0xD00C)
#define MVEBU_CPU_1_RESET_BIT 31
/* IRQ register */
#define MVEBU_NB_IRQ_STATUS_1_REG (MVEBU_NB_SB_IRQ_REG_BASE)
#define MVEBU_NB_IRQ_STATUS_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
0x10)
#define MVEBU_NB_IRQ_MASK_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
0x18)
#define MVEBU_SB_IRQ_STATUS_1_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
0x40)
#define MVEBU_SB_IRQ_STATUS_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
0x50)
#define MVEBU_NB_GPIO_IRQ_MASK_1_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
0xC8)
#define MVEBU_NB_GPIO_IRQ_MASK_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
0xD8)
#define MVEBU_SB_GPIO_IRQ_MASK_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
0xE8)
#define MVEBU_NB_GPIO_IRQ_EN_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE)
#define MVEBU_NB_GPIO_IRQ_EN_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
0x04)
#define MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
0x10)
#define MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
0x14)
#define MVEBU_NB_GPIO_IRQ_WK_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
0x18)
#define MVEBU_NB_GPIO_IRQ_WK_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
0x1C)
#define MVEBU_SB_GPIO_IRQ_EN_REG (MVEBU_SB_GPIO_IRQ_REG_BASE)
#define MVEBU_SB_GPIO_IRQ_STATUS_REG (MVEBU_SB_GPIO_IRQ_REG_BASE + \
0x10)
#define MVEBU_SB_GPIO_IRQ_WK_REG (MVEBU_SB_GPIO_IRQ_REG_BASE + \
0x18)
/* PMU registers */
#define MVEBU_PM_NB_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE)
#define MVEBU_PM_PWR_DN_CNT_SEL BIT(28)
#define MVEBU_PM_SB_PWR_DWN BIT(4)
#define MVEBU_PM_INTERFACE_IDLE BIT(0)
#define MVEBU_PM_NB_CPU_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x4)
#define MVEBU_PM_L2_FLUSH_EN BIT(22)
#define MVEBU_PM_NB_PWR_OPTION_REG (MVEBU_PMSU_REG_BASE + 0x8)
#define MVEBU_PM_DDR_SR_EN BIT(29)
#define MVEBU_PM_DDR_CLK_DIS_EN BIT(28)
#define MVEBU_PM_WARM_RESET_EN BIT(27)
#define MVEBU_PM_DDRPHY_PWRDWN_EN BIT(23)
#define MVEBU_PM_DDRPHY_PAD_PWRDWN_EN BIT(22)
#define MVEBU_PM_OSC_OFF_EN BIT(21)
#define MVEBU_PM_TBG_OFF_EN BIT(20)
#define MVEBU_PM_CPU_VDDV_OFF_EN BIT(19)
#define MVEBU_PM_AVS_DISABLE_MODE BIT(14)
#define MVEBU_PM_AVS_VDD2_MODE BIT(13)
#define MVEBU_PM_AVS_HOLD_MODE BIT(12)
#define MVEBU_PM_L2_SRAM_LKG_PD_EN BIT(8)
#define MVEBU_PM_EIP_SRAM_LKG_PD_EN BIT(7)
#define MVEBU_PM_DDRMC_SRAM_LKG_PD_EN BIT(6)
#define MVEBU_PM_MCI_SRAM_LKG_PD_EN BIT(5)
#define MVEBU_PM_MMC_SRAM_LKG_PD_EN BIT(4)
#define MVEBU_PM_SATA_SRAM_LKG_PD_EN BIT(3)
#define MVEBU_PM_DMA_SRAM_LKG_PD_EN BIT(2)
#define MVEBU_PM_SEC_SRAM_LKG_PD_EN BIT(1)
#define MVEBU_PM_CPU_SRAM_LKG_PD_EN BIT(0)
#define MVEBU_PM_NB_SRAM_LKG_PD_EN (MVEBU_PM_L2_SRAM_LKG_PD_EN |\
MVEBU_PM_EIP_SRAM_LKG_PD_EN | MVEBU_PM_DDRMC_SRAM_LKG_PD_EN |\
MVEBU_PM_MCI_SRAM_LKG_PD_EN | MVEBU_PM_MMC_SRAM_LKG_PD_EN |\
MVEBU_PM_SATA_SRAM_LKG_PD_EN | MVEBU_PM_DMA_SRAM_LKG_PD_EN |\
MVEBU_PM_SEC_SRAM_LKG_PD_EN | MVEBU_PM_CPU_SRAM_LKG_PD_EN)
#define MVEBU_PM_NB_PWR_DEBUG_REG (MVEBU_PMSU_REG_BASE + 0xC)
#define MVEBU_PM_NB_FORCE_CLK_ON BIT(30)
#define MVEBU_PM_IGNORE_CM3_SLEEP BIT(21)
#define MVEBU_PM_IGNORE_CM3_DEEP BIT(20)
#define MVEBU_PM_NB_WAKE_UP_EN_REG (MVEBU_PMSU_REG_BASE + 0x2C)
#define MVEBU_PM_SB_WKP_NB_EN BIT(31)
#define MVEBU_PM_NB_GPIO_WKP_EN BIT(27)
#define MVEBU_PM_SOC_TIMER_WKP_EN BIT(26)
#define MVEBU_PM_UART_WKP_EN BIT(25)
#define MVEBU_PM_UART2_WKP_EN BIT(19)
#define MVEBU_PM_CPU_TIMER_WKP_EN BIT(17)
#define MVEBU_PM_NB_WKP_EN BIT(16)
#define MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN BIT(13)
#define MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN BIT(12)
#define MVEBU_PM_CPU_0_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x34)
#define MVEBU_PM_CPU_1_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x38)
#define MVEBU_PM_CORE_SOC_PD BIT(2)
#define MVEBU_PM_CORE_PROC_PD BIT(1)
#define MVEBU_PM_CORE_PD BIT(0)
#define MVEBU_PM_CORE_1_RETURN_ADDR_REG (MVEBU_PMSU_REG_BASE + 0x44)
#define MVEBU_PM_CPU_VDD_OFF_INFO_1_REG (MVEBU_PMSU_REG_BASE + 0x48)
#define MVEBU_PM_CPU_VDD_OFF_INFO_2_REG (MVEBU_PMSU_REG_BASE + 0x4C)
#define MVEBU_PM_LOW_POWER_STATE BIT(0)
#define MVEBU_PM_CPU_WAKE_UP_CONF_REG (MVEBU_PMSU_REG_BASE + 0x54)
#define MVEBU_PM_CORE1_WAKEUP BIT(13)
#define MVEBU_PM_CORE0_WAKEUP BIT(12)
#define MVEBU_PM_WAIT_DDR_RDY_VALUE (0x15)
#define MVEBU_PM_SB_CPU_PWR_CTRL_REG (MVEBU_SB_WAKEUP_REG_BASE)
#define MVEBU_PM_SB_PM_START BIT(0)
#define MVEBU_PM_SB_PWR_OPTION_REG (MVEBU_SB_WAKEUP_REG_BASE + 0x4)
#define MVEBU_PM_SDIO_PHY_PDWN_EN BIT(17)
#define MVEBU_PM_SB_VDDV_OFF_EN BIT(16)
#define MVEBU_PM_EBM_SRAM_LKG_PD_EN BIT(11)
#define MVEBU_PM_PCIE_SRAM_LKG_PD_EN BIT(10)
#define MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN BIT(9)
#define MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN BIT(8)
#define MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN BIT(7)
#define MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN BIT(6)
#define MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN BIT(5)
#define MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN BIT(4)
#define MVEBU_PM_SDIO_SRAM_LKG_PD_EN BIT(3)
#define MVEBU_PM_USB2_SRAM_LKG_PD_EN BIT(2)
#define MVEBU_PM_USB3_H_SRAM_LKG_PD_EN BIT(1)
#define MVEBU_PM_SB_SRAM_LKG_PD_EN (MVEBU_PM_EBM_SRAM_LKG_PD_EN |\
MVEBU_PM_PCIE_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN |\
MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN |\
MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN | MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN |\
MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN | MVEBU_PM_SDIO_SRAM_LKG_PD_EN |\
MVEBU_PM_USB2_SRAM_LKG_PD_EN | MVEBU_PM_USB3_H_SRAM_LKG_PD_EN)
#define MVEBU_PM_SB_WK_EN_REG (MVEBU_SB_WAKEUP_REG_BASE + 0x10)
#define MVEBU_PM_SB_GPIO_WKP_EN BIT(24)
#define MVEBU_PM_SB_WKP_EN BIT(20)
/* DRAM registers */
#define MVEBU_DRAM_STATS_CH0_REG (MVEBU_DRAM_REG_BASE + 0x4)
#define MVEBU_DRAM_WCP_EMPTY BIT(19)
#define MVEBU_DRAM_CMD_0_REG (MVEBU_DRAM_REG_BASE + 0x20)
#define MVEBU_DRAM_CH0_CMD0 BIT(28)
#define MVEBU_DRAM_CS_CMD0 BIT(24)
#define MVEBU_DRAM_WCB_DRAIN_REQ BIT(1)
#define MVEBU_DRAM_PWR_CTRL_REG (MVEBU_DRAM_REG_BASE + 0x54)
#define MVEBU_DRAM_PHY_CLK_GATING_EN BIT(1)
#define MVEBU_DRAM_PHY_AUTO_AC_OFF_EN BIT(0)
/* AVS registers */
#define MVEBU_AVS_CTRL_2_REG (MVEBU_AVS_REG_BASE + 0x8)
#define MVEBU_LOW_VDD_MODE_EN BIT(6)
/* Clock registers */
#define MVEBU_NB_CLOCK_SEL_REG (MVEBU_NB_REGS_BASE + 0x10)
#define MVEBU_A53_CPU_CLK_SEL BIT(15)
/* North Bridge Step-Down Registers */
#define MVEBU_NB_STEP_DOWN_INT_EN_REG MVEBU_NB_STEP_DOWN_REG_BASE
#define MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK BIT(8)
#define MVEBU_NB_GPIO_18 18
#define MVEBU_NB_GPIO_19 19
#define MVEBU_NB_GPIO_25 25
#define MVEBU_NB_GPIO_26 26
typedef
int
(
*
wake_up_src_func
)(
union
pm_wake_up_src_data
*
);
struct
wake_up_src_func_map
{
enum
pm_wake_up_src_type
type
;
wake_up_src_func
func
;
};
void
marvell_psci_arch_init
(
int
die_index
)
{
}
static
void
a3700_pm_ack_irq
(
void
)
{
uint32_t
reg
;
reg
=
mmio_read_32
(
MVEBU_NB_IRQ_STATUS_1_REG
);
if
(
reg
)
mmio_write_32
(
MVEBU_NB_IRQ_STATUS_1_REG
,
reg
);
reg
=
mmio_read_32
(
MVEBU_NB_IRQ_STATUS_2_REG
);
if
(
reg
)
mmio_write_32
(
MVEBU_NB_IRQ_STATUS_2_REG
,
reg
);
reg
=
mmio_read_32
(
MVEBU_SB_IRQ_STATUS_1_REG
);
if
(
reg
)
mmio_write_32
(
MVEBU_SB_IRQ_STATUS_1_REG
,
reg
);
reg
=
mmio_read_32
(
MVEBU_SB_IRQ_STATUS_2_REG
);
if
(
reg
)
mmio_write_32
(
MVEBU_SB_IRQ_STATUS_2_REG
,
reg
);
reg
=
mmio_read_32
(
MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG
);
if
(
reg
)
mmio_write_32
(
MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG
,
reg
);
reg
=
mmio_read_32
(
MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG
);
if
(
reg
)
mmio_write_32
(
MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG
,
reg
);
reg
=
mmio_read_32
(
MVEBU_SB_GPIO_IRQ_STATUS_REG
);
if
(
reg
)
mmio_write_32
(
MVEBU_SB_GPIO_IRQ_STATUS_REG
,
reg
);
}
/*****************************************************************************
* A3700 handler called to check the validity of the power state
* parameter.
*****************************************************************************
*/
int
a3700_validate_power_state
(
unsigned
int
power_state
,
psci_power_state_t
*
req_state
)
{
ERROR
(
"%s needs to be implemented
\n
"
,
__func__
);
panic
();
}
/*****************************************************************************
* A3700 handler called when a CPU is about to enter standby.
*****************************************************************************
*/
void
a3700_cpu_standby
(
plat_local_state_t
cpu_state
)
{
ERROR
(
"%s needs to be implemented
\n
"
,
__func__
);
panic
();
}
/*****************************************************************************
* A3700 handler called when a power domain is about to be turned on. The
* mpidr determines the CPU to be turned on.
*****************************************************************************
*/
int
a3700_pwr_domain_on
(
u_register_t
mpidr
)
{
/* Set barrier */
dsbsy
();
/* Set the cpu start address to BL1 entry point */
mmio_write_32
(
MVEBU_CPU_1_RESET_VECTOR
,
PLAT_MARVELL_CPU_ENTRY_ADDR
>>
2
);
/* Get the cpu out of reset */
mmio_clrbits_32
(
MVEBU_CPU_1_RESET_REG
,
BIT
(
MVEBU_CPU_1_RESET_BIT
));
mmio_setbits_32
(
MVEBU_CPU_1_RESET_REG
,
BIT
(
MVEBU_CPU_1_RESET_BIT
));
return
0
;
}
/*****************************************************************************
* A3700 handler called to validate the entry point.
*****************************************************************************
*/
int
a3700_validate_ns_entrypoint
(
uintptr_t
entrypoint
)
{
return
PSCI_E_SUCCESS
;
}
/*****************************************************************************
* A3700 handler called when a power domain is about to be turned off. The
* target_state encodes the power state that each level should transition to.
*****************************************************************************
*/
void
a3700_pwr_domain_off
(
const
psci_power_state_t
*
target_state
)
{
uint32_t
cpu_idx
=
plat_my_core_pos
();
/* Prevent interrupts from spuriously waking up this cpu */
plat_marvell_gic_cpuif_disable
();
/*
* Enable Core VDD OFF, core is supposed to be powered
* off by PMU when WFI command is issued.
*/
mmio_setbits_32
(
MVEBU_PM_CPU_0_PWR_CTRL_REG
+
4
*
cpu_idx
,
MVEBU_PM_CORE_PD
);
/* Core can not be powered down with pending IRQ,
* acknowledge all the pending IRQ
*/
a3700_pm_ack_irq
();
}
static
void
a3700_set_gen_pwr_off_option
(
void
)
{
/* Enable L2 flush -> processor state-machine option */
mmio_setbits_32
(
MVEBU_PM_NB_CPU_PWR_CTRL_REG
,
MVEBU_PM_L2_FLUSH_EN
);
/*
* North bridge cannot be VDD off (always ON).
* The NB state machine support low power mode by its state machine.
* This bit MUST be set for north bridge power down, e.g.,
* OSC input cutoff(NOT TEST), SRAM power down, PMIC, etc.
* It is not related to CPU VDD OFF!!
*/
mmio_clrbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_CPU_VDDV_OFF_EN
);
/*
* MUST: Switch CPU/AXI clock to OSC
* NB state machine clock is always connected to OSC (slow clock).
* But Core0/1/processor state machine's clock are connected to AXI
* clock. Now, AXI clock takes the TBG as clock source.
* If using AXI clock, Core0/1/processor state machine may much faster
* than NB state machine. It will cause problem in this case if cores
* are released before north bridge gets ready.
*/
mmio_clrbits_32
(
MVEBU_NB_CLOCK_SEL_REG
,
MVEBU_A53_CPU_CLK_SEL
);
/*
* These register bits will trigger north bridge
* power-down state machine regardless CM3 status.
*/
mmio_setbits_32
(
MVEBU_PM_NB_PWR_DEBUG_REG
,
MVEBU_PM_IGNORE_CM3_SLEEP
);
mmio_setbits_32
(
MVEBU_PM_NB_PWR_DEBUG_REG
,
MVEBU_PM_IGNORE_CM3_DEEP
);
/*
* SRAM => controlled by north bridge state machine.
* Core VDD OFF is not related to CPU SRAM power down.
*/
mmio_setbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_NB_SRAM_LKG_PD_EN
);
/*
* Idle AXI interface in order to get L2_WFI
* L2 WFI is only asserted after CORE-0 and CORE-1 WFI asserted.
* (only both core-0/1in WFI, L2 WFI will be issued by CORE.)
* Once L2 WFI asserted, this bit is used for signalling assertion
* to AXI IO masters.
*/
mmio_setbits_32
(
MVEBU_PM_NB_PWR_CTRL_REG
,
MVEBU_PM_INTERFACE_IDLE
);
/* Enable core0 and core1 VDD_OFF */
mmio_setbits_32
(
MVEBU_PM_CPU_0_PWR_CTRL_REG
,
MVEBU_PM_CORE_PD
);
mmio_setbits_32
(
MVEBU_PM_CPU_1_PWR_CTRL_REG
,
MVEBU_PM_CORE_PD
);
/* Enable North bridge power down -
* Both Cores MUST enable this bit to power down north bridge!
*/
mmio_setbits_32
(
MVEBU_PM_CPU_0_PWR_CTRL_REG
,
MVEBU_PM_CORE_SOC_PD
);
mmio_setbits_32
(
MVEBU_PM_CPU_1_PWR_CTRL_REG
,
MVEBU_PM_CORE_SOC_PD
);
/* CA53 (processor domain) power down */
mmio_setbits_32
(
MVEBU_PM_CPU_0_PWR_CTRL_REG
,
MVEBU_PM_CORE_PROC_PD
);
mmio_setbits_32
(
MVEBU_PM_CPU_1_PWR_CTRL_REG
,
MVEBU_PM_CORE_PROC_PD
);
}
static
void
a3700_en_ddr_self_refresh
(
void
)
{
/*
* Both count is 16 bits and configurable. By default, osc stb cnt
* is 0xFFF for lower 12 bits.
* Thus, powerdown count is smaller than osc count.
* This count is used for exiting DDR SR mode on wakeup event.
* The powerdown count also has impact on the following
* state changes: idle -> count-down -> ... (power-down, vdd off, etc)
* Here, make stable counter shorter
* Use power down count value instead of osc_stb_cnt to speed up
* DDR self refresh exit
*/
mmio_setbits_32
(
MVEBU_PM_NB_PWR_CTRL_REG
,
MVEBU_PM_PWR_DN_CNT_SEL
);
/*
* Enable DDR SR mode => controlled by north bridge state machine
* Therefore, we must powerdown north bridge to trigger the DDR SR
* mode switching.
*/
mmio_setbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_DDR_SR_EN
);
/* Disable DDR clock, otherwise DDR will not enter into SR mode. */
mmio_setbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_DDR_CLK_DIS_EN
);
/* Power down DDR PHY (PAD) */
mmio_setbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_DDRPHY_PWRDWN_EN
);
mmio_setbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_DDRPHY_PAD_PWRDWN_EN
);
/* Set wait time for DDR ready in ROM code */
mmio_write_32
(
MVEBU_PM_CPU_VDD_OFF_INFO_1_REG
,
MVEBU_PM_WAIT_DDR_RDY_VALUE
);
/* DDR flush write buffer - mandatory */
mmio_write_32
(
MVEBU_DRAM_CMD_0_REG
,
MVEBU_DRAM_CH0_CMD0
|
MVEBU_DRAM_CS_CMD0
|
MVEBU_DRAM_WCB_DRAIN_REQ
);
while
((
mmio_read_32
(
MVEBU_DRAM_STATS_CH0_REG
)
&
MVEBU_DRAM_WCP_EMPTY
)
!=
MVEBU_DRAM_WCP_EMPTY
)
;
/* Trigger PHY reset after ddr out of self refresh =>
* supply reset pulse for DDR phy after wake up
*/
mmio_setbits_32
(
MVEBU_DRAM_PWR_CTRL_REG
,
MVEBU_DRAM_PHY_CLK_GATING_EN
|
MVEBU_DRAM_PHY_AUTO_AC_OFF_EN
);
}
static
void
a3700_pwr_dn_avs
(
void
)
{
/*
* AVS power down - controlled by north bridge statemachine
* Enable AVS power down by clear the AVS disable bit.
*/
mmio_clrbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_AVS_DISABLE_MODE
);
/*
* Should set BIT[12:13] to powerdown AVS.
* 1. Enable AVS VDD2 mode
* 2. After power down AVS, we must hold AVS output voltage.
* 3. We can choose the lower VDD for AVS power down.
*/
mmio_setbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_AVS_VDD2_MODE
);
mmio_setbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_AVS_HOLD_MODE
);
/* Enable low VDD mode, AVS will set CPU to lowest core VDD 747mV */
mmio_setbits_32
(
MVEBU_AVS_CTRL_2_REG
,
MVEBU_LOW_VDD_MODE_EN
);
}
static
void
a3700_pwr_dn_tbg
(
void
)
{
/* Power down TBG */
mmio_setbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_TBG_OFF_EN
);
}
static
void
a3700_pwr_dn_sb
(
void
)
{
/* Enable south bridge power down option */
mmio_setbits_32
(
MVEBU_PM_NB_PWR_CTRL_REG
,
MVEBU_PM_SB_PWR_DWN
);
/* Enable SDIO_PHY_PWRDWN */
mmio_setbits_32
(
MVEBU_PM_SB_PWR_OPTION_REG
,
MVEBU_PM_SDIO_PHY_PDWN_EN
);
/* Enable SRAM LRM on SB */
mmio_setbits_32
(
MVEBU_PM_SB_PWR_OPTION_REG
,
MVEBU_PM_SB_SRAM_LKG_PD_EN
);
/* Enable SB Power Off */
mmio_setbits_32
(
MVEBU_PM_SB_PWR_OPTION_REG
,
MVEBU_PM_SB_VDDV_OFF_EN
);
/* Kick off South Bridge Power Off */
mmio_setbits_32
(
MVEBU_PM_SB_CPU_PWR_CTRL_REG
,
MVEBU_PM_SB_PM_START
);
}
static
void
a3700_set_pwr_off_option
(
void
)
{
/* Set general power off option */
a3700_set_gen_pwr_off_option
();
/* Enable DDR self refresh in low power mode */
a3700_en_ddr_self_refresh
();
/* Power down AVS */
a3700_pwr_dn_avs
();
/* Power down TBG */
a3700_pwr_dn_tbg
();
/* Power down south bridge, pay attention south bridge setting
* should be done before
*/
a3700_pwr_dn_sb
();
}
static
void
a3700_set_wake_up_option
(
void
)
{
/*
* Enable the wakeup event for NB SOC => north-bridge
* state-machine enablement on wake-up event
*/
mmio_setbits_32
(
MVEBU_PM_NB_WAKE_UP_EN_REG
,
MVEBU_PM_NB_WKP_EN
);
/* Enable both core0 and core1 wakeup on demand */
mmio_setbits_32
(
MVEBU_PM_CPU_WAKE_UP_CONF_REG
,
MVEBU_PM_CORE1_WAKEUP
|
MVEBU_PM_CORE0_WAKEUP
);
/* Enable warm reset in low power mode */
mmio_setbits_32
(
MVEBU_PM_NB_PWR_OPTION_REG
,
MVEBU_PM_WARM_RESET_EN
);
}
static
void
a3700_pm_en_nb_gpio
(
uint32_t
gpio
)
{
/* For GPIO1 interrupt -- North bridge only */
if
(
gpio
>=
32
)
{
/* GPIO int mask */
mmio_clrbits_32
(
MVEBU_NB_GPIO_IRQ_MASK_2_REG
,
BIT
(
gpio
-
32
));
/* NB_CPU_WAKE-up ENABLE GPIO int */
mmio_setbits_32
(
MVEBU_NB_GPIO_IRQ_EN_HIGH_REG
,
BIT
(
gpio
-
32
));
}
else
{
/* GPIO int mask */
mmio_clrbits_32
(
MVEBU_NB_GPIO_IRQ_MASK_1_REG
,
BIT
(
gpio
));
/* NB_CPU_WAKE-up ENABLE GPIO int */
mmio_setbits_32
(
MVEBU_NB_GPIO_IRQ_EN_LOW_REG
,
BIT
(
gpio
));
}
mmio_setbits_32
(
MVEBU_NB_STEP_DOWN_INT_EN_REG
,
MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK
);
/* Enable using GPIO as wakeup event
* (actually not only for north bridge)
*/
mmio_setbits_32
(
MVEBU_PM_NB_WAKE_UP_EN_REG
,
MVEBU_PM_NB_GPIO_WKP_EN
|
MVEBU_PM_NB_WKP_EN
|
MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN
|
MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN
);
}
static
void
a3700_pm_en_sb_gpio
(
uint32_t
gpio
)
{
/* Enable using GPIO as wakeup event */
mmio_setbits_32
(
MVEBU_PM_NB_WAKE_UP_EN_REG
,
MVEBU_PM_SB_WKP_NB_EN
|
MVEBU_PM_NB_WKP_EN
|
MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN
|
MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN
);
/* SB GPIO Wake UP | South Bridge Wake Up Enable */
mmio_setbits_32
(
MVEBU_PM_SB_WK_EN_REG
,
MVEBU_PM_SB_GPIO_WKP_EN
|
MVEBU_PM_SB_GPIO_WKP_EN
);
/* GPIO int mask */
mmio_clrbits_32
(
MVEBU_SB_GPIO_IRQ_MASK_REG
,
BIT
(
gpio
));
/* NB_CPU_WAKE-up ENABLE GPIO int */
mmio_setbits_32
(
MVEBU_SB_GPIO_IRQ_EN_REG
,
BIT
(
gpio
));
}
int
a3700_pm_src_gpio
(
union
pm_wake_up_src_data
*
src_data
)
{
if
(
src_data
->
gpio_data
.
bank_num
==
0
)
/* North Bridge GPIO */
a3700_pm_en_nb_gpio
(
src_data
->
gpio_data
.
gpio_num
);
else
a3700_pm_en_sb_gpio
(
src_data
->
gpio_data
.
gpio_num
);
return
0
;
}
int
a3700_pm_src_uart1
(
union
pm_wake_up_src_data
*
src_data
)
{
/* Clear Uart1 select */
mmio_clrbits_32
(
MVEBU_NB_GPIO1_SEL_REG
,
MVEBU_NB_GPIO1_UART1_SEL
);
/* set pin 19 gpio usage*/
mmio_setbits_32
(
MVEBU_NB_GPIO1_SEL_REG
,
MVEBU_NB_GPIO1_GPIO_19_EN
);
/* Enable gpio wake-up*/
a3700_pm_en_nb_gpio
(
MVEBU_NB_GPIO_19
);
/* set pin 18 gpio usage*/
mmio_setbits_32
(
MVEBU_NB_GPIO1_SEL_REG
,
MVEBU_NB_GPIO1_GPIO_18_EN
);
/* Enable gpio wake-up*/
a3700_pm_en_nb_gpio
(
MVEBU_NB_GPIO_18
);
return
0
;
}
int
a3700_pm_src_uart0
(
union
pm_wake_up_src_data
*
src_data
)
{
/* set pin 25/26 gpio usage*/
mmio_setbits_32
(
MVEBU_NB_GPIO1_SEL_REG
,
MVEBU_NB_GPIO1_GPIO_25_26_EN
);
/* Enable gpio wake-up*/
a3700_pm_en_nb_gpio
(
MVEBU_NB_GPIO_25
);
/* Enable gpio wake-up*/
a3700_pm_en_nb_gpio
(
MVEBU_NB_GPIO_26
);
return
0
;
}
struct
wake_up_src_func_map
src_func_table
[
WAKE_UP_SRC_MAX
]
=
{
{
WAKE_UP_SRC_GPIO
,
a3700_pm_src_gpio
},
{
WAKE_UP_SRC_UART1
,
a3700_pm_src_uart1
},
{
WAKE_UP_SRC_UART0
,
a3700_pm_src_uart0
},
/* FOLLOWING SRC NOT SUPPORTED YET */
{
WAKE_UP_SRC_TIMER
,
NULL
}
};
static
wake_up_src_func
a3700_get_wake_up_src_func
(
enum
pm_wake_up_src_type
type
)
{
uint32_t
loop
;
for
(
loop
=
0
;
loop
<
WAKE_UP_SRC_MAX
;
loop
++
)
{
if
(
src_func_table
[
loop
].
type
==
type
)
return
src_func_table
[
loop
].
func
;
}
return
NULL
;
}
static
void
a3700_set_wake_up_source
(
void
)
{
struct
pm_wake_up_src_config
*
wake_up_src
;
uint32_t
loop
;
wake_up_src_func
src_func
=
NULL
;
wake_up_src
=
mv_wake_up_src_config_get
();
for
(
loop
=
0
;
loop
<
wake_up_src
->
wake_up_src_num
;
loop
++
)
{
src_func
=
a3700_get_wake_up_src_func
(
wake_up_src
->
wake_up_src
[
loop
].
wake_up_src_type
);
if
(
src_func
)
src_func
(
&
(
wake_up_src
->
wake_up_src
[
loop
].
wake_up_data
));
}
}
static
void
a3700_pm_save_lp_flag
(
void
)
{
/* Save the flag for enter the low power mode */
mmio_setbits_32
(
MVEBU_PM_CPU_VDD_OFF_INFO_2_REG
,
MVEBU_PM_LOW_POWER_STATE
);
}
static
void
a3700_pm_clear_lp_flag
(
void
)
{
/* Clear the flag for enter the low power mode */
mmio_clrbits_32
(
MVEBU_PM_CPU_VDD_OFF_INFO_2_REG
,
MVEBU_PM_LOW_POWER_STATE
);
}
static
uint32_t
a3700_pm_get_lp_flag
(
void
)
{
/* Get the flag for enter the low power mode */
return
mmio_read_32
(
MVEBU_PM_CPU_VDD_OFF_INFO_2_REG
)
&
MVEBU_PM_LOW_POWER_STATE
;
}
/*****************************************************************************
* A3700 handler called when a power domain is about to be suspended. The
* target_state encodes the power state that each level should transition to.
*****************************************************************************
*/
void
a3700_pwr_domain_suspend
(
const
psci_power_state_t
*
target_state
)
{
/* Prevent interrupts from spuriously waking up this cpu */
plat_marvell_gic_cpuif_disable
();
/* Save IRQ states */
plat_marvell_gic_irq_save
();
/* Set wake up options */
a3700_set_wake_up_option
();
/* Set wake up sources */
a3700_set_wake_up_source
();
/* SoC can not be powered down with pending IRQ,
* acknowledge all the pending IRQ
*/
a3700_pm_ack_irq
();
/* Set power off options */
a3700_set_pwr_off_option
();
/* Save the flag for enter the low power mode */
a3700_pm_save_lp_flag
();
isb
();
}
/*****************************************************************************
* A3700 handler called when a power domain has just been powered on after
* being turned off earlier. The target_state encodes the low power state that
* each level has woken up from.
*****************************************************************************
*/
void
a3700_pwr_domain_on_finish
(
const
psci_power_state_t
*
target_state
)
{
/* arch specific configuration */
marvell_psci_arch_init
(
0
);
/* Per-CPU interrupt initialization */
plat_marvell_gic_pcpu_init
();
plat_marvell_gic_cpuif_enable
();
/* Restore the per-cpu IRQ state */
if
(
a3700_pm_get_lp_flag
())
plat_marvell_gic_irq_pcpu_restore
();
}
/*****************************************************************************
* A3700 handler called when a power domain has just been powered on after
* having been suspended earlier. The target_state encodes the low power state
* that each level has woken up from.
* TODO: At the moment we reuse the on finisher and reinitialize the secure
* context. Need to implement a separate suspend finisher.
*****************************************************************************
*/
void
a3700_pwr_domain_suspend_finish
(
const
psci_power_state_t
*
target_state
)
{
struct
dec_win_config
*
io_dec_map
;
uint32_t
dec_win_num
;
struct
dram_win_map
dram_wins_map
;
/* arch specific configuration */
marvell_psci_arch_init
(
0
);
/* Interrupt initialization */
plat_marvell_gic_init
();
/* Restore IRQ states */
plat_marvell_gic_irq_restore
();
/*
* Initialize CCI for this cluster after resume from suspend state.
* No need for locks as no other CPU is active.
*/
plat_marvell_interconnect_init
();
/*
* Enable CCI coherency for the primary CPU's cluster.
* Platform specific PSCI code will enable coherency for other
* clusters.
*/
plat_marvell_interconnect_enter_coherency
();
/* CPU address decoder windows initialization. */
cpu_wins_init
();
/* fetch CPU-DRAM window mapping information by reading
* CPU-DRAM decode windows (only the enabled ones)
*/
dram_win_map_build
(
&
dram_wins_map
);
/* Get IO address decoder windows */
if
(
marvell_get_io_dec_win_conf
(
&
io_dec_map
,
&
dec_win_num
))
{
printf
(
"No IO address decoder windows configurations found!
\n
"
);
return
;
}
/* IO address decoder init */
if
(
init_io_addr_dec
(
&
dram_wins_map
,
io_dec_map
,
dec_win_num
))
{
printf
(
"IO address decoder windows initialization failed!
\n
"
);
return
;
}
/* Clear low power mode flag */
a3700_pm_clear_lp_flag
();
}
/*****************************************************************************
* This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND
* call to get the `power_state` parameter. This allows the platform to encode
* the appropriate State-ID field within the `power_state` parameter which can
* be utilized in `pwr_domain_suspend()` to suspend to system affinity level.
*****************************************************************************
*/
void
a3700_get_sys_suspend_power_state
(
psci_power_state_t
*
req_state
)
{
/* lower affinities use PLAT_MAX_OFF_STATE */
for
(
int
i
=
MPIDR_AFFLVL0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
req_state
->
pwr_domain_state
[
i
]
=
PLAT_MAX_OFF_STATE
;
}
/*****************************************************************************
* A3700 handlers to shutdown/reboot the system
*****************************************************************************
*/
static
void
__dead2
a3700_system_off
(
void
)
{
ERROR
(
"%s needs to be implemented
\n
"
,
__func__
);
panic
();
}
/*****************************************************************************
* A3700 handlers to reset the system
*****************************************************************************
*/
static
void
__dead2
a3700_system_reset
(
void
)
{
/* Clean the mailbox magic number to let it as act like cold boot */
mmio_write_32
(
PLAT_MARVELL_MAILBOX_BASE
,
0x0
);
dsbsy
();
/* Flush data cache if the mail box shared RAM is cached */
#if PLAT_MARVELL_SHARED_RAM_CACHED
flush_dcache_range
((
uintptr_t
)
PLAT_MARVELL_MAILBOX_BASE
,
2
*
sizeof
(
uint64_t
));
#endif
/* Trigger the warm reset */
mmio_write_32
(
MVEBU_WARM_RESET_REG
,
MVEBU_WARM_RESET_MAGIC
);
/* Shouldn't get to this point */
panic
();
}
/*****************************************************************************
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
* platform layer will take care of registering the handlers with PSCI.
*****************************************************************************
*/
const
plat_psci_ops_t
plat_arm_psci_pm_ops
=
{
.
cpu_standby
=
a3700_cpu_standby
,
.
pwr_domain_on
=
a3700_pwr_domain_on
,
.
pwr_domain_off
=
a3700_pwr_domain_off
,
.
pwr_domain_suspend
=
a3700_pwr_domain_suspend
,
.
pwr_domain_on_finish
=
a3700_pwr_domain_on_finish
,
.
pwr_domain_suspend_finish
=
a3700_pwr_domain_suspend_finish
,
.
get_sys_suspend_power_state
=
a3700_get_sys_suspend_power_state
,
.
system_off
=
a3700_system_off
,
.
system_reset
=
a3700_system_reset
,
.
validate_power_state
=
a3700_validate_power_state
,
.
validate_ns_entrypoint
=
a3700_validate_ns_entrypoint
};
plat/marvell/a8k/a70x0/platform.mk
View file @
eb47f14d
...
...
@@ -7,6 +7,9 @@
PCI_EP_SUPPORT
:=
0
CP_NUM
:=
1
$(eval
$(call
add_define,CP_NUM))
DOIMAGE_SEC
:=
tools/doimage/secure/sec_img_7K.cfg
MARVELL_MOCHI_DRV
:=
drivers/marvell/mochi/apn806_setup.c
...
...
plat/marvell/a8k/a70x0_amc/platform.mk
View file @
eb47f14d
...
...
@@ -7,6 +7,9 @@
PCI_EP_SUPPORT
:=
0
CP_NUM
:=
1
$(eval
$(call
add_define,CP_NUM))
DOIMAGE_SEC
:=
tools/doimage/secure/sec_img_7K.cfg
MARVELL_MOCHI_DRV
:=
drivers/marvell/mochi/apn806_setup.c
...
...
Prev
1
2
3
Next
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