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
5d787dd9
Commit
5d787dd9
authored
Apr 08, 2016
by
danh-arm
Browse files
Merge pull request #569 from Xilinx/zynqmp-v1
Support for Xilinx Zynq UltraScale+ MPSoC
parents
af984eef
498256ed
Changes
29
Show whitespace changes
Inline
Side-by-side
acknowledgements.md
View file @
5d787dd9
...
...
@@ -7,5 +7,7 @@ Linaro Limited
NVIDIA Corporation
Xilinx, Inc.
Individuals
-----------
docs/plat/xilinx-zynqmp.md
0 → 100644
View file @
5d787dd9
ARM Trusted Firmware for Xilinx Zynq UltraScale+ MPSoC
================================
ARM Trusted Firmware implements the EL3 firmware layer for Xilinx Zynq
UltraScale + MPSoC.
The platform only uses the runtime part of ATF as ZynqMP already has a
BootROM (BL1) and FSBL (BL2).
BL31 is ATF.
BL32 is an optional Secure Payload.
BL33 is the non-secure world software (U-Boot, Linux etc).
To build:
```
bash
make
ERROR_DEPRECATED
=
1
RESET_TO_BL31
=
1
CROSS_COMPILE
=
aarch64-none-elf-
PLAT
=
zynqmp bl31
```
To build bl32 TSP you have to rebuild bl31 too:
```
bash
make
ERROR_DEPRECATED
=
1
RESET_TO_BL31
=
1
CROSS_COMPILE
=
aarch64-none-elf-
PLAT
=
zynqmp
SPD
=
tspd bl31 bl32
```
# ZynqMP platform specific build options
*
`ZYNQMP_ATF_LOCATION`
: Specifies the location of the bl31 binary. Options:
-
`tsram`
: bl31 will be located in OCM (default)
-
`tdram`
: bl31 will be located in DRAM (address: 0x30000000)
*
`ZYNQMP_TSP_RAM_LOCATION`
: Specifies the location of the bl32 binary and
secure payload dispatcher. Options:
-
`tsram`
: bl32/spd will be located in OCM (default)
-
`tdram`
: bl32/spd will be located in DRAM (address: 0x30000000)
# Power Domain Tree
The following power domain tree represents the power domain model used by the
ATF for ZynqMP:
```
+-+
|0|
+-+
+-------+---+---+-------+
| | | |
| | | |
v v v v
+-+ +-+ +-+ +-+
|0| |1| |2| |3|
+-+ +-+ +-+ +-+
```
The 4 leaf power domains represent the individual A53 cores, while resources
common to the cluster are grouped in the power domain on the top.
drivers/cadence/uart/cdns_console.S
0 → 100644
View file @
5d787dd9
/*
*
Copyright
(
c
)
2016
,
ARM
Limited
and
Contributors
.
All
rights
reserved
.
*
*
Redistribution
and
use
in
source
and
binary
forms
,
with
or
without
*
modification
,
are
permitted
provided
that
the
following
conditions
are
met
:
*
*
Redistributions
of
source
code
must
retain
the
above
copyright
notice
,
this
*
list
of
conditions
and
the
following
disclaimer
.
*
*
Redistributions
in
binary
form
must
reproduce
the
above
copyright
notice
,
*
this
list
of
conditions
and
the
following
disclaimer
in
the
documentation
*
and
/
or
other
materials
provided
with
the
distribution
.
*
*
Neither
the
name
of
ARM
nor
the
names
of
its
contributors
may
be
used
*
to
endorse
or
promote
products
derived
from
this
software
without
specific
*
prior
written
permission
.
*
*
THIS
SOFTWARE
IS
PROVIDED
BY
THE
COPYRIGHT
HOLDERS
AND
CONTRIBUTORS
"AS IS"
*
AND
ANY
EXPRESS
OR
IMPLIED
WARRANTIES
,
INCLUDING
,
BUT
NOT
LIMITED
TO
,
THE
*
IMPLIED
WARRANTIES
OF
MERCHANTABILITY
AND
FITNESS
FOR
A
PARTICULAR
PURPOSE
*
ARE
DISCLAIMED
.
IN
NO
EVENT
SHALL
THE
COPYRIGHT
HOLDER
OR
CONTRIBUTORS
BE
*
LIABLE
FOR
ANY
DIRECT
,
INDIRECT
,
INCIDENTAL
,
SPECIAL
,
EXEMPLARY
,
OR
*
CONSEQUENTIAL
DAMAGES
(
INCLUDING
,
BUT
NOT
LIMITED
TO
,
PROCUREMENT
OF
*
SUBSTITUTE
GOODS
OR
SERVICES
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
*
INTERRUPTION
)
HOWEVER
CAUSED
AND
ON
ANY
THEORY
OF
LIABILITY
,
WHETHER
IN
*
CONTRACT
,
STRICT
LIABILITY
,
OR
TORT
(
INCLUDING
NEGLIGENCE
OR
OTHERWISE
)
*
ARISING
IN
ANY
WAY
OUT
OF
THE
USE
OF
THIS
SOFTWARE
,
EVEN
IF
ADVISED
OF
THE
*
POSSIBILITY
OF
SUCH
DAMAGE
.
*/
#include <arch.h>
#include <asm_macros.S>
#include <cadence/cdns_uart.h>
.
globl
console_core_init
.
globl
console_core_putc
.
globl
console_core_getc
/
*
-----------------------------------------------
*
int
console_core_init
(
unsigned
long
base_addr
,
*
unsigned
int
uart_clk
,
unsigned
int
baud_rate
)
*
Function
to
initialize
the
console
without
a
*
C
Runtime
to
print
debug
information
.
This
*
function
will
be
accessed
by
console_init
and
*
crash
reporting
.
*
We
assume
that
the
bootloader
already
set
up
*
the
HW
(
baud
,
...
)
and
only
enable
the
trans
-
*
mitter
and
receiver
here
.
*
In
:
x0
-
console
base
address
*
w1
-
Uart
clock
in
Hz
*
w2
-
Baud
rate
*
Out
:
return
1
on
success
else
0
on
error
*
Clobber
list
:
x1
,
x2
,
x3
*
-----------------------------------------------
*/
func
console_core_init
/
*
Check
the
input
base
address
*/
cbz
x0
,
core_init_fail
/
*
Check
baud
rate
and
uart
clock
for
sanity
*/
cbz
w1
,
core_init_fail
cbz
w2
,
core_init_fail
/
*
RX
/
TX
enabled
&
reset
*/
mov
w3
,
#(
R_UART_CR_TX_EN
| R_UART_CR_RX_EN |
R_UART_CR_TXRST
|
R_UART_CR_RXRST
)
str
w3
,
[
x0
,
#
R_UART_CR
]
mov
w0
,
#
1
ret
core_init_fail
:
mov
w0
,
wzr
ret
endfunc
console_core_init
/
*
--------------------------------------------------------
*
int
console_core_putc
(
int
c
,
unsigned
long
base_addr
)
*
Function
to
output
a
character
over
the
console
.
It
*
returns
the
character
printed
on
success
or
-
1
on
error
.
*
In
:
w0
-
character
to
be
printed
*
x1
-
console
base
address
*
Out
:
return
-
1
on
error
else
return
character
.
*
Clobber
list
:
x2
*
--------------------------------------------------------
*/
func
console_core_putc
/
*
Check
the
input
parameter
*/
cbz
x1
,
putc_error
/
*
Prepend
'\r'
to
'\n'
*/
cmp
w0
,
#
0xA
b.ne
2
f
1
:
/
*
Check
if
the
transmit
FIFO
is
full
*/
ldr
w2
,
[
x1
,
#
R_UART_SR
]
tbnz
w2
,
#
UART_SR_INTR_TFUL_BIT
,
1
b
mov
w2
,
#
0xD
str
w2
,
[
x1
,
#
R_UART_TX
]
2
:
/
*
Check
if
the
transmit
FIFO
is
full
*/
ldr
w2
,
[
x1
,
#
R_UART_SR
]
tbnz
w2
,
#
UART_SR_INTR_TFUL_BIT
,
2
b
str
w0
,
[
x1
,
#
R_UART_TX
]
ret
putc_error
:
mov
w0
,
#-
1
ret
endfunc
console_core_putc
/
*
---------------------------------------------
*
int
console_core_getc
(
unsigned
long
base_addr
)
*
Function
to
get
a
character
from
the
console
.
*
It
returns
the
character
grabbed
on
success
*
or
-
1
on
error
.
*
In
:
x0
-
console
base
address
*
Clobber
list
:
x0
,
x1
*
---------------------------------------------
*/
func
console_core_getc
cbz
x0
,
getc_error
1
:
/
*
Check
if
the
receive
FIFO
is
empty
*/
ldr
w1
,
[
x0
,
#
R_UART_SR
]
tbnz
w1
,
#
UART_SR_INTR_REMPTY_BIT
,
1
b
ldr
w1
,
[
x0
,
#
R_UART_RX
]
mov
w0
,
w1
ret
getc_error
:
mov
w0
,
#-
1
ret
endfunc
console_core_getc
include/drivers/cadence/cdns_uart.h
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __CADENCE_UART_H__
#define __CADENCE_UART_H__
/* This is very minimalistic and will only work in QEMU. */
/* CADENCE Registers */
#define R_UART_CR 0
#define R_UART_CR_RXRST (1 << 0)
/* RX logic reset */
#define R_UART_CR_TXRST (1 << 1)
/* TX logic reset */
#define R_UART_CR_RX_EN (1 << 2)
/* RX enabled */
#define R_UART_CR_TX_EN (1 << 4)
/* TX enabled */
#define R_UART_SR 0x2C
#define UART_SR_INTR_REMPTY_BIT 1
#define UART_SR_INTR_TFUL_BIT 4
#define R_UART_TX 0x30
#define R_UART_RX 0x30
#endif
plat/arm/common/aarch64/arm_common.c
View file @
5d787dd9
...
...
@@ -137,6 +137,7 @@ uint32_t arm_get_spsr_for_bl33_entry(void)
/*******************************************************************************
* Configures access to the system counter timer module.
******************************************************************************/
#ifdef ARM_SYS_TIMCTL_BASE
void
arm_configure_sys_timer
(
void
)
{
unsigned
int
reg_val
;
...
...
@@ -151,6 +152,7 @@ void arm_configure_sys_timer(void)
reg_val
=
(
1
<<
CNTNSAR_NS_SHIFT
(
PLAT_ARM_NSTIMER_FRAME_ID
));
mmio_write_32
(
ARM_SYS_TIMCTL_BASE
+
CNTNSAR
,
reg_val
);
}
#endif
/* ARM_SYS_TIMCTL_BASE */
/*******************************************************************************
* Returns ARM platform specific memory map regions.
...
...
plat/xilinx/zynqmp/aarch64/zynqmp_common.c
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch_helpers.h>
#include <cci.h>
#include <debug.h>
#include <gicv2.h>
#include <mmio.h>
#include <plat_arm.h>
#include <platform.h>
#include <xlat_tables.h>
#include "../zynqmp_private.h"
/*
* Table of regions to map using the MMU.
* This doesn't include TZRAM as the 'mem_layout' argument passed to
* configure_mmu_elx() will give the available subset of that,
*/
const
mmap_region_t
plat_arm_mmap
[]
=
{
{
DEVICE0_BASE
,
DEVICE0_BASE
,
DEVICE0_SIZE
,
MT_DEVICE
|
MT_RW
|
MT_SECURE
},
{
DEVICE1_BASE
,
DEVICE1_BASE
,
DEVICE1_SIZE
,
MT_DEVICE
|
MT_RW
|
MT_SECURE
},
{
CRF_APB_BASE
,
CRF_APB_BASE
,
CRF_APB_SIZE
,
MT_DEVICE
|
MT_RW
|
MT_SECURE
},
{
0
}
};
static
unsigned
int
zynqmp_get_silicon_ver
(
void
)
{
unsigned
int
ver
;
ver
=
mmio_read_32
(
ZYNQMP_CSU_BASEADDR
+
ZYNQMP_CSU_VERSION_OFFSET
);
ver
&=
ZYNQMP_SILICON_VER_MASK
;
ver
>>=
ZYNQMP_SILICON_VER_SHIFT
;
return
ver
;
}
unsigned
int
zynqmp_get_uart_clk
(
void
)
{
unsigned
int
ver
=
zynqmp_get_silicon_ver
();
switch
(
ver
)
{
case
ZYNQMP_CSU_VERSION_VELOCE
:
return
48000
;
case
ZYNQMP_CSU_VERSION_EP108
:
return
25000000
;
case
ZYNQMP_CSU_VERSION_QEMU
:
return
133000000
;
}
return
100000000
;
}
static
unsigned
int
zynqmp_get_system_timer_freq
(
void
)
{
unsigned
int
ver
=
zynqmp_get_silicon_ver
();
switch
(
ver
)
{
case
ZYNQMP_CSU_VERSION_VELOCE
:
return
10000
;
case
ZYNQMP_CSU_VERSION_EP108
:
return
4000000
;
case
ZYNQMP_CSU_VERSION_QEMU
:
return
50000000
;
}
return
100000000
;
}
#if LOG_LEVEL >= LOG_LEVEL_NOTICE
static
const
struct
{
unsigned
int
id
;
char
*
name
;
}
zynqmp_devices
[]
=
{
{
.
id
=
0x10
,
.
name
=
"3EG"
,
},
{
.
id
=
0x11
,
.
name
=
"2EG"
,
},
{
.
id
=
0x20
,
.
name
=
"5EV"
,
},
{
.
id
=
0x21
,
.
name
=
"4EV"
,
},
{
.
id
=
0x30
,
.
name
=
"7EV"
,
},
{
.
id
=
0x38
,
.
name
=
"9EG"
,
},
{
.
id
=
0x39
,
.
name
=
"6EG"
,
},
{
.
id
=
0x40
,
.
name
=
"11EG"
,
},
{
.
id
=
0x50
,
.
name
=
"15EG"
,
},
{
.
id
=
0x58
,
.
name
=
"19EG"
,
},
{
.
id
=
0x59
,
.
name
=
"17EG"
,
},
};
static
unsigned
int
zynqmp_get_silicon_id
(
void
)
{
uint32_t
id
;
id
=
mmio_read_32
(
ZYNQMP_CSU_BASEADDR
+
ZYNQMP_CSU_IDCODE_OFFSET
);
id
&=
ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK
|
ZYNQMP_CSU_IDCODE_SVD_MASK
;
id
>>=
ZYNQMP_CSU_IDCODE_SVD_SHIFT
;
return
id
;
}
static
char
*
zynqmp_get_silicon_idcode_name
(
void
)
{
unsigned
int
id
;
id
=
zynqmp_get_silicon_id
();
for
(
size_t
i
=
0
;
i
<
ARRAY_SIZE
(
zynqmp_devices
);
i
++
)
{
if
(
zynqmp_devices
[
i
].
id
==
id
)
return
zynqmp_devices
[
i
].
name
;
}
return
"UNKN"
;
}
static
unsigned
int
zynqmp_get_rtl_ver
(
void
)
{
uint32_t
ver
;
ver
=
mmio_read_32
(
ZYNQMP_CSU_BASEADDR
+
ZYNQMP_CSU_VERSION_OFFSET
);
ver
&=
ZYNQMP_RTL_VER_MASK
;
ver
>>=
ZYNQMP_RTL_VER_SHIFT
;
return
ver
;
}
static
char
*
zynqmp_print_silicon_idcode
(
void
)
{
uint32_t
id
,
maskid
,
tmp
;
id
=
mmio_read_32
(
ZYNQMP_CSU_BASEADDR
+
ZYNQMP_CSU_IDCODE_OFFSET
);
tmp
=
id
;
tmp
&=
ZYNQMP_CSU_IDCODE_XILINX_ID_MASK
|
ZYNQMP_CSU_IDCODE_FAMILY_MASK
|
ZYNQMP_CSU_IDCODE_REVISION_MASK
;
maskid
=
ZYNQMP_CSU_IDCODE_XILINX_ID
<<
ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT
|
ZYNQMP_CSU_IDCODE_FAMILY
<<
ZYNQMP_CSU_IDCODE_FAMILY_SHIFT
|
ZYNQMP_CSU_IDCODE_REVISION
<<
ZYNQMP_CSU_IDCODE_REVISION_SHIFT
;
if
(
tmp
!=
maskid
)
{
ERROR
(
"Incorrect XILINX IDCODE 0x%x, maskid 0x%x
\n
"
,
id
,
maskid
);
return
"UNKN"
;
}
VERBOSE
(
"Xilinx IDCODE 0x%x
\n
"
,
id
);
return
zynqmp_get_silicon_idcode_name
();
}
static
unsigned
int
zynqmp_get_ps_ver
(
void
)
{
uint32_t
ver
=
mmio_read_32
(
ZYNQMP_CSU_BASEADDR
+
ZYNQMP_CSU_VERSION_OFFSET
);
ver
&=
ZYNQMP_PS_VER_MASK
;
ver
>>=
ZYNQMP_PS_VER_SHIFT
;
return
ver
+
1
;
}
static
void
zynqmp_print_platform_name
(
void
)
{
unsigned
int
ver
=
zynqmp_get_silicon_ver
();
unsigned
int
rtl
=
zynqmp_get_rtl_ver
();
char
*
label
=
"Unknown"
;
switch
(
ver
)
{
case
ZYNQMP_CSU_VERSION_VELOCE
:
label
=
"VELOCE"
;
break
;
case
ZYNQMP_CSU_VERSION_EP108
:
label
=
"EP108"
;
break
;
case
ZYNQMP_CSU_VERSION_QEMU
:
label
=
"QEMU"
;
break
;
case
ZYNQMP_CSU_VERSION_SILICON
:
label
=
"silicon"
;
break
;
}
NOTICE
(
"ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s
\n
"
,
zynqmp_print_silicon_idcode
(),
label
,
zynqmp_get_ps_ver
(),
(
rtl
&
0xf0
)
>>
4
,
rtl
&
0xf
,
BL31_BASE
,
zynqmp_is_pmu_up
()
?
", with PMU firmware"
:
""
);
}
#else
static
inline
void
zynqmp_print_platform_name
(
void
)
{
}
#endif
/*
* Indicator for PMUFW discovery:
* 0 = No FW found
* non-zero = FW is present
*/
static
int
zynqmp_pmufw_present
;
/*
* zynqmp_discover_pmufw - Discover presence of PMUFW
*
* Discover the presence of PMUFW and store it for later run-time queries
* through zynqmp_is_pmu_up.
* NOTE: This discovery method is fragile and will break if:
* - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW
* (be it by error or intentionally)
* - XPPU/XMPU may restrict ATF's access to the PMU address space
*/
static
int
zynqmp_discover_pmufw
(
void
)
{
zynqmp_pmufw_present
=
mmio_read_32
(
PMU_GLOBAL_CNTRL
);
zynqmp_pmufw_present
&=
PMU_GLOBAL_CNTRL_FW_IS_PRESENT
;
return
!!
zynqmp_pmufw_present
;
}
/*
* zynqmp_is_pmu_up - Find if PMU firmware is up and running
*
* Return 0 if firmware is not available, non 0 otherwise
*/
int
zynqmp_is_pmu_up
(
void
)
{
return
zynqmp_pmufw_present
;
}
/*
* A single boot loader stack is expected to work on both the Foundation ZYNQMP
* models and the two flavours of the Base ZYNQMP models (AEMv8 & Cortex). The
* SYS_ID register provides a mechanism for detecting the differences between
* these platforms. This information is stored in a per-BL array to allow the
* code to take the correct path.Per BL platform configuration.
*/
void
zynqmp_config_setup
(
void
)
{
zynqmp_discover_pmufw
();
zynqmp_print_platform_name
();
/* Global timer init - Program time stamp reference clk */
uint32_t
val
=
mmio_read_32
(
CRL_APB_TIMESTAMP_REF_CTRL
);
val
|=
CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT
;
mmio_write_32
(
CRL_APB_TIMESTAMP_REF_CTRL
,
val
);
/* Program freq register in System counter and enable system counter. */
mmio_write_32
(
IOU_SCNTRS_BASEFREQ
,
zynqmp_get_system_timer_freq
());
mmio_write_32
(
IOU_SCNTRS_CONTROL
,
IOU_SCNTRS_CONTROL_EN
);
}
uint64_t
plat_get_syscnt_freq
(
void
)
{
uint64_t
counter_base_frequency
;
/* FIXME: Read the frequency from Frequency modes table */
counter_base_frequency
=
zynqmp_get_system_timer_freq
();
return
counter_base_frequency
;
}
plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
0 → 100644
View file @
5d787dd9
/*
*
Copyright
(
c
)
2013
-
2016
,
ARM
Limited
and
Contributors
.
All
rights
reserved
.
*
*
Redistribution
and
use
in
source
and
binary
forms
,
with
or
without
*
modification
,
are
permitted
provided
that
the
following
conditions
are
met
:
*
*
Redistributions
of
source
code
must
retain
the
above
copyright
notice
,
this
*
list
of
conditions
and
the
following
disclaimer
.
*
*
Redistributions
in
binary
form
must
reproduce
the
above
copyright
notice
,
*
this
list
of
conditions
and
the
following
disclaimer
in
the
documentation
*
and
/
or
other
materials
provided
with
the
distribution
.
*
*
Neither
the
name
of
ARM
nor
the
names
of
its
contributors
may
be
used
*
to
endorse
or
promote
products
derived
from
this
software
without
specific
*
prior
written
permission
.
*
*
THIS
SOFTWARE
IS
PROVIDED
BY
THE
COPYRIGHT
HOLDERS
AND
CONTRIBUTORS
"AS IS"
*
AND
ANY
EXPRESS
OR
IMPLIED
WARRANTIES
,
INCLUDING
,
BUT
NOT
LIMITED
TO
,
THE
*
IMPLIED
WARRANTIES
OF
MERCHANTABILITY
AND
FITNESS
FOR
A
PARTICULAR
PURPOSE
*
ARE
DISCLAIMED
.
IN
NO
EVENT
SHALL
THE
COPYRIGHT
HOLDER
OR
CONTRIBUTORS
BE
*
LIABLE
FOR
ANY
DIRECT
,
INDIRECT
,
INCIDENTAL
,
SPECIAL
,
EXEMPLARY
,
OR
*
CONSEQUENTIAL
DAMAGES
(
INCLUDING
,
BUT
NOT
LIMITED
TO
,
PROCUREMENT
OF
*
SUBSTITUTE
GOODS
OR
SERVICES
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
*
INTERRUPTION
)
HOWEVER
CAUSED
AND
ON
ANY
THEORY
OF
LIABILITY
,
WHETHER
IN
*
CONTRACT
,
STRICT
LIABILITY
,
OR
TORT
(
INCLUDING
NEGLIGENCE
OR
OTHERWISE
)
*
ARISING
IN
ANY
WAY
OUT
OF
THE
USE
OF
THIS
SOFTWARE
,
EVEN
IF
ADVISED
OF
THE
*
POSSIBILITY
OF
SUCH
DAMAGE
.
*/
#include <asm_macros.S>
#include <gicv2.h>
#include <platform_def.h>
.
globl
plat_secondary_cold_boot_setup
.
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
e
.
g
*
mark
the
cpu
's presence, mechanism to place it in a
*
holding
pen
etc
.
*
TODO
:
Should
we
read
the
PSYS
register
to
make
sure
*
that
the
request
has
gone
through
.
*
-----------------------------------------------------
*/
func
plat_secondary_cold_boot_setup
mrs
x0
,
mpidr_el1
/
*
Deactivate
the
gic
cpu
interface
*/
ldr
x1
,
=
BASE_GICC_BASE
mov
w0
,
#(
IRQ_BYP_DIS_GRP1
|
FIQ_BYP_DIS_GRP1
)
orr
w0
,
w0
,
#(
IRQ_BYP_DIS_GRP0
|
FIQ_BYP_DIS_GRP0
)
str
w0
,
[
x1
,
#
GICC_CTLR
]
/
*
*
There
is
no
sane
reason
to
come
out
of
this
wfi
.
This
*
cpu
will
be
powered
on
and
reset
by
the
cpu_on
pm
api
*/
dsb
sy
1
:
bl
plat_panic_handler
endfunc
plat_secondary_cold_boot_setup
func
plat_is_my_cpu_primary
mov
x9
,
x30
bl
plat_my_core_pos
cmp
x0
,
#
ZYNQMP_PRIMARY_CPU
cset
x0
,
eq
ret
x9
endfunc
plat_is_my_cpu_primary
plat/xilinx/zynqmp/bl31_zynqmp_setup.c
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <bl_common.h>
#include <bl31.h>
#include <console.h>
#include <debug.h>
#include <errno.h>
#include <plat_arm.h>
#include <platform.h>
#include "zynqmp_private.h"
/*
* Declarations of linker defined symbols which will help us find the layout
* of trusted SRAM
*/
extern
unsigned
long
__RO_START__
;
extern
unsigned
long
__RO_END__
;
extern
unsigned
long
__COHERENT_RAM_START__
;
extern
unsigned
long
__COHERENT_RAM_END__
;
/*
* The next 2 constants identify the extents of the code & RO data region.
* These addresses are used by the MMU setup code and therefore they must be
* page-aligned. It is the responsibility of the linker script to ensure that
* __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
*/
#define BL31_RO_BASE (unsigned long)(&__RO_START__)
#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
/*
* The next 2 constants identify the extents of the coherent memory region.
* These addresses are used by the MMU setup code and therefore they must be
* page-aligned. It is the responsibility of the linker script to ensure that
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols
* refer to page-aligned addresses.
*/
#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
static
entry_point_info_t
bl32_image_ep_info
;
static
entry_point_info_t
bl33_image_ep_info
;
/*
* Return a pointer to the 'entry_point_info' structure of the next image for
* the security state specified. BL33 corresponds to the non-secure image type
* while BL32 corresponds to the secure image type. A NULL pointer is returned
* if the image does not exist.
*/
entry_point_info_t
*
bl31_plat_get_next_image_ep_info
(
uint32_t
type
)
{
assert
(
sec_state_is_valid
(
type
));
if
(
type
==
NON_SECURE
)
return
&
bl33_image_ep_info
;
return
&
bl32_image_ep_info
;
}
/*
* Perform any BL31 specific platform actions. Here is an opportunity to copy
* parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
* are lost (potentially). This needs to be done before the MMU is initialized
* so that the memory layout can be used while creating page tables.
*/
void
bl31_early_platform_setup
(
bl31_params_t
*
from_bl2
,
void
*
plat_params_from_bl2
)
{
/* Initialize the console to provide early debug support */
console_init
(
ZYNQMP_UART0_BASE
,
zynqmp_get_uart_clk
(),
ZYNQMP_UART_BAUDRATE
);
/* Initialize the platform config for future decision making */
zynqmp_config_setup
();
/* There are no parameters from BL2 if BL31 is a reset vector */
assert
(
from_bl2
==
NULL
);
assert
(
plat_params_from_bl2
==
NULL
);
/*
* Do initial security configuration to allow DRAM/device access. On
* Base ZYNQMP only DRAM security is programmable (via TrustZone), but
* other platforms might have more programmable security devices
* present.
*/
/* Populate entry point information for BL32 and BL33 */
SET_PARAM_HEAD
(
&
bl32_image_ep_info
,
PARAM_EP
,
VERSION_1
,
0
);
SET_SECURITY_STATE
(
bl32_image_ep_info
.
h
.
attr
,
SECURE
);
bl32_image_ep_info
.
pc
=
BL32_BASE
;
bl32_image_ep_info
.
spsr
=
arm_get_spsr_for_bl32_entry
();
NOTICE
(
"BL31: Secure code at 0x%lx
\n
"
,
bl32_image_ep_info
.
pc
);
SET_PARAM_HEAD
(
&
bl33_image_ep_info
,
PARAM_EP
,
VERSION_1
,
0
);
/*
* Tell BL31 where the non-trusted software image
* is located and the entry state information
*/
bl33_image_ep_info
.
pc
=
plat_get_ns_image_entrypoint
();
bl33_image_ep_info
.
spsr
=
SPSR_64
(
MODE_EL2
,
MODE_SP_ELX
,
DISABLE_ALL_EXCEPTIONS
);
SET_SECURITY_STATE
(
bl33_image_ep_info
.
h
.
attr
,
NON_SECURE
);
NOTICE
(
"BL31: Non secure code at 0x%lx
\n
"
,
bl33_image_ep_info
.
pc
);
}
void
bl31_platform_setup
(
void
)
{
/* Initialize the gic cpu and distributor interfaces */
plat_arm_gic_driver_init
();
plat_arm_gic_init
();
}
void
bl31_plat_runtime_setup
(
void
)
{
}
/*
* Perform the very early platform specific architectural setup here. At the
* moment this is only intializes the MMU in a quick and dirty way.
*/
void
bl31_plat_arch_setup
(
void
)
{
plat_arm_interconnect_init
();
plat_arm_interconnect_enter_coherency
();
arm_configure_mmu_el3
(
BL31_RO_BASE
,
BL31_COHERENT_RAM_LIMIT
-
BL31_RO_BASE
,
BL31_RO_BASE
,
BL31_RO_LIMIT
,
BL31_COHERENT_RAM_BASE
,
BL31_COHERENT_RAM_LIMIT
);
}
plat/xilinx/zynqmp/include/plat_macros.S
0 → 100644
View file @
5d787dd9
/*
*
Copyright
(
c
)
2014
-
2016
,
ARM
Limited
and
Contributors
.
All
rights
reserved
.
*
*
Redistribution
and
use
in
source
and
binary
forms
,
with
or
without
*
modification
,
are
permitted
provided
that
the
following
conditions
are
met
:
*
*
Redistributions
of
source
code
must
retain
the
above
copyright
notice
,
this
*
list
of
conditions
and
the
following
disclaimer
.
*
*
Redistributions
in
binary
form
must
reproduce
the
above
copyright
notice
,
*
this
list
of
conditions
and
the
following
disclaimer
in
the
documentation
*
and
/
or
other
materials
provided
with
the
distribution
.
*
*
Neither
the
name
of
ARM
nor
the
names
of
its
contributors
may
be
used
*
to
endorse
or
promote
products
derived
from
this
software
without
specific
*
prior
written
permission
.
*
*
THIS
SOFTWARE
IS
PROVIDED
BY
THE
COPYRIGHT
HOLDERS
AND
CONTRIBUTORS
"AS IS"
*
AND
ANY
EXPRESS
OR
IMPLIED
WARRANTIES
,
INCLUDING
,
BUT
NOT
LIMITED
TO
,
THE
*
IMPLIED
WARRANTIES
OF
MERCHANTABILITY
AND
FITNESS
FOR
A
PARTICULAR
PURPOSE
*
ARE
DISCLAIMED
.
IN
NO
EVENT
SHALL
THE
COPYRIGHT
HOLDER
OR
CONTRIBUTORS
BE
*
LIABLE
FOR
ANY
DIRECT
,
INDIRECT
,
INCIDENTAL
,
SPECIAL
,
EXEMPLARY
,
OR
*
CONSEQUENTIAL
DAMAGES
(
INCLUDING
,
BUT
NOT
LIMITED
TO
,
PROCUREMENT
OF
*
SUBSTITUTE
GOODS
OR
SERVICES
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
*
INTERRUPTION
)
HOWEVER
CAUSED
AND
ON
ANY
THEORY
OF
LIABILITY
,
WHETHER
IN
*
CONTRACT
,
STRICT
LIABILITY
,
OR
TORT
(
INCLUDING
NEGLIGENCE
OR
OTHERWISE
)
*
ARISING
IN
ANY
WAY
OUT
OF
THE
USE
OF
THIS
SOFTWARE
,
EVEN
IF
ADVISED
OF
THE
*
POSSIBILITY
OF
SUCH
DAMAGE
.
*/
#ifndef __PLAT_MACROS_S__
#define __PLAT_MACROS_S__
#include <arm_macros.S>
#include <cci_macros.S>
#include "../zynqmp_def.h"
/
*
---------------------------------------------
*
The
below
required
platform
porting
macro
*
prints
out
relevant
GIC
registers
whenever
an
*
unhandled
exception
is
taken
in
BL31
.
*
Clobbers
:
x0
-
x10
,
x16
,
sp
*
---------------------------------------------
*/
.
macro
plat_print_gic_regs
mov_imm
x17
,
BASE_GICC_BASE
mov_imm
x16
,
BASE_GICD_BASE
arm_print_gic_regs
mov
x0
,
x1
.
endm
#endif /* __PLAT_MACROS_S__ */
plat/xilinx/zynqmp/include/platform_def.h
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __PLATFORM_DEF_H__
#define __PLATFORM_DEF_H__
#include <arch.h>
#include "../zynqmp_def.h"
/*******************************************************************************
* Generic platform constants
******************************************************************************/
/* Size of cacheable stacks */
#define PLATFORM_STACK_SIZE 0x440
#define PLATFORM_CORE_COUNT 4
#define PLAT_NUM_POWER_DOMAINS 5
#define PLAT_MAX_PWR_LVL 1
#define PLAT_MAX_RET_STATE 1
#define PLAT_MAX_OFF_STATE 2
/*******************************************************************************
* BL31 specific defines.
******************************************************************************/
#define ZYNQMP_BL31_SIZE 0x1b000
/*
* Put BL31 at the top of the Trusted SRAM (just below the shared memory, if
* present). BL31_BASE is calculated using the current BL31 debug size plus a
* little space for growth.
*/
#if ZYNQMP_ATF_LOCATION_ID == ZYNQMP_IN_TRUSTED_SRAM
# define BL31_BASE (ZYNQMP_TRUSTED_SRAM_LIMIT - \
ZYNQMP_BL31_SIZE)
# define BL31_PROGBITS_LIMIT (ZYNQMP_TRUSTED_SRAM_LIMIT - 0x6000)
# define BL31_LIMIT ZYNQMP_TRUSTED_SRAM_LIMIT
#elif ZYNQMP_ATF_LOCATION_ID == ZYNQMP_IN_TRUSTED_DRAM
# define BL31_BASE (ZYNQMP_TRUSTED_DRAM_LIMIT - \
ZYNQMP_BL31_SIZE)
# define BL31_PROGBITS_LIMIT (ZYNQMP_TRUSTED_DRAM_LIMIT - 0x6000)
# define BL31_LIMIT (ZYNQMP_TRUSTED_DRAM_BASE + \
ZYNQMP_TRUSTED_DRAM_SIZE)
#else
# error "Unsupported ZYNQMP_ATF_LOCATION_ID value"
#endif
/*******************************************************************************
* BL32 specific defines.
******************************************************************************/
/*
* On ZYNQMP, the TSP can execute either from Trusted SRAM or Trusted DRAM.
*/
#if ZYNQMP_TSP_RAM_LOCATION_ID == ZYNQMP_IN_TRUSTED_SRAM
# define TSP_SEC_MEM_BASE ZYNQMP_TRUSTED_SRAM_BASE
# define TSP_SEC_MEM_SIZE ZYNQMP_TRUSTED_SRAM_SIZE
# define TSP_PROGBITS_LIMIT (ZYNQMP_TRUSTED_SRAM_LIMIT - \
ZYNQMP_BL31_SIZE)
# define BL32_BASE ZYNQMP_TRUSTED_SRAM_BASE
# define BL32_LIMIT (ZYNQMP_TRUSTED_SRAM_LIMIT - \
ZYNQMP_BL31_SIZE)
#elif ZYNQMP_TSP_RAM_LOCATION_ID == ZYNQMP_IN_TRUSTED_DRAM
# define TSP_SEC_MEM_BASE ZYNQMP_TRUSTED_DRAM_BASE
# define TSP_SEC_MEM_SIZE (ZYNQMP_TRUSTED_DRAM_LIMIT - \
ZYNQMP_BL31_SIZE)
# define BL32_BASE ZYNQMP_TRUSTED_DRAM_BASE
# define BL32_LIMIT (ZYNQMP_TRUSTED_DRAM_LIMIT - \
ZYNQMP_BL31_SIZE)
#else
# error "Unsupported ZYNQMP_TSP_RAM_LOCATION_ID value"
#endif
/*
* ID of the secure physical generic timer interrupt used by the TSP.
*/
#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER
/*******************************************************************************
* Platform specific page table and MMU setup constants
******************************************************************************/
#define ADDR_SPACE_SIZE (1ull << 32)
#define MAX_XLAT_TABLES 5
#define MAX_MMAP_REGIONS 7
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
#define PLAT_ARM_GICD_BASE BASE_GICD_BASE
#define PLAT_ARM_GICC_BASE BASE_GICC_BASE
/*
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
* terminology. On a GICv2 system or mode, the lists will be merged and treated
* as Group 0 interrupts.
*/
#define PLAT_ARM_G1S_IRQS ARM_IRQ_SEC_PHY_TIMER, \
IRQ_SEC_IPI_APU, \
ARM_IRQ_SEC_SGI_0, \
ARM_IRQ_SEC_SGI_1, \
ARM_IRQ_SEC_SGI_2, \
ARM_IRQ_SEC_SGI_3, \
ARM_IRQ_SEC_SGI_4, \
ARM_IRQ_SEC_SGI_5, \
ARM_IRQ_SEC_SGI_6, \
ARM_IRQ_SEC_SGI_7
#define PLAT_ARM_G0_IRQS
#endif
/* __PLATFORM_DEF_H__ */
plat/xilinx/zynqmp/plat_psci.c
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch_helpers.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <gicv2.h>
#include <mmio.h>
#include <plat_arm.h>
#include <platform.h>
#include <psci.h>
#include "pm_api_sys.h"
#include "pm_client.h"
#include "zynqmp_private.h"
uintptr_t
zynqmp_sec_entry
;
void
zynqmp_cpu_standby
(
plat_local_state_t
cpu_state
)
{
VERBOSE
(
"%s: cpu_state: 0x%x
\n
"
,
__func__
,
cpu_state
);
dsb
();
wfi
();
}
static
int
zynqmp_nopmu_pwr_domain_on
(
u_register_t
mpidr
)
{
uint32_t
r
;
unsigned
int
cpu_id
=
plat_core_pos_by_mpidr
(
mpidr
);
VERBOSE
(
"%s: mpidr: 0x%lx
\n
"
,
__func__
,
mpidr
);
if
(
cpu_id
==
-
1
)
return
PSCI_E_INTERN_FAIL
;
/* program RVBAR */
mmio_write_32
(
APU_RVBAR_L_0
+
(
cpu_id
<<
3
),
zynqmp_sec_entry
);
mmio_write_32
(
APU_RVBAR_H_0
+
(
cpu_id
<<
3
),
zynqmp_sec_entry
>>
32
);
/* clear VINITHI */
r
=
mmio_read_32
(
APU_CONFIG_0
);
r
&=
~
(
1
<<
APU_CONFIG_0_VINITHI_SHIFT
<<
cpu_id
);
mmio_write_32
(
APU_CONFIG_0
,
r
);
/* clear power down request */
r
=
mmio_read_32
(
APU_PWRCTL
);
r
&=
~
(
1
<<
cpu_id
);
mmio_write_32
(
APU_PWRCTL
,
r
);
/* power up island */
mmio_write_32
(
PMU_GLOBAL_REQ_PWRUP_EN
,
1
<<
cpu_id
);
mmio_write_32
(
PMU_GLOBAL_REQ_PWRUP_TRIG
,
1
<<
cpu_id
);
/* FIXME: we should have a way to break out */
while
(
mmio_read_32
(
PMU_GLOBAL_REQ_PWRUP_STATUS
)
&
(
1
<<
cpu_id
))
;
/* release core reset */
r
=
mmio_read_32
(
CRF_APB_RST_FPD_APU
);
r
&=
~
((
CRF_APB_RST_FPD_APU_ACPU_PWRON_RESET
|
CRF_APB_RST_FPD_APU_ACPU_RESET
)
<<
cpu_id
);
mmio_write_32
(
CRF_APB_RST_FPD_APU
,
r
);
return
PSCI_E_SUCCESS
;
}
static
int
zynqmp_pwr_domain_on
(
u_register_t
mpidr
)
{
unsigned
int
cpu_id
=
plat_core_pos_by_mpidr
(
mpidr
);
const
struct
pm_proc
*
proc
;
VERBOSE
(
"%s: mpidr: 0x%lx
\n
"
,
__func__
,
mpidr
);
if
(
cpu_id
==
-
1
)
return
PSCI_E_INTERN_FAIL
;
proc
=
pm_get_proc
(
cpu_id
);
/* Send request to PMU to wake up selected APU CPU core */
pm_req_wakeup
(
proc
->
node_id
,
1
,
zynqmp_sec_entry
,
REQ_ACK_NO
);
return
PSCI_E_SUCCESS
;
}
static
void
zynqmp_nopmu_pwr_domain_off
(
const
psci_power_state_t
*
target_state
)
{
uint32_t
r
;
unsigned
int
cpu_id
=
plat_my_core_pos
();
for
(
size_t
i
=
0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
VERBOSE
(
"%s: target_state->pwr_domain_state[%lu]=%x
\n
"
,
__func__
,
i
,
target_state
->
pwr_domain_state
[
i
]);
/* Prevent interrupts from spuriously waking up this cpu */
gicv2_cpuif_disable
();
/* set power down request */
r
=
mmio_read_32
(
APU_PWRCTL
);
r
|=
(
1
<<
cpu_id
);
mmio_write_32
(
APU_PWRCTL
,
r
);
}
static
void
zynqmp_pwr_domain_off
(
const
psci_power_state_t
*
target_state
)
{
unsigned
int
cpu_id
=
plat_my_core_pos
();
const
struct
pm_proc
*
proc
=
pm_get_proc
(
cpu_id
);
for
(
size_t
i
=
0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
VERBOSE
(
"%s: target_state->pwr_domain_state[%lu]=%x
\n
"
,
__func__
,
i
,
target_state
->
pwr_domain_state
[
i
]);
/* Prevent interrupts from spuriously waking up this cpu */
gicv2_cpuif_disable
();
/*
* Send request to PMU to power down the appropriate APU CPU
* core.
* According to PSCI specification, CPU_off function does not
* have resume address and CPU core can only be woken up
* invoking CPU_on function, during which resume address will
* be set.
*/
pm_self_suspend
(
proc
->
node_id
,
MAX_LATENCY
,
0
,
0
);
}
static
void
zynqmp_nopmu_pwr_domain_suspend
(
const
psci_power_state_t
*
target_state
)
{
uint32_t
r
;
unsigned
int
cpu_id
=
plat_my_core_pos
();
for
(
size_t
i
=
0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
VERBOSE
(
"%s: target_state->pwr_domain_state[%lu]=%x
\n
"
,
__func__
,
i
,
target_state
->
pwr_domain_state
[
i
]);
/* set power down request */
r
=
mmio_read_32
(
APU_PWRCTL
);
r
|=
(
1
<<
cpu_id
);
mmio_write_32
(
APU_PWRCTL
,
r
);
/* program RVBAR */
mmio_write_32
(
APU_RVBAR_L_0
+
(
cpu_id
<<
3
),
zynqmp_sec_entry
);
mmio_write_32
(
APU_RVBAR_H_0
+
(
cpu_id
<<
3
),
zynqmp_sec_entry
>>
32
);
/* clear VINITHI */
r
=
mmio_read_32
(
APU_CONFIG_0
);
r
&=
~
(
1
<<
APU_CONFIG_0_VINITHI_SHIFT
<<
cpu_id
);
mmio_write_32
(
APU_CONFIG_0
,
r
);
/* enable power up on IRQ */
mmio_write_32
(
PMU_GLOBAL_REQ_PWRUP_EN
,
1
<<
cpu_id
);
}
static
void
zynqmp_pwr_domain_suspend
(
const
psci_power_state_t
*
target_state
)
{
unsigned
int
cpu_id
=
plat_my_core_pos
();
const
struct
pm_proc
*
proc
=
pm_get_proc
(
cpu_id
);
for
(
size_t
i
=
0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
VERBOSE
(
"%s: target_state->pwr_domain_state[%lu]=%x
\n
"
,
__func__
,
i
,
target_state
->
pwr_domain_state
[
i
]);
/* Send request to PMU to suspend this core */
pm_self_suspend
(
proc
->
node_id
,
MAX_LATENCY
,
0
,
zynqmp_sec_entry
);
/* APU is to be turned off */
if
(
target_state
->
pwr_domain_state
[
1
]
>
PLAT_MAX_RET_STATE
)
{
/* Power down L2 cache */
pm_set_requirement
(
NODE_L2
,
0
,
0
,
REQ_ACK_NO
);
/* Send request for OCM retention state */
set_ocm_retention
();
/* disable coherency */
plat_arm_interconnect_exit_coherency
();
}
}
static
void
zynqmp_pwr_domain_on_finish
(
const
psci_power_state_t
*
target_state
)
{
for
(
size_t
i
=
0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
VERBOSE
(
"%s: target_state->pwr_domain_state[%lu]=%x
\n
"
,
__func__
,
i
,
target_state
->
pwr_domain_state
[
i
]);
gicv2_cpuif_enable
();
gicv2_pcpu_distif_init
();
}
static
void
zynqmp_nopmu_pwr_domain_suspend_finish
(
const
psci_power_state_t
*
target_state
)
{
uint32_t
r
;
unsigned
int
cpu_id
=
plat_my_core_pos
();
for
(
size_t
i
=
0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
VERBOSE
(
"%s: target_state->pwr_domain_state[%lu]=%x
\n
"
,
__func__
,
i
,
target_state
->
pwr_domain_state
[
i
]);
/* disable power up on IRQ */
mmio_write_32
(
PMU_GLOBAL_REQ_PWRUP_DIS
,
1
<<
cpu_id
);
/* clear powerdown bit */
r
=
mmio_read_32
(
APU_PWRCTL
);
r
&=
~
(
1
<<
cpu_id
);
mmio_write_32
(
APU_PWRCTL
,
r
);
}
static
void
zynqmp_pwr_domain_suspend_finish
(
const
psci_power_state_t
*
target_state
)
{
unsigned
int
cpu_id
=
plat_my_core_pos
();
const
struct
pm_proc
*
proc
=
pm_get_proc
(
cpu_id
);
for
(
size_t
i
=
0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
VERBOSE
(
"%s: target_state->pwr_domain_state[%lu]=%x
\n
"
,
__func__
,
i
,
target_state
->
pwr_domain_state
[
i
]);
/* Clear the APU power control register for this cpu */
pm_client_wakeup
(
proc
);
/* enable coherency */
plat_arm_interconnect_enter_coherency
();
}
/*******************************************************************************
* ZynqMP handlers to shutdown/reboot the system
******************************************************************************/
static
void
__dead2
zynqmp_nopmu_system_off
(
void
)
{
ERROR
(
"ZynqMP System Off: operation not handled.
\n
"
);
/* disable coherency */
plat_arm_interconnect_exit_coherency
();
panic
();
}
static
void
__dead2
zynqmp_system_off
(
void
)
{
/* disable coherency */
plat_arm_interconnect_exit_coherency
();
/* Send the power down request to the PMU */
pm_system_shutdown
(
0
);
while
(
1
)
wfi
();
}
static
void
__dead2
zynqmp_nopmu_system_reset
(
void
)
{
/*
* This currently triggers a system reset. I.e. the whole
* system will be reset! Including RPUs, PMU, PL, etc.
*/
/* disable coherency */
plat_arm_interconnect_exit_coherency
();
/* bypass RPLL (needed on 1.0 silicon) */
uint32_t
reg
=
mmio_read_32
(
CRL_APB_RPLL_CTRL
);
reg
|=
CRL_APB_RPLL_CTRL_BYPASS
;
mmio_write_32
(
CRL_APB_RPLL_CTRL
,
reg
);
/* trigger system reset */
mmio_write_32
(
CRL_APB_RESET_CTRL
,
CRL_APB_RESET_CTRL_SOFT_RESET
);
while
(
1
)
wfi
();
}
static
void
__dead2
zynqmp_system_reset
(
void
)
{
/* disable coherency */
plat_arm_interconnect_exit_coherency
();
/* Send the system reset request to the PMU */
pm_system_shutdown
(
1
);
while
(
1
)
wfi
();
}
int
zynqmp_validate_power_state
(
unsigned
int
power_state
,
psci_power_state_t
*
req_state
)
{
VERBOSE
(
"%s: power_state: 0x%x
\n
"
,
__func__
,
power_state
);
/* FIXME: populate req_state */
return
PSCI_E_SUCCESS
;
}
int
zynqmp_validate_ns_entrypoint
(
unsigned
long
ns_entrypoint
)
{
VERBOSE
(
"%s: ns_entrypoint: 0x%lx
\n
"
,
__func__
,
ns_entrypoint
);
/* FIXME: Actually validate */
return
PSCI_E_SUCCESS
;
}
void
zynqmp_get_sys_suspend_power_state
(
psci_power_state_t
*
req_state
)
{
req_state
->
pwr_domain_state
[
PSCI_CPU_PWR_LVL
]
=
PLAT_MAX_OFF_STATE
;
req_state
->
pwr_domain_state
[
1
]
=
PLAT_MAX_OFF_STATE
;
}
/*******************************************************************************
* Export the platform handlers to enable psci to invoke them
******************************************************************************/
static
const
struct
plat_psci_ops
zynqmp_psci_ops
=
{
.
cpu_standby
=
zynqmp_cpu_standby
,
.
pwr_domain_on
=
zynqmp_pwr_domain_on
,
.
pwr_domain_off
=
zynqmp_pwr_domain_off
,
.
pwr_domain_suspend
=
zynqmp_pwr_domain_suspend
,
.
pwr_domain_on_finish
=
zynqmp_pwr_domain_on_finish
,
.
pwr_domain_suspend_finish
=
zynqmp_pwr_domain_suspend_finish
,
.
system_off
=
zynqmp_system_off
,
.
system_reset
=
zynqmp_system_reset
,
.
validate_power_state
=
zynqmp_validate_power_state
,
.
validate_ns_entrypoint
=
zynqmp_validate_ns_entrypoint
,
.
get_sys_suspend_power_state
=
zynqmp_get_sys_suspend_power_state
,
};
static
const
struct
plat_psci_ops
zynqmp_nopmu_psci_ops
=
{
.
cpu_standby
=
zynqmp_cpu_standby
,
.
pwr_domain_on
=
zynqmp_nopmu_pwr_domain_on
,
.
pwr_domain_off
=
zynqmp_nopmu_pwr_domain_off
,
.
pwr_domain_suspend
=
zynqmp_nopmu_pwr_domain_suspend
,
.
pwr_domain_on_finish
=
zynqmp_pwr_domain_on_finish
,
.
pwr_domain_suspend_finish
=
zynqmp_nopmu_pwr_domain_suspend_finish
,
.
system_off
=
zynqmp_nopmu_system_off
,
.
system_reset
=
zynqmp_nopmu_system_reset
,
.
validate_power_state
=
zynqmp_validate_power_state
,
.
validate_ns_entrypoint
=
zynqmp_validate_ns_entrypoint
,
.
get_sys_suspend_power_state
=
zynqmp_get_sys_suspend_power_state
,
};
/*******************************************************************************
* Export the platform specific power ops.
******************************************************************************/
int
plat_setup_psci_ops
(
uintptr_t
sec_entrypoint
,
const
struct
plat_psci_ops
**
psci_ops
)
{
zynqmp_sec_entry
=
sec_entrypoint
;
if
(
zynqmp_is_pmu_up
())
*
psci_ops
=
&
zynqmp_psci_ops
;
else
*
psci_ops
=
&
zynqmp_nopmu_psci_ops
;
return
0
;
}
plat/xilinx/zynqmp/plat_topology.c
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <platform_def.h>
#include <psci.h>
static
const
unsigned
char
plat_power_domain_tree_desc
[]
=
{
1
,
4
};
const
unsigned
char
*
plat_get_power_domain_tree_desc
(
void
)
{
return
plat_power_domain_tree_desc
;
}
plat/xilinx/zynqmp/plat_zynqmp.c
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <plat_arm.h>
int
plat_core_pos_by_mpidr
(
u_register_t
mpidr
)
{
if
(
mpidr
&
MPIDR_CLUSTER_MASK
)
return
-
1
;
if
((
mpidr
&
MPIDR_CPU_MASK
)
>=
PLATFORM_CORE_COUNT
)
return
-
1
;
return
plat_arm_calc_core_pos
(
mpidr
);
}
plat/xilinx/zynqmp/platform.mk
0 → 100644
View file @
5d787dd9
# Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# Neither the name of ARM nor the names of its contributors may be used
# to endorse or promote products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
ENABLE_PLAT_COMPAT
:=
0
PROGRAMMABLE_RESET_ADDRESS
:=
1
PSCI_EXTENDED_STATE_ID
:=
1
A53_DISABLE_NON_TEMPORAL_HINT
:=
0
ZYNQMP_ATF_LOCATION
?=
tsram
ifeq
(${ZYNQMP_ATF_LOCATION}, tsram)
ZYNQMP_ATF_LOCATION_ID
:=
ZYNQMP_IN_TRUSTED_SRAM
else
ifeq
(${ZYNQMP_ATF_LOCATION}, tdram)
ZYNQMP_ATF_LOCATION_ID
:=
ZYNQMP_IN_TRUSTED_DRAM
else
$(error
"Unsupported ZYNQMP_ATF_LOCATION value"
)
endif
# On ZYNQMP, the TSP can execute either from Trusted SRAM or Trusted DRAM.
# Trusted SRAM is the default.
ZYNQMP_TSP_RAM_LOCATION
?=
tsram
ifeq
(${ZYNQMP_TSP_RAM_LOCATION}, tsram)
ZYNQMP_TSP_RAM_LOCATION_ID
:=
ZYNQMP_IN_TRUSTED_SRAM
else
ifeq
(${ZYNQMP_TSP_RAM_LOCATION}, tdram)
ZYNQMP_TSP_RAM_LOCATION_ID
:=
ZYNQMP_IN_TRUSTED_DRAM
else
$(error
"Unsupported ZYNQMP_TSP_RAM_LOCATION value"
)
endif
# Process flags
$(eval
$(call
add_define,ZYNQMP_ATF_LOCATION_ID))
$(eval
$(call
add_define,ZYNQMP_TSP_RAM_LOCATION_ID))
PLAT_INCLUDES
:=
-Iinclude
/plat/arm/common/
\
-Iinclude
/plat/arm/common/aarch64/
\
-Iplat
/xilinx/zynqmp/include/
\
-Iplat
/xilinx/zynqmp/pm_service/
PLAT_BL_COMMON_SOURCES
:=
lib/aarch64/xlat_tables.c
\
drivers/arm/gic/common/gic_common.c
\
drivers/arm/gic/v2/gicv2_main.c
\
drivers/arm/gic/v2/gicv2_helpers.c
\
drivers/cadence/uart/cdns_console.S
\
drivers/console/console.S
\
plat/arm/common/aarch64/arm_common.c
\
plat/arm/common/aarch64/arm_helpers.S
\
plat/arm/common/arm_cci.c
\
plat/arm/common/arm_gicv2.c
\
plat/common/plat_gicv2.c
\
plat/common/aarch64/plat_common.c
\
plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
\
plat/xilinx/zynqmp/aarch64/zynqmp_common.c
BL31_SOURCES
+=
drivers/arm/cci/cci.c
\
lib/cpus/aarch64/aem_generic.S
\
lib/cpus/aarch64/cortex_a53.S
\
plat/common/aarch64/plat_psci_common.c
\
plat/common/aarch64/platform_mp_stack.S
\
plat/xilinx/zynqmp/bl31_zynqmp_setup.c
\
plat/xilinx/zynqmp/plat_psci.c
\
plat/xilinx/zynqmp/plat_zynqmp.c
\
plat/xilinx/zynqmp/plat_topology.c
\
plat/xilinx/zynqmp/sip_svc_setup.c
\
plat/xilinx/zynqmp/pm_service/pm_svc_main.c
\
plat/xilinx/zynqmp/pm_service/pm_api_sys.c
\
plat/xilinx/zynqmp/pm_service/pm_ipi.c
\
plat/xilinx/zynqmp/pm_service/pm_client.c
ifneq
(${RESET_TO_BL31},1)
$(error
"Using BL31 as the reset vector is only one option supported on ZynqMP. Please set RESET_TO_BL31 to 1."
)
endif
plat/xilinx/zynqmp/pm_service/pm_api_sys.c
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* ZynqMP system level PM-API functions and communication with PMU via
* IPI interrupts
*/
#include <arch_helpers.h>
#include <platform.h>
#include "pm_client.h"
#include "pm_common.h"
#include "pm_api_sys.h"
/**
* Assigning of argument values into array elements.
*/
#define PM_PACK_PAYLOAD1(pl, arg0) { \
pl[0] = (uint32_t)(arg0); \
}
#define PM_PACK_PAYLOAD2(pl, arg0, arg1) { \
pl[1] = (uint32_t)(arg1); \
PM_PACK_PAYLOAD1(pl, arg0); \
}
#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) { \
pl[2] = (uint32_t)(arg2); \
PM_PACK_PAYLOAD2(pl, arg0, arg1); \
}
#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) { \
pl[3] = (uint32_t)(arg3); \
PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2); \
}
#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) { \
pl[4] = (uint32_t)(arg4); \
PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3); \
}
#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) { \
pl[5] = (uint32_t)(arg5); \
PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4); \
}
/**
* pm_self_suspend() - PM call for processor to suspend itself
* @nid Node id of the processor or subsystem
* @latency Requested maximum wakeup latency (not supported)
* @state Requested state (not supported)
* @address Resume address
*
* This is a blocking call, it will return only once PMU has responded.
* On a wakeup, resume address will be automatically set by PMU.
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_self_suspend
(
enum
pm_node_id
nid
,
unsigned
int
latency
,
unsigned
int
state
,
uintptr_t
address
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
unsigned
int
cpuid
=
plat_my_core_pos
();
const
struct
pm_proc
*
proc
=
pm_get_proc
(
cpuid
);
/*
* Do client specific suspend operations
* (e.g. set powerdown request bit)
*/
pm_client_suspend
(
proc
);
/* Send request to the PMU */
PM_PACK_PAYLOAD6
(
payload
,
PM_SELF_SUSPEND
,
proc
->
node_id
,
latency
,
state
,
address
,
(
address
>>
32
));
return
pm_ipi_send_sync
(
proc
,
payload
,
NULL
);
}
/**
* pm_req_suspend() - PM call to request for another PU or subsystem to
* be suspended gracefully.
* @target Node id of the targeted PU or subsystem
* @ack Flag to specify whether acknowledge is requested
* @latency Requested wakeup latency (not supported)
* @state Requested state (not supported)
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_req_suspend
(
enum
pm_node_id
target
,
enum
pm_request_ack
ack
,
unsigned
int
latency
,
unsigned
int
state
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
/* Send request to the PMU */
PM_PACK_PAYLOAD5
(
payload
,
PM_REQ_SUSPEND
,
target
,
ack
,
latency
,
state
);
if
(
ack
==
REQ_ACK_BLOCKING
)
return
pm_ipi_send_sync
(
primary_proc
,
payload
,
NULL
);
else
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_req_wakeup() - PM call for processor to wake up selected processor
* or subsystem
* @target Node id of the processor or subsystem to wake up
* @ack Flag to specify whether acknowledge requested
* @set_address Resume address presence indicator
* 1 resume address specified, 0 otherwise
* @address Resume address
*
* This API function is either used to power up another APU core for SMP
* (by PSCI) or to power up an entirely different PU or subsystem, such
* as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
* automatically set by PMU.
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_req_wakeup
(
enum
pm_node_id
target
,
unsigned
int
set_address
,
uintptr_t
address
,
enum
pm_request_ack
ack
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
uint64_t
encoded_address
;
const
struct
pm_proc
*
proc
=
pm_get_proc_by_node
(
target
);
/* invoke APU-specific code for waking up another APU core */
pm_client_wakeup
(
proc
);
/* encode set Address into 1st bit of address */
encoded_address
=
address
;
encoded_address
|=
!!
set_address
;
/* Send request to the PMU to perform the wake of the PU */
PM_PACK_PAYLOAD5
(
payload
,
PM_REQ_WAKEUP
,
target
,
encoded_address
,
encoded_address
>>
32
,
ack
);
if
(
ack
==
REQ_ACK_BLOCKING
)
return
pm_ipi_send_sync
(
primary_proc
,
payload
,
NULL
);
else
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_force_powerdown() - PM call to request for another PU or subsystem to
* be powered down forcefully
* @target Node id of the targeted PU or subsystem
* @ack Flag to specify whether acknowledge is requested
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_force_powerdown
(
enum
pm_node_id
target
,
enum
pm_request_ack
ack
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
/* Send request to the PMU */
PM_PACK_PAYLOAD3
(
payload
,
PM_FORCE_POWERDOWN
,
target
,
ack
);
if
(
ack
==
REQ_ACK_BLOCKING
)
return
pm_ipi_send_sync
(
primary_proc
,
payload
,
NULL
);
else
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_abort_suspend() - PM call to announce that a prior suspend request
* is to be aborted.
* @reason Reason for the abort
*
* Calling PU expects the PMU to abort the initiated suspend procedure.
* This is a non-blocking call without any acknowledge.
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_abort_suspend
(
enum
pm_abort_reason
reason
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
/*
* Do client specific abort suspend operations
* (e.g. enable interrupts and clear powerdown request bit)
*/
pm_client_abort_suspend
();
/* Send request to the PMU */
/* TODO: allow passing the node ID of the affected CPU */
PM_PACK_PAYLOAD3
(
payload
,
PM_ABORT_SUSPEND
,
reason
,
primary_proc
->
node_id
);
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
* @target Node id of the targeted PU or subsystem
* @wkup_node Node id of the wakeup peripheral
* @enable Enable or disable the specified peripheral as wake source
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_set_wakeup_source
(
enum
pm_node_id
target
,
enum
pm_node_id
wkup_node
,
unsigned
int
enable
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
PM_PACK_PAYLOAD4
(
payload
,
PM_SET_WAKEUP_SOURCE
,
target
,
wkup_node
,
enable
);
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_system_shutdown() - PM call to request a system shutdown or restart
* @restart Shutdown or restart? 0 for shutdown, 1 for restart
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_system_shutdown
(
unsigned
int
restart
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
PM_PACK_PAYLOAD2
(
payload
,
PM_SYSTEM_SHUTDOWN
,
restart
);
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/* APIs for managing PM slaves: */
/**
* pm_req_node() - PM call to request a node with specific capabilities
* @nid Node id of the slave
* @capabilities Requested capabilities of the slave
* @qos Quality of service (not supported)
* @ack Flag to specify whether acknowledge is requested
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_req_node
(
enum
pm_node_id
nid
,
unsigned
int
capabilities
,
unsigned
int
qos
,
enum
pm_request_ack
ack
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
PM_PACK_PAYLOAD5
(
payload
,
PM_REQ_NODE
,
nid
,
capabilities
,
qos
,
ack
);
if
(
ack
==
REQ_ACK_BLOCKING
)
return
pm_ipi_send_sync
(
primary_proc
,
payload
,
NULL
);
else
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_set_requirement() - PM call to set requirement for PM slaves
* @nid Node id of the slave
* @capabilities Requested capabilities of the slave
* @qos Quality of service (not supported)
* @ack Flag to specify whether acknowledge is requested
*
* This API function is to be used for slaves a PU already has requested
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_set_requirement
(
enum
pm_node_id
nid
,
unsigned
int
capabilities
,
unsigned
int
qos
,
enum
pm_request_ack
ack
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
PM_PACK_PAYLOAD5
(
payload
,
PM_SET_REQUIREMENT
,
nid
,
capabilities
,
qos
,
ack
);
if
(
ack
==
REQ_ACK_BLOCKING
)
return
pm_ipi_send_sync
(
primary_proc
,
payload
,
NULL
);
else
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_release_node() - PM call to release a node
* @nid Node id of the slave
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_release_node
(
enum
pm_node_id
nid
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
PM_PACK_PAYLOAD2
(
payload
,
PM_RELEASE_NODE
,
nid
);
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_set_max_latency() - PM call to set wakeup latency requirements
* @nid Node id of the slave
* @latency Requested maximum wakeup latency
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_set_max_latency
(
enum
pm_node_id
nid
,
unsigned
int
latency
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
PM_PACK_PAYLOAD3
(
payload
,
PM_SET_MAX_LATENCY
,
nid
,
latency
);
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/* Miscellaneous API functions */
/**
* pm_get_api_version() - Get version number of PMU PM firmware
* @version Returns 32-bit version number of PMU Power Management Firmware
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_get_api_version
(
unsigned
int
*
version
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
/* Send request to the PMU */
PM_PACK_PAYLOAD1
(
payload
,
PM_GET_API_VERSION
);
return
pm_ipi_send_sync
(
primary_proc
,
payload
,
version
);
}
/**
* pm_set_configuration() - PM call to set system configuration
* @phys_addr Physical 32-bit address of data structure in memory
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_set_configuration
(
unsigned
int
phys_addr
)
{
return
PM_RET_ERROR_NOTSUPPORTED
;
}
/**
* pm_get_node_status() - PM call to request a node's current power state
* @nid Node id of the slave
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_get_node_status
(
enum
pm_node_id
nid
)
{
/* TODO: Add power state argument!! */
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
PM_PACK_PAYLOAD2
(
payload
,
PM_GET_NODE_STATUS
,
nid
);
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_register_notifier() - Register the PU to be notified of PM events
* @nid Node id of the slave
* @event The event to be notified about
* @wake Wake up on event
* @enable Enable or disable the notifier
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_register_notifier
(
enum
pm_node_id
nid
,
unsigned
int
event
,
unsigned
int
wake
,
unsigned
int
enable
)
{
return
PM_RET_ERROR_NOTSUPPORTED
;
}
/**
* pm_get_op_characteristic() - PM call to get a particular operating
* characteristic of a node
* @nid Node ID
* @type Operating characterstic type to be returned
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_get_op_characteristic
(
enum
pm_node_id
nid
,
enum
pm_opchar_type
type
)
{
return
PM_RET_ERROR_NOTSUPPORTED
;
}
/* Direct-Control API functions */
/**
* pm_reset_assert() - Assert reset
* @reset Reset ID
* @assert Assert (1) or de-assert (0)
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_reset_assert
(
unsigned
int
reset
,
unsigned
int
assert
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
/* Send request to the PMU */
PM_PACK_PAYLOAD3
(
payload
,
PM_RESET_ASSERT
,
reset
,
assert
);
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_reset_get_status() - Get current status of a reset line
* @reset Reset ID
* @reset_status Returns current status of selected reset line
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_reset_get_status
(
unsigned
int
reset
,
unsigned
int
*
reset_status
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
/* Send request to the PMU */
PM_PACK_PAYLOAD2
(
payload
,
PM_RESET_GET_STATUS
,
reset
);
return
pm_ipi_send_sync
(
primary_proc
,
payload
,
reset_status
);
}
/**
* pm_mmio_write() - Perform write to protected mmio
* @address Address to write to
* @mask Mask to apply
* @value Value to write
*
* This function provides access to PM-related control registers
* that may not be directly accessible by a particular PU.
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_mmio_write
(
uintptr_t
address
,
unsigned
int
mask
,
unsigned
int
value
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
/* Send request to the PMU */
PM_PACK_PAYLOAD4
(
payload
,
PM_MMIO_WRITE
,
address
,
mask
,
value
);
return
pm_ipi_send
(
primary_proc
,
payload
);
}
/**
* pm_mmio_read() - Read value from protected mmio
* @address Address to write to
* @value Value to write
*
* This function provides access to PM-related control registers
* that may not be directly accessible by a particular PU.
*
* @return Returns status, either success or error+reason
*/
enum
pm_ret_status
pm_mmio_read
(
uintptr_t
address
,
unsigned
int
*
value
)
{
uint32_t
payload
[
PAYLOAD_ARG_CNT
];
/* Send request to the PMU */
PM_PACK_PAYLOAD2
(
payload
,
PM_MMIO_READ
,
address
);
return
pm_ipi_send_sync
(
primary_proc
,
payload
,
value
);
}
plat/xilinx/zynqmp/pm_service/pm_api_sys.h
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PM_API_SYS_H_
#define _PM_API_SYS_H_
#include <stdint.h>
#include "pm_defs.h"
/**********************************************************
* System-level API function declarations
**********************************************************/
enum
pm_ret_status
pm_req_suspend
(
enum
pm_node_id
nid
,
enum
pm_request_ack
ack
,
unsigned
int
latency
,
unsigned
int
state
);
enum
pm_ret_status
pm_self_suspend
(
enum
pm_node_id
nid
,
unsigned
int
latency
,
unsigned
int
state
,
uintptr_t
address
);
enum
pm_ret_status
pm_force_powerdown
(
enum
pm_node_id
nid
,
enum
pm_request_ack
ack
);
enum
pm_ret_status
pm_abort_suspend
(
enum
pm_abort_reason
reason
);
enum
pm_ret_status
pm_req_wakeup
(
enum
pm_node_id
nid
,
unsigned
int
set_address
,
uintptr_t
address
,
enum
pm_request_ack
ack
);
enum
pm_ret_status
pm_set_wakeup_source
(
enum
pm_node_id
target
,
enum
pm_node_id
wkup_node
,
unsigned
int
enable
);
enum
pm_ret_status
pm_system_shutdown
(
unsigned
int
restart
);
enum
pm_ret_status
pm_init_suspend_cb
(
enum
pm_suspend_reason
reason
,
unsigned
int
latency
,
unsigned
int
state
,
unsigned
int
timeout
);
/* API functions for managing PM Slaves */
enum
pm_ret_status
pm_req_node
(
enum
pm_node_id
nid
,
unsigned
int
capabilities
,
unsigned
int
qos
,
enum
pm_request_ack
ack
);
enum
pm_ret_status
pm_release_node
(
enum
pm_node_id
nid
);
enum
pm_ret_status
pm_set_requirement
(
enum
pm_node_id
nid
,
unsigned
int
capabilities
,
unsigned
int
qos
,
enum
pm_request_ack
ack
);
enum
pm_ret_status
pm_set_max_latency
(
enum
pm_node_id
nid
,
unsigned
int
latency
);
/* Miscellaneous API functions */
enum
pm_ret_status
pm_get_api_version
(
unsigned
int
*
version
);
enum
pm_ret_status
pm_set_configuration
(
unsigned
int
phys_addr
);
enum
pm_ret_status
pm_get_node_status
(
enum
pm_node_id
node
);
enum
pm_ret_status
pm_register_notifier
(
enum
pm_node_id
nid
,
unsigned
int
event
,
unsigned
int
wake
,
unsigned
int
enable
);
enum
pm_ret_status
pm_get_op_characteristic
(
enum
pm_node_id
nid
,
enum
pm_opchar_type
type
);
enum
pm_ret_status
pm_acknowledge_cb
(
enum
pm_node_id
nid
,
enum
pm_ret_status
status
,
unsigned
int
oppoint
);
enum
pm_ret_status
pm_notify_cb
(
enum
pm_node_id
nid
,
unsigned
int
event
,
unsigned
int
oppoint
);
/* Direct-Control API functions */
enum
pm_ret_status
pm_reset_assert
(
unsigned
int
reset_id
,
unsigned
int
assert
);
enum
pm_ret_status
pm_reset_get_status
(
unsigned
int
reset_id
,
unsigned
int
*
reset_status
);
enum
pm_ret_status
pm_mmio_write
(
uintptr_t
address
,
unsigned
int
mask
,
unsigned
int
value
);
enum
pm_ret_status
pm_mmio_read
(
uintptr_t
address
,
unsigned
int
*
value
);
#endif
/* _PM_API_SYS_H_ */
plat/xilinx/zynqmp/pm_service/pm_client.c
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* APU specific definition of processors in the subsystem as well as functions
* for getting information about and changing state of the APU.
*/
#include <gicv2.h>
#include <bl_common.h>
#include <mmio.h>
#include "pm_api_sys.h"
#include "pm_client.h"
#include "pm_ipi.h"
#include "../zynqmp_def.h"
#define OCM_BANK_0 0xFFFC0000
#define OCM_BANK_1 (OCM_BANK_0 + 0x10000)
#define OCM_BANK_2 (OCM_BANK_1 + 0x10000)
#define OCM_BANK_3 (OCM_BANK_2 + 0x10000)
#define UNDEFINED_CPUID (~0)
/* Declaration of linker defined symbol */
extern
unsigned
long
__BL31_END__
;
extern
const
struct
pm_ipi
apu_ipi
;
/* Order in pm_procs_all array must match cpu ids */
static
const
struct
pm_proc
const
pm_procs_all
[]
=
{
{
.
node_id
=
NODE_APU_0
,
.
pwrdn_mask
=
APU_0_PWRCTL_CPUPWRDWNREQ_MASK
,
.
ipi
=
&
apu_ipi
,
},
{
.
node_id
=
NODE_APU_1
,
.
pwrdn_mask
=
APU_1_PWRCTL_CPUPWRDWNREQ_MASK
,
.
ipi
=
&
apu_ipi
,
},
{
.
node_id
=
NODE_APU_2
,
.
pwrdn_mask
=
APU_2_PWRCTL_CPUPWRDWNREQ_MASK
,
.
ipi
=
&
apu_ipi
,
},
{
.
node_id
=
NODE_APU_3
,
.
pwrdn_mask
=
APU_3_PWRCTL_CPUPWRDWNREQ_MASK
,
.
ipi
=
&
apu_ipi
,
},
};
/**
* set_ocm_retention() - Configure OCM memory banks for retention
*
* APU specific requirements for suspend action:
* OCM has to enter retention state in order to preserve saved
* context after suspend request. OCM banks are determined by
* __BL31_END__ linker symbol.
*
* Return: Returns status, either success or error+reason
*/
enum
pm_ret_status
set_ocm_retention
(
void
)
{
enum
pm_ret_status
ret
;
/* OCM_BANK_0 will always be occupied */
ret
=
pm_set_requirement
(
NODE_OCM_BANK_0
,
PM_CAP_CONTEXT
,
0
,
REQ_ACK_NO
);
/* Check for other OCM banks */
if
((
unsigned
long
)
&
__BL31_END__
>=
OCM_BANK_1
)
ret
=
pm_set_requirement
(
NODE_OCM_BANK_1
,
PM_CAP_CONTEXT
,
0
,
REQ_ACK_NO
);
if
((
unsigned
long
)
&
__BL31_END__
>=
OCM_BANK_2
)
ret
=
pm_set_requirement
(
NODE_OCM_BANK_2
,
PM_CAP_CONTEXT
,
0
,
REQ_ACK_NO
);
if
((
unsigned
long
)
&
__BL31_END__
>=
OCM_BANK_3
)
ret
=
pm_set_requirement
(
NODE_OCM_BANK_3
,
PM_CAP_CONTEXT
,
0
,
REQ_ACK_NO
);
return
ret
;
}
/**
* pm_get_proc() - returns pointer to the proc structure
* @cpuid: id of the cpu whose proc struct pointer should be returned
*
* Return: pointer to a proc structure if proc is found, otherwise NULL
*/
const
struct
pm_proc
*
pm_get_proc
(
unsigned
int
cpuid
)
{
if
(
cpuid
<
ARRAY_SIZE
(
pm_procs_all
))
return
&
pm_procs_all
[
cpuid
];
return
NULL
;
}
/**
* pm_get_proc_by_node() - returns pointer to the proc structure
* @nid: node id of the processor
*
* Return: pointer to a proc structure if proc is found, otherwise NULL
*/
const
struct
pm_proc
*
pm_get_proc_by_node
(
enum
pm_node_id
nid
)
{
for
(
size_t
i
=
0
;
i
<
ARRAY_SIZE
(
pm_procs_all
);
i
++
)
{
if
(
nid
==
pm_procs_all
[
i
].
node_id
)
return
&
pm_procs_all
[
i
];
}
return
NULL
;
}
/**
* pm_get_cpuid() - get the local cpu ID for a global node ID
* @nid: node id of the processor
*
* Return: the cpu ID (starting from 0) for the subsystem
*/
static
unsigned
int
pm_get_cpuid
(
enum
pm_node_id
nid
)
{
for
(
size_t
i
=
0
;
i
<
ARRAY_SIZE
(
pm_procs_all
);
i
++
)
{
if
(
pm_procs_all
[
i
].
node_id
==
nid
)
return
i
;
}
return
UNDEFINED_CPUID
;
}
const
struct
pm_proc
*
primary_proc
=
&
pm_procs_all
[
0
];
/**
* pm_client_suspend() - Client-specific suspend actions
*
* This function should contain any PU-specific actions
* required prior to sending suspend request to PMU
*/
void
pm_client_suspend
(
const
struct
pm_proc
*
proc
)
{
/* Set powerdown request */
mmio_write_32
(
APU_PWRCTL
,
mmio_read_32
(
APU_PWRCTL
)
|
proc
->
pwrdn_mask
);
}
/**
* pm_client_abort_suspend() - Client-specific abort-suspend actions
*
* This function should contain any PU-specific actions
* required for aborting a prior suspend request
*/
void
pm_client_abort_suspend
(
void
)
{
/* Enable interrupts at processor level (for current cpu) */
gicv2_cpuif_enable
();
/* Clear powerdown request */
mmio_write_32
(
APU_PWRCTL
,
mmio_read_32
(
APU_PWRCTL
)
&
~
primary_proc
->
pwrdn_mask
);
}
/**
* pm_client_wakeup() - Client-specific wakeup actions
*
* This function should contain any PU-specific actions
* required for waking up another APU core
*/
void
pm_client_wakeup
(
const
struct
pm_proc
*
proc
)
{
unsigned
int
cpuid
=
pm_get_cpuid
(
proc
->
node_id
);
if
(
cpuid
==
UNDEFINED_CPUID
)
return
;
/* clear powerdown bit for affected cpu */
uint32_t
val
=
mmio_read_32
(
APU_PWRCTL
);
val
&=
~
(
proc
->
pwrdn_mask
);
mmio_write_32
(
APU_PWRCTL
,
val
);
}
plat/xilinx/zynqmp/pm_service/pm_client.h
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Contains APU specific macros and macros to be defined depending on
* the execution environment.
*/
#ifndef _PM_CLIENT_H_
#define _PM_CLIENT_H_
#include "pm_defs.h"
#include "pm_common.h"
/* Functions to be implemented by each PU */
enum
pm_ret_status
pm_ipi_send
(
const
struct
pm_proc
*
proc
,
uint32_t
payload
[
PAYLOAD_ARG_CNT
]);
enum
pm_ret_status
pm_ipi_send_sync
(
const
struct
pm_proc
*
proc
,
uint32_t
payload
[
PAYLOAD_ARG_CNT
],
uint32_t
*
val
);
void
pm_client_suspend
(
const
struct
pm_proc
*
proc
);
void
pm_client_abort_suspend
(
void
);
void
pm_client_wakeup
(
const
struct
pm_proc
*
proc
);
enum
pm_ret_status
set_ocm_retention
(
void
);
/* Global variables to be set in pm_client.c */
extern
const
struct
pm_proc
*
primary_proc
;
#endif
/* _PM_CLIENT_H_ */
plat/xilinx/zynqmp/pm_service/pm_common.h
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Contains definitions of commonly used macros and data types needed
* for PU Power Management. This file should be common for all PU's.
*/
#ifndef _PM_COMMON_H_
#define _PM_COMMON_H_
#include <debug.h>
#include <stdint.h>
#include "pm_defs.h"
#define PAYLOAD_ARG_CNT 6U
#define PAYLOAD_ARG_SIZE 4U
/* size in bytes */
/**
* pm_ipi - struct for capturing IPI-channel specific info
* @mask mask for enabling/disabling and triggering the IPI
* @base base address for IPI
* @buffer_base base address for payload buffer
*/
struct
pm_ipi
{
const
unsigned
int
mask
;
const
uintptr_t
base
;
const
uintptr_t
buffer_base
;
};
/**
* pm_proc - struct for capturing processor related info
* @node_id node-ID of the processor
* @pwrdn_mask cpu-specific mask to be used for power control register
* @ipi pointer to IPI channel structure
* (in APU all processors share one IPI channel)
*/
struct
pm_proc
{
const
enum
pm_node_id
node_id
;
const
unsigned
int
pwrdn_mask
;
const
struct
pm_ipi
*
ipi
;
};
const
struct
pm_proc
*
pm_get_proc
(
unsigned
int
cpuid
);
const
struct
pm_proc
*
pm_get_proc_by_node
(
enum
pm_node_id
nid
);
#endif
/* _PM_COMMON_H_ */
plat/xilinx/zynqmp/pm_service/pm_defs.h
0 → 100644
View file @
5d787dd9
/*
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* ZynqMP power management enums and defines */
#ifndef _PM_DEFS_H_
#define _PM_DEFS_H_
/*********************************************************************
* Macro definitions
********************************************************************/
/*
* Version number is a 32bit value, like:
* (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR
*/
#define PM_VERSION_MAJOR 0
#define PM_VERSION_MINOR 2
#define PM_VERSION ((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR)
/* Capabilities for RAM */
#define PM_CAP_ACCESS 0x1U
#define PM_CAP_CONTEXT 0x2U
#define MAX_LATENCY (~0U)
#define MAX_QOS 100U
/*********************************************************************
* Enum definitions
********************************************************************/
enum
pm_api_id
{
/* Miscellaneous API functions: */
PM_GET_API_VERSION
=
1
,
/* Do not change or move */
PM_SET_CONFIGURATION
,
PM_GET_NODE_STATUS
,
PM_GET_OP_CHARACTERISTIC
,
PM_REGISTER_NOTIFIER
,
/* API for suspending of PUs: */
PM_REQ_SUSPEND
,
PM_SELF_SUSPEND
,
PM_FORCE_POWERDOWN
,
PM_ABORT_SUSPEND
,
PM_REQ_WAKEUP
,
PM_SET_WAKEUP_SOURCE
,
PM_SYSTEM_SHUTDOWN
,
/* API for managing PM slaves: */
PM_REQ_NODE
,
PM_RELEASE_NODE
,
PM_SET_REQUIREMENT
,
PM_SET_MAX_LATENCY
,
/* Direct control API functions: */
PM_RESET_ASSERT
,
PM_RESET_GET_STATUS
,
PM_MMIO_WRITE
,
PM_MMIO_READ
,
PM_API_MAX
};
enum
pm_node_id
{
NODE_UNKNOWN
=
0
,
NODE_APU
,
NODE_APU_0
,
NODE_APU_1
,
NODE_APU_2
,
NODE_APU_3
,
NODE_RPU
,
NODE_RPU_0
,
NODE_RPU_1
,
NODE_PL
,
NODE_FPD
,
NODE_OCM_BANK_0
,
NODE_OCM_BANK_1
,
NODE_OCM_BANK_2
,
NODE_OCM_BANK_3
,
NODE_TCM_0_A
,
NODE_TCM_0_B
,
NODE_TCM_1_A
,
NODE_TCM_1_B
,
NODE_L2
,
NODE_GPU_PP_0
,
NODE_GPU_PP_1
,
NODE_USB_0
,
NODE_USB_1
,
NODE_TTC_0
,
NODE_TTC_1
,
NODE_TTC_2
,
NODE_TTC_3
,
NODE_SATA
,
NODE_ETH_0
,
NODE_ETH_1
,
NODE_ETH_2
,
NODE_ETH_3
,
NODE_UART_0
,
NODE_UART_1
,
NODE_SPI_0
,
NODE_SPI_1
,
NODE_I2C_0
,
NODE_I2C_1
,
NODE_SD_0
,
NODE_SD_1
,
NODE_DP
,
NODE_GDMA
,
NODE_ADMA
,
NODE_NAND
,
NODE_QSPI
,
NODE_GPIO
,
NODE_CAN_0
,
NODE_CAN_1
,
NODE_AFI
,
NODE_APLL
,
NODE_VPLL
,
NODE_DPLL
,
NODE_RPLL
,
NODE_IOPLL
,
NODE_DDR
,
};
enum
pm_request_ack
{
REQ_ACK_NO
=
1
,
REQ_ACK_BLOCKING
,
REQ_ACK_NON_BLOCKING
,
};
enum
pm_abort_reason
{
ABORT_REASON_WKUP_EVENT
=
100
,
ABORT_REASON_PU_BUSY
,
ABORT_REASON_NO_PWRDN
,
ABORT_REASON_UNKNOWN
,
};
enum
pm_suspend_reason
{
SUSPEND_REASON_PU_REQ
=
201
,
SUSPEND_REASON_ALERT
,
SUSPEND_REASON_SYS_SHUTDOWN
,
};
enum
pm_ram_state
{
PM_RAM_STATE_OFF
=
1
,
PM_RAM_STATE_RETENTION
,
PM_RAM_STATE_ON
,
};
enum
pm_opchar_type
{
PM_OPCHAR_TYPE_POWER
=
1
,
PM_OPCHAR_TYPE_ENERGY
,
PM_OPCHAR_TYPE_TEMP
,
};
/**
* @PM_RET_SUCCESS: success
* @PM_RET_ERROR_ARGS: illegal arguments provided
* @PM_RET_ERROR_ACCESS: access rights violation
* @PM_RET_ERROR_TIMEOUT: timeout in communication with PMU
* @PM_RET_ERROR_NOTSUPPORTED: feature not supported
* @PM_RET_ERROR_PROC: node is not a processor node
* @PM_RET_ERROR_API_ID: illegal API ID
* @PM_RET_ERROR_OTHER: other error
*/
enum
pm_ret_status
{
PM_RET_SUCCESS
,
PM_RET_ERROR_ARGS
,
PM_RET_ERROR_ACCESS
,
PM_RET_ERROR_TIMEOUT
,
PM_RET_ERROR_NOTSUPPORTED
,
PM_RET_ERROR_PROC
,
PM_RET_ERROR_API_ID
,
PM_RET_ERROR_FAILURE
,
PM_RET_ERROR_COMMUNIC
,
PM_RET_ERROR_DOUBLEREQ
,
PM_RET_ERROR_OTHER
,
};
/**
* @PM_INITIAL_BOOT: boot is a fresh system startup
* @PM_RESUME: boot is a resume
* @PM_BOOT_ERROR: error, boot cause cannot be identified
*/
enum
pm_boot_status
{
PM_INITIAL_BOOT
,
PM_RESUME
,
PM_BOOT_ERROR
,
};
#endif
/* _PM_DEFS_H_ */
Prev
1
2
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