2016-11-12 15:38:26 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2015 Siarhei Siamashka <siarhei.siamashka@gmail.com>
|
|
|
|
|
* Copyright (C) 2016 Bernhard Nortmann <bernhard.nortmann@web.de>
|
|
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
#ifndef _SUNXI_TOOLS_SOC_INFO_H
|
|
|
|
|
#define _SUNXI_TOOLS_SOC_INFO_H
|
|
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
|
/* SoC version information, as retrieved by the FEL protocol */
|
|
|
|
|
struct aw_fel_version {
|
|
|
|
|
char signature[8];
|
|
|
|
|
uint32_t soc_id; /* 0x00162300 */
|
|
|
|
|
uint32_t unknown_0a; /* 1 */
|
|
|
|
|
uint16_t protocol; /* 1 */
|
|
|
|
|
uint8_t unknown_12; /* 0x44 */
|
|
|
|
|
uint8_t unknown_13; /* 0x08 */
|
|
|
|
|
uint32_t scratchpad; /* 0x7e00 */
|
|
|
|
|
uint32_t pad[2]; /* unused */
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
2016-11-20 21:29:11 +01:00
|
|
|
/*
|
|
|
|
|
* Buffer for a SoC name string. We want at least 6 + 1 characters, to store
|
|
|
|
|
* the hexadecimal ID "0xABCD" for unknown SoCs, plus the terminating NUL.
|
|
|
|
|
*/
|
|
|
|
|
typedef char soc_name_t[8];
|
|
|
|
|
|
2016-11-12 15:38:26 +01:00
|
|
|
/*
|
|
|
|
|
* The 'sram_swap_buffers' structure is used to describe information about
|
|
|
|
|
* pairwise memory regions in SRAM, the content of which needs to be exchanged
|
|
|
|
|
* before calling the U-Boot SPL code and then exchanged again before returning
|
|
|
|
|
* control back to the FEL code from the BROM.
|
|
|
|
|
*/
|
|
|
|
|
typedef struct {
|
|
|
|
|
uint32_t buf1; /* BROM buffer */
|
|
|
|
|
uint32_t buf2; /* backup storage location */
|
|
|
|
|
uint32_t size; /* buffer size */
|
|
|
|
|
} sram_swap_buffers;
|
|
|
|
|
|
2020-04-19 21:16:24 +00:00
|
|
|
/*
|
|
|
|
|
* Contains information on the watchdog peripheral, to enable reset
|
|
|
|
|
*/
|
|
|
|
|
typedef struct {
|
|
|
|
|
/* Register that needs to be written to */
|
|
|
|
|
uint32_t reg_mode;
|
|
|
|
|
/* Value to write to trigger a reset */
|
|
|
|
|
uint32_t reg_mode_value;
|
|
|
|
|
} watchdog_info;
|
|
|
|
|
|
2023-02-10 17:29:34 +08:00
|
|
|
/*
|
|
|
|
|
* sunxi sid sections
|
|
|
|
|
*/
|
|
|
|
|
typedef struct {
|
|
|
|
|
const char *name;
|
|
|
|
|
uint32_t offset;
|
|
|
|
|
uint32_t size_bits;
|
|
|
|
|
} sid_section;
|
|
|
|
|
|
|
|
|
|
#define SID_SECTION(_name, _offset, _size_bits) { \
|
|
|
|
|
.name = _name, \
|
|
|
|
|
.offset = _offset, \
|
|
|
|
|
.size_bits = _size_bits, \
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-12 15:38:26 +01:00
|
|
|
/*
|
|
|
|
|
* Each SoC variant may have its own list of memory buffers to be exchanged
|
|
|
|
|
* and the information about the placement of the thunk code, which handles
|
|
|
|
|
* the transition of execution from the BROM FEL code to the U-Boot SPL and
|
|
|
|
|
* back.
|
|
|
|
|
*
|
|
|
|
|
* Note: the entries in the 'swap_buffers' tables need to be sorted by 'buf1'
|
|
|
|
|
* addresses. And the 'buf1' addresses are the BROM data buffers, while 'buf2'
|
|
|
|
|
* addresses are the intended backup locations.
|
|
|
|
|
*
|
|
|
|
|
* Also for performance reasons, we optionally want to have MMU enabled with
|
|
|
|
|
* optimal section attributes configured (the code from the BROM should use
|
|
|
|
|
* I-cache, writing data to the DRAM area should use write combining). The
|
|
|
|
|
* reason is that the BROM FEL protocol implementation moves data using the
|
|
|
|
|
* CPU somewhere on the performance critical path when transferring data over
|
|
|
|
|
* USB. The older SoC variants (A10/A13/A20/A31/A23) already have MMU enabled
|
|
|
|
|
* and we only need to adjust section attributes. The BROM in newer SoC variants
|
|
|
|
|
* (A33/A83T/H3) doesn't enable MMU any more, so we need to find some 16K of
|
|
|
|
|
* spare space in SRAM to place the translation table there and specify it as
|
|
|
|
|
* the 'mmu_tt_addr' field in the 'soc_sram_info' structure. The 'mmu_tt_addr'
|
|
|
|
|
* address must be 16K aligned.
|
2017-02-28 20:57:01 +02:00
|
|
|
*
|
|
|
|
|
* If an SoC has the "secure boot" fuse burned, it will enter FEL mode in
|
|
|
|
|
* non-secure state, so with the SCR.NS bit set. Since in this mode the
|
|
|
|
|
* secure/non-secure state restrictions are actually observed, we suffer
|
|
|
|
|
* from several restrictions:
|
|
|
|
|
* - No access to the SID information (both via memory mapped and "register").
|
|
|
|
|
* - No access to secure SRAM (SRAM A2 on H3/A64/H5).
|
|
|
|
|
* - No access to the secure side of the GIC, so it can't be configured to
|
|
|
|
|
* be accessible from non-secure world.
|
|
|
|
|
* - No RMR trigger on ARMv8 cores to bring the core into AArch64.
|
|
|
|
|
* However it has been found out that a simple "smc" call will immediately
|
|
|
|
|
* return from monitor mode, but with the NS bit cleared, so access to all
|
|
|
|
|
* secure peripherals is suddenly possible.
|
|
|
|
|
* The 'needs_smc_workaround_if_zero_word_at_addr' field can be used to
|
|
|
|
|
* have a check for this condition (reading from restricted addresses
|
|
|
|
|
* typically returns zero) and then activate the SMC workaround if needed.
|
2016-11-12 15:38:26 +01:00
|
|
|
*/
|
|
|
|
|
typedef struct {
|
|
|
|
|
uint32_t soc_id; /* ID of the SoC */
|
2016-11-20 21:29:11 +01:00
|
|
|
const char *name; /* human-readable SoC name string */
|
2016-11-12 15:38:26 +01:00
|
|
|
uint32_t spl_addr; /* SPL load address */
|
|
|
|
|
uint32_t scratch_addr; /* A safe place to upload & run code */
|
|
|
|
|
uint32_t thunk_addr; /* Address of the thunk code */
|
|
|
|
|
uint32_t thunk_size; /* Maximal size of the thunk code */
|
|
|
|
|
bool needs_l2en; /* Set the L2EN bit */
|
|
|
|
|
uint32_t mmu_tt_addr; /* MMU translation table address */
|
2016-12-28 13:29:47 +01:00
|
|
|
uint32_t sid_base; /* base address for SID registers */
|
|
|
|
|
uint32_t sid_offset; /* offset for SID_KEY[0-3], "root key" */
|
2023-02-10 17:29:34 +08:00
|
|
|
const sid_section *sid_sections; /* sid memory maps */
|
2016-11-12 15:38:26 +01:00
|
|
|
uint32_t rvbar_reg; /* MMIO address of RVBARADDR0_L register */
|
2020-04-19 21:16:24 +00:00
|
|
|
const watchdog_info *watchdog; /* Used for reset */
|
2016-12-20 00:27:37 +08:00
|
|
|
bool sid_fix; /* Use SID workaround (read via register) */
|
2022-07-06 04:54:15 +08:00
|
|
|
/* Use I$ workaround (disable I$ before first write to prevent stale thunk */
|
|
|
|
|
bool icache_fix;
|
2017-02-28 20:57:01 +02:00
|
|
|
/* Use SMC workaround (enter secure mode) if can't read from this address */
|
|
|
|
|
uint32_t needs_smc_workaround_if_zero_word_at_addr;
|
2020-12-28 23:51:14 +00:00
|
|
|
uint32_t sram_size; /* Usable contiguous SRAM at spl_addr */
|
2016-11-12 15:38:26 +01:00
|
|
|
sram_swap_buffers *swap_buffers;
|
|
|
|
|
} soc_info_t;
|
|
|
|
|
|
|
|
|
|
|
2016-11-20 21:29:11 +01:00
|
|
|
void get_soc_name_from_id(soc_name_t buffer, uint32_t soc_id);
|
2016-11-12 15:38:26 +01:00
|
|
|
soc_info_t *get_soc_info_from_id(uint32_t soc_id);
|
|
|
|
|
soc_info_t *get_soc_info_from_version(struct aw_fel_version *buf);
|
|
|
|
|
|
|
|
|
|
#endif /* _SUNXI_TOOLS_SOC_INFO_H */
|