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
5747ecab
Commit
5747ecab
authored
Jun 08, 2017
by
danh-arm
Committed by
GitHub
Jun 08, 2017
Browse files
Merge pull request #959 from hzhuang1/hikey960_v1
Hikey960 v1
parents
f9a050e4
7fe08b2b
Changes
27
Hide whitespace changes
Inline
Side-by-side
docs/plat/hikey960.md
0 → 100644
View file @
5747ecab
Description
====================
HiKey960 is one of 96boards. Hisilicon Hi3660 processor is installed on HiKey960.
More information are listed in
[
link
](
http://www.96boards.org/documentation/ConsumerEdition/HiKey960/README.md
)
.
How to build
====================
1.
Code Locations
-----------------
*
ARM Trusted Firmware:
[
link
](
https://github.com/ARM-software/arm-trusted-firmware
)
*
edk2:
[
link
](
https://github.com/96boards-hikey/edk2/tree/testing/hikey960_v2.5
)
*
OpenPlatformPkg:
[
link
](
https://github.com/96boards-hikey/OpenPlatformPkg/tree/testing/hikey960_v1.3.4
)
*
l-loader:
[
link
](
https://github.com/96boards-hikey/l-loader/tree/testing/hikey960_v1.2
)
*
uefi-tools:
[
link
](
https://github.com/96boards-hikey/uefi-tools/tree/hikey960_v1
)
2. Build Procedure
------------------
*
Fetch all the above 5 repositories into local host.
Make all the repositories in the same ${BUILD_PATH}.
*
Create the symbol link to OpenPlatformPkg in edk2.
<br>
`$cd ${BUILD_PATH}/edk2`
</br>
<br>
`$ln -sf ../OpenPlatformPkg`
</br>
*
Prepare AARCH64 toolchain.
*
If your hikey960 hardware is v1, update _uefi-tools/platform.config_ first. _(optional)_
<br>
__
Uncomment the below sentence. Otherwise, UEFI can't output messages on serial
console on hikey960 v1.__
</br>
<br>
`BUILDFLAGS=-DSERIAL_BASE=0xFDF05000`
</br>
<br>
If your hikey960 hardware is v2 or newer, nothing to do.
</br>
*
Build it as debug mode. Create script file for build.
<br>
`BUILD_OPTION=DEBUG`
</br>
<br>
`export AARCH64_TOOLCHAIN=GCC48`
</br>
<br>
`export UEFI_TOOLS_DIR=${BUILD_PATH}/uefi-tools`
<br>
<br>
`export EDK2_DIR=${BUILD_PATH}/edk2`
</br>
<br>
`EDK2_OUTPUT_DIR=${EDK2_DIR}/Build/HiKey960/${BUILD_OPTION}_${AARCH64_TOOLCHAIN}`
</br>
<br>
`cd ${EDK2_DIR}`
</br>
<br>
`# Build UEFI & ARM Trust Firmware`
</br>
<br>
`${UEFI_TOOLS_DIR}/uefi-build.sh -b ${BUILD_OPTION} -a ../arm-trusted-firmware hikey960`
</br>
<br>
`# Generate l-loader.bin`
</br>
<br>
`cd ${BUILD_PATH}/l-loader`
</br>
<br>
`ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin`
</br>
<br>
`ln -sf ${EDK2_OUTPUT_DIR}/FV/fip.bin`
</br>
<br>
`ln -sf ${EDK2_OUTPUT_DIR}/FV/BL33_AP_UEFI.fd`
</br>
<br>
`python gen_loader.py -o l-loader.bin --img_bl1=bl1.bin --img_ns_bl1u=BL33_AP_UEFI.fd`
</br>
*
Generate partition table.
<br>
_Make sure that you're using the sgdisk in the l-loader directory._
</br>
<br>
`$PTABLE=aosp-32g SECTOR_SIZE=4096 SGDISK=./sgdisk bash -x generate_ptable.sh`
</br>
3. Setup Console
----------------
*
Install ser2net. Use telnet as the console since UEFI will output window
that fails to display in minicom.
<br>
`$sudo apt-get install ser2net`
</br>
*
Configure ser2net.
<br>
`$sudo vi /etc/ser2net.conf`
</br>
<br>
Append one line for serial-over-USB in below.
</br>
<br>
_#ser2net.conf_
</br>
<br>
`2004:telnet:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT banner`
</br>
*
Open the console.
<br>
`$telnet localhost 2004`
</br>
<br>
And you could open the console remotely, too.
</br>
4. Boot UEFI in recovery mode
-----------------------------
*
Fetch that are used in recovery mode. The code location is in below.
[
link
](
https://github.com/96boards-hikey/tools-images-hikey960
)
*
Generate l-loader.bin.
<br>
`$cd tools-images-hikey960`
</br>
<br>
`$ln -sf ${BUILD_PATH}/l-loader/l-loader.bin`
</br>
*
Prepare config file.
<br>
_$vi config_
</br>
<br>
_# The content of config file_
</br>
<br>
`./sec_user_xloader.img 0x00020000`
</br>
<br>
`./sec_uce_boot.img 0x6A908000`
</br>
<br>
`./l-loader.bin 0x1AC00000`
</br>
*
Remove the modemmanager package. This package may causes hikey_idt tool failure.
<br>
`$sudo apt-get purge modemmanager`
</br>
*
Run the command to download l-loader.bin into HiKey960.
<br>
`$sudo ./hikey_idt -c config -p /dev/ttyUSB1`
</br>
*
UEFI running in recovery mode.
<br>
When prompt '.' is displayed on console, press hotkey 'f' in keyboard. Then Android fastboot app is running.
</br>
<br>
The timeout of prompt '.' is 10 seconds.
</br>
*
Update images.
<br>
`$sudo fastboot flash ptable prm_ptable.img`
</br>
<br>
`$sudo fastboot flash xloader sec_xloader.img`
</br>
<br>
`$sudo fastboot flash fastboot l-loader.bin`
</br>
<br>
`$sudo fastboot flash fip fip.bin`
</br>
<br>
`$sudo fastboot flash boot boot.img`
</br>
<br>
`$sudo fastboot flash cache cache.img`
</br>
<br>
`$sudo fastboot flash system system.img`
</br>
<br>
`$sudo fastboot flash userdata userdata.img`
</br>
*
Notice: UEFI could also boot kernel in recovery mode, but BL31 isn't loaded in
recovery mode.
5. Boot UEFI in normal mode
-----------------------------
*
Make sure "Boot Mode" switch is OFF for normal boot mode. Then power on HiKey960.
*
Reference
[
link
](
https://github.com/96boards-hikey/tools-images-hikey960/blob/master/build-from-source/README-ATF-UEFI-build-from-source.md
)
include/lib/stdlib/machine/endian.h
0 → 100644
View file @
5747ecab
/*-
* Copyright (c) 2001 David E. O'Brien
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)endian.h 8.1 (Berkeley) 6/10/93
* $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $
* $FreeBSD$
*/
/*
* Portions copyright (c) 2017, ARM Limited and Contributors.
* All rights reserved.
*/
#ifndef _MACHINE_ENDIAN_H_
#define _MACHINE_ENDIAN_H_
#include <sys/_types.h>
/*
* Definitions for byte order, according to byte significance from low
* address to high.
*/
#define _LITTLE_ENDIAN 1234
/* LSB first: i386, vax */
#define _BIG_ENDIAN 4321
/* MSB first: 68000, ibm, net */
#define _PDP_ENDIAN 3412
/* LSB first in word, MSW first in long */
#define _BYTE_ORDER _LITTLE_ENDIAN
#if __BSD_VISIBLE
#define LITTLE_ENDIAN _LITTLE_ENDIAN
#define BIG_ENDIAN _BIG_ENDIAN
#define PDP_ENDIAN _PDP_ENDIAN
#define BYTE_ORDER _BYTE_ORDER
#endif
#define _QUAD_HIGHWORD 1
#define _QUAD_LOWWORD 0
#define __ntohl(x) (__bswap32(x))
#define __ntohs(x) (__bswap16(x))
#define __htonl(x) (__bswap32(x))
#define __htons(x) (__bswap16(x))
#ifdef AARCH32
static
__inline
__uint64_t
__bswap64
(
__uint64_t
_x
)
{
return
((
_x
>>
56
)
|
((
_x
>>
40
)
&
0xff00
)
|
((
_x
>>
24
)
&
0xff0000
)
|
((
_x
>>
8
)
&
0xff000000
)
|
((
_x
<<
8
)
&
((
__uint64_t
)
0xff
<<
32
))
|
((
_x
<<
24
)
&
((
__uint64_t
)
0xff
<<
40
))
|
((
_x
<<
40
)
&
((
__uint64_t
)
0xff
<<
48
))
|
((
_x
<<
56
)));
}
static
__inline
__uint32_t
__bswap32_var
(
__uint32_t
v
)
{
__uint32_t
t1
;
__asm
__volatile
(
"eor %1, %0, %0, ror #16
\n
"
"bic %1, %1, #0x00ff0000
\n
"
"mov %0, %0, ror #8
\n
"
"eor %0, %0, %1, lsr #8
\n
"
:
"+r"
(
v
),
"=r"
(
t1
));
return
(
v
);
}
static
__inline
__uint16_t
__bswap16_var
(
__uint16_t
v
)
{
__uint32_t
ret
=
v
&
0xffff
;
__asm
__volatile
(
"mov %0, %0, ror #8
\n
"
"orr %0, %0, %0, lsr #16
\n
"
"bic %0, %0, %0, lsl #16"
:
"+r"
(
ret
));
return
((
__uint16_t
)
ret
);
}
#elif defined AARCH64
static
__inline
__uint64_t
__bswap64
(
__uint64_t
x
)
{
__uint64_t
ret
;
__asm
__volatile
(
"rev %0, %1
\n
"
:
"=&r"
(
ret
),
"+r"
(
x
));
return
(
ret
);
}
static
__inline
__uint32_t
__bswap32_var
(
__uint32_t
v
)
{
__uint32_t
ret
;
__asm
__volatile
(
"rev32 %x0, %x1
\n
"
:
"=&r"
(
ret
),
"+r"
(
v
));
return
(
ret
);
}
static
__inline
__uint16_t
__bswap16_var
(
__uint16_t
v
)
{
__uint32_t
ret
;
__asm
__volatile
(
"rev16 %w0, %w1
\n
"
:
"=&r"
(
ret
),
"+r"
(
v
));
return
((
__uint16_t
)
ret
);
}
#else
#error "Only AArch32 or AArch64 supported"
#endif
/* AARCH32 */
#ifdef __OPTIMIZE__
#define __bswap32_constant(x) \
((((x) & 0xff000000U) >> 24) | \
(((x) & 0x00ff0000U) >> 8) | \
(((x) & 0x0000ff00U) << 8) | \
(((x) & 0x000000ffU) << 24))
#define __bswap16_constant(x) \
((((x) & 0xff00) >> 8) | \
(((x) & 0x00ff) << 8))
#define __bswap16(x) \
((__uint16_t)(__builtin_constant_p(x) ? \
__bswap16_constant(x) : \
__bswap16_var(x)))
#define __bswap32(x) \
((__uint32_t)(__builtin_constant_p(x) ? \
__bswap32_constant(x) : \
__bswap32_var(x)))
#else
#define __bswap16(x) __bswap16_var(x)
#define __bswap32(x) __bswap32_var(x)
#endif
/* __OPTIMIZE__ */
#endif
/* !_MACHINE_ENDIAN_H_ */
include/lib/stdlib/sys/endian.h
0 → 100644
View file @
5747ecab
/*-
* Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#ifndef _SYS_ENDIAN_H_
#define _SYS_ENDIAN_H_
#include <sys/cdefs.h>
#include <sys/_types.h>
#include <machine/endian.h>
#ifndef _UINT8_T_DECLARED
typedef
__uint8_t
uint8_t
;
#define _UINT8_T_DECLARED
#endif
#ifndef _UINT16_T_DECLARED
typedef
__uint16_t
uint16_t
;
#define _UINT16_T_DECLARED
#endif
#ifndef _UINT32_T_DECLARED
typedef
__uint32_t
uint32_t
;
#define _UINT32_T_DECLARED
#endif
#ifndef _UINT64_T_DECLARED
typedef
__uint64_t
uint64_t
;
#define _UINT64_T_DECLARED
#endif
/*
* General byte order swapping functions.
*/
#define bswap16(x) __bswap16(x)
#define bswap32(x) __bswap32(x)
#define bswap64(x) __bswap64(x)
/*
* Host to big endian, host to little endian, big endian to host, and little
* endian to host byte order functions as detailed in byteorder(9).
*/
#if _BYTE_ORDER == _LITTLE_ENDIAN
#define htobe16(x) bswap16((x))
#define htobe32(x) bswap32((x))
#define htobe64(x) bswap64((x))
#define htole16(x) ((uint16_t)(x))
#define htole32(x) ((uint32_t)(x))
#define htole64(x) ((uint64_t)(x))
#define be16toh(x) bswap16((x))
#define be32toh(x) bswap32((x))
#define be64toh(x) bswap64((x))
#define le16toh(x) ((uint16_t)(x))
#define le32toh(x) ((uint32_t)(x))
#define le64toh(x) ((uint64_t)(x))
#else
/* _BYTE_ORDER != _LITTLE_ENDIAN */
#define htobe16(x) ((uint16_t)(x))
#define htobe32(x) ((uint32_t)(x))
#define htobe64(x) ((uint64_t)(x))
#define htole16(x) bswap16((x))
#define htole32(x) bswap32((x))
#define htole64(x) bswap64((x))
#define be16toh(x) ((uint16_t)(x))
#define be32toh(x) ((uint32_t)(x))
#define be64toh(x) ((uint64_t)(x))
#define le16toh(x) bswap16((x))
#define le32toh(x) bswap32((x))
#define le64toh(x) bswap64((x))
#endif
/* _BYTE_ORDER == _LITTLE_ENDIAN */
/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
static
__inline
uint16_t
be16dec
(
const
void
*
pp
)
{
uint8_t
const
*
p
=
(
uint8_t
const
*
)
pp
;
return
((
p
[
0
]
<<
8
)
|
p
[
1
]);
}
static
__inline
uint32_t
be32dec
(
const
void
*
pp
)
{
uint8_t
const
*
p
=
(
uint8_t
const
*
)
pp
;
return
(((
unsigned
)
p
[
0
]
<<
24
)
|
(
p
[
1
]
<<
16
)
|
(
p
[
2
]
<<
8
)
|
p
[
3
]);
}
static
__inline
uint64_t
be64dec
(
const
void
*
pp
)
{
uint8_t
const
*
p
=
(
uint8_t
const
*
)
pp
;
return
(((
uint64_t
)
be32dec
(
p
)
<<
32
)
|
be32dec
(
p
+
4
));
}
static
__inline
uint16_t
le16dec
(
const
void
*
pp
)
{
uint8_t
const
*
p
=
(
uint8_t
const
*
)
pp
;
return
((
p
[
1
]
<<
8
)
|
p
[
0
]);
}
static
__inline
uint32_t
le32dec
(
const
void
*
pp
)
{
uint8_t
const
*
p
=
(
uint8_t
const
*
)
pp
;
return
(((
unsigned
)
p
[
3
]
<<
24
)
|
(
p
[
2
]
<<
16
)
|
(
p
[
1
]
<<
8
)
|
p
[
0
]);
}
static
__inline
uint64_t
le64dec
(
const
void
*
pp
)
{
uint8_t
const
*
p
=
(
uint8_t
const
*
)
pp
;
return
(((
uint64_t
)
le32dec
(
p
+
4
)
<<
32
)
|
le32dec
(
p
));
}
static
__inline
void
be16enc
(
void
*
pp
,
uint16_t
u
)
{
uint8_t
*
p
=
(
uint8_t
*
)
pp
;
p
[
0
]
=
(
u
>>
8
)
&
0xff
;
p
[
1
]
=
u
&
0xff
;
}
static
__inline
void
be32enc
(
void
*
pp
,
uint32_t
u
)
{
uint8_t
*
p
=
(
uint8_t
*
)
pp
;
p
[
0
]
=
(
u
>>
24
)
&
0xff
;
p
[
1
]
=
(
u
>>
16
)
&
0xff
;
p
[
2
]
=
(
u
>>
8
)
&
0xff
;
p
[
3
]
=
u
&
0xff
;
}
static
__inline
void
be64enc
(
void
*
pp
,
uint64_t
u
)
{
uint8_t
*
p
=
(
uint8_t
*
)
pp
;
be32enc
(
p
,
(
uint32_t
)(
u
>>
32
));
be32enc
(
p
+
4
,
(
uint32_t
)(
u
&
0xffffffffU
));
}
static
__inline
void
le16enc
(
void
*
pp
,
uint16_t
u
)
{
uint8_t
*
p
=
(
uint8_t
*
)
pp
;
p
[
0
]
=
u
&
0xff
;
p
[
1
]
=
(
u
>>
8
)
&
0xff
;
}
static
__inline
void
le32enc
(
void
*
pp
,
uint32_t
u
)
{
uint8_t
*
p
=
(
uint8_t
*
)
pp
;
p
[
0
]
=
u
&
0xff
;
p
[
1
]
=
(
u
>>
8
)
&
0xff
;
p
[
2
]
=
(
u
>>
16
)
&
0xff
;
p
[
3
]
=
(
u
>>
24
)
&
0xff
;
}
static
__inline
void
le64enc
(
void
*
pp
,
uint64_t
u
)
{
uint8_t
*
p
=
(
uint8_t
*
)
pp
;
le32enc
(
p
,
(
uint32_t
)(
u
&
0xffffffffU
));
le32enc
(
p
+
4
,
(
uint32_t
)(
u
>>
32
));
}
#endif
/* _SYS_ENDIAN_H_ */
plat/hisilicon/hikey960/aarch64/hikey960_common.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <arm_gic.h>
#include <assert.h>
#include <bl_common.h>
#include <debug.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <xlat_tables.h>
#include "../hikey960_def.h"
#include "../hikey960_private.h"
#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \
DDR_SIZE, \
MT_MEMORY | MT_RW | MT_NS)
#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \
DEVICE_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
#define MAP_BL1_RW MAP_REGION_FLAT(BL1_RW_BASE, \
BL1_RW_LIMIT - BL1_RW_BASE, \
MT_MEMORY | MT_RW | MT_NS)
#define MAP_UFS_DATA MAP_REGION_FLAT(HIKEY960_UFS_DATA_BASE, \
HIKEY960_UFS_DATA_SIZE, \
MT_MEMORY | MT_RW | MT_NS)
#define MAP_UFS_DESC MAP_REGION_FLAT(HIKEY960_UFS_DESC_BASE, \
HIKEY960_UFS_DESC_SIZE, \
MT_MEMORY | MT_RW | MT_NS)
/*
* Table of regions for different BL stages to map using the MMU.
* This doesn't include Trusted RAM as the 'mem_layout' argument passed to
* hikey960_init_mmu_elx() will give the available subset of that,
*/
#if IMAGE_BL1
static
const
mmap_region_t
hikey960_mmap
[]
=
{
MAP_UFS_DATA
,
MAP_BL1_RW
,
MAP_UFS_DESC
,
MAP_DEVICE
,
{
0
}
};
#endif
#if IMAGE_BL2
static
const
mmap_region_t
hikey960_mmap
[]
=
{
MAP_DDR
,
MAP_DEVICE
,
{
0
}
};
#endif
#if IMAGE_BL31
static
const
mmap_region_t
hikey960_mmap
[]
=
{
MAP_DEVICE
,
{
0
}
};
#endif
/*
* Macro generating the code for the function setting up the pagetables as per
* the platform memory map & initialize the mmu, for the given exception level
*/
#define HIKEY960_CONFIGURE_MMU_EL(_el) \
void hikey960_init_mmu_el##_el(unsigned long total_base, \
unsigned long total_size, \
unsigned long ro_start, \
unsigned long ro_limit, \
unsigned long coh_start, \
unsigned long coh_limit) \
{ \
mmap_add_region(total_base, total_base, \
total_size, \
MT_MEMORY | MT_RW | MT_SECURE); \
mmap_add_region(ro_start, ro_start, \
ro_limit - ro_start, \
MT_MEMORY | MT_RO | MT_SECURE); \
mmap_add_region(coh_start, coh_start, \
coh_limit - coh_start, \
MT_DEVICE | MT_RW | MT_SECURE); \
mmap_add(hikey960_mmap); \
init_xlat_tables(); \
\
enable_mmu_el##_el(0); \
}
/* Define EL1 and EL3 variants of the function initialising the MMU */
HIKEY960_CONFIGURE_MMU_EL
(
1
)
HIKEY960_CONFIGURE_MMU_EL
(
3
)
unsigned
long
plat_get_ns_image_entrypoint
(
void
)
{
return
NS_BL1U_BASE
;
}
unsigned
int
plat_get_syscnt_freq2
(
void
)
{
return
1920000
;
}
plat/hisilicon/hikey960/aarch64/hikey960_helpers.S
0 → 100644
View file @
5747ecab
/*
*
Copyright
(
c
)
2017
,
ARM
Limited
and
Contributors
.
All
rights
reserved
.
*
*
SPDX
-
License
-
Identifier
:
BSD
-
3
-
Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <cortex_a53.h>
#include <cortex_a73.h>
#include "../hikey960_def.h"
.
globl
plat_my_core_pos
.
globl
platform_mem_init
.
globl
plat_crash_console_init
.
globl
plat_crash_console_putc
.
globl
plat_report_exception
.
globl
plat_reset_handler
.
globl
set_retention_ticks
.
globl
clr_retention_ticks
.
globl
clr_ex
.
globl
nop
func
plat_my_core_pos
mrs
x0
,
mpidr_el1
and
x1
,
x0
,
#
MPIDR_CPU_MASK
and
x0
,
x0
,
#
MPIDR_CLUSTER_MASK
add
x0
,
x1
,
x0
,
LSR
#
6
ret
endfunc
plat_my_core_pos
/
*
-----------------------------------------------------
*
void
platform_mem_init
(
void
)
;
*
*
We
don
't need to carry out any memory initialization
*
on
HIKEY
.
The
Secure
RAM
is
accessible
straight
away
.
*
-----------------------------------------------------
*/
func
platform_mem_init
ret
endfunc
platform_mem_init
/
*
---------------------------------------------
*
int
plat_crash_console_init
(
void
)
*
Function
to
initialize
the
crash
console
*
without
a
C
Runtime
to
print
crash
report
.
*
Clobber
list
:
x0
,
x1
,
x2
*
---------------------------------------------
*/
func
plat_crash_console_init
mov_imm
x0
,
CRASH_CONSOLE_BASE
mov_imm
x1
,
PL011_UART_CLK_IN_HZ
mov_imm
x2
,
PL011_BAUDRATE
b
console_core_init
endfunc
plat_crash_console_init
/
*
---------------------------------------------
*
int
plat_crash_console_putc
(
int
c
)
*
Function
to
print
a
character
on
the
crash
*
console
without
a
C
Runtime
.
*
Clobber
list
:
x1
,
x2
*
---------------------------------------------
*/
func
plat_crash_console_putc
mov_imm
x1
,
CRASH_CONSOLE_BASE
b
console_core_putc
endfunc
plat_crash_console_putc
/
*
---------------------------------------------
*
void
plat_report_exception
(
unsigned
int
type
)
*
Function
to
report
an
unhandled
exception
*
with
platform
-
specific
means
.
*
On
HIKEY
platform
,
it
updates
the
LEDs
*
to
indicate
where
we
are
*
---------------------------------------------
*/
func
plat_report_exception
mov
x8
,
x30
/
*
Turn
on
LED
according
to
x0
(
0
--
f
)
*/
ldr
x2
,
=
0xf7020000
and
x1
,
x0
,
#
1
str
w1
,
[
x2
,
#
4
]
and
x1
,
x0
,
#
2
str
w1
,
[
x2
,
#
8
]
and
x1
,
x0
,
#
4
str
w1
,
[
x2
,
#
16
]
and
x1
,
x0
,
#
8
str
w1
,
[
x2
,
#
32
]
mrs
x2
,
currentel
and
x2
,
x2
,
#
0x0c
/
*
Check
EL1
*/
cmp
x2
,
#
0x04
beq
plat_report_el1
adr
x4
,
plat_err_str
bl
asm_print_str
adr
x4
,
esr_el3_str
bl
asm_print_str
mrs
x4
,
esr_el3
bl
asm_print_hex
adr
x4
,
elr_el3_str
bl
asm_print_str
mrs
x4
,
elr_el3
bl
asm_print_hex
b
plat_report_end
plat_report_el1
:
adr
x4
,
plat_err_str
bl
asm_print_str
adr
x4
,
esr_el1_str
bl
asm_print_str
mrs
x4
,
esr_el1
bl
asm_print_hex
adr
x4
,
elr_el1_str
bl
asm_print_str
mrs
x4
,
elr_el1
bl
asm_print_hex
plat_report_end
:
mov
x30
,
x8
ret
endfunc
plat_report_exception
/
*
-----------------------------------------------------
*
void
plat_reset_handler
(
void
)
;
*
-----------------------------------------------------
*/
func
plat_reset_handler
ret
endfunc
plat_reset_handler
/
*
-----------------------------------------------------
*
void
set_retention_ticks
(
unsigned
int
val
)
;
*
Clobber
list
:
x0
*
-----------------------------------------------------
*/
func
set_retention_ticks
mrs
x0
,
CPUECTLR_EL1
bic
x0
,
x0
,
#
CPUECTLR_CPU_RET_CTRL_MASK
orr
x0
,
x0
,
#
RETENTION_ENTRY_TICKS_8
msr
CPUECTLR_EL1
,
x0
isb
dsb
sy
ret
endfunc
set_retention_ticks
/
*
-----------------------------------------------------
*
void
clr_retention_ticks
(
unsigned
int
val
)
;
*
Clobber
list
:
x0
*
-----------------------------------------------------
*/
func
clr_retention_ticks
mrs
x0
,
CPUECTLR_EL1
bic
x0
,
x0
,
#
CPUECTLR_CPU_RET_CTRL_MASK
msr
CPUECTLR_EL1
,
x0
isb
dsb
sy
ret
endfunc
clr_retention_ticks
/
*
-----------------------------------------------------
*
void
clrex
(
void
)
;
*
-----------------------------------------------------
*/
func
clr_ex
clrex
ret
endfunc
clr_ex
/
*
-----------------------------------------------------
*
void
nop
(
void
)
;
*
-----------------------------------------------------
*/
func
nop
nop
ret
endfunc
nop
.
section
.
rodata.
rev_err_str
,
"aS"
plat_err_str
:
.
asciz
"\nPlatform exception reporting:"
esr_el3_str
:
.
asciz
"\nESR_EL3: "
elr_el3_str
:
.
asciz
"\nELR_EL3: "
esr_el1_str
:
.
asciz
"\nESR_EL1: "
elr_el1_str
:
.
asciz
"\nELR_EL1: "
plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <hi3660.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <hisi_ipc.h>
#include <debug.h>
#include "../../hikey960_private.h"
#define IPC_MBX_SOURCE_REG(m) (IPC_BASE + ((m) << 6))
#define IPC_MBX_DSET_REG(m) (IPC_BASE + ((m) << 6) + 0x04)
#define IPC_MBX_DCLEAR_REG(m) (IPC_BASE + ((m) << 6) + 0x08)
#define IPC_MBX_DSTATUS_REG(m) (IPC_BASE + ((m) << 6) + 0x0C)
#define IPC_MBX_MODE_REG(m) (IPC_BASE + ((m) << 6) + 0x10)
#define IPC_MBX_IMASK_REG(m) (IPC_BASE + ((m) << 6) + 0x14)
#define IPC_MBX_ICLR_REG(m) (IPC_BASE + ((m) << 6) + 0x18)
#define IPC_MBX_SEND_REG(m) (IPC_BASE + ((m) << 6) + 0x1C)
#define IPC_MBX_DATA_REG(m, d) (IPC_BASE + ((m) << 6) + 0x20 + \
((d) * 4))
#define IPC_CPU_IMST_REG(m) (IPC_BASE + ((m) << 3))
#define IPC_LOCK_REG (IPC_BASE + 0xA00)
#define IPC_ACK_BIT_SHIFT (1 << 7)
#define IPC_UNLOCK_VALUE (0x1ACCE551)
/*********************************************************
*bit[31:24]:0~AP
*bit[23:16]:0x1~A15, 0x2~A7
*bit[15:8]:0~ON, 1~OFF
*bit[7:0]:0x3 cpu power mode
*********************************************************/
#define IPC_CMD_TYPE(src_obj, cluster_obj, is_off, mode) \
((src_obj << 24) | (((cluster_obj) + 1) << 16) | (is_off << 8) | (mode))
/*********************************************************
*bit[15:8]:0~no idle, 1~idle
*bit[7:0]:cpux
*********************************************************/
#define IPC_CMD_PARA(is_idle, cpu) \
((is_idle << 8) | (cpu))
#define IPC_STATE_IDLE 0x10
enum
src_id
{
SRC_IDLE
=
0
,
SRC_A15
=
1
<<
0
,
SRC_A7
=
1
<<
1
,
SRC_IOM3
=
1
<<
2
,
SRC_LPM3
=
1
<<
3
};
/*lpm3's mailboxs are 13~17*/
enum
lpm3_mbox_id
{
LPM3_MBX0
=
13
,
LPM3_MBX1
,
LPM3_MBX2
,
LPM3_MBX3
,
LPM3_MBX4
,
};
static
void
cpu_relax
(
void
)
{
volatile
int
i
;
for
(
i
=
0
;
i
<
10
;
i
++
)
nop
();
}
static
inline
void
hisi_ipc_clear_ack
(
enum
src_id
source
,
enum
lpm3_mbox_id
mbox
)
{
unsigned
int
int_status
=
0
;
do
{
int_status
=
mmio_read_32
(
IPC_MBX_MODE_REG
(
mbox
));
int_status
&=
0xF0
;
cpu_relax
();
}
while
(
int_status
!=
IPC_ACK_BIT_SHIFT
);
mmio_write_32
(
IPC_MBX_ICLR_REG
(
mbox
),
source
);
}
static
void
hisi_ipc_send_cmd_with_ack
(
enum
src_id
source
,
enum
lpm3_mbox_id
mbox
,
unsigned
int
cmdtype
,
unsigned
int
cmdpara
)
{
unsigned
int
regval
;
unsigned
int
mask
;
unsigned
int
state
;
mmio_write_32
(
IPC_LOCK_REG
,
IPC_UNLOCK_VALUE
);
/* wait for idle and occupy */
do
{
state
=
mmio_read_32
(
IPC_MBX_MODE_REG
(
mbox
));
if
(
state
==
IPC_STATE_IDLE
)
{
mmio_write_32
(
IPC_MBX_SOURCE_REG
(
mbox
),
source
);
regval
=
mmio_read_32
(
IPC_MBX_SOURCE_REG
(
mbox
));
if
(
regval
==
source
)
break
;
}
cpu_relax
();
}
while
(
1
);
/* auto answer */
mmio_write_32
(
IPC_MBX_MODE_REG
(
mbox
),
0x1
);
mask
=
(
~
((
int
)
source
|
SRC_LPM3
)
&
0x3F
);
/* mask the other cpus */
mmio_write_32
(
IPC_MBX_IMASK_REG
(
mbox
),
mask
);
/* set data */
mmio_write_32
(
IPC_MBX_DATA_REG
(
mbox
,
0
),
cmdtype
);
mmio_write_32
(
IPC_MBX_DATA_REG
(
mbox
,
1
),
cmdpara
);
/* send cmd */
mmio_write_32
(
IPC_MBX_SEND_REG
(
mbox
),
source
);
/* wait ack and clear */
hisi_ipc_clear_ack
(
source
,
mbox
);
/* release mailbox */
mmio_write_32
(
IPC_MBX_SOURCE_REG
(
mbox
),
source
);
}
void
hisi_ipc_pm_on_off
(
unsigned
int
core
,
unsigned
int
cluster
,
enum
pm_mode
mode
)
{
unsigned
int
cmdtype
=
0
;
unsigned
int
cmdpara
=
0
;
enum
src_id
source
=
SRC_IDLE
;
enum
lpm3_mbox_id
mailbox
=
(
enum
lpm3_mbox_id
)(
LPM3_MBX0
+
core
);
cmdtype
=
IPC_CMD_TYPE
(
0
,
cluster
,
mode
,
0x3
);
cmdpara
=
IPC_CMD_PARA
(
0
,
core
);
source
=
cluster
?
SRC_A7
:
SRC_A15
;
hisi_ipc_send_cmd_with_ack
(
source
,
mailbox
,
cmdtype
,
cmdpara
);
}
void
hisi_ipc_pm_suspend
(
unsigned
int
core
,
unsigned
int
cluster
,
unsigned
int
affinity_level
)
{
unsigned
int
cmdtype
=
0
;
unsigned
int
cmdpara
=
0
;
enum
src_id
source
=
SRC_IDLE
;
enum
lpm3_mbox_id
mailbox
=
(
enum
lpm3_mbox_id
)(
LPM3_MBX0
+
core
);
if
(
affinity_level
==
0x3
)
cmdtype
=
IPC_CMD_TYPE
(
0
,
-
1
,
0x1
,
0x3
+
affinity_level
);
else
cmdtype
=
IPC_CMD_TYPE
(
0
,
cluster
,
0x1
,
0x3
+
affinity_level
);
cmdpara
=
IPC_CMD_PARA
(
1
,
core
);
source
=
cluster
?
SRC_A7
:
SRC_A15
;
hisi_ipc_send_cmd_with_ack
(
source
,
mailbox
,
cmdtype
,
cmdpara
);
}
void
hisi_ipc_psci_system_off
(
unsigned
int
core
,
unsigned
int
cluster
)
{
unsigned
int
cmdtype
=
0
;
unsigned
int
cmdpara
=
0
;
enum
src_id
source
=
SRC_IDLE
;
enum
lpm3_mbox_id
mailbox
=
(
enum
lpm3_mbox_id
)(
LPM3_MBX0
+
core
);
cmdtype
=
IPC_CMD_TYPE
(
0
,
(
0x10
-
1
),
0x1
,
0x0
);
cmdpara
=
IPC_CMD_PARA
(
0
,
0
);
source
=
cluster
?
SRC_A7
:
SRC_A15
;
hisi_ipc_send_cmd_with_ack
(
source
,
mailbox
,
cmdtype
,
cmdpara
);
}
void
hisi_ipc_psci_system_reset
(
unsigned
int
core
,
unsigned
int
cluster
,
unsigned
int
cmd_id
)
{
unsigned
int
cmdtype
=
0
;
unsigned
int
cmdpara
=
0
;
enum
src_id
source
=
SRC_IDLE
;
enum
lpm3_mbox_id
mailbox
=
(
enum
lpm3_mbox_id
)(
LPM3_MBX0
+
core
);
cmdtype
=
IPC_CMD_TYPE
(
0
,
(
0x10
-
1
),
0x0
,
0x0
);
cmdpara
=
cmd_id
;
source
=
cluster
?
SRC_A7
:
SRC_A15
;
hisi_ipc_send_cmd_with_ack
(
source
,
mailbox
,
cmdtype
,
cmdpara
);
}
int
hisi_ipc_init
(
void
)
{
int
ret
=
0
;
enum
lpm3_mbox_id
i
=
LPM3_MBX0
;
mmio_write_32
(
IPC_LOCK_REG
,
IPC_UNLOCK_VALUE
);
for
(
i
=
LPM3_MBX0
;
i
<=
LPM3_MBX4
;
i
++
)
{
mmio_write_32
(
IPC_MBX_MODE_REG
(
i
),
1
);
mmio_write_32
(
IPC_MBX_IMASK_REG
(
i
),
((
int
)
SRC_IOM3
|
(
int
)
SRC_A15
|
(
int
)
SRC_A7
));
mmio_write_32
(
IPC_MBX_ICLR_REG
(
i
),
SRC_A7
);
}
return
ret
;
}
plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <../hikey960_def.h>
#include <hisi_ipc.h>
#include "hisi_pwrc.h"
/* resource lock api */
#define RES0_LOCK_BASE (SOC_PCTRL_RESOURCE0_LOCK_ADDR(PCTRL_BASE))
#define RES1_LOCK_BASE (SOC_PCTRL_RESOURCE1_LOCK_ADDR(PCTRL_BASE))
#define RES2_LOCK_BASE (SOC_PCTRL_RESOURCE2_LOCK_ADDR(PCTRL_BASE))
#define LOCK_BIT (0x1 << 28)
#define LOCK_ID_MASK (0x7 << 29)
#define CPUIDLE_LOCK_ID(core) (0x6 - (core))
#define LOCK_UNLOCK_OFFSET 0x4
#define LOCK_STAT_OFFSET 0x8
#define CLUSTER0_CPUS_ONLINE_MASK (0xF << 16)
#define CLUSTER1_CPUS_ONLINE_MASK (0xF << 20)
/* cpu hotplug flag api */
#define SCTRL_BASE (SOC_ACPU_SCTRL_BASE_ADDR)
#define REG_SCBAKDATA3_OFFSET (SOC_SCTRL_SCBAKDATA3_ADDR(SCTRL_BASE))
#define REG_SCBAKDATA8_OFFSET (SOC_SCTRL_SCBAKDATA8_ADDR(SCTRL_BASE))
#define REG_SCBAKDATA9_OFFSET (SOC_SCTRL_SCBAKDATA9_ADDR(SCTRL_BASE))
#define CPUIDLE_FLAG_REG(cluster) \
((cluster == 0) ? REG_SCBAKDATA8_OFFSET : \
REG_SCBAKDATA9_OFFSET)
#define CLUSTER_IDLE_BIT BIT(8)
#define CLUSTER_IDLE_MASK (CLUSTER_IDLE_BIT | 0x0F)
#define AP_SUSPEND_FLAG (1 << 16)
#define CLUSTER_PWDN_IDLE (0<<28)
#define CLUSTER_PWDN_HOTPLUG (1<<28)
#define CLUSTER_PWDN_SR (2<<28)
#define CLUSTER0_PDC_OFFSET 0x260
#define CLUSTER1_PDC_OFFSET 0x300
#define PDC_EN_OFFSET 0x0
#define PDC_COREPWRINTEN_OFFSET 0x4
#define PDC_COREPWRINTSTAT_OFFSET 0x8
#define PDC_COREGICMASK_OFFSET 0xc
#define PDC_COREPOWERUP_OFFSET 0x10
#define PDC_COREPOWERDN_OFFSET 0x14
#define PDC_COREPOWERSTAT_OFFSET 0x18
#define PDC_COREPWRSTAT_MASK (0XFFFF)
enum
pdc_gic_mask
{
PDC_MASK_GIC_WAKE_IRQ
,
PDC_UNMASK_GIC_WAKE_IRQ
};
enum
pdc_finish_int_mask
{
PDC_DISABLE_FINISH_INT
,
PDC_ENABLE_FINISH_INT
};
static
void
hisi_resource_lock
(
unsigned
int
lockid
,
unsigned
int
offset
)
{
unsigned
int
lock_id
=
(
lockid
<<
29
);
unsigned
int
lock_val
=
lock_id
|
LOCK_BIT
;
unsigned
int
lock_state
;
do
{
mmio_write_32
(
offset
,
lock_val
);
lock_state
=
mmio_read_32
(
LOCK_STAT_OFFSET
+
(
uintptr_t
)
offset
);
}
while
((
lock_state
&
LOCK_ID_MASK
)
!=
lock_id
);
}
static
void
hisi_resource_unlock
(
unsigned
int
lockid
,
unsigned
int
offset
)
{
unsigned
int
lock_val
=
(
lockid
<<
29
)
|
LOCK_BIT
;
mmio_write_32
((
LOCK_UNLOCK_OFFSET
+
(
uintptr_t
)
offset
),
lock_val
);
}
static
void
hisi_cpuhotplug_lock
(
unsigned
int
cluster
,
unsigned
int
core
)
{
unsigned
int
lock_id
;
lock_id
=
(
cluster
<<
2
)
+
core
;
hisi_resource_lock
(
lock_id
,
RES2_LOCK_BASE
);
}
static
void
hisi_cpuhotplug_unlock
(
unsigned
int
cluster
,
unsigned
int
core
)
{
unsigned
int
lock_id
;
lock_id
=
(
cluster
<<
2
)
+
core
;
hisi_resource_unlock
(
lock_id
,
RES2_LOCK_BASE
);
}
/* get the resource lock */
void
hisi_cpuidle_lock
(
unsigned
int
cluster
,
unsigned
int
core
)
{
unsigned
int
offset
=
(
cluster
==
0
?
RES0_LOCK_BASE
:
RES1_LOCK_BASE
);
hisi_resource_lock
(
CPUIDLE_LOCK_ID
(
core
),
offset
);
}
/* release the resource lock */
void
hisi_cpuidle_unlock
(
unsigned
int
cluster
,
unsigned
int
core
)
{
unsigned
int
offset
=
(
cluster
==
0
?
RES0_LOCK_BASE
:
RES1_LOCK_BASE
);
hisi_resource_unlock
(
CPUIDLE_LOCK_ID
(
core
),
offset
);
}
unsigned
int
hisi_get_cpuidle_flag
(
unsigned
int
cluster
)
{
unsigned
int
val
;
val
=
mmio_read_32
(
CPUIDLE_FLAG_REG
(
cluster
));
val
&=
0xF
;
return
val
;
}
void
hisi_set_cpuidle_flag
(
unsigned
int
cluster
,
unsigned
int
core
)
{
mmio_setbits_32
(
CPUIDLE_FLAG_REG
(
cluster
),
BIT
(
core
));
}
void
hisi_clear_cpuidle_flag
(
unsigned
int
cluster
,
unsigned
int
core
)
{
mmio_clrbits_32
(
CPUIDLE_FLAG_REG
(
cluster
),
BIT
(
core
));
}
int
hisi_test_ap_suspend_flag
(
unsigned
int
cluster
)
{
unsigned
int
val
;
val
=
mmio_read_32
(
CPUIDLE_FLAG_REG
(
cluster
));
val
&=
AP_SUSPEND_FLAG
;
return
!!
val
;
}
void
hisi_set_cluster_pwdn_flag
(
unsigned
int
cluster
,
unsigned
int
core
,
unsigned
int
value
)
{
unsigned
int
val
;
hisi_cpuhotplug_lock
(
cluster
,
core
);
val
=
mmio_read_32
(
REG_SCBAKDATA3_OFFSET
);
val
=
(
value
<<
(
cluster
<<
1
))
|
(
val
&
0xFFFFFFF
);
mmio_write_32
(
REG_SCBAKDATA3_OFFSET
,
val
);
hisi_cpuhotplug_unlock
(
cluster
,
core
);
}
unsigned
int
hisi_get_cpu_boot_flag
(
unsigned
int
cluster
,
unsigned
int
core
)
{
unsigned
int
val
;
hisi_cpuhotplug_lock
(
cluster
,
core
);
val
=
mmio_read_32
(
REG_SCBAKDATA3_OFFSET
);
val
=
val
>>
(
16
+
(
cluster
<<
2
));
val
&=
0xF
;
hisi_cpuhotplug_unlock
(
cluster
,
core
);
return
val
;
}
unsigned
int
hisi_test_cpu_down
(
unsigned
int
cluster
,
unsigned
int
core
)
{
unsigned
int
val
;
hisi_cpuhotplug_lock
(
cluster
,
core
);
val
=
mmio_read_32
(
REG_SCBAKDATA3_OFFSET
);
val
=
val
>>
(
16
+
(
cluster
<<
2
));
val
&=
0xF
;
hisi_cpuhotplug_unlock
(
cluster
,
core
);
if
(
val
)
return
0
;
else
return
1
;
}
void
hisi_set_cpu_boot_flag
(
unsigned
int
cluster
,
unsigned
int
core
)
{
unsigned
int
flag
=
BIT
((
cluster
<<
2
)
+
core
+
16
);
hisi_cpuhotplug_lock
(
cluster
,
core
);
mmio_setbits_32
(
REG_SCBAKDATA3_OFFSET
,
flag
);
hisi_cpuhotplug_unlock
(
cluster
,
core
);
}
void
hisi_clear_cpu_boot_flag
(
unsigned
int
cluster
,
unsigned
int
core
)
{
unsigned
int
flag
=
BIT
((
cluster
<<
2
)
+
core
+
16
);
hisi_cpuhotplug_lock
(
cluster
,
core
);
mmio_clrbits_32
(
REG_SCBAKDATA3_OFFSET
,
flag
);
hisi_cpuhotplug_unlock
(
cluster
,
core
);
}
int
cluster_is_powered_on
(
unsigned
int
cluster
)
{
unsigned
int
val
=
mmio_read_32
(
REG_SCBAKDATA3_OFFSET
);
int
ret
;
if
(
cluster
==
0
)
ret
=
val
&
CLUSTER0_CPUS_ONLINE_MASK
;
else
ret
=
val
&
CLUSTER1_CPUS_ONLINE_MASK
;
return
!!
ret
;
}
static
void
*
hisi_get_pdc_addr
(
unsigned
int
cluster
)
{
void
*
pdc_base_addr
;
uintptr_t
addr
;
if
(
cluster
==
0
)
addr
=
SOC_CRGPERIPH_A53_PDCEN_ADDR
(
CRG_BASE
);
else
addr
=
SOC_CRGPERIPH_MAIA_PDCEN_ADDR
(
CRG_BASE
);
pdc_base_addr
=
(
void
*
)
addr
;
return
pdc_base_addr
;
}
static
unsigned
int
hisi_get_pdc_stat
(
unsigned
int
cluster
)
{
void
*
pdc_base_addr
=
hisi_get_pdc_addr
(
cluster
);
unsigned
int
val
;
val
=
mmio_read_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREPOWERSTAT_OFFSET
);
return
val
;
}
int
hisi_test_pwrdn_allcores
(
unsigned
int
cluster
,
unsigned
int
core
)
{
unsigned
int
mask
=
0xf
<<
(
core
*
4
);
unsigned
int
pdc_stat
=
hisi_get_pdc_stat
(
cluster
);
unsigned
int
boot_flag
=
hisi_get_cpu_boot_flag
(
cluster
,
core
);
unsigned
int
cpuidle_flag
=
hisi_get_cpuidle_flag
(
cluster
);
mask
=
(
PDC_COREPWRSTAT_MASK
&
(
~
mask
));
pdc_stat
&=
mask
;
if
((
boot_flag
^
cpuidle_flag
)
||
pdc_stat
)
return
0
;
else
return
1
;
}
void
hisi_disable_pdc
(
unsigned
int
cluster
)
{
void
*
pdc_base_addr
=
hisi_get_pdc_addr
(
cluster
);
mmio_write_32
((
uintptr_t
)
pdc_base_addr
,
0x0
);
}
void
hisi_enable_pdc
(
unsigned
int
cluster
)
{
void
*
pdc_base_addr
=
hisi_get_pdc_addr
(
cluster
);
mmio_write_32
((
uintptr_t
)
pdc_base_addr
,
0x1
);
}
static
inline
void
hisi_pdc_set_intmask
(
void
*
pdc_base_addr
,
unsigned
int
core
,
enum
pdc_finish_int_mask
intmask
)
{
unsigned
int
val
;
val
=
mmio_read_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREPWRINTEN_OFFSET
);
if
(
intmask
==
PDC_ENABLE_FINISH_INT
)
val
|=
BIT
(
core
);
else
val
&=
~
BIT
(
core
);
mmio_write_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREPWRINTEN_OFFSET
,
val
);
}
static
inline
void
hisi_pdc_set_gicmask
(
void
*
pdc_base_addr
,
unsigned
int
core
,
enum
pdc_gic_mask
gicmask
)
{
unsigned
int
val
;
val
=
mmio_read_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREGICMASK_OFFSET
);
if
(
gicmask
==
PDC_MASK_GIC_WAKE_IRQ
)
val
|=
BIT
(
core
);
else
val
&=
~
BIT
(
core
);
mmio_write_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREGICMASK_OFFSET
,
val
);
}
void
hisi_pdc_mask_cluster_wakeirq
(
unsigned
int
cluster
)
{
int
i
;
void
*
pdc_base_addr
=
hisi_get_pdc_addr
(
cluster
);
for
(
i
=
0
;
i
<
4
;
i
++
)
hisi_pdc_set_gicmask
(
pdc_base_addr
,
i
,
PDC_MASK_GIC_WAKE_IRQ
);
}
static
void
hisi_pdc_powerup_core
(
unsigned
int
cluster
,
unsigned
int
core
,
enum
pdc_gic_mask
gicmask
,
enum
pdc_finish_int_mask
intmask
)
{
void
*
pdc_base_addr
=
hisi_get_pdc_addr
(
cluster
);
mmio_write_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREPOWERUP_OFFSET
,
BIT
(
core
));
}
static
void
hisi_pdc_powerdn_core
(
unsigned
int
cluster
,
unsigned
int
core
,
enum
pdc_gic_mask
gicmask
,
enum
pdc_finish_int_mask
intmask
)
{
void
*
pdc_base_addr
=
hisi_get_pdc_addr
(
cluster
);
mmio_write_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREPOWERDN_OFFSET
,
BIT
(
core
));
}
void
hisi_powerup_core
(
unsigned
int
cluster
,
unsigned
int
core
)
{
hisi_pdc_powerup_core
(
cluster
,
core
,
PDC_MASK_GIC_WAKE_IRQ
,
PDC_DISABLE_FINISH_INT
);
}
void
hisi_powerdn_core
(
unsigned
int
cluster
,
unsigned
int
core
)
{
hisi_pdc_powerdn_core
(
cluster
,
core
,
PDC_MASK_GIC_WAKE_IRQ
,
PDC_DISABLE_FINISH_INT
);
}
void
hisi_powerup_cluster
(
unsigned
int
cluster
,
unsigned
int
core
)
{
hisi_ipc_pm_on_off
(
core
,
cluster
,
PM_ON
);
}
void
hisi_powerdn_cluster
(
unsigned
int
cluster
,
unsigned
int
core
)
{
void
*
pdc_base_addr
=
hisi_get_pdc_addr
(
cluster
);
hisi_set_cluster_pwdn_flag
(
cluster
,
core
,
CLUSTER_PWDN_HOTPLUG
);
mmio_write_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREPWRINTEN_OFFSET
,
(
0x10001
<<
core
));
mmio_write_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREPOWERDN_OFFSET
,
BIT
(
core
));
}
void
hisi_enter_core_idle
(
unsigned
int
cluster
,
unsigned
int
core
)
{
hisi_pdc_powerdn_core
(
cluster
,
core
,
PDC_UNMASK_GIC_WAKE_IRQ
,
PDC_DISABLE_FINISH_INT
);
}
void
hisi_enter_cluster_idle
(
unsigned
int
cluster
,
unsigned
int
core
)
{
void
*
pdc_base_addr
=
hisi_get_pdc_addr
(
cluster
);
hisi_set_cluster_pwdn_flag
(
cluster
,
core
,
CLUSTER_PWDN_IDLE
);
mmio_write_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREPWRINTEN_OFFSET
,
(
0x10001
<<
core
));
mmio_write_32
((
uintptr_t
)
pdc_base_addr
+
PDC_COREPOWERDN_OFFSET
,
BIT
(
core
));
}
void
hisi_enter_ap_suspend
(
unsigned
int
cluster
,
unsigned
int
core
)
{
hisi_ipc_pm_suspend
(
core
,
cluster
,
0x3
);
}
plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __HISI_PWRC_H__
#define __HISI_PWRC_H__
#include <hi3660.h>
#include <hi3660_crg.h>
#define PCTRL_BASE (PCTRL_REG_BASE)
#define CRG_BASE (CRG_REG_BASE)
#define SOC_CRGPERIPH_A53_PDCEN_ADDR(base) ((base) + (0x260))
#define SOC_CRGPERIPH_MAIA_PDCEN_ADDR(base) ((base) + (0x300))
#define SOC_PCTRL_RESOURCE0_LOCK_ADDR(base) ((base) + (0x400))
#define SOC_PCTRL_RESOURCE0_UNLOCK_ADDR(base) ((base) + (0x404))
#define SOC_PCTRL_RESOURCE0_LOCK_ST_ADDR(base) ((base) + (0x408))
#define SOC_PCTRL_RESOURCE1_LOCK_ADDR(base) ((base) + (0x40C))
#define SOC_PCTRL_RESOURCE1_UNLOCK_ADDR(base) ((base) + (0x410))
#define SOC_PCTRL_RESOURCE1_LOCK_ST_ADDR(base) ((base) + (0x414))
#define SOC_PCTRL_RESOURCE2_LOCK_ADDR(base) ((base) + (0x418))
#define SOC_SCTRL_SCBAKDATA3_ADDR(base) ((base) + (0x418))
#define SOC_SCTRL_SCBAKDATA8_ADDR(base) ((base) + (0x42C))
#define SOC_SCTRL_SCBAKDATA9_ADDR(base) ((base) + (0x430))
#define SOC_ACPU_SCTRL_BASE_ADDR (0xFFF0A000)
void
hisi_cpuidle_lock
(
unsigned
int
cluster
,
unsigned
int
core
);
void
hisi_cpuidle_unlock
(
unsigned
int
cluster
,
unsigned
int
core
);
void
hisi_set_cpuidle_flag
(
unsigned
int
cluster
,
unsigned
int
core
);
void
hisi_clear_cpuidle_flag
(
unsigned
int
cluster
,
unsigned
int
core
);
void
hisi_set_cpu_boot_flag
(
unsigned
int
cluster
,
unsigned
int
core
);
void
hisi_clear_cpu_boot_flag
(
unsigned
int
cluster
,
unsigned
int
core
);
int
cluster_is_powered_on
(
unsigned
int
cluster
);
void
hisi_enter_core_idle
(
unsigned
int
cluster
,
unsigned
int
core
);
void
hisi_enter_cluster_idle
(
unsigned
int
cluster
,
unsigned
int
core
);
int
hisi_test_ap_suspend_flag
(
unsigned
int
cluster
);
void
hisi_enter_ap_suspend
(
unsigned
int
cluster
,
unsigned
int
core
);
/* pdc api */
void
hisi_pdc_mask_cluster_wakeirq
(
unsigned
int
cluster
);
int
hisi_test_pwrdn_allcores
(
unsigned
int
cluster
,
unsigned
int
core
);
void
hisi_disable_pdc
(
unsigned
int
cluster
);
void
hisi_enable_pdc
(
unsigned
int
cluster
);
void
hisi_powerup_core
(
unsigned
int
cluster
,
unsigned
int
core
);
void
hisi_powerdn_core
(
unsigned
int
cluster
,
unsigned
int
core
);
void
hisi_powerup_cluster
(
unsigned
int
cluster
,
unsigned
int
core
);
void
hisi_powerdn_cluster
(
unsigned
int
cluster
,
unsigned
int
core
);
unsigned
int
hisi_test_cpu_down
(
unsigned
int
cluster
,
unsigned
int
core
);
#endif
/* __HISI_PWRC_H__ */
plat/hisilicon/hikey960/hi3660_mailbox.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <debug.h>
#include <errno.h>
#include <hi3660_mailbox.h>
#include <mailbox.h>
#include <mmio.h>
#include <string.h>
typedef
struct
hi3660_chan
{
unsigned
char
src
;
unsigned
char
dst
;
unsigned
char
used
;
}
hi3660_chan_t
;
static
hi3660_chan_t
chan_map
[
MBX_MAX_CHANNELS
];
static
void
hi3660_mbox_check_state
(
int
chan
,
unsigned
int
state
)
{
unsigned
int
data
;
data
=
mmio_read_32
(
MBX_MODE
(
chan
));
assert
((
data
&
(
MBX_MODE_AUTO_ANSWER
|
MBX_MODE_AUTO_LINK
))
==
0
);
data
&=
MBX_MODE_STATE_STATUS_MASK
;
assert
(
data
==
state
);
(
void
)
state
;
}
static
int
hi3660_mbox_send
(
int
chan
,
void
*
message
,
int
len
)
{
int
i
;
unsigned
int
*
buf
;
unsigned
int
data
;
assert
((
chan
>=
0
)
&&
(
chan
<
MBX_MAX_CHANNELS
)
&&
(
message
!=
NULL
)
&&
(
len
<=
MBX_MAX_DATA_LEN
));
assert
((
chan_map
[
chan
].
used
!=
0
)
&&
(
chan_map
[
chan
].
src
!=
0
)
&&
(
chan_map
[
chan
].
dst
!=
0
));
buf
=
(
unsigned
int
*
)
message
;
len
=
((
len
+
3
)
>>
2
);
/* convert to word count */
for
(
i
=
0
;
i
<
len
;
i
++
)
mmio_write_32
(
MBX_DATA0
(
chan
)
+
(
i
<<
2
),
*
(
buf
+
i
));
/* send out */
mmio_write_32
(
MBX_SEND
(
chan
),
chan_map
[
chan
].
src
);
do
{
data
=
mmio_read_32
(
MBX_ICLR
(
chan
));
}
while
((
data
&
chan_map
[
chan
].
src
)
==
0
);
/* ack */
mmio_write_32
(
MBX_ICLR
(
chan
),
chan_map
[
chan
].
src
);
return
0
;
}
static
int
hi3660_mbox_recv
(
int
chan
,
void
*
message
,
int
*
len
)
{
unsigned
int
*
buf
,
data
;
int
i
;
assert
((
chan
>=
0
)
&&
(
chan
<
MBX_MAX_CHANNELS
)
&&
(
message
!=
NULL
)
&&
(
len
!=
NULL
));
assert
((
chan_map
[
chan
].
used
!=
0
)
&&
(
chan_map
[
chan
].
src
!=
0
)
&&
(
chan_map
[
chan
].
dst
!=
0
));
/* wait IPC event */
do
{
data
=
mmio_read_32
(
MBX_MODE
(
chan
));
}
while
((
data
&
MBX_MODE_STATE_STATUS_MASK
)
!=
MBX_MODE_STATE_DEST
);
/* wait to clear interrupt */
do
{
data
=
mmio_read_32
(
MBX_ICLR
(
chan
));
}
while
(
data
==
0
);
do
{
mmio_write_32
(
MBX_ICLR
(
chan
),
chan_map
[
chan
].
dst
);
data
=
mmio_read_32
(
MBX_ICLR
(
chan
));
}
while
(
data
);
/* read data from IPC */
buf
=
(
unsigned
int
*
)
message
;
for
(
i
=
0
;
i
<
MBX_MAX_DATA_LEN
;
i
+=
4
)
*
(
buf
+
(
i
>>
2
))
=
mmio_read_32
(
MBX_DATA0
(
chan
)
+
i
);
*
len
=
MBX_MAX_DATA_LEN
;
/* ack */
mmio_write_32
(
MBX_SEND
(
chan
),
chan_map
[
chan
].
dst
);
return
0
;
}
static
int
hi3660_mbox_request
(
int
chan
,
int
direction
)
{
unsigned
int
data
;
unsigned
int
src
,
dst
;
assert
((
chan
>=
0
)
&&
(
chan
<
MBX_MAX_CHANNELS
));
if
(
direction
==
MAILBOX_DIR_TX
)
{
src
=
CPU_A53
;
dst
=
CPU_LPM3
;
}
else
if
(
direction
==
MAILBOX_DIR_RX
)
{
src
=
CPU_LPM3
;
dst
=
CPU_A53
;
}
else
assert
(
0
);
mmio_write_32
(
MBX_SOURCE
(
chan
),
src
);
data
=
mmio_read_32
(
MBX_SOURCE
(
chan
));
assert
(
data
==
src
);
/* mask all interrupts */
mmio_write_32
(
MBX_IMASK
(
chan
),
CPU_MASK
);
/* unmask interrupt */
mmio_write_32
(
MBX_IMASK
(
chan
),
~
(
src
|
dst
));
/* set destination */
mmio_write_32
(
MBX_DCLEAR
(
chan
),
(
~
dst
)
&
CPU_MASK
);
mmio_write_32
(
MBX_DSET
(
chan
),
dst
);
data
=
mmio_read_32
(
MBX_DSTATUS
(
chan
));
assert
((
data
&
dst
)
!=
0
);
/* clear auto link & auto answer */
data
=
mmio_read_32
(
MBX_MODE
(
chan
));
data
&=
~
(
MBX_MODE_AUTO_ANSWER
|
MBX_MODE_AUTO_LINK
);
mmio_write_32
(
MBX_MODE
(
chan
),
data
);
hi3660_mbox_check_state
(
chan
,
MBX_MODE_STATE_SOURCE
);
chan_map
[
chan
].
used
=
1
;
chan_map
[
chan
].
src
=
src
;
chan_map
[
chan
].
dst
=
dst
;
return
0
;
}
static
void
hi3660_mbox_free
(
int
chan
)
{
assert
((
chan
>=
0
)
&&
(
chan
<
MBX_MAX_CHANNELS
));
}
static
mbox_ops_t
hi3660_mbox_ops
=
{
.
send
=
hi3660_mbox_send
,
.
recv
=
hi3660_mbox_recv
,
.
request
=
hi3660_mbox_request
,
.
free
=
hi3660_mbox_free
,
};
int
hi3660_mbox_init
(
mbox_params_t
*
params
)
{
int
result
;
unsigned
int
data
;
assert
(
params
!=
NULL
);
result
=
mbox_init
(
&
hi3660_mbox_ops
,
params
);
assert
(
result
==
0
);
memset
(
&
chan_map
,
0
,
sizeof
(
chan_map
));
/* unlock mailbox */
data
=
mmio_read_32
(
IPC_LOCK
);
while
(
data
==
MBX_IPC_LOCKED
)
{
mmio_write_32
(
IPC_LOCK
,
MBX_IPC_UNLOCK_MAGIC
);
data
=
mmio_read_32
(
IPC_LOCK
);
}
(
void
)
result
;
return
0
;
}
plat/hisilicon/hikey960/hikey960_bl1_setup.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <arm_gic.h>
#include <assert.h>
#include <bl_common.h>
#include <console.h>
#include <debug.h>
#include <delay_timer.h>
#include <dw_ufs.h>
#include <errno.h>
#include <gicv2.h>
#include <hi3660.h>
#include <mmio.h>
#include <generic_delay_timer.h>
#include <platform.h>
#include <platform_def.h>
#include <string.h>
#include <tbbr/tbbr_img_desc.h>
#include <ufs.h>
#include "../../bl1/bl1_private.h"
#include "hikey960_def.h"
#include "hikey960_private.h"
enum
{
BOOT_MODE_RECOVERY
=
0
,
BOOT_MODE_NORMAL
,
BOOT_MODE_MASK
=
1
,
};
/*
* Declarations of linker defined symbols which will help us find the layout
* of trusted RAM
*/
extern
unsigned
long
__COHERENT_RAM_START__
;
extern
unsigned
long
__COHERENT_RAM_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 BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
/* Data structure which holds the extents of the trusted RAM for BL1 */
static
meminfo_t
bl1_tzram_layout
;
/******************************************************************************
* On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
* interrupts.
*****************************************************************************/
const
unsigned
int
g0_interrupt_array
[]
=
{
IRQ_SEC_PHY_TIMER
,
IRQ_SEC_SGI_0
};
const
gicv2_driver_data_t
hikey960_gic_data
=
{
.
gicd_base
=
GICD_REG_BASE
,
.
gicc_base
=
GICC_REG_BASE
,
.
g0_interrupt_num
=
ARRAY_SIZE
(
g0_interrupt_array
),
.
g0_interrupt_array
=
g0_interrupt_array
,
};
meminfo_t
*
bl1_plat_sec_mem_layout
(
void
)
{
return
&
bl1_tzram_layout
;
}
/*
* Perform any BL1 specific platform actions.
*/
void
bl1_early_platform_setup
(
void
)
{
const
size_t
bl1_size
=
BL1_RAM_LIMIT
-
BL1_RAM_BASE
;
unsigned
int
id
,
uart_base
;
generic_delay_timer_init
();
hikey960_read_boardid
(
&
id
);
if
(
id
==
5300
)
uart_base
=
PL011_UART5_BASE
;
else
uart_base
=
PL011_UART6_BASE
;
/* Initialize the console to provide early debug support */
console_init
(
uart_base
,
PL011_UART_CLK_IN_HZ
,
PL011_BAUDRATE
);
/* Allow BL1 to see the whole Trusted RAM */
bl1_tzram_layout
.
total_base
=
BL1_RW_BASE
;
bl1_tzram_layout
.
total_size
=
BL1_RW_SIZE
;
/* Calculate how much RAM BL1 is using and how much remains free */
bl1_tzram_layout
.
free_base
=
BL1_RW_BASE
;
bl1_tzram_layout
.
free_size
=
BL1_RW_SIZE
;
reserve_mem
(
&
bl1_tzram_layout
.
free_base
,
&
bl1_tzram_layout
.
free_size
,
BL1_RAM_BASE
,
bl1_size
);
INFO
(
"BL1: 0x%lx - 0x%lx [size = %lu]
\n
"
,
BL1_RAM_BASE
,
BL1_RAM_LIMIT
,
bl1_size
);
}
/*
* Perform the very early platform specific architecture setup here. At the
* moment this only does basic initialization. Later architectural setup
* (bl1_arch_setup()) does not do anything platform specific.
*/
void
bl1_plat_arch_setup
(
void
)
{
hikey960_init_mmu_el3
(
bl1_tzram_layout
.
total_base
,
bl1_tzram_layout
.
total_size
,
BL1_RO_BASE
,
BL1_RO_LIMIT
,
BL1_COHERENT_RAM_BASE
,
BL1_COHERENT_RAM_LIMIT
);
}
static
void
hikey960_clk_init
(
void
)
{
/* change ldi0 sel to ppll2 */
mmio_write_32
(
0xfff350b4
,
0xf0002000
);
/* ldi0 20' */
mmio_write_32
(
0xfff350bc
,
0xfc004c00
);
}
static
void
hikey960_pmu_init
(
void
)
{
/* clear np_xo_abb_dig_START bit in PMIC_CLK_TOP_CTRL7 register */
mmio_clrbits_32
(
PMU_SSI0_CLK_TOP_CTRL7_REG
,
NP_XO_ABB_DIG
);
}
static
void
hikey960_enable_ppll3
(
void
)
{
/* enable ppll3 */
mmio_write_32
(
PMC_PPLL3_CTRL0_REG
,
0x4904305
);
mmio_write_32
(
PMC_PPLL3_CTRL1_REG
,
0x2300000
);
mmio_write_32
(
PMC_PPLL3_CTRL1_REG
,
0x6300000
);
}
static
void
bus_idle_clear
(
unsigned
int
value
)
{
unsigned
int
pmc_value
,
value1
,
value2
;
int
timeout
=
100
;
pmc_value
=
value
<<
16
;
pmc_value
&=
~
value
;
mmio_write_32
(
PMC_NOC_POWER_IDLEREQ_REG
,
pmc_value
);
for
(;;)
{
value1
=
(
unsigned
int
)
mmio_read_32
(
PMC_NOC_POWER_IDLEACK_REG
);
value2
=
(
unsigned
int
)
mmio_read_32
(
PMC_NOC_POWER_IDLE_REG
);
if
(((
value1
&
value
)
==
0
)
&&
((
value2
&
value
)
==
0
))
break
;
udelay
(
1
);
timeout
--
;
if
(
timeout
<=
0
)
{
WARN
(
"%s timeout
\n
"
,
__func__
);
break
;
}
}
}
static
void
set_vivobus_power_up
(
void
)
{
/* clk enable */
mmio_write_32
(
CRG_CLKDIV20_REG
,
0x00020002
);
mmio_write_32
(
CRG_PEREN0_REG
,
0x00001000
);
}
static
void
set_dss_power_up
(
void
)
{
/* set edc0 133MHz = 1600MHz / 12 */
mmio_write_32
(
CRG_CLKDIV5_REG
,
0x003f000b
);
/* set ldi0 ppl0 */
mmio_write_32
(
CRG_CLKDIV3_REG
,
0xf0001000
);
/* set ldi0 133MHz, 1600MHz / 12 */
mmio_write_32
(
CRG_CLKDIV5_REG
,
0xfc002c00
);
/* mtcmos on */
mmio_write_32
(
CRG_PERPWREN_REG
,
0x00000020
);
udelay
(
100
);
/* DISP CRG */
mmio_write_32
(
CRG_PERRSTDIS4_REG
,
0x00000010
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV18_REG
,
0x01400140
);
mmio_write_32
(
CRG_PEREN0_REG
,
0x00002000
);
mmio_write_32
(
CRG_PEREN3_REG
,
0x0003b000
);
udelay
(
1
);
/* clk disable */
mmio_write_32
(
CRG_PERDIS3_REG
,
0x0003b000
);
mmio_write_32
(
CRG_PERDIS0_REG
,
0x00002000
);
mmio_write_32
(
CRG_CLKDIV18_REG
,
0x01400000
);
udelay
(
1
);
/* iso disable */
mmio_write_32
(
CRG_ISODIS_REG
,
0x00000040
);
/* unreset */
mmio_write_32
(
CRG_PERRSTDIS4_REG
,
0x00000006
);
mmio_write_32
(
CRG_PERRSTDIS3_REG
,
0x00000c00
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV18_REG
,
0x01400140
);
mmio_write_32
(
CRG_PEREN0_REG
,
0x00002000
);
mmio_write_32
(
CRG_PEREN3_REG
,
0x0003b000
);
/* bus idle clear */
bus_idle_clear
(
PMC_NOC_POWER_IDLEREQ_DSS
);
/* set edc0 400MHz for 2K 1600MHz / 4 */
mmio_write_32
(
CRG_CLKDIV5_REG
,
0x003f0003
);
/* set ldi 266MHz, 1600MHz / 6 */
mmio_write_32
(
CRG_CLKDIV5_REG
,
0xfc001400
);
}
static
void
set_vcodec_power_up
(
void
)
{
/* clk enable */
mmio_write_32
(
CRG_CLKDIV20_REG
,
0x00040004
);
mmio_write_32
(
CRG_PEREN0_REG
,
0x00000060
);
mmio_write_32
(
CRG_PEREN2_REG
,
0x10000000
);
/* unreset */
mmio_write_32
(
CRG_PERRSTDIS0_REG
,
0x00000018
);
/* bus idle clear */
bus_idle_clear
(
PMC_NOC_POWER_IDLEREQ_VCODEC
);
}
static
void
set_vdec_power_up
(
void
)
{
/* mtcmos on */
mmio_write_32
(
CRG_PERPWREN_REG
,
0x00000004
);
udelay
(
100
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV18_REG
,
0x80008000
);
mmio_write_32
(
CRG_PEREN2_REG
,
0x20080000
);
mmio_write_32
(
CRG_PEREN3_REG
,
0x00000800
);
udelay
(
1
);
/* clk disable */
mmio_write_32
(
CRG_PERDIS3_REG
,
0x00000800
);
mmio_write_32
(
CRG_PERDIS2_REG
,
0x20080000
);
mmio_write_32
(
CRG_CLKDIV18_REG
,
0x80000000
);
udelay
(
1
);
/* iso disable */
mmio_write_32
(
CRG_ISODIS_REG
,
0x00000004
);
/* unreset */
mmio_write_32
(
CRG_PERRSTDIS3_REG
,
0x00000200
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV18_REG
,
0x80008000
);
mmio_write_32
(
CRG_PEREN2_REG
,
0x20080000
);
mmio_write_32
(
CRG_PEREN3_REG
,
0x00000800
);
/* bus idle clear */
bus_idle_clear
(
PMC_NOC_POWER_IDLEREQ_VDEC
);
}
static
void
set_venc_power_up
(
void
)
{
/* set venc ppll3 */
mmio_write_32
(
CRG_CLKDIV8_REG
,
0x18001000
);
/* set venc 258MHz, 1290MHz / 5 */
mmio_write_32
(
CRG_CLKDIV8_REG
,
0x07c00100
);
/* mtcmos on */
mmio_write_32
(
CRG_PERPWREN_REG
,
0x00000002
);
udelay
(
100
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV19_REG
,
0x00010001
);
mmio_write_32
(
CRG_PEREN2_REG
,
0x40000100
);
mmio_write_32
(
CRG_PEREN3_REG
,
0x00000400
);
udelay
(
1
);
/* clk disable */
mmio_write_32
(
CRG_PERDIS3_REG
,
0x00000400
);
mmio_write_32
(
CRG_PERDIS2_REG
,
0x40000100
);
mmio_write_32
(
CRG_CLKDIV19_REG
,
0x00010000
);
udelay
(
1
);
/* iso disable */
mmio_write_32
(
CRG_ISODIS_REG
,
0x00000002
);
/* unreset */
mmio_write_32
(
CRG_PERRSTDIS3_REG
,
0x00000100
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV19_REG
,
0x00010001
);
mmio_write_32
(
CRG_PEREN2_REG
,
0x40000100
);
mmio_write_32
(
CRG_PEREN3_REG
,
0x00000400
);
/* bus idle clear */
bus_idle_clear
(
PMC_NOC_POWER_IDLEREQ_VENC
);
/* set venc 645MHz, 1290MHz / 2 */
mmio_write_32
(
CRG_CLKDIV8_REG
,
0x07c00040
);
}
static
void
set_isp_power_up
(
void
)
{
/* mtcmos on */
mmio_write_32
(
CRG_PERPWREN_REG
,
0x00000001
);
udelay
(
100
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV18_REG
,
0x70007000
);
mmio_write_32
(
CRG_CLKDIV20_REG
,
0x00100010
);
mmio_write_32
(
CRG_PEREN5_REG
,
0x01000010
);
mmio_write_32
(
CRG_PEREN3_REG
,
0x0bf00000
);
udelay
(
1
);
/* clk disable */
mmio_write_32
(
CRG_PERDIS5_REG
,
0x01000010
);
mmio_write_32
(
CRG_PERDIS3_REG
,
0x0bf00000
);
mmio_write_32
(
CRG_CLKDIV18_REG
,
0x70000000
);
mmio_write_32
(
CRG_CLKDIV20_REG
,
0x00100000
);
udelay
(
1
);
/* iso disable */
mmio_write_32
(
CRG_ISODIS_REG
,
0x00000001
);
/* unreset */
mmio_write_32
(
CRG_ISP_SEC_RSTDIS_REG
,
0x0000002f
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV18_REG
,
0x70007000
);
mmio_write_32
(
CRG_CLKDIV20_REG
,
0x00100010
);
mmio_write_32
(
CRG_PEREN5_REG
,
0x01000010
);
mmio_write_32
(
CRG_PEREN3_REG
,
0x0bf00000
);
/* bus idle clear */
bus_idle_clear
(
PMC_NOC_POWER_IDLEREQ_ISP
);
/* csi clk enable */
mmio_write_32
(
CRG_PEREN3_REG
,
0x00700000
);
}
static
void
set_ivp_power_up
(
void
)
{
/* set ivp ppll0 */
mmio_write_32
(
CRG_CLKDIV0_REG
,
0xc0000000
);
/* set ivp 267MHz, 1600MHz / 6 */
mmio_write_32
(
CRG_CLKDIV0_REG
,
0x3c001400
);
/* mtcmos on */
mmio_write_32
(
CRG_PERPWREN_REG
,
0x00200000
);
udelay
(
100
);
/* IVP CRG unreset */
mmio_write_32
(
CRG_IVP_SEC_RSTDIS_REG
,
0x00000001
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV20_REG
,
0x02000200
);
mmio_write_32
(
CRG_PEREN4_REG
,
0x000000a8
);
udelay
(
1
);
/* clk disable */
mmio_write_32
(
CRG_PERDIS4_REG
,
0x000000a8
);
mmio_write_32
(
CRG_CLKDIV20_REG
,
0x02000000
);
udelay
(
1
);
/* iso disable */
mmio_write_32
(
CRG_ISODIS_REG
,
0x01000000
);
/* unreset */
mmio_write_32
(
CRG_IVP_SEC_RSTDIS_REG
,
0x00000002
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV20_REG
,
0x02000200
);
mmio_write_32
(
CRG_PEREN4_REG
,
0x000000a8
);
/* bus idle clear */
bus_idle_clear
(
PMC_NOC_POWER_IDLEREQ_IVP
);
/* set ivp 533MHz, 1600MHz / 3 */
mmio_write_32
(
CRG_CLKDIV0_REG
,
0x3c000800
);
}
static
void
set_audio_power_up
(
void
)
{
unsigned
int
ret
;
int
timeout
=
100
;
/* mtcmos on */
mmio_write_32
(
SCTRL_SCPWREN_REG
,
0x00000001
);
udelay
(
100
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV19_REG
,
0x80108010
);
mmio_write_32
(
SCTRL_SCCLKDIV2_REG
,
0x00010001
);
mmio_write_32
(
SCTRL_SCPEREN0_REG
,
0x0c000000
);
mmio_write_32
(
CRG_PEREN0_REG
,
0x04000000
);
mmio_write_32
(
CRG_PEREN5_REG
,
0x00000080
);
mmio_write_32
(
SCTRL_SCPEREN1_REG
,
0x0000000f
);
udelay
(
1
);
/* clk disable */
mmio_write_32
(
SCTRL_SCPERDIS1_REG
,
0x0000000f
);
mmio_write_32
(
SCTRL_SCPERDIS0_REG
,
0x0c000000
);
mmio_write_32
(
CRG_PERDIS5_REG
,
0x00000080
);
mmio_write_32
(
CRG_PERDIS0_REG
,
0x04000000
);
mmio_write_32
(
SCTRL_SCCLKDIV2_REG
,
0x00010000
);
mmio_write_32
(
CRG_CLKDIV19_REG
,
0x80100000
);
udelay
(
1
);
/* iso disable */
mmio_write_32
(
SCTRL_SCISODIS_REG
,
0x00000001
);
udelay
(
1
);
/* unreset */
mmio_write_32
(
SCTRL_PERRSTDIS1_SEC_REG
,
0x00000001
);
mmio_write_32
(
SCTRL_SCPERRSTDIS0_REG
,
0x00000780
);
/* clk enable */
mmio_write_32
(
CRG_CLKDIV19_REG
,
0x80108010
);
mmio_write_32
(
SCTRL_SCCLKDIV2_REG
,
0x00010001
);
mmio_write_32
(
SCTRL_SCPEREN0_REG
,
0x0c000000
);
mmio_write_32
(
CRG_PEREN0_REG
,
0x04000000
);
mmio_write_32
(
CRG_PEREN5_REG
,
0x00000080
);
mmio_write_32
(
SCTRL_SCPEREN1_REG
,
0x0000000f
);
/* bus idle clear */
mmio_write_32
(
SCTRL_SCPERCTRL7_REG
,
0x00040000
);
for
(;;)
{
ret
=
mmio_read_32
(
SCTRL_SCPERSTAT6_REG
);
if
(((
ret
&
(
1
<<
5
))
==
0
)
&&
((
ret
&
(
1
<<
8
))
==
0
))
break
;
udelay
(
1
);
timeout
--
;
if
(
timeout
<=
0
)
{
WARN
(
"%s timeout
\n
"
,
__func__
);
break
;
}
}
mmio_write_32
(
ASP_CFG_MMBUF_CTRL_REG
,
0x00ff0000
);
}
static
void
set_pcie_power_up
(
void
)
{
/* mtcmos on */
mmio_write_32
(
SCTRL_SCPWREN_REG
,
0x00000010
);
udelay
(
100
);
/* clk enable */
mmio_write_32
(
SCTRL_SCCLKDIV6_REG
,
0x08000800
);
mmio_write_32
(
SCTRL_SCPEREN2_REG
,
0x00104000
);
mmio_write_32
(
CRG_PEREN7_REG
,
0x000003a0
);
udelay
(
1
);
/* clk disable */
mmio_write_32
(
SCTRL_SCPERDIS2_REG
,
0x00104000
);
mmio_write_32
(
CRG_PERDIS7_REG
,
0x000003a0
);
mmio_write_32
(
SCTRL_SCCLKDIV6_REG
,
0x08000000
);
udelay
(
1
);
/* iso disable */
mmio_write_32
(
SCTRL_SCISODIS_REG
,
0x00000030
);
/* unreset */
mmio_write_32
(
CRG_PERRSTDIS3_REG
,
0x8c000000
);
/* clk enable */
mmio_write_32
(
SCTRL_SCCLKDIV6_REG
,
0x08000800
);
mmio_write_32
(
SCTRL_SCPEREN2_REG
,
0x00104000
);
mmio_write_32
(
CRG_PEREN7_REG
,
0x000003a0
);
}
static
void
ispfunc_enable
(
void
)
{
/* enable ispfunc. Otherwise powerup isp_srt causes exception. */
mmio_write_32
(
0xfff35000
,
0x00000008
);
mmio_write_32
(
0xfff35460
,
0xc004ffff
);
mmio_write_32
(
0xfff35030
,
0x02000000
);
mdelay
(
10
);
}
static
void
isps_control_clock
(
int
flag
)
{
unsigned
int
ret
;
/* flag: 0 -- disable clock, 1 -- enable clock */
if
(
flag
)
{
ret
=
mmio_read_32
(
0xe8420364
);
ret
|=
1
;
mmio_write_32
(
0xe8420364
,
ret
);
}
else
{
ret
=
mmio_read_32
(
0xe8420364
);
ret
&=
~
1
;
mmio_write_32
(
0xe8420364
,
ret
);
}
}
static
void
set_isp_srt_power_up
(
void
)
{
unsigned
int
ret
;
ispfunc_enable
();
/* reset */
mmio_write_32
(
0xe8420374
,
0x00000001
);
mmio_write_32
(
0xe8420350
,
0x00000000
);
mmio_write_32
(
0xe8420358
,
0x00000000
);
/* mtcmos on */
mmio_write_32
(
0xfff35150
,
0x00400000
);
udelay
(
100
);
/* clk enable */
isps_control_clock
(
1
);
udelay
(
1
);
isps_control_clock
(
0
);
udelay
(
1
);
/* iso disable */
mmio_write_32
(
0xfff35148
,
0x08000000
);
/* unreset */
ret
=
mmio_read_32
(
0xe8420374
);
ret
&=
~
0x1
;
mmio_write_32
(
0xe8420374
,
ret
);
/* clk enable */
isps_control_clock
(
1
);
/* enable clock gating for accessing csi registers */
mmio_write_32
(
0xe8420010
,
~
0
);
}
static
void
hikey960_regulator_enable
(
void
)
{
set_vivobus_power_up
();
hikey960_enable_ppll3
();
set_dss_power_up
();
set_vcodec_power_up
();
set_vdec_power_up
();
set_venc_power_up
();
set_isp_power_up
();
set_ivp_power_up
();
set_audio_power_up
();
set_pcie_power_up
();
set_isp_srt_power_up
();
}
static
void
hikey960_ufs_reset
(
void
)
{
unsigned
int
data
,
mask
;
mmio_write_32
(
CRG_PERDIS7_REG
,
1
<<
14
);
mmio_clrbits_32
(
UFS_SYS_PHY_CLK_CTRL_REG
,
BIT_SYSCTRL_REF_CLOCK_EN
);
do
{
data
=
mmio_read_32
(
UFS_SYS_PHY_CLK_CTRL_REG
);
}
while
(
data
&
BIT_SYSCTRL_REF_CLOCK_EN
);
/* use abb clk */
mmio_clrbits_32
(
UFS_SYS_UFS_SYSCTRL_REG
,
BIT_UFS_REFCLK_SRC_SE1
);
mmio_clrbits_32
(
UFS_SYS_PHY_ISO_EN_REG
,
BIT_UFS_REFCLK_ISO_EN
);
mmio_write_32
(
PCTRL_PERI_CTRL3_REG
,
(
1
<<
0
)
|
(
1
<<
16
));
mdelay
(
1
);
mmio_write_32
(
CRG_PEREN7_REG
,
1
<<
14
);
mmio_setbits_32
(
UFS_SYS_PHY_CLK_CTRL_REG
,
BIT_SYSCTRL_REF_CLOCK_EN
);
mmio_write_32
(
CRG_PERRSTEN3_REG
,
PERI_UFS_BIT
);
do
{
data
=
mmio_read_32
(
CRG_PERRSTSTAT3_REG
);
}
while
((
data
&
PERI_UFS_BIT
)
==
0
);
mmio_setbits_32
(
UFS_SYS_PSW_POWER_CTRL_REG
,
BIT_UFS_PSW_MTCMOS_EN
);
mdelay
(
1
);
mmio_setbits_32
(
UFS_SYS_HC_LP_CTRL_REG
,
BIT_SYSCTRL_PWR_READY
);
mmio_write_32
(
UFS_SYS_UFS_DEVICE_RESET_CTRL_REG
,
MASK_UFS_DEVICE_RESET
);
/* clear SC_DIV_UFS_PERIBUS */
mask
=
SC_DIV_UFS_PERIBUS
<<
16
;
mmio_write_32
(
CRG_CLKDIV17_REG
,
mask
);
/* set SC_DIV_UFSPHY_CFG(3) */
mask
=
SC_DIV_UFSPHY_CFG_MASK
<<
16
;
data
=
SC_DIV_UFSPHY_CFG
(
3
);
mmio_write_32
(
CRG_CLKDIV16_REG
,
mask
|
data
);
data
=
mmio_read_32
(
UFS_SYS_PHY_CLK_CTRL_REG
);
data
&=
~
MASK_SYSCTRL_CFG_CLOCK_FREQ
;
data
|=
0x39
;
mmio_write_32
(
UFS_SYS_PHY_CLK_CTRL_REG
,
data
);
mmio_clrbits_32
(
UFS_SYS_PHY_CLK_CTRL_REG
,
MASK_SYSCTRL_REF_CLOCK_SEL
);
mmio_setbits_32
(
UFS_SYS_CLOCK_GATE_BYPASS_REG
,
MASK_UFS_CLK_GATE_BYPASS
);
mmio_setbits_32
(
UFS_SYS_UFS_SYSCTRL_REG
,
MASK_UFS_SYSCTRL_BYPASS
);
mmio_setbits_32
(
UFS_SYS_PSW_CLK_CTRL_REG
,
BIT_SYSCTRL_PSW_CLK_EN
);
mmio_clrbits_32
(
UFS_SYS_PSW_POWER_CTRL_REG
,
BIT_UFS_PSW_ISO_CTRL
);
mmio_clrbits_32
(
UFS_SYS_PHY_ISO_EN_REG
,
BIT_UFS_PHY_ISO_CTRL
);
mmio_clrbits_32
(
UFS_SYS_HC_LP_CTRL_REG
,
BIT_SYSCTRL_LP_ISOL_EN
);
mmio_write_32
(
CRG_PERRSTDIS3_REG
,
PERI_ARST_UFS_BIT
);
mmio_setbits_32
(
UFS_SYS_RESET_CTRL_EN_REG
,
BIT_SYSCTRL_LP_RESET_N
);
mdelay
(
1
);
mmio_write_32
(
UFS_SYS_UFS_DEVICE_RESET_CTRL_REG
,
MASK_UFS_DEVICE_RESET
|
BIT_UFS_DEVICE_RESET
);
mdelay
(
20
);
mmio_write_32
(
UFS_SYS_UFS_DEVICE_RESET_CTRL_REG
,
0x03300330
);
mmio_write_32
(
CRG_PERRSTDIS3_REG
,
PERI_UFS_BIT
);
do
{
data
=
mmio_read_32
(
CRG_PERRSTSTAT3_REG
);
}
while
(
data
&
PERI_UFS_BIT
);
}
static
void
hikey960_ufs_init
(
void
)
{
dw_ufs_params_t
ufs_params
;
memset
(
&
ufs_params
,
0
,
sizeof
(
ufs_params
));
ufs_params
.
reg_base
=
UFS_REG_BASE
;
ufs_params
.
desc_base
=
HIKEY960_UFS_DESC_BASE
;
ufs_params
.
desc_size
=
HIKEY960_UFS_DESC_SIZE
;
if
((
ufs_params
.
flags
&
UFS_FLAGS_SKIPINIT
)
==
0
)
hikey960_ufs_reset
();
dw_ufs_init
(
&
ufs_params
);
}
static
void
hikey960_tzc_init
(
void
)
{
mmio_write_32
(
TZC_EN0_REG
,
0x7fbff066
);
mmio_write_32
(
TZC_EN1_REG
,
0xfffff5fc
);
mmio_write_32
(
TZC_EN2_REG
,
0x0007005c
);
mmio_write_32
(
TZC_EN3_REG
,
0x37030700
);
mmio_write_32
(
TZC_EN4_REG
,
0xf63fefae
);
mmio_write_32
(
TZC_EN5_REG
,
0x000410fd
);
mmio_write_32
(
TZC_EN6_REG
,
0x0063ff68
);
mmio_write_32
(
TZC_EN7_REG
,
0x030000f3
);
mmio_write_32
(
TZC_EN8_REG
,
0x00000007
);
}
static
void
hikey960_peri_init
(
void
)
{
/* unreset */
mmio_setbits_32
(
CRG_PERRSTDIS4_REG
,
1
);
}
static
void
hikey960_pinmux_init
(
void
)
{
unsigned
int
id
;
hikey960_read_boardid
(
&
id
);
if
(
id
==
5301
)
{
/* hikey960 hardware v2 */
/* GPIO150: LED */
mmio_write_32
(
IOMG_FIX_006_REG
,
0
);
/* GPIO151: LED */
mmio_write_32
(
IOMG_FIX_007_REG
,
0
);
/* GPIO189: LED */
mmio_write_32
(
IOMG_AO_011_REG
,
0
);
/* GPIO190: LED */
mmio_write_32
(
IOMG_AO_012_REG
,
0
);
/* GPIO46 */
mmio_write_32
(
IOMG_044_REG
,
0
);
/* GPIO202 */
mmio_write_32
(
IOMG_AO_023_REG
,
0
);
/* GPIO206 */
mmio_write_32
(
IOMG_AO_026_REG
,
0
);
/* GPIO219 - PD pullup */
mmio_write_32
(
IOMG_AO_039_REG
,
0
);
mmio_write_32
(
IOCG_AO_043_REG
,
1
<<
0
);
}
/* GPIO005 - PMU SSI, 10mA */
mmio_write_32
(
IOCG_006_REG
,
2
<<
4
);
}
/*
* Function which will perform any remaining platform-specific setup that can
* occur after the MMU and data cache have been enabled.
*/
void
bl1_platform_setup
(
void
)
{
hikey960_clk_init
();
hikey960_pmu_init
();
hikey960_regulator_enable
();
hikey960_tzc_init
();
hikey960_peri_init
();
hikey960_ufs_init
();
hikey960_pinmux_init
();
hikey960_io_setup
();
}
/*
* The following function checks if Firmware update is needed,
* by checking if TOC in FIP image is valid or not.
*/
unsigned
int
bl1_plat_get_next_image_id
(
void
)
{
unsigned
int
mode
,
ret
;
mode
=
mmio_read_32
(
SCTRL_BAK_DATA0_REG
);
switch
(
mode
&
BOOT_MODE_MASK
)
{
case
BOOT_MODE_RECOVERY
:
ret
=
NS_BL1U_IMAGE_ID
;
break
;
case
BOOT_MODE_NORMAL
:
ret
=
BL2_IMAGE_ID
;
break
;
default:
WARN
(
"Invalid boot mode is found:%d
\n
"
,
mode
);
panic
();
}
return
ret
;
}
image_desc_t
*
bl1_plat_get_image_desc
(
unsigned
int
image_id
)
{
unsigned
int
index
=
0
;
while
(
bl1_tbbr_image_descs
[
index
].
image_id
!=
INVALID_IMAGE_ID
)
{
if
(
bl1_tbbr_image_descs
[
index
].
image_id
==
image_id
)
return
&
bl1_tbbr_image_descs
[
index
];
index
++
;
}
return
NULL
;
}
void
bl1_plat_set_ep_info
(
unsigned
int
image_id
,
entry_point_info_t
*
ep_info
)
{
unsigned
int
data
=
0
;
uintptr_t
tmp
=
HIKEY960_NS_TMP_OFFSET
;
if
(
image_id
==
BL2_IMAGE_ID
)
return
;
/* Copy NS BL1U from 0x1AC1_8000 to 0x1AC9_8000 */
memcpy
((
void
*
)
tmp
,
(
void
*
)
HIKEY960_NS_IMAGE_OFFSET
,
NS_BL1U_SIZE
);
memcpy
((
void
*
)
NS_BL1U_BASE
,
(
void
*
)
tmp
,
NS_BL1U_SIZE
);
inv_dcache_range
(
NS_BL1U_BASE
,
NS_BL1U_SIZE
);
/* Initialize the GIC driver, cpu and distributor interfaces */
gicv2_driver_init
(
&
hikey960_gic_data
);
gicv2_distif_init
();
gicv2_pcpu_distif_init
();
gicv2_cpuif_enable
();
/* CNTFRQ is read-only in EL1 */
write_cntfrq_el0
(
plat_get_syscnt_freq2
());
data
=
read_cpacr_el1
();
do
{
data
|=
3
<<
20
;
write_cpacr_el1
(
data
);
data
=
read_cpacr_el1
();
}
while
((
data
&
(
3
<<
20
))
!=
(
3
<<
20
));
INFO
(
"cpacr_el1:0x%x
\n
"
,
data
);
ep_info
->
args
.
arg0
=
0xffff
&
read_mpidr
();
ep_info
->
spsr
=
SPSR_64
(
MODE_EL1
,
MODE_SP_ELX
,
DISABLE_ALL_EXCEPTIONS
);
}
plat/hisilicon/hikey960/hikey960_bl2_setup.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <console.h>
#include <debug.h>
#include <errno.h>
#include <generic_delay_timer.h>
#include <hi3660.h>
#include <mmio.h>
#include <platform_def.h>
#include <string.h>
#include <ufs.h>
#include "hikey960_def.h"
#include "hikey960_private.h"
/*
* 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 BL2_RO_BASE (unsigned long)(&__RO_START__)
#define BL2_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 BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
static
meminfo_t
bl2_tzram_layout
__aligned
(
CACHE_WRITEBACK_GRANULE
);
typedef
struct
bl2_to_bl31_params_mem
{
bl31_params_t
bl31_params
;
image_info_t
bl31_image_info
;
image_info_t
bl32_image_info
;
image_info_t
bl33_image_info
;
entry_point_info_t
bl33_ep_info
;
entry_point_info_t
bl32_ep_info
;
entry_point_info_t
bl31_ep_info
;
}
bl2_to_bl31_params_mem_t
;
static
bl2_to_bl31_params_mem_t
bl31_params_mem
;
meminfo_t
*
bl2_plat_sec_mem_layout
(
void
)
{
return
&
bl2_tzram_layout
;
}
bl31_params_t
*
bl2_plat_get_bl31_params
(
void
)
{
bl31_params_t
*
bl2_to_bl31_params
=
NULL
;
/*
* Initialise the memory for all the arguments that needs to
* be passed to BL3-1
*/
memset
(
&
bl31_params_mem
,
0
,
sizeof
(
bl2_to_bl31_params_mem_t
));
/* Assign memory for TF related information */
bl2_to_bl31_params
=
&
bl31_params_mem
.
bl31_params
;
SET_PARAM_HEAD
(
bl2_to_bl31_params
,
PARAM_BL31
,
VERSION_1
,
0
);
/* Fill BL3-1 related information */
bl2_to_bl31_params
->
bl31_image_info
=
&
bl31_params_mem
.
bl31_image_info
;
SET_PARAM_HEAD
(
bl2_to_bl31_params
->
bl31_image_info
,
PARAM_IMAGE_BINARY
,
VERSION_1
,
0
);
/* Fill BL3-2 related information if it exists */
#if BL32_BASE
bl2_to_bl31_params
->
bl32_ep_info
=
&
bl31_params_mem
.
bl32_ep_info
;
SET_PARAM_HEAD
(
bl2_to_bl31_params
->
bl32_ep_info
,
PARAM_EP
,
VERSION_1
,
0
);
bl2_to_bl31_params
->
bl32_image_info
=
&
bl31_params_mem
.
bl32_image_info
;
SET_PARAM_HEAD
(
bl2_to_bl31_params
->
bl32_image_info
,
PARAM_IMAGE_BINARY
,
VERSION_1
,
0
);
#endif
/* Fill BL3-3 related information */
bl2_to_bl31_params
->
bl33_ep_info
=
&
bl31_params_mem
.
bl33_ep_info
;
SET_PARAM_HEAD
(
bl2_to_bl31_params
->
bl33_ep_info
,
PARAM_EP
,
VERSION_1
,
0
);
/* BL3-3 expects to receive the primary CPU MPID (through x0) */
bl2_to_bl31_params
->
bl33_ep_info
->
args
.
arg0
=
0xffff
&
read_mpidr
();
bl2_to_bl31_params
->
bl33_image_info
=
&
bl31_params_mem
.
bl33_image_info
;
SET_PARAM_HEAD
(
bl2_to_bl31_params
->
bl33_image_info
,
PARAM_IMAGE_BINARY
,
VERSION_1
,
0
);
return
bl2_to_bl31_params
;
}
/*******************************************************************************
* Populate the extents of memory available for loading SCP_BL2 (if used),
* i.e. anywhere in trusted RAM as long as it doesn't overwrite BL2.
******************************************************************************/
void
bl2_plat_get_scp_bl2_meminfo
(
meminfo_t
*
scp_bl2_meminfo
)
{
ufs_params_t
ufs_params
;
memset
(
&
ufs_params
,
0
,
sizeof
(
ufs_params_t
));
ufs_params
.
reg_base
=
UFS_REG_BASE
;
ufs_params
.
desc_base
=
HIKEY960_UFS_DESC_BASE
;
ufs_params
.
desc_size
=
HIKEY960_UFS_DESC_SIZE
;
ufs_params
.
flags
=
UFS_FLAGS_SKIPINIT
;
ufs_init
(
NULL
,
&
ufs_params
);
hikey960_io_setup
();
*
scp_bl2_meminfo
=
bl2_tzram_layout
;
}
extern
int
load_lpm3
(
void
);
int
bl2_plat_handle_scp_bl2
(
image_info_t
*
scp_bl2_image_info
)
{
int
i
;
int
*
buf
;
assert
(
scp_bl2_image_info
->
image_size
<
SCP_MEM_SIZE
);
INFO
(
"BL2: Initiating SCP_BL2 transfer to SCP
\n
"
);
INFO
(
"BL2: SCP_BL2: 0x%lx@0x%x
\n
"
,
scp_bl2_image_info
->
image_base
,
scp_bl2_image_info
->
image_size
);
buf
=
(
int
*
)
scp_bl2_image_info
->
image_base
;
INFO
(
"BL2: SCP_BL2 HEAD:
\n
"
);
for
(
i
=
0
;
i
<
64
;
i
+=
4
)
INFO
(
"BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x
\n
"
,
buf
[
i
],
buf
[
i
+
1
],
buf
[
i
+
2
],
buf
[
i
+
3
]);
buf
=
(
int
*
)(
scp_bl2_image_info
->
image_base
+
scp_bl2_image_info
->
image_size
-
256
);
INFO
(
"BL2: SCP_BL2 TAIL:
\n
"
);
for
(
i
=
0
;
i
<
64
;
i
+=
4
)
INFO
(
"BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x
\n
"
,
buf
[
i
],
buf
[
i
+
1
],
buf
[
i
+
2
],
buf
[
i
+
3
]);
memcpy
((
void
*
)
SCP_MEM_BASE
,
(
void
*
)
scp_bl2_image_info
->
image_base
,
scp_bl2_image_info
->
image_size
);
INFO
(
"BL2: SCP_BL2 transferred to SCP
\n
"
);
load_lpm3
();
(
void
)
buf
;
return
0
;
}
struct
entry_point_info
*
bl2_plat_get_bl31_ep_info
(
void
)
{
return
&
bl31_params_mem
.
bl31_ep_info
;
}
void
bl2_plat_set_bl31_ep_info
(
image_info_t
*
image
,
entry_point_info_t
*
bl31_ep_info
)
{
SET_SECURITY_STATE
(
bl31_ep_info
->
h
.
attr
,
SECURE
);
bl31_ep_info
->
spsr
=
SPSR_64
(
MODE_EL3
,
MODE_SP_ELX
,
DISABLE_ALL_EXCEPTIONS
);
}
void
bl2_plat_set_bl33_ep_info
(
image_info_t
*
image
,
entry_point_info_t
*
bl33_ep_info
)
{
unsigned
long
el_status
;
unsigned
int
mode
;
/* Figure out what mode we enter the non-secure world in */
el_status
=
read_id_aa64pfr0_el1
()
>>
ID_AA64PFR0_EL2_SHIFT
;
el_status
&=
ID_AA64PFR0_ELX_MASK
;
if
(
el_status
)
mode
=
MODE_EL2
;
else
mode
=
MODE_EL1
;
/*
* TODO: Consider the possibility of specifying the SPSR in
* the FIP ToC and allowing the platform to have a say as
* well.
*/
bl33_ep_info
->
spsr
=
SPSR_64
(
mode
,
MODE_SP_ELX
,
DISABLE_ALL_EXCEPTIONS
);
SET_SECURITY_STATE
(
bl33_ep_info
->
h
.
attr
,
NON_SECURE
);
}
void
bl2_plat_flush_bl31_params
(
void
)
{
flush_dcache_range
((
unsigned
long
)
&
bl31_params_mem
,
sizeof
(
bl2_to_bl31_params_mem_t
));
}
void
bl2_plat_get_bl33_meminfo
(
meminfo_t
*
bl33_meminfo
)
{
bl33_meminfo
->
total_base
=
DDR_BASE
;
bl33_meminfo
->
total_size
=
DDR_SIZE
;
bl33_meminfo
->
free_base
=
DDR_BASE
;
bl33_meminfo
->
free_size
=
DDR_SIZE
;
}
void
bl2_early_platform_setup
(
meminfo_t
*
mem_layout
)
{
unsigned
int
id
,
uart_base
;
generic_delay_timer_init
();
hikey960_read_boardid
(
&
id
);
if
(
id
==
5300
)
uart_base
=
PL011_UART5_BASE
;
else
uart_base
=
PL011_UART6_BASE
;
/* Initialize the console to provide early debug support */
console_init
(
uart_base
,
PL011_UART_CLK_IN_HZ
,
PL011_BAUDRATE
);
/* Setup the BL2 memory layout */
bl2_tzram_layout
=
*
mem_layout
;
}
void
bl2_plat_arch_setup
(
void
)
{
hikey960_init_mmu_el1
(
bl2_tzram_layout
.
total_base
,
bl2_tzram_layout
.
total_size
,
BL2_RO_BASE
,
BL2_RO_LIMIT
,
BL2_COHERENT_RAM_BASE
,
BL2_COHERENT_RAM_LIMIT
);
}
void
bl2_platform_setup
(
void
)
{
/* disable WDT0 */
if
(
mmio_read_32
(
WDT0_REG_BASE
+
WDT_LOCK_OFFSET
)
==
WDT_LOCKED
)
{
mmio_write_32
(
WDT0_REG_BASE
+
WDT_LOCK_OFFSET
,
WDT_UNLOCK
);
mmio_write_32
(
WDT0_REG_BASE
+
WDT_CONTROL_OFFSET
,
0
);
mmio_write_32
(
WDT0_REG_BASE
+
WDT_LOCK_OFFSET
,
0
);
}
}
plat/hisilicon/hikey960/hikey960_bl31_setup.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <arm_gic.h>
#include <assert.h>
#include <bl_common.h>
#include <cci.h>
#include <console.h>
#include <debug.h>
#include <errno.h>
#include <generic_delay_timer.h>
#include <gicv2.h>
#include <hi3660.h>
#include <hisi_ipc.h>
#include <platform_def.h>
#include "hikey960_def.h"
#include "hikey960_private.h"
/*
* 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_ep_info
;
static
entry_point_info_t
bl33_ep_info
;
/******************************************************************************
* On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
* interrupts.
*****************************************************************************/
const
unsigned
int
g0_interrupt_array
[]
=
{
IRQ_SEC_PHY_TIMER
,
IRQ_SEC_SGI_0
};
const
gicv2_driver_data_t
hikey960_gic_data
=
{
.
gicd_base
=
GICD_REG_BASE
,
.
gicc_base
=
GICC_REG_BASE
,
.
g0_interrupt_num
=
ARRAY_SIZE
(
g0_interrupt_array
),
.
g0_interrupt_array
=
g0_interrupt_array
,
};
static
const
int
cci_map
[]
=
{
CCI400_SL_IFACE3_CLUSTER_IX
,
CCI400_SL_IFACE4_CLUSTER_IX
};
entry_point_info_t
*
bl31_plat_get_next_image_ep_info
(
unsigned
int
type
)
{
entry_point_info_t
*
next_image_info
;
next_image_info
=
(
type
==
NON_SECURE
)
?
&
bl33_ep_info
:
&
bl32_ep_info
;
/* None of the images on this platform can have 0x0 as the entrypoint */
if
(
next_image_info
->
pc
)
return
next_image_info
;
return
NULL
;
}
void
bl31_early_platform_setup
(
bl31_params_t
*
from_bl2
,
void
*
plat_params_from_bl2
)
{
unsigned
int
id
,
uart_base
;
generic_delay_timer_init
();
hikey960_read_boardid
(
&
id
);
if
(
id
==
5300
)
uart_base
=
PL011_UART5_BASE
;
else
uart_base
=
PL011_UART6_BASE
;
/* Initialize the console to provide early debug support */
console_init
(
uart_base
,
PL011_UART_CLK_IN_HZ
,
PL011_BAUDRATE
);
/* Initialize CCI driver */
cci_init
(
CCI400_REG_BASE
,
cci_map
,
ARRAY_SIZE
(
cci_map
));
cci_enable_snoop_dvm_reqs
(
MPIDR_AFFLVL1_VAL
(
read_mpidr_el1
()));
/*
* Copy BL3-2 and BL3-3 entry point information.
* They are stored in Secure RAM, in BL2's address space.
*/
bl32_ep_info
=
*
from_bl2
->
bl32_ep_info
;
bl33_ep_info
=
*
from_bl2
->
bl33_ep_info
;
}
void
bl31_plat_arch_setup
(
void
)
{
hikey960_init_mmu_el3
(
BL31_BASE
,
BL31_LIMIT
-
BL31_BASE
,
BL31_RO_BASE
,
BL31_RO_LIMIT
,
BL31_COHERENT_RAM_BASE
,
BL31_COHERENT_RAM_LIMIT
);
}
void
bl31_platform_setup
(
void
)
{
/* Initialize the GIC driver, cpu and distributor interfaces */
gicv2_driver_init
(
&
hikey960_gic_data
);
gicv2_distif_init
();
gicv2_pcpu_distif_init
();
gicv2_cpuif_enable
();
hisi_ipc_init
();
}
void
bl31_plat_runtime_setup
(
void
)
{
}
plat/hisilicon/hikey960/hikey960_boardid.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <debug.h>
#include <delay_timer.h>
#include <errno.h>
#include <hi3660.h>
#include <mmio.h>
#include "hikey960_private.h"
#define ADC_ADCIN0 0
#define ADC_ADCIN1 1
#define ADC_ADCIN2 2
#define HKADC_DATA_GRADE0 0
#define HKADC_DATA_GRADE1 100
#define HKADC_DATA_GRADE2 300
#define HKADC_DATA_GRADE3 500
#define HKADC_DATA_GRADE4 700
#define HKADC_DATA_GRADE5 900
#define HKADC_DATA_GRADE6 1100
#define HKADC_DATA_GRADE7 1300
#define HKADC_DATA_GRADE8 1500
#define HKADC_DATA_GRADE9 1700
#define HKADC_DATA_GRADE10 1800
#define BOARDID_VALUE0 0
#define BOARDID_VALUE1 1
#define BOARDID_VALUE2 2
#define BOARDID_VALUE3 3
#define BOARDID_VALUE4 4
#define BOARDID_VALUE5 5
#define BOARDID_VALUE6 6
#define BOARDID_VALUE7 7
#define BOARDID_VALUE8 8
#define BOARDID_VALUE9 9
#define BOARDID_UNKNOWN 0xF
#define BOARDID3_BASE 5
static
void
init_adc
(
void
)
{
/* reset hkadc */
mmio_write_32
(
CRG_PERRSTEN2_REG
,
PERRSTEN2_HKADCSSI
);
/* wait a few clock cycles */
udelay
(
2
);
mmio_write_32
(
CRG_PERRSTDIS2_REG
,
PERRSTEN2_HKADCSSI
);
udelay
(
2
);
/* enable hkadc clock */
mmio_write_32
(
CRG_PERDIS2_REG
,
PEREN2_HKADCSSI
);
udelay
(
2
);
mmio_write_32
(
CRG_PEREN2_REG
,
PEREN2_HKADCSSI
);
udelay
(
2
);
}
static
int
get_adc
(
unsigned
int
channel
,
unsigned
int
*
value
)
{
unsigned
int
data
,
value1
,
value0
;
if
(
channel
>
HKADC_CHANNEL_MAX
)
{
WARN
(
"invalid channel:%d
\n
"
,
channel
);
return
-
EFAULT
;
}
/* configure the read/write operation for external HKADC */
mmio_write_32
(
HKADC_WR01_DATA_REG
,
HKADC_WR01_VALUE
|
channel
);
mmio_write_32
(
HKADC_WR23_DATA_REG
,
HKADC_WR23_VALUE
);
mmio_write_32
(
HKADC_WR45_DATA_REG
,
HKADC_WR45_VALUE
);
/* configure the number of accessing registers */
mmio_write_32
(
HKADC_WR_NUM_REG
,
HKADC_WR_NUM_VALUE
);
/* configure delay of accessing registers */
mmio_write_32
(
HKADC_DELAY01_REG
,
HKADC_CHANNEL0_DELAY01_VALUE
);
mmio_write_32
(
HKADC_DELAY23_REG
,
HKADC_DELAY23_VALUE
);
/* start HKADC */
mmio_write_32
(
HKADC_DSP_START_REG
,
1
);
do
{
data
=
mmio_read_32
(
HKADC_DSP_START_REG
);
}
while
(
data
&
1
);
/* convert AD result */
value1
=
mmio_read_32
(
HKADC_DSP_RD2_DATA_REG
)
&
0xffff
;
value0
=
mmio_read_32
(
HKADC_DSP_RD3_DATA_REG
)
&
0xffff
;
data
=
((
value1
<<
4
)
&
HKADC_VALUE_HIGH
)
|
((
value0
>>
4
)
&
HKADC_VALUE_LOW
);
*
value
=
data
;
return
0
;
}
static
int
get_value
(
unsigned
int
channel
,
unsigned
int
*
value
)
{
int
ret
;
ret
=
get_adc
(
channel
,
value
);
if
(
ret
)
return
ret
;
/* convert ADC value to micro-volt */
ret
=
((
*
value
&
HKADC_VALID_VALUE
)
*
HKADC_VREF_1V8
)
/
HKADC_ACCURACY
;
*
value
=
ret
;
return
0
;
}
static
int
adcin_data_remap
(
unsigned
int
adcin_value
)
{
int
ret
;
if
(
adcin_value
<
HKADC_DATA_GRADE0
)
ret
=
BOARDID_UNKNOWN
;
else
if
(
adcin_value
<
HKADC_DATA_GRADE1
)
ret
=
BOARDID_VALUE0
;
else
if
(
adcin_value
<
HKADC_DATA_GRADE2
)
ret
=
BOARDID_VALUE1
;
else
if
(
adcin_value
<
HKADC_DATA_GRADE3
)
ret
=
BOARDID_VALUE2
;
else
if
(
adcin_value
<
HKADC_DATA_GRADE4
)
ret
=
BOARDID_VALUE3
;
else
if
(
adcin_value
<
HKADC_DATA_GRADE5
)
ret
=
BOARDID_VALUE4
;
else
if
(
adcin_value
<
HKADC_DATA_GRADE6
)
ret
=
BOARDID_VALUE5
;
else
if
(
adcin_value
<
HKADC_DATA_GRADE7
)
ret
=
BOARDID_VALUE6
;
else
if
(
adcin_value
<
HKADC_DATA_GRADE8
)
ret
=
BOARDID_VALUE7
;
else
if
(
adcin_value
<
HKADC_DATA_GRADE9
)
ret
=
BOARDID_VALUE8
;
else
if
(
adcin_value
<
HKADC_DATA_GRADE10
)
ret
=
BOARDID_VALUE9
;
else
ret
=
BOARDID_UNKNOWN
;
return
ret
;
}
int
hikey960_read_boardid
(
unsigned
int
*
id
)
{
unsigned
int
adcin0
,
adcin1
,
adcin2
;
unsigned
int
adcin0_remap
,
adcin1_remap
,
adcin2_remap
;
assert
(
id
!=
NULL
);
init_adc
();
/* read ADC channel0 data */
get_value
(
ADC_ADCIN0
,
&
adcin0
);
adcin0_remap
=
adcin_data_remap
(
adcin0
);
INFO
(
"[BDID]adcin0:%d adcin0_remap:%d
\n
"
,
adcin0
,
adcin0_remap
);
if
(
adcin0_remap
==
BOARDID_UNKNOWN
)
return
-
EINVAL
;
/* read ADC channel1 data */
get_value
(
ADC_ADCIN1
,
&
adcin1
);
adcin1_remap
=
adcin_data_remap
(
adcin1
);
INFO
(
"[BDID]adcin1:%d adcin1_remap:%d
\n
"
,
adcin1
,
adcin1_remap
);
if
(
adcin1_remap
==
BOARDID_UNKNOWN
)
return
-
EINVAL
;
/* read ADC channel2 data */
get_value
(
ADC_ADCIN2
,
&
adcin2
);
adcin2_remap
=
adcin_data_remap
(
adcin2
);
INFO
(
"[BDID]adcin2:%d adcin2_remap:%d
\n
"
,
adcin2
,
adcin2_remap
);
if
(
adcin2_remap
==
BOARDID_UNKNOWN
)
return
-
EINVAL
;
*
id
=
BOARDID3_BASE
*
1000
+
(
adcin2_remap
*
100
)
+
(
adcin1_remap
*
10
)
+
adcin0_remap
;
INFO
(
"[BDID]boardid: %d
\n
"
,
*
id
);
return
0
;
}
plat/hisilicon/hikey960/hikey960_def.h
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __HIKEY960_DEF_H__
#define __HIKEY960_DEF_H__
#include <common_def.h>
#include <tbbr_img_def.h>
#define DDR_BASE 0x0
#define DDR_SIZE 0xC0000000
#define DEVICE_BASE 0xE0000000
#define DEVICE_SIZE 0x20000000
/*
* PL011 related constants
*/
#define PL011_UART5_BASE 0xFDF05000
#define PL011_UART6_BASE 0xFFF32000
#define PL011_BAUDRATE 115200
#define PL011_UART_CLK_IN_HZ 19200000
#define UFS_BASE 0
/* FIP partition */
#define HIKEY960_FIP_BASE (UFS_BASE + 0x1400000)
#define HIKEY960_FIP_MAX_SIZE (12 << 20)
#define HIKEY960_UFS_DESC_BASE 0x20000000
#define HIKEY960_UFS_DESC_SIZE 0x00200000
/* 2MB */
#define HIKEY960_UFS_DATA_BASE 0x10000000
#define HIKEY960_UFS_DATA_SIZE 0x0A000000
/* 160MB */
#endif
/* __HIKEY960_DEF_H__ */
plat/hisilicon/hikey960/hikey960_io_storage.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>
#include <firmware_image_package.h>
#include <io_block.h>
#include <io_driver.h>
#include <io_fip.h>
#include <io_memmap.h>
#include <io_storage.h>
#include <mmio.h>
#include <platform_def.h>
#include <semihosting.h>
/* For FOPEN_MODE_... */
#include <string.h>
#include <ufs.h>
struct
plat_io_policy
{
uintptr_t
*
dev_handle
;
uintptr_t
image_spec
;
int
(
*
check
)(
const
uintptr_t
spec
);
};
static
const
io_dev_connector_t
*
ufs_dev_con
,
*
fip_dev_con
;
static
uintptr_t
ufs_dev_handle
,
fip_dev_handle
;
static
int
check_ufs
(
const
uintptr_t
spec
);
static
int
check_fip
(
const
uintptr_t
spec
);
size_t
ufs_read_lun3_blks
(
int
lba
,
uintptr_t
buf
,
size_t
size
);
size_t
ufs_write_lun3_blks
(
int
lba
,
const
uintptr_t
buf
,
size_t
size
);
static
const
io_block_spec_t
ufs_fip_spec
=
{
.
offset
=
HIKEY960_FIP_BASE
,
.
length
=
HIKEY960_FIP_MAX_SIZE
,
};
static
const
io_block_spec_t
ufs_data_spec
=
{
.
offset
=
0
,
.
length
=
256
<<
20
,
};
static
const
io_block_dev_spec_t
ufs_dev_spec
=
{
/* It's used as temp buffer in block driver. */
.
buffer
=
{
.
offset
=
HIKEY960_UFS_DATA_BASE
,
.
length
=
HIKEY960_UFS_DATA_SIZE
,
},
.
ops
=
{
.
read
=
ufs_read_lun3_blks
,
.
write
=
ufs_write_lun3_blks
,
},
.
block_size
=
UFS_BLOCK_SIZE
,
};
static
const
io_uuid_spec_t
bl2_uuid_spec
=
{
.
uuid
=
UUID_TRUSTED_BOOT_FIRMWARE_BL2
,
};
static
const
io_uuid_spec_t
scp_bl2_uuid_spec
=
{
.
uuid
=
UUID_SCP_FIRMWARE_SCP_BL2
,
};
static
const
io_uuid_spec_t
bl31_uuid_spec
=
{
.
uuid
=
UUID_EL3_RUNTIME_FIRMWARE_BL31
,
};
static
const
io_uuid_spec_t
bl33_uuid_spec
=
{
.
uuid
=
UUID_NON_TRUSTED_FIRMWARE_BL33
,
};
static
const
struct
plat_io_policy
policies
[]
=
{
[
FIP_IMAGE_ID
]
=
{
&
ufs_dev_handle
,
(
uintptr_t
)
&
ufs_fip_spec
,
check_ufs
},
[
BL2_IMAGE_ID
]
=
{
&
fip_dev_handle
,
(
uintptr_t
)
&
bl2_uuid_spec
,
check_fip
},
[
SCP_BL2_IMAGE_ID
]
=
{
&
fip_dev_handle
,
(
uintptr_t
)
&
scp_bl2_uuid_spec
,
check_fip
},
[
BL31_IMAGE_ID
]
=
{
&
fip_dev_handle
,
(
uintptr_t
)
&
bl31_uuid_spec
,
check_fip
},
[
BL33_IMAGE_ID
]
=
{
&
fip_dev_handle
,
(
uintptr_t
)
&
bl33_uuid_spec
,
check_fip
},
[
BL2U_IMAGE_ID
]
=
{
&
ufs_dev_handle
,
(
uintptr_t
)
&
ufs_data_spec
,
check_ufs
}
};
static
int
check_ufs
(
const
uintptr_t
spec
)
{
int
result
;
uintptr_t
local_handle
;
result
=
io_dev_init
(
ufs_dev_handle
,
(
uintptr_t
)
NULL
);
if
(
result
==
0
)
{
result
=
io_open
(
ufs_dev_handle
,
spec
,
&
local_handle
);
if
(
result
==
0
)
io_close
(
local_handle
);
}
return
result
;
}
static
int
check_fip
(
const
uintptr_t
spec
)
{
int
result
;
uintptr_t
local_image_handle
;
/* See if a Firmware Image Package is available */
result
=
io_dev_init
(
fip_dev_handle
,
(
uintptr_t
)
FIP_IMAGE_ID
);
if
(
result
==
0
)
{
result
=
io_open
(
fip_dev_handle
,
spec
,
&
local_image_handle
);
if
(
result
==
0
)
{
VERBOSE
(
"Using FIP
\n
"
);
io_close
(
local_image_handle
);
}
}
return
result
;
}
void
hikey960_io_setup
(
void
)
{
int
result
;
result
=
register_io_dev_block
(
&
ufs_dev_con
);
assert
(
result
==
0
);
result
=
register_io_dev_fip
(
&
fip_dev_con
);
assert
(
result
==
0
);
result
=
io_dev_open
(
ufs_dev_con
,
(
uintptr_t
)
&
ufs_dev_spec
,
&
ufs_dev_handle
);
assert
(
result
==
0
);
result
=
io_dev_open
(
fip_dev_con
,
(
uintptr_t
)
NULL
,
&
fip_dev_handle
);
assert
(
result
==
0
);
/* Ignore improbable errors in release builds */
(
void
)
result
;
}
/* Return an IO device handle and specification which can be used to access
* an image. Use this to enforce platform load policy
*/
int
plat_get_image_source
(
unsigned
int
image_id
,
uintptr_t
*
dev_handle
,
uintptr_t
*
image_spec
)
{
int
result
;
const
struct
plat_io_policy
*
policy
;
assert
(
image_id
<
ARRAY_SIZE
(
policies
));
policy
=
&
policies
[
image_id
];
result
=
policy
->
check
(
policy
->
image_spec
);
assert
(
result
==
0
);
*
image_spec
=
policy
->
image_spec
;
*
dev_handle
=
*
(
policy
->
dev_handle
);
return
result
;
}
size_t
ufs_read_lun3_blks
(
int
lba
,
uintptr_t
buf
,
size_t
size
)
{
return
ufs_read_blocks
(
3
,
lba
,
buf
,
size
);
}
size_t
ufs_write_lun3_blks
(
int
lba
,
const
uintptr_t
buf
,
size_t
size
)
{
return
ufs_write_blocks
(
3
,
lba
,
buf
,
size
);
}
plat/hisilicon/hikey960/hikey960_mcu_load.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <debug.h>
#include <delay_timer.h>
#include <errno.h>
#include <hi3660.h>
#include <mmio.h>
#include <string.h>
#define ADDR_CONVERT(addr) ((addr) < 0x40000 ? \
(addr) + 0xFFF30000 : \
(addr) + 0x40000000)
static
void
fw_data_init
(
void
)
{
unsigned
long
data_head_addr
;
unsigned
int
*
data_addr
;
data_head_addr
=
mmio_read_32
((
uintptr_t
)
HISI_DATA_HEAD_BASE
)
+
0x14
;
data_addr
=
(
unsigned
int
*
)
ADDR_CONVERT
(
data_head_addr
);
memcpy
((
void
*
)
HISI_DATA0_BASE
,
(
const
void
*
)(
unsigned
long
)
ADDR_CONVERT
(
data_addr
[
0
]),
HISI_DATA0_SIZE
);
memcpy
((
void
*
)
HISI_DATA1_BASE
,
(
const
void
*
)(
unsigned
long
)
ADDR_CONVERT
(
data_addr
[
1
]),
HISI_DATA1_SIZE
);
}
int
load_lpm3
(
void
)
{
INFO
(
"start fw loading
\n
"
);
fw_data_init
();
flush_dcache_range
((
uintptr_t
)
HISI_RESERVED_MEM_BASE
,
HISI_RESERVED_MEM_SIZE
);
sev
();
sev
();
INFO
(
"fw load success
\n
"
);
return
0
;
}
plat/hisilicon/hikey960/hikey960_pm.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <cci.h>
#include <console.h>
#include <debug.h>
#include <gicv2.h>
#include <hi3660.h>
#include <hi3660_crg.h>
#include <mmio.h>
#include <psci.h>
#include "drivers/pwrc/hisi_pwrc.h"
#include "hikey960_def.h"
#include "hikey960_private.h"
#define CORE_PWR_STATE(state) \
((state)->pwr_domain_state[MPIDR_AFFLVL0])
#define CLUSTER_PWR_STATE(state) \
((state)->pwr_domain_state[MPIDR_AFFLVL1])
#define SYSTEM_PWR_STATE(state) \
((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
#define DMAC_GLB_REG_SEC 0x694
#define AXI_CONF_BASE 0x820
static
uintptr_t
hikey960_sec_entrypoint
;
static
void
hikey960_pwr_domain_standby
(
plat_local_state_t
cpu_state
)
{
unsigned
long
scr
;
unsigned
int
val
=
0
;
assert
(
cpu_state
==
PLAT_MAX_RET_STATE
);
scr
=
read_scr_el3
();
/* Enable Physical IRQ and FIQ to wake the CPU*/
write_scr_el3
(
scr
|
SCR_IRQ_BIT
|
SCR_FIQ_BIT
);
set_retention_ticks
(
val
);
wfi
();
clr_retention_ticks
(
val
);
/*
* Restore SCR to the original value, synchronisazion of
* scr_el3 is done by eret while el3_exit to save some
* execution cycles.
*/
write_scr_el3
(
scr
);
}
static
int
hikey960_pwr_domain_on
(
u_register_t
mpidr
)
{
unsigned
int
core
=
mpidr
&
MPIDR_CPU_MASK
;
unsigned
int
cluster
=
(
mpidr
&
MPIDR_CLUSTER_MASK
)
>>
MPIDR_AFFINITY_BITS
;
int
cluster_stat
=
cluster_is_powered_on
(
cluster
);
hisi_set_cpu_boot_flag
(
cluster
,
core
);
mmio_write_32
(
CRG_REG_BASE
+
CRG_RVBAR
(
cluster
,
core
),
hikey960_sec_entrypoint
>>
2
);
if
(
cluster_stat
)
hisi_powerup_core
(
cluster
,
core
);
else
hisi_powerup_cluster
(
cluster
,
core
);
return
PSCI_E_SUCCESS
;
}
static
void
hikey960_pwr_domain_on_finish
(
const
psci_power_state_t
*
target_state
)
{
if
(
CLUSTER_PWR_STATE
(
target_state
)
==
PLAT_MAX_OFF_STATE
)
cci_enable_snoop_dvm_reqs
(
MPIDR_AFFLVL1_VAL
(
read_mpidr_el1
()));
gicv2_pcpu_distif_init
();
gicv2_cpuif_enable
();
}
void
hikey960_pwr_domain_off
(
const
psci_power_state_t
*
target_state
)
{
unsigned
long
mpidr
=
read_mpidr_el1
();
unsigned
int
core
=
mpidr
&
MPIDR_CPU_MASK
;
unsigned
int
cluster
=
(
mpidr
&
MPIDR_CLUSTER_MASK
)
>>
MPIDR_AFFINITY_BITS
;
clr_ex
();
isb
();
dsbsy
();
gicv2_cpuif_disable
();
hisi_clear_cpu_boot_flag
(
cluster
,
core
);
hisi_powerdn_core
(
cluster
,
core
);
/* check if any core is powered up */
if
(
hisi_test_pwrdn_allcores
(
cluster
,
core
))
{
cci_disable_snoop_dvm_reqs
(
MPIDR_AFFLVL1_VAL
(
read_mpidr_el1
()));
isb
();
dsbsy
();
hisi_powerdn_cluster
(
cluster
,
core
);
}
}
static
void
__dead2
hikey960_system_reset
(
void
)
{
mmio_write_32
(
SCTRL_SCPEREN1_REG
,
SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS
);
mmio_write_32
(
SCTRL_SCSYSSTAT_REG
,
0xdeadbeef
);
panic
();
}
int
hikey960_validate_power_state
(
unsigned
int
power_state
,
psci_power_state_t
*
req_state
)
{
int
pstate
=
psci_get_pstate_type
(
power_state
);
int
pwr_lvl
=
psci_get_pstate_pwrlvl
(
power_state
);
int
i
;
assert
(
req_state
);
if
(
pwr_lvl
>
PLAT_MAX_PWR_LVL
)
return
PSCI_E_INVALID_PARAMS
;
/* Sanity check the requested state */
if
(
pstate
==
PSTATE_TYPE_STANDBY
)
{
/*
* It's possible to enter standby only on power level 0
* Ignore any other power level.
*/
if
(
pwr_lvl
!=
MPIDR_AFFLVL0
)
return
PSCI_E_INVALID_PARAMS
;
req_state
->
pwr_domain_state
[
MPIDR_AFFLVL0
]
=
PLAT_MAX_RET_STATE
;
}
else
{
for
(
i
=
MPIDR_AFFLVL0
;
i
<=
pwr_lvl
;
i
++
)
req_state
->
pwr_domain_state
[
i
]
=
PLAT_MAX_OFF_STATE
;
}
/*
* We expect the 'state id' to be zero.
*/
if
(
psci_get_pstate_id
(
power_state
))
return
PSCI_E_INVALID_PARAMS
;
return
PSCI_E_SUCCESS
;
}
static
int
hikey960_validate_ns_entrypoint
(
uintptr_t
entrypoint
)
{
/*
* Check if the non secure entrypoint lies within the non
* secure DRAM.
*/
if
((
entrypoint
>
DDR_BASE
)
&&
(
entrypoint
<
(
DDR_BASE
+
DDR_SIZE
)))
return
PSCI_E_SUCCESS
;
return
PSCI_E_INVALID_ADDRESS
;
}
static
void
hikey960_pwr_domain_suspend
(
const
psci_power_state_t
*
target_state
)
{
u_register_t
mpidr
=
read_mpidr_el1
();
unsigned
int
core
=
mpidr
&
MPIDR_CPU_MASK
;
unsigned
int
cluster
=
(
mpidr
&
MPIDR_CLUSTER_MASK
)
>>
MPIDR_AFFINITY_BITS
;
if
(
CORE_PWR_STATE
(
target_state
)
!=
PLAT_MAX_OFF_STATE
)
return
;
if
(
CORE_PWR_STATE
(
target_state
)
==
PLAT_MAX_OFF_STATE
)
{
clr_ex
();
isb
();
dsbsy
();
gicv2_cpuif_disable
();
hisi_cpuidle_lock
(
cluster
,
core
);
hisi_set_cpuidle_flag
(
cluster
,
core
);
hisi_cpuidle_unlock
(
cluster
,
core
);
mmio_write_32
(
CRG_REG_BASE
+
CRG_RVBAR
(
cluster
,
core
),
hikey960_sec_entrypoint
>>
2
);
hisi_enter_core_idle
(
cluster
,
core
);
}
/* Perform the common cluster specific operations */
if
(
CLUSTER_PWR_STATE
(
target_state
)
==
PLAT_MAX_OFF_STATE
)
{
hisi_cpuidle_lock
(
cluster
,
core
);
hisi_disable_pdc
(
cluster
);
/* check if any core is powered up */
if
(
hisi_test_pwrdn_allcores
(
cluster
,
core
))
{
cci_disable_snoop_dvm_reqs
(
MPIDR_AFFLVL1_VAL
(
mpidr
));
isb
();
dsbsy
();
/* mask the pdc wakeup irq, then
* enable pdc to power down the core
*/
hisi_pdc_mask_cluster_wakeirq
(
cluster
);
hisi_enable_pdc
(
cluster
);
hisi_cpuidle_unlock
(
cluster
,
core
);
/* check the SR flag bit to determine
* CLUSTER_IDLE_IPC or AP_SR_IPC to send
*/
if
(
hisi_test_ap_suspend_flag
(
cluster
))
hisi_enter_ap_suspend
(
cluster
,
core
);
else
hisi_enter_cluster_idle
(
cluster
,
core
);
}
else
{
/* enable pdc */
hisi_enable_pdc
(
cluster
);
hisi_cpuidle_unlock
(
cluster
,
core
);
}
}
}
static
void
hikey960_sr_dma_reinit
(
void
)
{
unsigned
int
ctr
=
0
;
mmio_write_32
(
DMAC_BASE
+
DMAC_GLB_REG_SEC
,
0x3
);
/* 1~15 channel is set non_secure */
for
(
ctr
=
1
;
ctr
<=
15
;
ctr
++
)
mmio_write_32
(
DMAC_BASE
+
AXI_CONF_BASE
+
ctr
*
(
0x40
),
(
1
<<
6
)
|
(
1
<<
18
));
}
static
void
hikey960_pwr_domain_suspend_finish
(
const
psci_power_state_t
*
target_state
)
{
unsigned
long
mpidr
=
read_mpidr_el1
();
unsigned
int
cluster
=
(
mpidr
&
MPIDR_CLUSTER_MASK
)
>>
MPIDR_AFFINITY_BITS
;
/* Nothing to be done on waking up from retention from CPU level */
if
(
CORE_PWR_STATE
(
target_state
)
!=
PLAT_MAX_OFF_STATE
)
return
;
if
(
hisi_test_ap_suspend_flag
(
cluster
))
{
hikey960_sr_dma_reinit
();
gicv2_cpuif_enable
();
console_init
(
PL011_UART6_BASE
,
PL011_UART_CLK_IN_HZ
,
PL011_BAUDRATE
);
}
hikey960_pwr_domain_on_finish
(
target_state
);
}
static
void
hikey960_get_sys_suspend_power_state
(
psci_power_state_t
*
req_state
)
{
int
i
;
for
(
i
=
MPIDR_AFFLVL0
;
i
<=
PLAT_MAX_PWR_LVL
;
i
++
)
req_state
->
pwr_domain_state
[
i
]
=
PLAT_MAX_OFF_STATE
;
}
static
const
plat_psci_ops_t
hikey960_psci_ops
=
{
.
cpu_standby
=
hikey960_pwr_domain_standby
,
.
pwr_domain_on
=
hikey960_pwr_domain_on
,
.
pwr_domain_on_finish
=
hikey960_pwr_domain_on_finish
,
.
pwr_domain_off
=
hikey960_pwr_domain_off
,
.
pwr_domain_suspend
=
hikey960_pwr_domain_suspend
,
.
pwr_domain_suspend_finish
=
hikey960_pwr_domain_suspend_finish
,
.
system_off
=
NULL
,
.
system_reset
=
hikey960_system_reset
,
.
validate_power_state
=
hikey960_validate_power_state
,
.
validate_ns_entrypoint
=
hikey960_validate_ns_entrypoint
,
.
get_sys_suspend_power_state
=
hikey960_get_sys_suspend_power_state
,
};
int
plat_setup_psci_ops
(
uintptr_t
sec_entrypoint
,
const
plat_psci_ops_t
**
psci_ops
)
{
hikey960_sec_entrypoint
=
sec_entrypoint
;
INFO
(
"%s: sec_entrypoint=0x%lx
\n
"
,
__func__
,
(
unsigned
long
)
hikey960_sec_entrypoint
);
/*
* Initialize PSCI ops struct
*/
*
psci_ops
=
&
hikey960_psci_ops
;
return
0
;
}
plat/hisilicon/hikey960/hikey960_private.h
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __HIKEY960_PRIVATE_H__
#define __HIKEY960_PRIVATE_H__
#include <bl_common.h>
/*
* Function and variable prototypes
*/
void
hikey960_init_mmu_el1
(
unsigned
long
total_base
,
unsigned
long
total_size
,
unsigned
long
ro_start
,
unsigned
long
ro_limit
,
unsigned
long
coh_start
,
unsigned
long
coh_limit
);
void
hikey960_init_mmu_el3
(
unsigned
long
total_base
,
unsigned
long
total_size
,
unsigned
long
ro_start
,
unsigned
long
ro_limit
,
unsigned
long
coh_start
,
unsigned
long
coh_limit
);
void
hikey960_io_setup
(
void
);
int
hikey960_read_boardid
(
unsigned
int
*
id
);
void
set_retention_ticks
(
unsigned
int
val
);
void
clr_retention_ticks
(
unsigned
int
val
);
void
clr_ex
(
void
);
void
nop
(
void
);
#endif
/* __HIKEY960_PRIVATE_H__ */
plat/hisilicon/hikey960/hikey960_topology.c
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <platform_def.h>
#include <psci.h>
/*
* The HiKey power domain tree descriptor. The cluster power domains
* are arranged so that when the PSCI generic code creates the power
* domain tree, the indices of the CPU power domain nodes it allocates
* match the linear indices returned by plat_core_pos_by_mpidr().
*/
const
unsigned
char
hikey960_power_domain_tree_desc
[]
=
{
/* Number of root nodes */
1
,
/* Number of clusters */
PLATFORM_CLUSTER_COUNT
,
/* Number of children for the first cluster node */
PLATFORM_CORE_COUNT_PER_CLUSTER
,
/* Number of children for the second cluster node */
PLATFORM_CORE_COUNT_PER_CLUSTER
,
};
/*******************************************************************************
* This function returns the HiKey topology tree information.
******************************************************************************/
const
unsigned
char
*
plat_get_power_domain_tree_desc
(
void
)
{
return
hikey960_power_domain_tree_desc
;
}
/*******************************************************************************
* This function implements a part of the critical interface between the psci
* generic layer and the platform that allows the former to query the platform
* to convert an MPIDR to a unique linear index. An error code (-1) is returned
* in case the MPIDR is invalid.
******************************************************************************/
int
plat_core_pos_by_mpidr
(
u_register_t
mpidr
)
{
unsigned
int
cluster_id
,
cpu_id
;
mpidr
&=
MPIDR_AFFINITY_MASK
;
if
(
mpidr
&
~
(
MPIDR_CLUSTER_MASK
|
MPIDR_CPU_MASK
))
return
-
1
;
cluster_id
=
(
mpidr
>>
MPIDR_AFF1_SHIFT
)
&
MPIDR_AFFLVL_MASK
;
cpu_id
=
(
mpidr
>>
MPIDR_AFF0_SHIFT
)
&
MPIDR_AFFLVL_MASK
;
if
(
cluster_id
>=
PLATFORM_CLUSTER_COUNT
)
return
-
1
;
/*
* Validate cpu_id by checking whether it represents a CPU in
* one of the two clusters present on the platform.
*/
if
(
cpu_id
>=
PLATFORM_CORE_COUNT_PER_CLUSTER
)
return
-
1
;
return
(
cpu_id
+
(
cluster_id
*
4
));
}
plat/hisilicon/hikey960/include/hi3660.h
0 → 100644
View file @
5747ecab
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __HI3660_H__
#define __HI3660_H__
#include <hi3660_crg.h>
#include <hi3660_hkadc.h>
#include <hi3660_mem_map.h>
#define ASP_CFG_REG_BASE 0xE804E000
#define ASP_CFG_MMBUF_CTRL_REG (ASP_CFG_REG_BASE + 0x148)
#define LP_RAM_BASE 0xFFF50000
#define SCTRL_REG_BASE 0xFFF0A000
#define SCTRL_CONTROL_REG (SCTRL_REG_BASE + 0x000)
#define SCTRL_CONTROL_SYS_MODE(x) (((x) & 0xf) << 3)
#define SCTRL_CONTROL_SYS_MODE_NORMAL ((1 << 2) << 3)
#define SCTRL_CONTROL_SYS_MODE_SLOW ((1 << 1) << 3)
#define SCTRL_CONTROL_SYS_MODE_MASK (0xf << 3)
#define SCTRL_CONTROL_MODE_CTRL_NORMAL (1 << 2)
#define SCTRL_CONTROL_MODE_CTRL_SLOW (1 << 1)
#define SCTRL_CONTROL_MODE_CTRL_MASK 0x7
#define SCTRL_SCSYSSTAT_REG (SCTRL_REG_BASE + 0x004)
#define SCTRL_DEEPSLEEPED_REG (SCTRL_REG_BASE + 0x008)
#define SCTRL_EFUSE_USB_MASK (1 << 30)
#define SCTRL_EFUSE_USB_PLL (1 << 30)
#define SCTRL_EFUSE_USB_ABB (0 << 30)
#define SCTRL_EFUSE_UFS_MASK (3 << 6)
#define SCTRL_EFUSE_UFS_PLL (1 << 6)
#define SCTRL_EFUSE_UFS_ABB (0 << 6)
#define SCTRL_SCISOEN_REG (SCTRL_REG_BASE + 0x040)
#define SCTRL_SCISODIS_REG (SCTRL_REG_BASE + 0x044)
#define SCISO_MMBUFISO (1 << 3)
#define SCTRL_SCPWREN_REG (SCTRL_REG_BASE + 0x060)
#define SCPWREN_MMBUFPWREN (1 << 3)
#define SCTRL_PLL_CTRL0_REG (SCTRL_REG_BASE + 0x100)
#define SCTRL_PLL0_POSTDIV2(x) (((x) & 0x7) << 23)
#define SCTRL_PLL0_POSTDIV1(x) (((x) & 0x7) << 20)
#define SCTRL_PLL0_FBDIV(x) (((x) & 0xfff) << 8)
#define SCTRL_PLL0_REFDIV(x) (((x) & 0x3f) << 2)
#define SCTRL_PLL0_EN (1 << 0)
#define SCTRL_PLL_CTRL1_REG (SCTRL_REG_BASE + 0x104)
#define SCTRL_PLL0_CLK_NO_GATE (1 << 26)
#define SCTRL_PLL0_CFG_VLD (1 << 25)
#define SCTRL_PLL0_FRACDIV(x) ((x) & 0xFFFFFF)
#define SCTRL_PLL_STAT_REG (SCTRL_REG_BASE + 0x10C)
#define SCTRL_PLL0_STAT (1 << 0)
#define SCTRL_SCPEREN0_REG (SCTRL_REG_BASE + 0x160)
#define SCTRL_SCPERDIS0_REG (SCTRL_REG_BASE + 0x164)
#define SCTRL_SCPERSTAT0_REG (SCTRL_REG_BASE + 0x168)
#define SCTRL_SCPEREN1_REG (SCTRL_REG_BASE + 0x170)
#define SCTRL_SCPERDIS1_REG (SCTRL_REG_BASE + 0x174)
#define SCTRL_SCPEREN1_REG (SCTRL_REG_BASE + 0x170)
#define SCTRL_SCPERDIS1_REG (SCTRL_REG_BASE + 0x174)
#define SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS (1 << 31)
#define SCPEREN_GT_PCLK_MMBUFCFG (1 << 25)
#define SCPEREN_GT_PCLK_MMBUF (1 << 23)
#define SCPEREN_GT_ACLK_MMBUF (1 << 22)
#define SCPEREN_GT_CLK_NOC_AOBUS2MMBUF (1 << 6)
#define SCTRL_SCPEREN2_REG (SCTRL_REG_BASE + 0x190)
#define SCTRL_SCPERDIS2_REG (SCTRL_REG_BASE + 0x194)
#define SCTRL_SCPERSTAT2_REG (SCTRL_REG_BASE + 0x198)
#define SCTRL_SCPERRSTEN0_REG (SCTRL_REG_BASE + 0x200)
#define SCTRL_SCPERRSTDIS0_REG (SCTRL_REG_BASE + 0x204)
#define SCTRL_SCPERRSTSTAT0_REG (SCTRL_REG_BASE + 0x208)
#define SCTRL_SCPERRSTEN1_REG (SCTRL_REG_BASE + 0x20C)
#define SCTRL_SCPERRSTDIS1_REG (SCTRL_REG_BASE + 0x210)
#define SCTRL_SCPERRSTSTAT1_REG (SCTRL_REG_BASE + 0x214)
#define IP_RST_MMBUFCFG (1 << 12)
#define IP_RST_MMBUF (1 << 11)
#define SCTRL_SCPERRSTEN2_REG (SCTRL_REG_BASE + 0x218)
#define SCTRL_SCPERRSTDIS2_REG (SCTRL_REG_BASE + 0x21C)
#define SCTRL_SCPERRSTSTAT2_REG (SCTRL_REG_BASE + 0x220)
#define SCTRL_SCCLKDIV2_REG (SCTRL_REG_BASE + 0x258)
#define SEL_CLK_MMBUF_MASK (0x3 << 8)
#define SEL_CLK_MMBUF_PLL0 (0x3 << 8)
#define SCCLKDIV2_GT_PCLK_MMBUF (1 << 7)
#define SCTRL_SCCLKDIV4_REG (SCTRL_REG_BASE + 0x260)
#define GT_MMBUF_SYS (1 << 13)
#define GT_MMBUF_FLL (1 << 12)
#define GT_PLL_CLK_MMBUF (1 << 11)
#define SCTRL_SCCLKDIV6_REG (SCTRL_REG_BASE + 0x268)
#define SCTRL_SCPERCTRL7_REG (SCTRL_REG_BASE + 0x31C)
#define SCTRL_SCPERSTAT6_REG (SCTRL_REG_BASE + 0x378)
#define SCTRL_SCINNERSTAT_REG (SCTRL_REG_BASE + 0x3A0)
#define EMMC_UFS_SEL (1 << 15)
#define SCTRL_BAK_DATA0_REG (SCTRL_REG_BASE + 0x40C)
#define SCTRL_BAK_DATA4_REG (SCTRL_REG_BASE + 0x41C)
#define SCTRL_LPMCU_CLKEN_REG (SCTRL_REG_BASE + 0x480)
#define SCTRL_LPMCU_CLKDIS_REG (SCTRL_REG_BASE + 0x484)
#define SCTRL_LPMCU_RSTEN_REG (SCTRL_REG_BASE + 0x500)
#define SCTRL_LPMCU_RSTDIS_REG (SCTRL_REG_BASE + 0x504)
#define DDRC_SOFT_BIT (1 << 6)
#define DDRC_CLK_BIT (1 << 5)
#define SCTRL_SCPEREN0_SEC_REG (SCTRL_REG_BASE + 0x900)
#define SCTRL_SCPERDIS0_SEC_REG (SCTRL_REG_BASE + 0x904)
#define MMBUF_SEC_CTRL_MASK (0xfff << 20)
#define MMBUF_SEC_CTRL(x) (((x) & 0xfff) << 20)
#define SCTRL_PERRSTEN1_SEC_REG (SCTRL_REG_BASE + 0xA50)
#define SCTRL_PERRSTDIS1_SEC_REG (SCTRL_REG_BASE + 0xA54)
#define SCTRL_PERRSTSTAT1_SEC_REG (SCTRL_REG_BASE + 0xA58)
#define RST_ASP_SUBSYS_BIT (1 << 0)
#define SCTRL_PERRSTEN2_SEC_REG (SCTRL_REG_BASE + 0xB50)
#define SCTRL_PERRSTDIS2_SEC_REG (SCTRL_REG_BASE + 0xB54)
#define SCTRL_PERRSTSTAT2_SEC_REG (SCTRL_REG_BASE + 0xB58)
#define SCTRL_HISEECLKDIV_REG (SCTRL_REG_BASE + 0xC28)
#define SC_SEL_HISEE_PLL_MASK (1 << 4)
#define SC_SEL_HISEE_PLL0 (1 << 4)
#define SC_SEL_HISEE_PLL2 (0 << 4)
#define SC_DIV_HISEE_PLL_MASK (7 << 16)
#define SC_DIV_HISEE_PLL(x) ((x) & 0x7)
#define SCTRL_SCSOCID0_REG (SCTRL_REG_BASE + 0xE00)
#define PMC_REG_BASE 0xFFF31000
#define PMC_PPLL1_CTRL0_REG (PMC_REG_BASE + 0x038)
#define PMC_PPLL1_CTRL1_REG (PMC_REG_BASE + 0x03C)
#define PMC_PPLL2_CTRL0_REG (PMC_REG_BASE + 0x040)
#define PMC_PPLL2_CTRL1_REG (PMC_REG_BASE + 0x044)
#define PMC_PPLL3_CTRL0_REG (PMC_REG_BASE + 0x048)
#define PMC_PPLL3_CTRL1_REG (PMC_REG_BASE + 0x04C)
#define PPLLx_LOCK (1 << 26)
#define PPLLx_WITHOUT_CLK_GATE (1 << 26)
#define PPLLx_CFG_VLD (1 << 25)
#define PPLLx_INT_MOD (1 << 24)
#define PPLLx_POSTDIV2_MASK (0x7 << 23)
#define PPLLx_POSTDIV2(x) (((x) & 0x7) << 23)
#define PPLLx_POSTDIV1_MASK (0x7 << 20)
#define PPLLx_POSTDIV1(x) (((x) & 0x7) << 20)
#define PPLLx_FRACDIV_MASK (0x00FFFFFF)
#define PPLLx_FRACDIV(x) ((x) & 0x00FFFFFF)
#define PPLLx_FBDIV_MASK (0xfff << 8)
#define PPLLx_FBDIV(x) (((x) & 0xfff) << 8)
#define PPLLx_REFDIV_MASK (0x3f << 2)
#define PPLLx_REFDIV(x) (((x) & 0x3f) << 2)
#define PPLLx_BP (1 << 1)
#define PPLLx_EN (1 << 0)
#define PMC_DDRLP_CTRL_REG (PMC_REG_BASE + 0x30C)
#define DDRC_CSYSREQ_CFG(x) ((x) & 0xF)
#define PMC_NOC_POWER_IDLEREQ_REG (PMC_REG_BASE + 0x380)
#define PMC_NOC_POWER_IDLEREQ_IVP (1 << 14)
#define PMC_NOC_POWER_IDLEREQ_DSS (1 << 13)
#define PMC_NOC_POWER_IDLEREQ_VENC (1 << 11)
#define PMC_NOC_POWER_IDLEREQ_VDEC (1 << 10)
#define PMC_NOC_POWER_IDLEREQ_ISP (1 << 5)
#define PMC_NOC_POWER_IDLEREQ_VCODEC (1 << 4)
#define DDRPHY_BYPASS_MODE (1 << 0)
#define PMC_NOC_POWER_IDLEACK_REG (PMC_REG_BASE + 0x384)
#define PMC_NOC_POWER_IDLE_REG (PMC_REG_BASE + 0x388)
#define PMU_SSI0_REG_BASE 0xFFF34000
#define PMU_SSI0_LDO8_CTRL0_REG (PMU_SSI0_REG_BASE + (0x68 << 2))
#define LDO8_CTRL0_EN_1_8V 0x02
#define PMU_SSI0_CLK_TOP_CTRL7_REG (PMU_SSI0_REG_BASE + (0x10C << 2))
#define NP_XO_ABB_DIG (1 << 1)
#define LP_CONFIG_REG_BASE 0xFFF3F000
#define DMAC_BASE 0xFDF30000
#define CCI400_REG_BASE 0xE8100000
#define CCI400_SL_IFACE3_CLUSTER_IX 0
#define CCI400_SL_IFACE4_CLUSTER_IX 1
#define GICD_REG_BASE 0xE82B1000
#define GICC_REG_BASE 0xE82B2000
/*
* GIC400 interrupt handling related constants
*/
#define IRQ_SEC_PHY_TIMER 29
#define IRQ_SEC_SGI_0 8
#define IRQ_SEC_SGI_1 9
#define IRQ_SEC_SGI_2 10
#define IRQ_SEC_SGI_3 11
#define IRQ_SEC_SGI_4 12
#define IRQ_SEC_SGI_5 13
#define IRQ_SEC_SGI_6 14
#define IRQ_SEC_SGI_7 15
#define IRQ_SEC_SGI_8 16
#define IPC_REG_BASE 0xE896A000
#define IPC_BASE (IPC_REG_BASE)
#define IOMG_REG_BASE 0xE896C000
/* GPIO46: HUB 3.3V enable. active low */
#define IOMG_044_REG (IOMG_REG_BASE + 0x0B0)
#define IOMG_UART5_RX_REG (IOMG_REG_BASE + 0x0BC)
#define IOMG_UART5_TX_REG (IOMG_REG_BASE + 0x0C0)
#define IOCG_REG_BASE 0xE896C800
/* GPIO005: PMIC SSI. (2 << 4) */
#define IOCG_006_REG (IOCG_REG_BASE + 0x018)
#define TIMER9_REG_BASE 0xE8A00000
#define WDT0_REG_BASE 0xE8A06000
#define WDT1_REG_BASE 0xE8A07000
#define WDT_CONTROL_OFFSET 0x008
#define WDT_LOCK_OFFSET 0xC00
#define WDT_UNLOCK 0x1ACCE551
#define WDT_LOCKED 1
#define PCTRL_REG_BASE 0xE8A09000
#define PCTRL_PERI_CTRL3_REG (PCTRL_REG_BASE + 0x010)
#define PCTRL_PERI_CTRL24_REG (PCTRL_REG_BASE + 0x064)
#define TZC_REG_BASE 0xE8A21000
#define TZC_STAT0_REG (TZC_REG_BASE + 0x800)
#define TZC_EN0_REG (TZC_REG_BASE + 0x804)
#define TZC_DIS0_REG (TZC_REG_BASE + 0x808)
#define TZC_STAT1_REG (TZC_REG_BASE + 0x80C)
#define TZC_EN1_REG (TZC_REG_BASE + 0x810)
#define TZC_DIS1_REG (TZC_REG_BASE + 0x814)
#define TZC_STAT2_REG (TZC_REG_BASE + 0x818)
#define TZC_EN2_REG (TZC_REG_BASE + 0x81C)
#define TZC_DIS2_REG (TZC_REG_BASE + 0x820)
#define TZC_STAT3_REG (TZC_REG_BASE + 0x824)
#define TZC_EN3_REG (TZC_REG_BASE + 0x828)
#define TZC_DIS3_REG (TZC_REG_BASE + 0x82C)
#define TZC_STAT4_REG (TZC_REG_BASE + 0x830)
#define TZC_EN4_REG (TZC_REG_BASE + 0x834)
#define TZC_DIS4_REG (TZC_REG_BASE + 0x838)
#define TZC_STAT5_REG (TZC_REG_BASE + 0x83C)
#define TZC_EN5_REG (TZC_REG_BASE + 0x840)
#define TZC_DIS5_REG (TZC_REG_BASE + 0x844)
#define TZC_STAT6_REG (TZC_REG_BASE + 0x848)
#define TZC_EN6_REG (TZC_REG_BASE + 0x84C)
#define TZC_DIS6_REG (TZC_REG_BASE + 0x850)
#define TZC_STAT7_REG (TZC_REG_BASE + 0x854)
#define TZC_EN7_REG (TZC_REG_BASE + 0x858)
#define TZC_DIS7_REG (TZC_REG_BASE + 0x85C)
#define TZC_STAT8_REG (TZC_REG_BASE + 0x860)
#define TZC_EN8_REG (TZC_REG_BASE + 0x864)
#define TZC_DIS8_REG (TZC_REG_BASE + 0x868)
#define MMBUF_BASE 0xEA800000
#define ACPU_DMCPACK0_BASE 0xEA900000
#define ACPU_DMCPACK1_BASE 0xEA920000
#define ACPU_DMCPACK2_BASE 0xEA940000
#define ACPU_DMCPACK3_BASE 0xEA960000
#define UART5_REG_BASE 0xFDF05000
#define USB3OTG_REG_BASE 0xFF100000
#define UFS_REG_BASE 0xFF3B0000
#define UFS_SYS_REG_BASE 0xFF3B1000
#define UFS_SYS_PSW_POWER_CTRL_REG (UFS_SYS_REG_BASE + 0x004)
#define UFS_SYS_PHY_ISO_EN_REG (UFS_SYS_REG_BASE + 0x008)
#define UFS_SYS_HC_LP_CTRL_REG (UFS_SYS_REG_BASE + 0x00C)
#define UFS_SYS_PHY_CLK_CTRL_REG (UFS_SYS_REG_BASE + 0x010)
#define UFS_SYS_PSW_CLK_CTRL_REG (UFS_SYS_REG_BASE + 0x014)
#define UFS_SYS_CLOCK_GATE_BYPASS_REG (UFS_SYS_REG_BASE + 0x018)
#define UFS_SYS_RESET_CTRL_EN_REG (UFS_SYS_REG_BASE + 0x01C)
#define UFS_SYS_MONITOR_HH_REG (UFS_SYS_REG_BASE + 0x03C)
#define UFS_SYS_UFS_SYSCTRL_REG (UFS_SYS_REG_BASE + 0x05C)
#define UFS_SYS_UFS_DEVICE_RESET_CTRL_REG (UFS_SYS_REG_BASE + 0x060)
#define UFS_SYS_UFS_APB_ADDR_MASK_REG (UFS_SYS_REG_BASE + 0x064)
#define BIT_UFS_PSW_ISO_CTRL (1 << 16)
#define BIT_UFS_PSW_MTCMOS_EN (1 << 0)
#define BIT_UFS_REFCLK_ISO_EN (1 << 16)
#define BIT_UFS_PHY_ISO_CTRL (1 << 0)
#define BIT_SYSCTRL_LP_ISOL_EN (1 << 16)
#define BIT_SYSCTRL_PWR_READY (1 << 8)
#define BIT_SYSCTRL_REF_CLOCK_EN (1 << 24)
#define MASK_SYSCTRL_REF_CLOCK_SEL (3 << 8)
#define MASK_SYSCTRL_CFG_CLOCK_FREQ (0xFF)
#define BIT_SYSCTRL_PSW_CLK_EN (1 << 4)
#define MASK_UFS_CLK_GATE_BYPASS (0x3F)
#define BIT_SYSCTRL_LP_RESET_N (1 << 0)
#define BIT_UFS_REFCLK_SRC_SE1 (1 << 0)
#define MASK_UFS_SYSCTRL_BYPASS (0x3F << 16)
#define MASK_UFS_DEVICE_RESET (1 << 16)
#define BIT_UFS_DEVICE_RESET (1 << 0)
#define IOMG_FIX_REG_BASE 0xFF3B6000
/* GPIO150: LED */
#define IOMG_FIX_006_REG (IOMG_FIX_REG_BASE + 0x018)
/* GPIO151: LED */
#define IOMG_FIX_007_REG (IOMG_FIX_REG_BASE + 0x01C)
#define IOMG_AO_REG_BASE 0xFFF11000
/* GPIO189: LED */
#define IOMG_AO_011_REG (IOMG_AO_REG_BASE + 0x02C)
/* GPIO190: LED */
#define IOMG_AO_012_REG (IOMG_AO_REG_BASE + 0x030)
/* GPIO202: type C enable. active low */
#define IOMG_AO_023_REG (IOMG_AO_REG_BASE + 0x05C)
/* GPIO206: USB switch. active low */
#define IOMG_AO_026_REG (IOMG_AO_REG_BASE + 0x068)
/* GPIO219: PD interrupt. pull up */
#define IOMG_AO_039_REG (IOMG_AO_REG_BASE + 0x09C)
#define IOCG_AO_REG_BASE 0xFFF1187C
/* GPIO219: PD interrupt. pull up */
#define IOCG_AO_043_REG (IOCG_AO_REG_BASE + 0x030)
#endif
/* __HI3660_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