danh-arm
6 years ago
committed by
GitHub
65 changed files with 12015 additions and 0 deletions
@ -0,0 +1,82 @@ |
|||
Trusted Firmware-A for STM32MP1 |
|||
=============================== |
|||
|
|||
STM32MP1 is a microprocessor designed by STMicroelectronics |
|||
based on a dual Arm Cortex-A7. |
|||
It is an Armv7-A platform, using dedicated code from TF-A. |
|||
|
|||
|
|||
Design |
|||
------ |
|||
The STM32MP1 resets in the ROM code of the Cortex-A7. |
|||
The primary boot core (core 0) executes the boot sequence while |
|||
secondary boot core (core 1) is kept in a holding pen loop. |
|||
The ROM code boot sequence loads the TF-A binary image from boot device |
|||
to embedded SRAM. |
|||
|
|||
The TF-A image must be properly formatted with a STM32 header structure |
|||
for ROM code is able to load this image. |
|||
Tool stm32image can be used to prepend this header to the generated TF-A binary. |
|||
|
|||
At compilation step, BL2, BL32 and DTB file are linked together in a single |
|||
binary. The stm32image tool is also generated and the header is added to TF-A |
|||
binary. This binary file with header is named tf-a-stm32mp157c-ev1.stm32. |
|||
It can then be copied in the first partition of the boot device. |
|||
|
|||
|
|||
Memory mapping |
|||
~~~~~~~~~~~~~~ |
|||
|
|||
:: |
|||
|
|||
0x00000000 +-----------------+ |
|||
| | ROM |
|||
0x00020000 +-----------------+ |
|||
| | |
|||
| ... | |
|||
| | |
|||
0x2FFC0000 +-----------------+ \ |
|||
| | | |
|||
| ... | | |
|||
| | | |
|||
0x2FFD8000 +-----------------+ | |
|||
| TF-A DTB | | Embedded SRAM |
|||
0x2FFDC000 +-----------------+ | |
|||
| BL2 | | |
|||
0x2FFEF000 +-----------------+ | |
|||
| BL32 | | |
|||
0x30000000 +-----------------+ / |
|||
| | |
|||
| ... | |
|||
| | |
|||
0x40000000 +-----------------+ |
|||
| | |
|||
| | Devices |
|||
| | |
|||
0xC0000000 +-----------------+ \ |
|||
| | | |
|||
0xC0100000 +-----------------+ | |
|||
| BL33 | | Non-secure RAM (DDR) |
|||
| ... | | |
|||
| | | |
|||
0xFFFFFFFF +-----------------+ / |
|||
|
|||
|
|||
Boot sequence |
|||
~~~~~~~~~~~~~ |
|||
|
|||
ROM code -> BL2 (compiled with BL2_AT_EL3) -> BL32 (SP_min) -> BL33 (U-Boot) |
|||
|
|||
|
|||
Build Instructions |
|||
------------------ |
|||
|
|||
To build: |
|||
|
|||
.. code:: bash |
|||
|
|||
make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min |
|||
|
|||
The following build options are supported: |
|||
|
|||
- ``ENABLE_STACK_PROTECTOR``: To enable the stack protection. |
File diff suppressed because it is too large
@ -0,0 +1,365 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <dt-bindings/clock/stm32mp1-clksrc.h> |
|||
#include <errno.h> |
|||
#include <libfdt.h> |
|||
#include <stm32mp1_clk.h> |
|||
#include <stm32mp1_clkfunc.h> |
|||
#include <stm32mp1_dt.h> |
|||
|
|||
#define DT_RCC_NODE_NAME "rcc@50000000" |
|||
#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" |
|||
#define DT_RCC_COMPAT "syscon" |
|||
#define DT_STGEN_COMPAT "st,stm32-stgen" |
|||
#define DT_UART_COMPAT "st,stm32h7-uart" |
|||
#define DT_USART_COMPAT "st,stm32h7-usart" |
|||
|
|||
const char *stm32mp_osc_node_label[NB_OSC] = { |
|||
[_LSI] = "clk-lsi", |
|||
[_LSE] = "clk-lse", |
|||
[_HSI] = "clk-hsi", |
|||
[_HSE] = "clk-hse", |
|||
[_CSI] = "clk-csi", |
|||
[_I2S_CKIN] = "i2s_ckin", |
|||
[_USB_PHY_48] = "ck_usbo_48m" |
|||
}; |
|||
|
|||
/*******************************************************************************
|
|||
* This function reads the frequency of an oscillator from its name. |
|||
* It reads the value indicated inside the device tree. |
|||
* Returns 0 if success, and a negative value else. |
|||
* If success, value is stored in the second parameter. |
|||
******************************************************************************/ |
|||
int fdt_osc_read_freq(const char *name, uint32_t *freq) |
|||
{ |
|||
int node, subnode; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return -ENOENT; |
|||
} |
|||
|
|||
node = fdt_path_offset(fdt, "/clocks"); |
|||
if (node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
fdt_for_each_subnode(subnode, fdt, node) { |
|||
const char *cchar; |
|||
int ret; |
|||
|
|||
cchar = fdt_get_name(fdt, subnode, &ret); |
|||
if (cchar == NULL) { |
|||
return ret; |
|||
} |
|||
|
|||
if (strncmp(cchar, name, (size_t)ret) == 0) { |
|||
const fdt32_t *cuint; |
|||
|
|||
cuint = fdt_getprop(fdt, subnode, "clock-frequency", |
|||
&ret); |
|||
if (cuint == NULL) { |
|||
return ret; |
|||
} |
|||
|
|||
*freq = fdt32_to_cpu(*cuint); |
|||
|
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
/* Oscillator not found, freq=0 */ |
|||
*freq = 0; |
|||
return 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function checks the presence of an oscillator property from its id. |
|||
* The search is done inside the device tree. |
|||
* Returns true/false regarding search result. |
|||
******************************************************************************/ |
|||
bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) |
|||
{ |
|||
int node, subnode; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return false; |
|||
} |
|||
|
|||
if (osc_id >= NB_OSC) { |
|||
return false; |
|||
} |
|||
|
|||
node = fdt_path_offset(fdt, "/clocks"); |
|||
if (node < 0) { |
|||
return false; |
|||
} |
|||
|
|||
fdt_for_each_subnode(subnode, fdt, node) { |
|||
const char *cchar; |
|||
int ret; |
|||
|
|||
cchar = fdt_get_name(fdt, subnode, &ret); |
|||
if (cchar == NULL) { |
|||
return false; |
|||
} |
|||
|
|||
if (strncmp(cchar, stm32mp_osc_node_label[osc_id], |
|||
(size_t)ret) != 0) { |
|||
continue; |
|||
} |
|||
|
|||
if (fdt_getprop(fdt, subnode, prop_name, NULL) != NULL) { |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function reads a value of a oscillator property from its id. |
|||
* Returns value if success, and a default value if property not found. |
|||
* Default value is passed as parameter. |
|||
******************************************************************************/ |
|||
uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, |
|||
const char *prop_name, uint32_t dflt_value) |
|||
{ |
|||
int node, subnode; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return dflt_value; |
|||
} |
|||
|
|||
if (osc_id >= NB_OSC) { |
|||
return dflt_value; |
|||
} |
|||
|
|||
node = fdt_path_offset(fdt, "/clocks"); |
|||
if (node < 0) { |
|||
return dflt_value; |
|||
} |
|||
|
|||
fdt_for_each_subnode(subnode, fdt, node) { |
|||
const char *cchar; |
|||
int ret; |
|||
|
|||
cchar = fdt_get_name(fdt, subnode, &ret); |
|||
if (cchar == NULL) { |
|||
return dflt_value; |
|||
} |
|||
|
|||
if (strncmp(cchar, stm32mp_osc_node_label[osc_id], |
|||
(size_t)ret) != 0) { |
|||
continue; |
|||
} |
|||
|
|||
return fdt_read_uint32_default(subnode, prop_name, dflt_value); |
|||
} |
|||
|
|||
return dflt_value; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function reads the rcc base address. |
|||
* It reads the value indicated inside the device tree. |
|||
* Returns address if success, and 0 value else. |
|||
******************************************************************************/ |
|||
uint32_t fdt_rcc_read_addr(void) |
|||
{ |
|||
int node, subnode; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return 0; |
|||
} |
|||
|
|||
node = fdt_path_offset(fdt, "/soc"); |
|||
if (node < 0) { |
|||
return 0; |
|||
} |
|||
|
|||
fdt_for_each_subnode(subnode, fdt, node) { |
|||
const char *cchar; |
|||
int ret; |
|||
|
|||
cchar = fdt_get_name(fdt, subnode, &ret); |
|||
if (cchar == NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
if (strncmp(cchar, DT_RCC_NODE_NAME, (size_t)ret) == 0) { |
|||
const fdt32_t *cuint; |
|||
|
|||
cuint = fdt_getprop(fdt, subnode, "reg", NULL); |
|||
if (cuint == NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
return fdt32_to_cpu(*cuint); |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function reads a series of parameters in rcc-clk section. |
|||
* It reads the values indicated inside the device tree, from property name. |
|||
* The number of parameters is also indicated as entry parameter. |
|||
* Returns 0 if success, and a negative value else. |
|||
* If success, values are stored at the second parameter address. |
|||
******************************************************************************/ |
|||
int fdt_rcc_read_uint32_array(const char *prop_name, |
|||
uint32_t *array, uint32_t count) |
|||
{ |
|||
int node; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return -ENOENT; |
|||
} |
|||
|
|||
node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); |
|||
if (node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
return fdt_read_uint32_array(node, prop_name, array, count); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets the subnode offset in rcc-clk section from its name. |
|||
* It reads the values indicated inside the device tree. |
|||
* Returns offset if success, and a negative value else. |
|||
******************************************************************************/ |
|||
int fdt_rcc_subnode_offset(const char *name) |
|||
{ |
|||
int node, subnode; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return -ENOENT; |
|||
} |
|||
|
|||
node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); |
|||
if (node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
subnode = fdt_subnode_offset(fdt, node, name); |
|||
if (subnode <= 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
return subnode; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets the pointer to a rcc-clk property from its name. |
|||
* It reads the values indicated inside the device tree. |
|||
* Length of the property is stored in the second parameter. |
|||
* Returns pointer if success, and NULL value else. |
|||
******************************************************************************/ |
|||
const uint32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) |
|||
{ |
|||
const uint32_t *cuint; |
|||
int node, len; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return NULL; |
|||
} |
|||
|
|||
node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); |
|||
if (node < 0) { |
|||
return NULL; |
|||
} |
|||
|
|||
cuint = fdt_getprop(fdt, node, prop_name, &len); |
|||
if (cuint == NULL) { |
|||
return NULL; |
|||
} |
|||
|
|||
*lenp = len; |
|||
return cuint; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets the secure status for rcc node. |
|||
* It reads secure-status in device tree. |
|||
* Returns 1 if rcc is available from secure world, 0 else. |
|||
******************************************************************************/ |
|||
bool fdt_get_rcc_secure_status(void) |
|||
{ |
|||
int node; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return false; |
|||
} |
|||
|
|||
node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_COMPAT); |
|||
if (node < 0) { |
|||
return false; |
|||
} |
|||
|
|||
return fdt_check_secure_status(node); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function reads the stgen base address. |
|||
* It reads the value indicated inside the device tree. |
|||
* Returns address if success, and NULL value else. |
|||
******************************************************************************/ |
|||
uintptr_t fdt_get_stgen_base(void) |
|||
{ |
|||
int node; |
|||
const fdt32_t *cuint; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return 0; |
|||
} |
|||
|
|||
node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT); |
|||
if (node < 0) { |
|||
return 0; |
|||
} |
|||
|
|||
cuint = fdt_getprop(fdt, node, "reg", NULL); |
|||
if (cuint == NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
return fdt32_to_cpu(*cuint); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets the clock ID of the given node. |
|||
* It reads the value indicated inside the device tree. |
|||
* Returns ID if success, and a negative value else. |
|||
******************************************************************************/ |
|||
int fdt_get_clock_id(int node) |
|||
{ |
|||
const fdt32_t *cuint; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return -ENOENT; |
|||
} |
|||
|
|||
cuint = fdt_getprop(fdt, node, "clocks", NULL); |
|||
if (cuint == NULL) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
cuint++; |
|||
return (int)fdt32_to_cpu(*cuint); |
|||
} |
@ -0,0 +1,895 @@ |
|||
/*
|
|||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <arch.h> |
|||
#include <arch_helpers.h> |
|||
#include <debug.h> |
|||
#include <delay_timer.h> |
|||
#include <dt-bindings/clock/stm32mp1-clks.h> |
|||
#include <mmio.h> |
|||
#include <platform.h> |
|||
#include <stddef.h> |
|||
#include <stm32mp1_clk.h> |
|||
#include <stm32mp1_ddr.h> |
|||
#include <stm32mp1_ddr_regs.h> |
|||
#include <stm32mp1_dt.h> |
|||
#include <stm32mp1_pmic.h> |
|||
#include <stm32mp1_pwr.h> |
|||
#include <stm32mp1_ram.h> |
|||
#include <stm32mp1_rcc.h> |
|||
|
|||
struct reg_desc { |
|||
const char *name; |
|||
uint16_t offset; /* Offset for base address */ |
|||
uint8_t par_offset; /* Offset for parameter array */ |
|||
}; |
|||
|
|||
#define INVALID_OFFSET 0xFFU |
|||
|
|||
#define TIMESLOT_1US (plat_get_syscnt_freq2() / 1000000U) |
|||
|
|||
#define DDRCTL_REG(x, y) \ |
|||
{ \ |
|||
.name = #x, \ |
|||
.offset = offsetof(struct stm32mp1_ddrctl, x), \ |
|||
.par_offset = offsetof(struct y, x) \ |
|||
} |
|||
|
|||
#define DDRPHY_REG(x, y) \ |
|||
{ \ |
|||
.name = #x, \ |
|||
.offset = offsetof(struct stm32mp1_ddrphy, x), \ |
|||
.par_offset = offsetof(struct y, x) \ |
|||
} |
|||
|
|||
#define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg) |
|||
static const struct reg_desc ddr_reg[] = { |
|||
DDRCTL_REG_REG(mstr), |
|||
DDRCTL_REG_REG(mrctrl0), |
|||
DDRCTL_REG_REG(mrctrl1), |
|||
DDRCTL_REG_REG(derateen), |
|||
DDRCTL_REG_REG(derateint), |
|||
DDRCTL_REG_REG(pwrctl), |
|||
DDRCTL_REG_REG(pwrtmg), |
|||
DDRCTL_REG_REG(hwlpctl), |
|||
DDRCTL_REG_REG(rfshctl0), |
|||
DDRCTL_REG_REG(rfshctl3), |
|||
DDRCTL_REG_REG(crcparctl0), |
|||
DDRCTL_REG_REG(zqctl0), |
|||
DDRCTL_REG_REG(dfitmg0), |
|||
DDRCTL_REG_REG(dfitmg1), |
|||
DDRCTL_REG_REG(dfilpcfg0), |
|||
DDRCTL_REG_REG(dfiupd0), |
|||
DDRCTL_REG_REG(dfiupd1), |
|||
DDRCTL_REG_REG(dfiupd2), |
|||
DDRCTL_REG_REG(dfiphymstr), |
|||
DDRCTL_REG_REG(odtmap), |
|||
DDRCTL_REG_REG(dbg0), |
|||
DDRCTL_REG_REG(dbg1), |
|||
DDRCTL_REG_REG(dbgcmd), |
|||
DDRCTL_REG_REG(poisoncfg), |
|||
DDRCTL_REG_REG(pccfg), |
|||
}; |
|||
|
|||
#define DDRCTL_REG_TIMING(x) DDRCTL_REG(x, stm32mp1_ddrctrl_timing) |
|||
static const struct reg_desc ddr_timing[] = { |
|||
DDRCTL_REG_TIMING(rfshtmg), |
|||
DDRCTL_REG_TIMING(dramtmg0), |
|||
DDRCTL_REG_TIMING(dramtmg1), |
|||
DDRCTL_REG_TIMING(dramtmg2), |
|||
DDRCTL_REG_TIMING(dramtmg3), |
|||
DDRCTL_REG_TIMING(dramtmg4), |
|||
DDRCTL_REG_TIMING(dramtmg5), |
|||
DDRCTL_REG_TIMING(dramtmg6), |
|||
DDRCTL_REG_TIMING(dramtmg7), |
|||
DDRCTL_REG_TIMING(dramtmg8), |
|||
DDRCTL_REG_TIMING(dramtmg14), |
|||
DDRCTL_REG_TIMING(odtcfg), |
|||
}; |
|||
|
|||
#define DDRCTL_REG_MAP(x) DDRCTL_REG(x, stm32mp1_ddrctrl_map) |
|||
static const struct reg_desc ddr_map[] = { |
|||
DDRCTL_REG_MAP(addrmap1), |
|||
DDRCTL_REG_MAP(addrmap2), |
|||
DDRCTL_REG_MAP(addrmap3), |
|||
DDRCTL_REG_MAP(addrmap4), |
|||
DDRCTL_REG_MAP(addrmap5), |
|||
DDRCTL_REG_MAP(addrmap6), |
|||
DDRCTL_REG_MAP(addrmap9), |
|||
DDRCTL_REG_MAP(addrmap10), |
|||
DDRCTL_REG_MAP(addrmap11), |
|||
}; |
|||
|
|||
#define DDRCTL_REG_PERF(x) DDRCTL_REG(x, stm32mp1_ddrctrl_perf) |
|||
static const struct reg_desc ddr_perf[] = { |
|||
DDRCTL_REG_PERF(sched), |
|||
DDRCTL_REG_PERF(sched1), |
|||
DDRCTL_REG_PERF(perfhpr1), |
|||
DDRCTL_REG_PERF(perflpr1), |
|||
DDRCTL_REG_PERF(perfwr1), |
|||
DDRCTL_REG_PERF(pcfgr_0), |
|||
DDRCTL_REG_PERF(pcfgw_0), |
|||
DDRCTL_REG_PERF(pcfgqos0_0), |
|||
DDRCTL_REG_PERF(pcfgqos1_0), |
|||
DDRCTL_REG_PERF(pcfgwqos0_0), |
|||
DDRCTL_REG_PERF(pcfgwqos1_0), |
|||
DDRCTL_REG_PERF(pcfgr_1), |
|||
DDRCTL_REG_PERF(pcfgw_1), |
|||
DDRCTL_REG_PERF(pcfgqos0_1), |
|||
DDRCTL_REG_PERF(pcfgqos1_1), |
|||
DDRCTL_REG_PERF(pcfgwqos0_1), |
|||
DDRCTL_REG_PERF(pcfgwqos1_1), |
|||
}; |
|||
|
|||
#define DDRPHY_REG_REG(x) DDRPHY_REG(x, stm32mp1_ddrphy_reg) |
|||
static const struct reg_desc ddrphy_reg[] = { |
|||
DDRPHY_REG_REG(pgcr), |
|||
DDRPHY_REG_REG(aciocr), |
|||
DDRPHY_REG_REG(dxccr), |
|||
DDRPHY_REG_REG(dsgcr), |
|||
DDRPHY_REG_REG(dcr), |
|||
DDRPHY_REG_REG(odtcr), |
|||
DDRPHY_REG_REG(zq0cr1), |
|||
DDRPHY_REG_REG(dx0gcr), |
|||
DDRPHY_REG_REG(dx1gcr), |
|||
DDRPHY_REG_REG(dx2gcr), |
|||
DDRPHY_REG_REG(dx3gcr), |
|||
}; |
|||
|
|||
#define DDRPHY_REG_TIMING(x) DDRPHY_REG(x, stm32mp1_ddrphy_timing) |
|||
static const struct reg_desc ddrphy_timing[] = { |
|||
DDRPHY_REG_TIMING(ptr0), |
|||
DDRPHY_REG_TIMING(ptr1), |
|||
DDRPHY_REG_TIMING(ptr2), |
|||
DDRPHY_REG_TIMING(dtpr0), |
|||
DDRPHY_REG_TIMING(dtpr1), |
|||
DDRPHY_REG_TIMING(dtpr2), |
|||
DDRPHY_REG_TIMING(mr0), |
|||
DDRPHY_REG_TIMING(mr1), |
|||
DDRPHY_REG_TIMING(mr2), |
|||
DDRPHY_REG_TIMING(mr3), |
|||
}; |
|||
|
|||
#define DDRPHY_REG_CAL(x) DDRPHY_REG(x, stm32mp1_ddrphy_cal) |
|||
static const struct reg_desc ddrphy_cal[] = { |
|||
DDRPHY_REG_CAL(dx0dllcr), |
|||
DDRPHY_REG_CAL(dx0dqtr), |
|||
DDRPHY_REG_CAL(dx0dqstr), |
|||
DDRPHY_REG_CAL(dx1dllcr), |
|||
DDRPHY_REG_CAL(dx1dqtr), |
|||
DDRPHY_REG_CAL(dx1dqstr), |
|||
DDRPHY_REG_CAL(dx2dllcr), |
|||
DDRPHY_REG_CAL(dx2dqtr), |
|||
DDRPHY_REG_CAL(dx2dqstr), |
|||
DDRPHY_REG_CAL(dx3dllcr), |
|||
DDRPHY_REG_CAL(dx3dqtr), |
|||
DDRPHY_REG_CAL(dx3dqstr), |
|||
}; |
|||
|
|||
#define DDR_REG_DYN(x) \ |
|||
{ \ |
|||
.name = #x, \ |
|||
.offset = offsetof(struct stm32mp1_ddrctl, x), \ |
|||
.par_offset = INVALID_OFFSET \ |
|||
} |
|||
|
|||
static const struct reg_desc ddr_dyn[] = { |
|||
DDR_REG_DYN(stat), |
|||
DDR_REG_DYN(init0), |
|||
DDR_REG_DYN(dfimisc), |
|||
DDR_REG_DYN(dfistat), |
|||
DDR_REG_DYN(swctl), |
|||
DDR_REG_DYN(swstat), |
|||
DDR_REG_DYN(pctrl_0), |
|||
DDR_REG_DYN(pctrl_1), |
|||
}; |
|||
|
|||
#define DDRPHY_REG_DYN(x) \ |
|||
{ \ |
|||
.name = #x, \ |
|||
.offset = offsetof(struct stm32mp1_ddrphy, x), \ |
|||
.par_offset = INVALID_OFFSET \ |
|||
} |
|||
|
|||
static const struct reg_desc ddrphy_dyn[] = { |
|||
DDRPHY_REG_DYN(pir), |
|||
DDRPHY_REG_DYN(pgsr), |
|||
}; |
|||
|
|||
enum reg_type { |
|||
REG_REG, |
|||
REG_TIMING, |
|||
REG_PERF, |
|||
REG_MAP, |
|||
REGPHY_REG, |
|||
REGPHY_TIMING, |
|||
REGPHY_CAL, |
|||
/*
|
|||
* Dynamic registers => managed in driver or not changed, |
|||
* can be dumped in interactive mode. |
|||
*/ |
|||
REG_DYN, |
|||
REGPHY_DYN, |
|||
REG_TYPE_NB |
|||
}; |
|||
|
|||
enum base_type { |
|||
DDR_BASE, |
|||
DDRPHY_BASE, |
|||
NONE_BASE |
|||
}; |
|||
|
|||
struct ddr_reg_info { |
|||
const char *name; |
|||
const struct reg_desc *desc; |
|||
uint8_t size; |
|||
enum base_type base; |
|||
}; |
|||
|
|||
static const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = { |
|||
[REG_REG] = { |
|||
"static", ddr_reg, ARRAY_SIZE(ddr_reg), DDR_BASE |
|||
}, |
|||
[REG_TIMING] = { |
|||
"timing", ddr_timing, ARRAY_SIZE(ddr_timing), DDR_BASE |
|||
}, |
|||
[REG_PERF] = { |
|||
"perf", ddr_perf, ARRAY_SIZE(ddr_perf), DDR_BASE |
|||
}, |
|||
[REG_MAP] = { |
|||
"map", ddr_map, ARRAY_SIZE(ddr_map), DDR_BASE |
|||
}, |
|||
[REGPHY_REG] = { |
|||
"static", ddrphy_reg, ARRAY_SIZE(ddrphy_reg), DDRPHY_BASE |
|||
}, |
|||
[REGPHY_TIMING] = { |
|||
"timing", ddrphy_timing, ARRAY_SIZE(ddrphy_timing), DDRPHY_BASE |
|||
}, |
|||
[REGPHY_CAL] = { |
|||
"cal", ddrphy_cal, ARRAY_SIZE(ddrphy_cal), DDRPHY_BASE |
|||
}, |
|||
[REG_DYN] = { |
|||
"dyn", ddr_dyn, ARRAY_SIZE(ddr_dyn), DDR_BASE |
|||
}, |
|||
[REGPHY_DYN] = { |
|||
"dyn", ddrphy_dyn, ARRAY_SIZE(ddrphy_dyn), DDRPHY_BASE |
|||
}, |
|||
}; |
|||
|
|||
static uint32_t get_base_addr(const struct ddr_info *priv, enum base_type base) |
|||
{ |
|||
if (base == DDRPHY_BASE) { |
|||
return (uint32_t)priv->phy; |
|||
} else { |
|||
return (uint32_t)priv->ctl; |
|||
} |
|||
} |
|||
|
|||
static void set_reg(const struct ddr_info *priv, |
|||
enum reg_type type, |
|||
const void *param) |
|||
{ |
|||
unsigned int i; |
|||
unsigned int *ptr, value; |
|||
enum base_type base = ddr_registers[type].base; |
|||
uint32_t base_addr = get_base_addr(priv, base); |
|||
const struct reg_desc *desc = ddr_registers[type].desc; |
|||
|
|||
VERBOSE("init %s\n", ddr_registers[type].name); |
|||
for (i = 0; i < ddr_registers[type].size; i++) { |
|||
ptr = (unsigned int *)(base_addr + desc[i].offset); |
|||
if (desc[i].par_offset == INVALID_OFFSET) { |
|||
ERROR("invalid parameter offset for %s", desc[i].name); |
|||
panic(); |
|||
} else { |
|||
value = *((uint32_t *)((uint32_t)param + |
|||
desc[i].par_offset)); |
|||
mmio_write_32((uint32_t)ptr, value); |
|||
} |
|||
} |
|||
} |
|||
|
|||
static void stm32mp1_ddrphy_idone_wait(struct stm32mp1_ddrphy *phy) |
|||
{ |
|||
uint32_t pgsr; |
|||
int error = 0; |
|||
unsigned long start; |
|||
unsigned long time0, time; |
|||
|
|||
start = get_timer(0); |
|||
time0 = start; |
|||
|
|||
do { |
|||
pgsr = mmio_read_32((uint32_t)&phy->pgsr); |
|||
time = get_timer(start); |
|||
if (time != time0) { |
|||
VERBOSE(" > [0x%x] pgsr = 0x%x &\n", |
|||
(uint32_t)&phy->pgsr, pgsr); |
|||
VERBOSE(" [0x%x] pir = 0x%x (time=%x)\n", |
|||
(uint32_t)&phy->pir, |
|||
mmio_read_32((uint32_t)&phy->pir), |
|||
(uint32_t)time); |
|||
} |
|||
|
|||
time0 = time; |
|||
if (time > plat_get_syscnt_freq2()) { |
|||
panic(); |
|||
} |
|||
if ((pgsr & DDRPHYC_PGSR_DTERR) != 0U) { |
|||
VERBOSE("DQS Gate Trainig Error\n"); |
|||
error++; |
|||
} |
|||
if ((pgsr & DDRPHYC_PGSR_DTIERR) != 0U) { |
|||
VERBOSE("DQS Gate Trainig Intermittent Error\n"); |
|||
error++; |
|||
} |
|||
if ((pgsr & DDRPHYC_PGSR_DFTERR) != 0U) { |
|||
VERBOSE("DQS Drift Error\n"); |
|||
error++; |
|||
} |
|||
if ((pgsr & DDRPHYC_PGSR_RVERR) != 0U) { |
|||
VERBOSE("Read Valid Training Error\n"); |
|||
error++; |
|||
} |
|||
if ((pgsr & DDRPHYC_PGSR_RVEIRR) != 0U) { |
|||
VERBOSE("Read Valid Training Intermittent Error\n"); |
|||
error++; |
|||
} |
|||
} while ((pgsr & DDRPHYC_PGSR_IDONE) == 0U && error == 0); |
|||
VERBOSE("\n[0x%x] pgsr = 0x%x\n", |
|||
(uint32_t)&phy->pgsr, pgsr); |
|||
} |
|||
|
|||
static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir) |
|||
{ |
|||
uint32_t pir_init = pir | DDRPHYC_PIR_INIT; |
|||
|
|||
mmio_write_32((uint32_t)&phy->pir, pir_init); |
|||
VERBOSE("[0x%x] pir = 0x%x -> 0x%x\n", |
|||
(uint32_t)&phy->pir, pir_init, |
|||
mmio_read_32((uint32_t)&phy->pir)); |
|||
|
|||
/* Need to wait 10 configuration clock before start polling */ |
|||
udelay(10); |
|||
|
|||
/* Wait DRAM initialization and Gate Training Evaluation complete */ |
|||
stm32mp1_ddrphy_idone_wait(phy); |
|||
} |
|||
|
|||
/* Start quasi dynamic register update */ |
|||
static void stm32mp1_start_sw_done(struct stm32mp1_ddrctl *ctl) |
|||
{ |
|||
mmio_clrbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); |
|||
VERBOSE("[0x%x] swctl = 0x%x\n", |
|||
(uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl)); |
|||
} |
|||
|
|||
/* Wait quasi dynamic register update */ |
|||
static void stm32mp1_wait_sw_done_ack(struct stm32mp1_ddrctl *ctl) |
|||
{ |
|||
unsigned long start; |
|||
uint32_t swstat; |
|||
|
|||
mmio_setbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); |
|||
VERBOSE("[0x%x] swctl = 0x%x\n", |
|||
(uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl)); |
|||
|
|||
start = get_timer(0); |
|||
do { |
|||
swstat = mmio_read_32((uint32_t)&ctl->swstat); |
|||
VERBOSE("[0x%x] swstat = 0x%x ", |
|||
(uint32_t)&ctl->swstat, swstat); |
|||
VERBOSE("timer in ms 0x%x = start 0x%lx\r", |
|||
get_timer(0), start); |
|||
if (get_timer(start) > plat_get_syscnt_freq2()) { |
|||
panic(); |
|||
} |
|||
} while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U); |
|||
|
|||
VERBOSE("[0x%x] swstat = 0x%x\n", |
|||
(uint32_t)&ctl->swstat, swstat); |
|||
} |
|||
|
|||
/* Wait quasi dynamic register update */ |
|||
static void stm32mp1_wait_operating_mode(struct ddr_info *priv, uint32_t mode) |
|||
{ |
|||
unsigned long start; |
|||
uint32_t stat; |
|||
uint32_t operating_mode; |
|||
uint32_t selref_type; |
|||
int break_loop = 0; |
|||
|
|||
start = get_timer(0); |
|||
for ( ; ; ) { |
|||
stat = mmio_read_32((uint32_t)&priv->ctl->stat); |
|||
operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK; |
|||
selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK; |
|||
VERBOSE("[0x%x] stat = 0x%x\n", |
|||
(uint32_t)&priv->ctl->stat, stat); |
|||
VERBOSE("timer in ms 0x%x = start 0x%lx\r", |
|||
get_timer(0), start); |
|||
if (get_timer(start) > plat_get_syscnt_freq2()) { |
|||
panic(); |
|||
} |
|||
|
|||
if (mode == DDRCTRL_STAT_OPERATING_MODE_SR) { |
|||
/*
|
|||
* Self-refresh due to software |
|||
* => checking also STAT.selfref_type. |
|||
*/ |
|||
if ((operating_mode == |
|||
DDRCTRL_STAT_OPERATING_MODE_SR) && |
|||
(selref_type == DDRCTRL_STAT_SELFREF_TYPE_SR)) { |
|||
break_loop = 1; |
|||
} |
|||
} else if (operating_mode == mode) { |
|||
break_loop = 1; |
|||
} else if ((mode == DDRCTRL_STAT_OPERATING_MODE_NORMAL) && |
|||
(operating_mode == DDRCTRL_STAT_OPERATING_MODE_SR) && |
|||
(selref_type == DDRCTRL_STAT_SELFREF_TYPE_ASR)) { |
|||
/* Normal mode: handle also automatic self refresh */ |
|||
break_loop = 1; |
|||
} |
|||
|
|||
if (break_loop == 1) { |
|||
break; |
|||
} |
|||
} |
|||
|
|||
VERBOSE("[0x%x] stat = 0x%x\n", |
|||
(uint32_t)&priv->ctl->stat, stat); |
|||
} |
|||
|
|||
/* Mode Register Writes (MRW or MRS) */ |
|||
static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr, |
|||
uint32_t data) |
|||
{ |
|||
uint32_t mrctrl0; |
|||
|
|||
VERBOSE("MRS: %d = %x\n", addr, data); |
|||
|
|||
/*
|
|||
* 1. Poll MRSTAT.mr_wr_busy until it is '0'. |
|||
* This checks that there is no outstanding MR transaction. |
|||
* No write should be performed to MRCTRL0 and MRCTRL1 |
|||
* if MRSTAT.mr_wr_busy = 1. |
|||
*/ |
|||
while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) & |
|||
DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) { |
|||
; |
|||
} |
|||
|
|||
/*
|
|||
* 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr, MRCTRL0.mr_rank |
|||
* and (for MRWs) MRCTRL1.mr_data to define the MR transaction. |
|||
*/ |
|||
mrctrl0 = DDRCTRL_MRCTRL0_MR_TYPE_WRITE | |
|||
DDRCTRL_MRCTRL0_MR_RANK_ALL | |
|||
(((uint32_t)addr << DDRCTRL_MRCTRL0_MR_ADDR_SHIFT) & |
|||
DDRCTRL_MRCTRL0_MR_ADDR_MASK); |
|||
mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0); |
|||
VERBOSE("[0x%x] mrctrl0 = 0x%x (0x%x)\n", |
|||
(uint32_t)&priv->ctl->mrctrl0, |
|||
mmio_read_32((uint32_t)&priv->ctl->mrctrl0), mrctrl0); |
|||
mmio_write_32((uint32_t)&priv->ctl->mrctrl1, data); |
|||
VERBOSE("[0x%x] mrctrl1 = 0x%x\n", |
|||
(uint32_t)&priv->ctl->mrctrl1, |
|||
mmio_read_32((uint32_t)&priv->ctl->mrctrl1)); |
|||
|
|||
/*
|
|||
* 3. In a separate APB transaction, write the MRCTRL0.mr_wr to 1. This |
|||
* bit is self-clearing, and triggers the MR transaction. |
|||
* The uMCTL2 then asserts the MRSTAT.mr_wr_busy while it performs |
|||
* the MR transaction to SDRAM, and no further access can be |
|||
* initiated until it is deasserted. |
|||
*/ |
|||
mrctrl0 |= DDRCTRL_MRCTRL0_MR_WR; |
|||
mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0); |
|||
|
|||
while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) & |
|||
DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) { |
|||
; |
|||
} |
|||
|
|||
VERBOSE("[0x%x] mrctrl0 = 0x%x\n", |
|||
(uint32_t)&priv->ctl->mrctrl0, mrctrl0); |
|||
} |
|||
|
|||
/* Switch DDR3 from DLL-on to DLL-off */ |
|||
static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) |
|||
{ |
|||
uint32_t mr1 = mmio_read_32((uint32_t)&priv->phy->mr1); |
|||
uint32_t mr2 = mmio_read_32((uint32_t)&priv->phy->mr2); |
|||
uint32_t dbgcam; |
|||
|
|||
VERBOSE("mr1: 0x%x\n", mr1); |
|||
VERBOSE("mr2: 0x%x\n", mr2); |
|||
|
|||
/*
|
|||
* 1. Set the DBG1.dis_hif = 1. |
|||
* This prevents further reads/writes being received on the HIF. |
|||
*/ |
|||
mmio_setbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); |
|||
VERBOSE("[0x%x] dbg1 = 0x%x\n", |
|||
(uint32_t)&priv->ctl->dbg1, |
|||
mmio_read_32((uint32_t)&priv->ctl->dbg1)); |
|||
|
|||
/*
|
|||
* 2. Ensure all commands have been flushed from the uMCTL2 by polling |
|||
* DBGCAM.wr_data_pipeline_empty = 1, |
|||
* DBGCAM.rd_data_pipeline_empty = 1, |
|||
* DBGCAM.dbg_wr_q_depth = 0 , |
|||
* DBGCAM.dbg_lpr_q_depth = 0, and |
|||
* DBGCAM.dbg_hpr_q_depth = 0. |
|||
*/ |
|||
do { |
|||
dbgcam = mmio_read_32((uint32_t)&priv->ctl->dbgcam); |
|||
VERBOSE("[0x%x] dbgcam = 0x%x\n", |
|||
(uint32_t)&priv->ctl->dbgcam, dbgcam); |
|||
} while ((((dbgcam & DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY) == |
|||
DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY)) && |
|||
((dbgcam & DDRCTRL_DBGCAM_DBG_Q_DEPTH) == 0U)); |
|||
|
|||
/*
|
|||
* 3. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) |
|||
* to disable RTT_NOM: |
|||
* a. DDR3: Write to MR1[9], MR1[6] and MR1[2] |
|||
* b. DDR4: Write to MR1[10:8] |
|||
*/ |
|||
mr1 &= ~(BIT(9) | BIT(6) | BIT(2)); |
|||
stm32mp1_mode_register_write(priv, 1, mr1); |
|||
|
|||
/*
|
|||
* 4. For DDR4 only: Perform an MRS command |
|||
* (using MRCTRL0 and MRCTRL1 registers) to write to MR5[8:6] |
|||
* to disable RTT_PARK |
|||
*/ |
|||
|
|||
/*
|
|||
* 5. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) |
|||
* to write to MR2[10:9], to disable RTT_WR |
|||
* (and therefore disable dynamic ODT). |
|||
* This applies for both DDR3 and DDR4. |
|||
*/ |
|||
mr2 &= ~GENMASK(10, 9); |
|||
stm32mp1_mode_register_write(priv, 2, mr2); |
|||
|
|||
/*
|
|||
* 6. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) |
|||
* to disable the DLL. The timing of this MRS is automatically |
|||
* handled by the uMCTL2. |
|||
* a. DDR3: Write to MR1[0] |
|||
* b. DDR4: Write to MR1[0] |
|||
*/ |
|||
mr1 |= BIT(0); |
|||
stm32mp1_mode_register_write(priv, 1, mr1); |
|||
|
|||
/*
|
|||
* 7. Put the SDRAM into self-refresh mode by setting |
|||
* PWRCTL.selfref_sw = 1, and polling STAT.operating_mode to ensure |
|||
* the DDRC has entered self-refresh. |
|||
*/ |
|||
mmio_setbits_32((uint32_t)&priv->ctl->pwrctl, |
|||
DDRCTRL_PWRCTL_SELFREF_SW); |
|||
VERBOSE("[0x%x] pwrctl = 0x%x\n", |
|||
(uint32_t)&priv->ctl->pwrctl, |
|||
mmio_read_32((uint32_t)&priv->ctl->pwrctl)); |
|||
|
|||
/*
|
|||
* 8. Wait until STAT.operating_mode[1:0]==11 indicating that the |
|||
* DWC_ddr_umctl2 core is in self-refresh mode. |
|||
* Ensure transition to self-refresh was due to software |
|||
* by checking that STAT.selfref_type[1:0]=2. |
|||
*/ |
|||
stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_SR); |
|||
|
|||
/*
|
|||
* 9. Set the MSTR.dll_off_mode = 1. |
|||
* warning: MSTR.dll_off_mode is a quasi-dynamic type 2 field |
|||
*/ |
|||
stm32mp1_start_sw_done(priv->ctl); |
|||
|
|||
mmio_setbits_32((uint32_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE); |
|||
VERBOSE("[0x%x] mstr = 0x%x\n", |
|||
(uint32_t)&priv->ctl->mstr, |
|||
mmio_read_32((uint32_t)&priv->ctl->mstr)); |
|||
|
|||
stm32mp1_wait_sw_done_ack(priv->ctl); |
|||
|
|||
/* 10. Change the clock frequency to the desired value. */ |
|||
|
|||
/*
|
|||
* 11. Update any registers which may be required to change for the new |
|||
* frequency. This includes static and dynamic registers. |
|||
* This includes both uMCTL2 registers and PHY registers. |
|||
*/ |
|||
|
|||
/* Change Bypass Mode Frequency Range */ |
|||
if (stm32mp1_clk_get_rate(DDRPHYC) < 100000000U) { |
|||
mmio_clrbits_32((uint32_t)&priv->phy->dllgcr, |
|||
DDRPHYC_DLLGCR_BPS200); |
|||
} else { |
|||
mmio_setbits_32((uint32_t)&priv->phy->dllgcr, |
|||
DDRPHYC_DLLGCR_BPS200); |
|||
} |
|||
|
|||
mmio_setbits_32((uint32_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS); |
|||
|
|||
mmio_setbits_32((uint32_t)&priv->phy->dx0dllcr, |
|||
DDRPHYC_DXNDLLCR_DLLDIS); |
|||
mmio_setbits_32((uint32_t)&priv->phy->dx1dllcr, |
|||
DDRPHYC_DXNDLLCR_DLLDIS); |
|||
mmio_setbits_32((uint32_t)&priv->phy->dx2dllcr, |
|||
DDRPHYC_DXNDLLCR_DLLDIS); |
|||
mmio_setbits_32((uint32_t)&priv->phy->dx3dllcr, |
|||
DDRPHYC_DXNDLLCR_DLLDIS); |
|||
|
|||
/* 12. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */ |
|||
mmio_clrbits_32((uint32_t)&priv->ctl->pwrctl, |
|||
DDRCTRL_PWRCTL_SELFREF_SW); |
|||
stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); |
|||
|
|||
/*
|
|||
* 13. If ZQCTL0.dis_srx_zqcl = 0, the uMCTL2 performs a ZQCL command |
|||
* at this point. |
|||
*/ |
|||
|
|||
/*
|
|||
* 14. Perform MRS commands as required to re-program timing registers |
|||
* in the SDRAM for the new frequency |
|||
* (in particular, CL, CWL and WR may need to be changed). |
|||
*/ |
|||
|
|||
/* 15. Write DBG1.dis_hif = 0 to re-enable reads and writes. */ |
|||
mmio_clrbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); |
|||
VERBOSE("[0x%x] dbg1 = 0x%x\n", |
|||
(uint32_t)&priv->ctl->dbg1, |
|||
mmio_read_32((uint32_t)&priv->ctl->dbg1)); |
|||
} |
|||
|
|||
static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) |
|||
{ |
|||
stm32mp1_start_sw_done(ctl); |
|||
/* Quasi-dynamic register update*/ |
|||
mmio_setbits_32((uint32_t)&ctl->rfshctl3, |
|||
DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); |
|||
mmio_clrbits_32((uint32_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); |
|||
mmio_clrbits_32((uint32_t)&ctl->dfimisc, |
|||
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); |
|||
stm32mp1_wait_sw_done_ack(ctl); |
|||
} |
|||
|
|||
static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, |
|||
uint32_t rfshctl3, uint32_t pwrctl) |
|||
{ |
|||
stm32mp1_start_sw_done(ctl); |
|||
if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) { |
|||
mmio_clrbits_32((uint32_t)&ctl->rfshctl3, |
|||
DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); |
|||
} |
|||
if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) { |
|||
mmio_setbits_32((uint32_t)&ctl->pwrctl, |
|||
DDRCTRL_PWRCTL_POWERDOWN_EN); |
|||
} |
|||
mmio_setbits_32((uint32_t)&ctl->dfimisc, |
|||
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); |
|||
stm32mp1_wait_sw_done_ack(ctl); |
|||
} |
|||
|
|||
static int board_ddr_power_init(enum ddr_type ddr_type) |
|||
{ |
|||
if (dt_check_pmic()) { |
|||
return pmic_ddr_power_init(ddr_type); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void stm32mp1_ddr_init(struct ddr_info *priv, |
|||
struct stm32mp1_ddr_config *config) |
|||
{ |
|||
uint32_t pir; |
|||
int ret; |
|||
|
|||
if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { |
|||
ret = board_ddr_power_init(STM32MP_DDR3); |
|||
} else { |
|||
ret = board_ddr_power_init(STM32MP_LPDDR2); |
|||
} |
|||
|
|||
if (ret != 0) { |
|||
panic(); |
|||
} |
|||
|
|||
VERBOSE("name = %s\n", config->info.name); |
|||
VERBOSE("speed = %d MHz\n", config->info.speed); |
|||
VERBOSE("size = 0x%x\n", config->info.size); |
|||
|
|||
/* DDR INIT SEQUENCE */ |
|||
|
|||
/*
|
|||
* 1. Program the DWC_ddr_umctl2 registers |
|||
* nota: check DFIMISC.dfi_init_complete = 0 |
|||
*/ |
|||
|
|||
/* 1.1 RESETS: presetn, core_ddrc_rstn, aresetn */ |
|||
mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST); |
|||
mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST); |
|||
mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); |
|||
mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST); |
|||
mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST); |
|||
mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST); |
|||
|
|||
/* 1.2. start CLOCK */ |
|||
if (stm32mp1_ddr_clk_enable(priv, config->info.speed) != 0) { |
|||
panic(); |
|||
} |
|||
|
|||
/* 1.3. deassert reset */ |
|||
/* De-assert PHY rstn and ctl_rstn via DPHYRST and DPHYCTLRST. */ |
|||
mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST); |
|||
mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST); |
|||
/*
|
|||
* De-assert presetn once the clocks are active |
|||
* and stable via DDRCAPBRST bit. |
|||
*/ |
|||
mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST); |
|||
|
|||
/* 1.4. wait 128 cycles to permit initialization of end logic */ |
|||
udelay(2); |
|||
/* For PCLK = 133MHz => 1 us is enough, 2 to allow lower frequency */ |
|||
|
|||
/* 1.5. initialize registers ddr_umctl2 */ |
|||
/* Stop uMCTL2 before PHY is ready */ |
|||
mmio_clrbits_32((uint32_t)&priv->ctl->dfimisc, |
|||
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); |
|||
VERBOSE("[0x%x] dfimisc = 0x%x\n", |
|||
(uint32_t)&priv->ctl->dfimisc, |
|||
mmio_read_32((uint32_t)&priv->ctl->dfimisc)); |
|||
|
|||
set_reg(priv, REG_REG, &config->c_reg); |
|||
|
|||
/* DDR3 = don't set DLLOFF for init mode */ |
|||
if ((config->c_reg.mstr & |
|||
(DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) |
|||
== (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) { |
|||
VERBOSE("deactivate DLL OFF in mstr\n"); |
|||
mmio_clrbits_32((uint32_t)&priv->ctl->mstr, |
|||
DDRCTRL_MSTR_DLL_OFF_MODE); |
|||
VERBOSE("[0x%x] mstr = 0x%x\n", |
|||
(uint32_t)&priv->ctl->mstr, |
|||
mmio_read_32((uint32_t)&priv->ctl->mstr)); |
|||
} |
|||
|
|||
set_reg(priv, REG_TIMING, &config->c_timing); |
|||
set_reg(priv, REG_MAP, &config->c_map); |
|||
|
|||
/* Skip CTRL init, SDRAM init is done by PHY PUBL */ |
|||
mmio_clrsetbits_32((uint32_t)&priv->ctl->init0, |
|||
DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK, |
|||
DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL); |
|||
VERBOSE("[0x%x] init0 = 0x%x\n", |
|||
(uint32_t)&priv->ctl->init0, |
|||
mmio_read_32((uint32_t)&priv->ctl->init0)); |
|||
|
|||
set_reg(priv, REG_PERF, &config->c_perf); |
|||
|
|||
/* 2. deassert reset signal core_ddrc_rstn, aresetn and presetn */ |
|||
mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); |
|||
mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST); |
|||
mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST); |
|||
|
|||
/*
|
|||
* 3. start PHY init by accessing relevant PUBL registers |
|||
* (DXGCR, DCR, PTR*, MR*, DTPR*) |
|||
*/ |
|||
set_reg(priv, REGPHY_REG, &config->p_reg); |
|||
set_reg(priv, REGPHY_TIMING, &config->p_timing); |
|||
set_reg(priv, REGPHY_CAL, &config->p_cal); |
|||
|
|||
/* DDR3 = don't set DLLOFF for init mode */ |
|||
if ((config->c_reg.mstr & |
|||
(DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) |
|||
== (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) { |
|||
VERBOSE("deactivate DLL OFF in mr1\n"); |
|||
mmio_clrbits_32((uint32_t)&priv->phy->mr1, BIT(0)); |
|||
VERBOSE("[0x%x] mr1 = 0x%x\n", |
|||
(uint32_t)&priv->phy->mr1, |
|||
mmio_read_32((uint32_t)&priv->phy->mr1)); |
|||
} |
|||
|
|||
/*
|
|||
* 4. Monitor PHY init status by polling PUBL register PGSR.IDONE |
|||
* Perform DDR PHY DRAM initialization and Gate Training Evaluation |
|||
*/ |
|||
stm32mp1_ddrphy_idone_wait(priv->phy); |
|||
|
|||
/*
|
|||
* 5. Indicate to PUBL that controller performs SDRAM initialization |
|||
* by setting PIR.INIT and PIR CTLDINIT and pool PGSR.IDONE |
|||
* DRAM init is done by PHY, init0.skip_dram.init = 1 |
|||
*/ |
|||
|
|||
pir = DDRPHYC_PIR_DLLSRST | DDRPHYC_PIR_DLLLOCK | DDRPHYC_PIR_ZCAL | |
|||
DDRPHYC_PIR_ITMSRST | DDRPHYC_PIR_DRAMINIT | DDRPHYC_PIR_ICPC; |
|||
|
|||
if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { |
|||
pir |= DDRPHYC_PIR_DRAMRST; /* Only for DDR3 */ |
|||
} |
|||
|
|||
stm32mp1_ddrphy_init(priv->phy, pir); |
|||
|
|||
/*
|
|||
* 6. SET DFIMISC.dfi_init_complete_en to 1 |
|||
* Enable quasi-dynamic register programming. |
|||
*/ |
|||
stm32mp1_start_sw_done(priv->ctl); |
|||
|
|||
mmio_setbits_32((uint32_t)&priv->ctl->dfimisc, |
|||
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); |
|||
VERBOSE("[0x%x] dfimisc = 0x%x\n", |
|||
(uint32_t)&priv->ctl->dfimisc, |
|||
mmio_read_32((uint32_t)&priv->ctl->dfimisc)); |
|||
|
|||
stm32mp1_wait_sw_done_ack(priv->ctl); |
|||
|
|||
/*
|
|||
* 7. Wait for DWC_ddr_umctl2 to move to normal operation mode |
|||
* by monitoring STAT.operating_mode signal |
|||
*/ |
|||
|
|||
/* Wait uMCTL2 ready */ |
|||
stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); |
|||
|
|||
/* Switch to DLL OFF mode */ |
|||
if ((config->c_reg.mstr & DDRCTRL_MSTR_DLL_OFF_MODE) != 0U) { |
|||
stm32mp1_ddr3_dll_off(priv); |
|||
} |
|||
|
|||
VERBOSE("DDR DQS training : "); |
|||
|
|||
/*
|
|||
* 8. Disable Auto refresh and power down by setting |
|||
* - RFSHCTL3.dis_au_refresh = 1 |
|||
* - PWRCTL.powerdown_en = 0 |
|||
* - DFIMISC.dfiinit_complete_en = 0 |
|||
*/ |
|||
stm32mp1_refresh_disable(priv->ctl); |
|||
|
|||
/*
|
|||
* 9. Program PUBL PGCR to enable refresh during training |
|||
* and rank to train |
|||
* not done => keep the programed value in PGCR |
|||
*/ |
|||
|
|||
/*
|
|||
* 10. configure PUBL PIR register to specify which training step |
|||
* to run |
|||
* Warning : RVTRN is not supported by this PUBL |
|||
*/ |
|||
stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN); |
|||
|
|||
/* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */ |
|||
stm32mp1_ddrphy_idone_wait(priv->phy); |
|||
|
|||
/*
|
|||
* 12. set back registers in step 8 to the orginal values if desidered |
|||
*/ |
|||
stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3, |
|||
config->c_reg.pwrctl); |
|||
|
|||
/* Enable uMCTL2 AXI port 0 */ |
|||
mmio_setbits_32((uint32_t)&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); |
|||
VERBOSE("[0x%x] pctrl_0 = 0x%x\n", |
|||
(uint32_t)&priv->ctl->pctrl_0, |
|||
mmio_read_32((uint32_t)&priv->ctl->pctrl_0)); |
|||
|
|||
/* Enable uMCTL2 AXI port 1 */ |
|||
mmio_setbits_32((uint32_t)&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); |
|||
VERBOSE("[0x%x] pctrl_1 = 0x%x\n", |
|||
(uint32_t)&priv->ctl->pctrl_1, |
|||
mmio_read_32((uint32_t)&priv->ctl->pctrl_1)); |
|||
} |
@ -0,0 +1,20 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <mmio.h> |
|||
#include <platform_def.h> |
|||
#include <stm32mp1_ddr_helpers.h> |
|||
#include <stm32mp1_rcc.h> |
|||
|
|||
void ddr_enable_clock(void) |
|||
{ |
|||
mmio_setbits_32(RCC_BASE + RCC_DDRITFCR, |
|||
RCC_DDRITFCR_DDRC1EN | |
|||
RCC_DDRITFCR_DDRC2EN | |
|||
RCC_DDRITFCR_DDRPHYCEN | |
|||
RCC_DDRITFCR_DDRPHYCAPBEN | |
|||
RCC_DDRITFCR_DDRCAPBEN); |
|||
} |
@ -0,0 +1,308 @@ |
|||
/*
|
|||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <boot_api.h> |
|||
#include <debug.h> |
|||
#include <dt-bindings/clock/stm32mp1-clks.h> |
|||
#include <errno.h> |
|||
#include <libfdt.h> |
|||
#include <mmio.h> |
|||
#include <platform_def.h> |
|||
#include <stm32mp1_clk.h> |
|||
#include <stm32mp1_ddr.h> |
|||
#include <stm32mp1_ddr_helpers.h> |
|||
#include <stm32mp1_dt.h> |
|||
#include <stm32mp1_private.h> |
|||
#include <stm32mp1_ram.h> |
|||
#include <stm32mp1_rcc.h> |
|||
|
|||
#define DDR_PATTERN 0xAAAAAAAAU |
|||
#define DDR_ANTIPATTERN 0x55555555U |
|||
|
|||
static struct ddr_info ddr_priv_data; |
|||
|
|||
int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed) |
|||
{ |
|||
unsigned long ddrphy_clk, ddr_clk, mem_speed_hz; |
|||
|
|||
ddr_enable_clock(); |
|||
|
|||
ddrphy_clk = stm32mp1_clk_get_rate(DDRPHYC); |
|||
|
|||
VERBOSE("DDR: mem_speed (%d MHz), RCC %ld MHz\n", |
|||
mem_speed, ddrphy_clk / 1000U / 1000U); |
|||
|
|||
mem_speed_hz = (uint32_t)mem_speed * 1000U * 1000U; |
|||
|
|||
/* Max 10% frequency delta */ |
|||
if (ddrphy_clk > mem_speed_hz) { |
|||
ddr_clk = ddrphy_clk - mem_speed_hz; |
|||
} else { |
|||
ddr_clk = mem_speed_hz - ddrphy_clk; |
|||
} |
|||
if (ddr_clk > mem_speed_hz) { |
|||
ERROR("DDR expected freq %d MHz, current is %ld MHz\n", |
|||
mem_speed, ddrphy_clk / 1000U / 1000U); |
|||
return -1; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function tests the DDR data bus wiring. |
|||
* This is inspired from the Data Bus Test algorithm written by Michael Barr |
|||
* in "Programming Embedded Systems in C and C++" book. |
|||
* resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ |
|||
* File: memtest.c - This source code belongs to Public Domain. |
|||
* Returns 0 if success, and address value else. |
|||
******************************************************************************/ |
|||
static uint32_t ddr_test_data_bus(void) |
|||
{ |
|||
uint32_t pattern; |
|||
|
|||
for (pattern = 1U; pattern != 0U; pattern <<= 1) { |
|||
mmio_write_32(STM32MP1_DDR_BASE, pattern); |
|||
|
|||
if (mmio_read_32(STM32MP1_DDR_BASE) != pattern) { |
|||
return (uint32_t)STM32MP1_DDR_BASE; |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function tests the DDR address bus wiring. |
|||
* This is inspired from the Data Bus Test algorithm written by Michael Barr |
|||
* in "Programming Embedded Systems in C and C++" book. |
|||
* resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ |
|||
* File: memtest.c - This source code belongs to Public Domain. |
|||
* Returns 0 if success, and address value else. |
|||
******************************************************************************/ |
|||
static uint32_t ddr_test_addr_bus(void) |
|||
{ |
|||
uint64_t addressmask = (ddr_priv_data.info.size - 1U); |
|||
uint64_t offset; |
|||
uint64_t testoffset = 0; |
|||
|
|||
/* Write the default pattern at each of the power-of-two offsets. */ |
|||
for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; |
|||
offset <<= 1) { |
|||
mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)offset, |
|||
DDR_PATTERN); |
|||
} |
|||
|
|||
/* Check for address bits stuck high. */ |
|||
mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, |
|||
DDR_ANTIPATTERN); |
|||
|
|||
for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; |
|||
offset <<= 1) { |
|||
if (mmio_read_32(STM32MP1_DDR_BASE + (uint32_t)offset) != |
|||
DDR_PATTERN) { |
|||
return (uint32_t)(STM32MP1_DDR_BASE + offset); |
|||
} |
|||
} |
|||
|
|||
mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN); |
|||
|
|||
/* Check for address bits stuck low or shorted. */ |
|||
for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U; |
|||
testoffset <<= 1) { |
|||
mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, |
|||
DDR_ANTIPATTERN); |
|||
|
|||
if (mmio_read_32(STM32MP1_DDR_BASE) != DDR_PATTERN) { |
|||
return STM32MP1_DDR_BASE; |
|||
} |
|||
|
|||
for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; |
|||
offset <<= 1) { |
|||
if ((mmio_read_32(STM32MP1_DDR_BASE + |
|||
(uint32_t)offset) != DDR_PATTERN) && |
|||
(offset != testoffset)) { |
|||
return (uint32_t)(STM32MP1_DDR_BASE + offset); |
|||
} |
|||
} |
|||
|
|||
mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, |
|||
DDR_PATTERN); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function checks the DDR size. It has to be run with Data Cache off. |
|||
* This test is run before data have been put in DDR, and is only done for |
|||
* cold boot. The DDR data can then be overwritten, and it is not useful to |
|||
* restore its content. |
|||
* Returns DDR computed size. |
|||
******************************************************************************/ |
|||
static uint32_t ddr_check_size(void) |
|||
{ |
|||
uint32_t offset = sizeof(uint32_t); |
|||
|
|||
mmio_write_32(STM32MP1_DDR_BASE, DDR_PATTERN); |
|||
|
|||
while (offset < STM32MP1_DDR_MAX_SIZE) { |
|||
mmio_write_32(STM32MP1_DDR_BASE + offset, DDR_ANTIPATTERN); |
|||
dsb(); |
|||
|
|||
if (mmio_read_32(STM32MP1_DDR_BASE) != DDR_PATTERN) { |
|||
break; |
|||
} |
|||
|
|||
offset <<= 1; |
|||
} |
|||
|
|||
INFO("Memory size = 0x%x (%d MB)\n", offset, offset / (1024U * 1024U)); |
|||
|
|||
return offset; |
|||
} |
|||
|
|||
static int stm32mp1_ddr_setup(void) |
|||
{ |
|||
struct ddr_info *priv = &ddr_priv_data; |
|||
int ret; |
|||
struct stm32mp1_ddr_config config; |
|||
int node, len; |
|||
uint32_t tamp_clk_off = 0, uret, idx; |
|||
void *fdt; |
|||
|
|||
#define PARAM(x, y) \ |
|||
{ \ |
|||
.name = x, \ |
|||
.offset = offsetof(struct stm32mp1_ddr_config, y), \ |
|||
.size = sizeof(config.y) / sizeof(uint32_t) \ |
|||
} |
|||
|
|||
#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x) |
|||
#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x) |
|||
|
|||
const struct { |
|||
const char *name; /* Name in DT */ |
|||
const uint32_t offset; /* Offset in config struct */ |
|||
const uint32_t size; /* Size of parameters */ |
|||
} param[] = { |
|||
CTL_PARAM(reg), |
|||
CTL_PARAM(timing), |
|||
CTL_PARAM(map), |
|||
CTL_PARAM(perf), |
|||
PHY_PARAM(reg), |
|||
PHY_PARAM(timing), |
|||
PHY_PARAM(cal) |
|||
}; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return -ENOENT; |
|||
} |
|||
|
|||
node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); |
|||
if (node < 0) { |
|||
ERROR("%s: Cannot read DDR node in DT\n", __func__); |
|||
return -EINVAL; |
|||
} |
|||
|
|||
config.info.speed = |
|||
(uint16_t)fdt_read_uint32_default(node, "st,mem-speed", |
|||
STM32MP1_DDR_SPEED_DFLT); |
|||
config.info.size = fdt_read_uint32_default(node, "st,mem-size", |
|||
STM32MP1_DDR_SIZE_DFLT); |
|||
config.info.name = fdt_getprop(fdt, node, "st,mem-name", &len); |
|||
if (config.info.name == NULL) { |
|||
VERBOSE("%s: no st,mem-name\n", __func__); |
|||
return -EINVAL; |
|||
} |
|||
INFO("RAM: %s\n", config.info.name); |
|||
|
|||
for (idx = 0; idx < ARRAY_SIZE(param); idx++) { |
|||
ret = fdt_read_uint32_array(node, param[idx].name, |
|||
(void *)((uint32_t)&config + |
|||
param[idx].offset), |
|||
param[idx].size); |
|||
|
|||
VERBOSE("%s: %s[0x%x] = %d\n", __func__, |
|||
param[idx].name, param[idx].size, ret); |
|||
if (ret != 0) { |
|||
ERROR("%s: Cannot read %s\n", |
|||
__func__, param[idx].name); |
|||
return -EINVAL; |
|||
} |
|||
} |
|||
|
|||
if (!stm32mp1_clk_is_enabled(RTCAPB)) { |
|||
tamp_clk_off = 1; |
|||
if (stm32mp1_clk_enable(RTCAPB) != 0) { |
|||
return -EINVAL; |
|||
} |
|||
} |
|||
|
|||
if (tamp_clk_off != 0U) { |
|||
if (stm32mp1_clk_disable(RTCAPB) != 0) { |
|||
return -EINVAL; |
|||
} |
|||
} |
|||
|
|||
/* Disable axidcg clock gating during init */ |
|||
mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); |
|||
|
|||
stm32mp1_ddr_init(priv, &config); |
|||
|
|||
/* Enable axidcg clock gating */ |
|||
mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); |
|||
|
|||
priv->info.size = config.info.size; |
|||
|
|||
VERBOSE("%s : ram size(%x, %x)\n", __func__, |
|||
(uint32_t)priv->info.base, (uint32_t)priv->info.size); |
|||
|
|||
dcsw_op_all(DC_OP_CISW); |
|||
write_sctlr(read_sctlr() & ~SCTLR_C_BIT); |
|||
|
|||
uret = ddr_test_data_bus(); |
|||
if (uret != 0U) { |
|||
ERROR("DDR data bus test: can't access memory @ 0x%x\n", |
|||
uret); |
|||
panic(); |
|||
} |
|||
|
|||
uret = ddr_test_addr_bus(); |
|||
if (uret != 0U) { |
|||
ERROR("DDR addr bus test: can't access memory @ 0x%x\n", |
|||
uret); |
|||
panic(); |
|||
} |
|||
|
|||
uret = ddr_check_size(); |
|||
if (uret < config.info.size) { |
|||
ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", |
|||
uret, config.info.size); |
|||
panic(); |
|||
} |
|||
|
|||
write_sctlr(read_sctlr() | SCTLR_C_BIT); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int stm32mp1_ddr_probe(void) |
|||
{ |
|||
struct ddr_info *priv = &ddr_priv_data; |
|||
|
|||
VERBOSE("STM32MP DDR probe\n"); |
|||
|
|||
priv->ctl = (struct stm32mp1_ddrctl *)DDRCTRL_BASE; |
|||
priv->phy = (struct stm32mp1_ddrphy *)DDRPHYC_BASE; |
|||
priv->pwr = PWR_BASE; |
|||
priv->rcc = RCC_BASE; |
|||
|
|||
priv->info.base = STM32MP1_DDR_BASE; |
|||
priv->info.size = 0; |
|||
|
|||
return stm32mp1_ddr_setup(); |
|||
} |
@ -0,0 +1,86 @@ |
|||
/*
|
|||
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <bl_common.h> |
|||
#include <debug.h> |
|||
#include <mmio.h> |
|||
#include <stdbool.h> |
|||
#include <stm32_gpio.h> |
|||
|
|||
static bool check_gpio(uint32_t bank, uint32_t pin) |
|||
{ |
|||
if (pin > GPIO_PIN_MAX) { |
|||
ERROR("%s: wrong pin number (%d)\n", __func__, pin); |
|||
return false; |
|||
} |
|||
|
|||
if ((bank > GPIO_BANK_K) && (bank != GPIO_BANK_Z)) { |
|||
ERROR("%s: wrong GPIO bank number (%d)\n", __func__, bank); |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, |
|||
uint32_t pull, uint32_t alternate) |
|||
{ |
|||
volatile uint32_t bank_address; |
|||
|
|||
if (!check_gpio(bank, pin)) { |
|||
return; |
|||
} |
|||
|
|||
if (bank == GPIO_BANK_Z) { |
|||
bank_address = STM32_GPIOZ_BANK; |
|||
} else { |
|||
bank_address = STM32_GPIOA_BANK + |
|||
(bank * STM32_GPIO_BANK_OFFSET); |
|||
} |
|||
|
|||
mmio_clrbits_32(bank_address + GPIO_MODE_OFFSET, |
|||
((uint32_t)GPIO_MODE_MASK << (pin << 1))); |
|||
mmio_setbits_32(bank_address + GPIO_MODE_OFFSET, |
|||
(mode & ~GPIO_OPEN_DRAIN) << (pin << 1)); |
|||
|
|||
if ((mode & GPIO_OPEN_DRAIN) != 0U) { |
|||
mmio_setbits_32(bank_address + GPIO_TYPE_OFFSET, |
|||
BIT(pin)); |
|||
} |
|||
|
|||
mmio_clrbits_32(bank_address + GPIO_SPEED_OFFSET, |
|||
((uint32_t)GPIO_SPEED_MASK << (pin << 1))); |
|||
mmio_setbits_32(bank_address + GPIO_SPEED_OFFSET, speed << (pin << 1)); |
|||
|
|||
mmio_clrbits_32(bank_address + GPIO_PUPD_OFFSET, |
|||
((uint32_t)GPIO_PULL_MASK << (pin << 1))); |
|||
mmio_setbits_32(bank_address + GPIO_PUPD_OFFSET, pull << (pin << 1)); |
|||
|
|||
if (pin < GPIO_ALT_LOWER_LIMIT) { |
|||
mmio_clrbits_32(bank_address + GPIO_AFRL_OFFSET, |
|||
((uint32_t)GPIO_ALTERNATE_MASK << (pin << 2))); |
|||
mmio_setbits_32(bank_address + GPIO_AFRL_OFFSET, |
|||
alternate << (pin << 2)); |
|||
} else { |
|||
mmio_clrbits_32(bank_address + GPIO_AFRH_OFFSET, |
|||
((uint32_t)GPIO_ALTERNATE_MASK << |
|||
((pin - GPIO_ALT_LOWER_LIMIT) << 2))); |
|||
mmio_setbits_32(bank_address + GPIO_AFRH_OFFSET, |
|||
alternate << ((pin - GPIO_ALT_LOWER_LIMIT) << |
|||
2)); |
|||
} |
|||
|
|||
VERBOSE("GPIO %u mode set to 0x%x\n", bank, |
|||
mmio_read_32(bank_address + GPIO_MODE_OFFSET)); |
|||
VERBOSE("GPIO %u speed set to 0x%x\n", bank, |
|||
mmio_read_32(bank_address + GPIO_SPEED_OFFSET)); |
|||
VERBOSE("GPIO %u mode pull to 0x%x\n", bank, |
|||
mmio_read_32(bank_address + GPIO_PUPD_OFFSET)); |
|||
VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank, |
|||
mmio_read_32(bank_address + GPIO_AFRL_OFFSET)); |
|||
VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, |
|||
mmio_read_32(bank_address + GPIO_AFRH_OFFSET)); |
|||
} |
@ -0,0 +1,851 @@ |
|||
/*
|
|||
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <delay_timer.h> |
|||
#include <errno.h> |
|||
#include <mmio.h> |
|||
#include <stdbool.h> |
|||
#include <stdlib.h> |
|||
#include <stm32_i2c.h> |
|||
|
|||
/* STM32 I2C registers offsets */ |
|||
#define I2C_CR1 0x00U |
|||
#define I2C_CR2 0x04U |
|||
#define I2C_OAR1 0x08U |
|||
#define I2C_OAR2 0x0CU |
|||
#define I2C_TIMINGR 0x10U |
|||
#define I2C_TIMEOUTR 0x14U |
|||
#define I2C_ISR 0x18U |
|||
#define I2C_ICR 0x1CU |
|||
#define I2C_PECR 0x20U |
|||
#define I2C_RXDR 0x24U |
|||
#define I2C_TXDR 0x28U |
|||
|
|||
#define MAX_DELAY 0xFFFFFFFFU |
|||
|
|||
/* I2C TIMING clear register Mask */ |
|||
#define TIMING_CLEAR_MASK 0xF0FFFFFFU |
|||
/* Timeout 25 ms */ |
|||
#define I2C_TIMEOUT_BUSY 25U |
|||
|
|||
#define MAX_NBYTE_SIZE 255U |
|||
|
|||
static int i2c_request_memory_write(struct i2c_handle_s *hi2c, |
|||
uint16_t dev_addr, uint16_t mem_addr, |
|||
uint16_t mem_add_size, uint32_t timeout, |
|||
uint32_t tick_start); |
|||
static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, |
|||
uint16_t mem_addr, uint16_t mem_add_size, |
|||
uint32_t timeout, uint32_t tick_start); |
|||
|
|||
/* Private functions to handle flags during polling transfer */ |
|||
static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, |
|||
uint8_t awaited_value, uint32_t timeout, |
|||
uint32_t tick_start); |
|||
static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint32_t timeout, |
|||
uint32_t tick_start); |
|||
static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout, |
|||
uint32_t tick_start); |
|||
static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout, |
|||
uint32_t tick_start); |
|||
|
|||
/* Private function to flush TXDR register */ |
|||
static void i2c_flush_txdr(struct i2c_handle_s *hi2c); |
|||
|
|||
/* Private function to start, restart or stop a transfer */ |
|||
static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, |
|||
uint16_t size, uint32_t i2c_mode, |
|||
uint32_t request); |
|||
|
|||
/*
|
|||
* @brief Initialize the I2C device. |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2C. |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
int stm32_i2c_init(struct i2c_handle_s *hi2c) |
|||
{ |
|||
if (hi2c == NULL) { |
|||
return -ENOENT; |
|||
} |
|||
|
|||
if (hi2c->i2c_state == I2C_STATE_RESET) { |
|||
hi2c->lock = 0; |
|||
} |
|||
|
|||
hi2c->i2c_state = I2C_STATE_BUSY; |
|||
|
|||
/* Disable the selected I2C peripheral */ |
|||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); |
|||
|
|||
/* Configure I2Cx: Frequency range */ |
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR, |
|||
hi2c->i2c_init.timing & TIMING_CLEAR_MASK); |
|||
|
|||
/* Disable Own Address1 before set the Own Address1 configuration */ |
|||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN); |
|||
|
|||
/* Configure I2Cx: Own Address1 and ack own address1 mode */ |
|||
if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_7BIT) { |
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, |
|||
I2C_OAR1_OA1EN | hi2c->i2c_init.own_address1); |
|||
} else { /* I2C_ADDRESSINGMODE_10BIT */ |
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, |
|||
I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | |
|||
hi2c->i2c_init.own_address1); |
|||
} |
|||
|
|||
/* Configure I2Cx: Addressing Master mode */ |
|||
if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_10BIT) { |
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10); |
|||
} |
|||
|
|||
/*
|
|||
* Enable the AUTOEND by default, and enable NACK |
|||
* (should be disable only during Slave process) |
|||
*/ |
|||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, |
|||
I2C_CR2_AUTOEND | I2C_CR2_NACK); |
|||
|
|||
/* Disable Own Address2 before set the Own Address2 configuration */ |
|||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE); |
|||
|
|||
/* Configure I2Cx: Dual mode and Own Address2 */ |
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2, |
|||
hi2c->i2c_init.dual_address_mode | |
|||
hi2c->i2c_init.own_address2 | |
|||
(hi2c->i2c_init.own_address2_masks << 8)); |
|||
|
|||
/* Configure I2Cx: Generalcall and NoStretch mode */ |
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_CR1, |
|||
hi2c->i2c_init.general_call_mode | |
|||
hi2c->i2c_init.no_stretch_mode); |
|||
|
|||
/* Enable the selected I2C peripheral */ |
|||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); |
|||
|
|||
hi2c->i2c_err = I2C_ERROR_NONE; |
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
hi2c->i2c_mode = I2C_MODE_NONE; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* @brief Write an amount of data in blocking mode to a specific memory address |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2C. |
|||
* @param dev_addr: Target device address |
|||
* @param mem_addr: Internal memory address |
|||
* @param mem_add_size: size of internal memory address |
|||
* @param p_data: Pointer to data buffer |
|||
* @param size: Amount of data to be sent |
|||
* @param timeout: timeout duration |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, |
|||
uint16_t mem_addr, uint16_t mem_add_size, |
|||
uint8_t *p_data, uint16_t size, uint32_t timeout) |
|||
{ |
|||
uint32_t tickstart; |
|||
|
|||
if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { |
|||
return -EBUSY; |
|||
} |
|||
|
|||
if ((p_data == NULL) || (size == 0U)) { |
|||
return -EINVAL; |
|||
} |
|||
|
|||
hi2c->lock = 1; |
|||
|
|||
tickstart = (uint32_t)read_cntpct_el0(); |
|||
|
|||
if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, I2C_TIMEOUT_BUSY, |
|||
tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
hi2c->i2c_state = I2C_STATE_BUSY_TX; |
|||
hi2c->i2c_mode = I2C_MODE_MEM; |
|||
hi2c->i2c_err = I2C_ERROR_NONE; |
|||
|
|||
hi2c->p_buff = p_data; |
|||
hi2c->xfer_count = size; |
|||
|
|||
/* Send Slave Address and Memory Address */ |
|||
if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, mem_add_size, |
|||
timeout, tickstart) != 0) { |
|||
hi2c->lock = 0; |
|||
return -EIO; |
|||
} |
|||
|
|||
/*
|
|||
* Set NBYTES to write and reload |
|||
* if hi2c->xfer_count > MAX_NBYTE_SIZE |
|||
*/ |
|||
if (hi2c->xfer_count > MAX_NBYTE_SIZE) { |
|||
hi2c->xfer_size = MAX_NBYTE_SIZE; |
|||
i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size, |
|||
I2C_RELOAD_MODE, I2C_NO_STARTSTOP); |
|||
} else { |
|||
hi2c->xfer_size = hi2c->xfer_count; |
|||
i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size, |
|||
I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); |
|||
} |
|||
|
|||
do { |
|||
if (i2c_wait_txis(hi2c, timeout, tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *hi2c->p_buff); |
|||
hi2c->p_buff++; |
|||
hi2c->xfer_count--; |
|||
hi2c->xfer_size--; |
|||
|
|||
if ((hi2c->xfer_count != 0U) && (hi2c->xfer_size == 0U)) { |
|||
/* Wait until TCR flag is set */ |
|||
if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout, |
|||
tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
if (hi2c->xfer_count > MAX_NBYTE_SIZE) { |
|||
hi2c->xfer_size = MAX_NBYTE_SIZE; |
|||
i2c_transfer_config(hi2c, dev_addr, |
|||
hi2c->xfer_size, |
|||
I2C_RELOAD_MODE, |
|||
I2C_NO_STARTSTOP); |
|||
} else { |
|||
hi2c->xfer_size = hi2c->xfer_count; |
|||
i2c_transfer_config(hi2c, dev_addr, |
|||
hi2c->xfer_size, |
|||
I2C_AUTOEND_MODE, |
|||
I2C_NO_STARTSTOP); |
|||
} |
|||
} |
|||
|
|||
} while (hi2c->xfer_count > 0U); |
|||
|
|||
/*
|
|||
* No need to Check TC flag, with AUTOEND mode the stop |
|||
* is automatically generated. |
|||
* Wait until STOPF flag is reset. |
|||
*/ |
|||
if (i2c_wait_stop(hi2c, timeout, tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); |
|||
|
|||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); |
|||
|
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
hi2c->i2c_mode = I2C_MODE_NONE; |
|||
|
|||
hi2c->lock = 0; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* @brief Read an amount of data in blocking mode from a specific memory |
|||
* address |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2C. |
|||
* @param dev_addr: Target device address |
|||
* @param mem_addr: Internal memory address |
|||
* @param mem_add_size: size of internal memory address |
|||
* @param p_data: Pointer to data buffer |
|||
* @param size: Amount of data to be sent |
|||
* @param timeout: timeout duration |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, |
|||
uint16_t mem_addr, uint16_t mem_add_size, |
|||
uint8_t *p_data, uint16_t size, uint32_t timeout) |
|||
{ |
|||
uint32_t tickstart; |
|||
|
|||
if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { |
|||
return -EBUSY; |
|||
} |
|||
|
|||
if ((p_data == NULL) || (size == 0U)) { |
|||
return -EINVAL; |
|||
} |
|||
|
|||
hi2c->lock = 1; |
|||
|
|||
tickstart = (uint32_t)read_cntpct_el0(); |
|||
|
|||
if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, I2C_TIMEOUT_BUSY, |
|||
tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
hi2c->i2c_state = I2C_STATE_BUSY_RX; |
|||
hi2c->i2c_mode = I2C_MODE_MEM; |
|||
hi2c->i2c_err = I2C_ERROR_NONE; |
|||
|
|||
hi2c->p_buff = p_data; |
|||
hi2c->xfer_count = size; |
|||
|
|||
/* Send Slave Address and Memory Address */ |
|||
if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, mem_add_size, |
|||
timeout, tickstart) != 0) { |
|||
hi2c->lock = 0; |
|||
return -EIO; |
|||
} |
|||
|
|||
/*
|
|||
* Send Slave Address. |
|||
* Set NBYTES to write and reload if hi2c->xfer_count > MAX_NBYTE_SIZE |
|||
* and generate RESTART. |
|||
*/ |
|||
if (hi2c->xfer_count > MAX_NBYTE_SIZE) { |
|||
hi2c->xfer_size = MAX_NBYTE_SIZE; |
|||
i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size, |
|||
I2C_RELOAD_MODE, I2C_GENERATE_START_READ); |
|||
} else { |
|||
hi2c->xfer_size = hi2c->xfer_count; |
|||
i2c_transfer_config(hi2c, dev_addr, hi2c->xfer_size, |
|||
I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); |
|||
} |
|||
|
|||
do { |
|||
if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout, |
|||
tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
*hi2c->p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR); |
|||
hi2c->p_buff++; |
|||
hi2c->xfer_size--; |
|||
hi2c->xfer_count--; |
|||
|
|||
if ((hi2c->xfer_count != 0U) && (hi2c->xfer_size == 0U)) { |
|||
if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout, |
|||
tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
if (hi2c->xfer_count > MAX_NBYTE_SIZE) { |
|||
hi2c->xfer_size = MAX_NBYTE_SIZE; |
|||
i2c_transfer_config(hi2c, dev_addr, |
|||
hi2c->xfer_size, |
|||
I2C_RELOAD_MODE, |
|||
I2C_NO_STARTSTOP); |
|||
} else { |
|||
hi2c->xfer_size = hi2c->xfer_count; |
|||
i2c_transfer_config(hi2c, dev_addr, |
|||
hi2c->xfer_size, |
|||
I2C_AUTOEND_MODE, |
|||
I2C_NO_STARTSTOP); |
|||
} |
|||
} |
|||
} while (hi2c->xfer_count > 0U); |
|||
|
|||
/*
|
|||
* No need to Check TC flag, with AUTOEND mode the stop |
|||
* is automatically generated |
|||
* Wait until STOPF flag is reset |
|||
*/ |
|||
if (i2c_wait_stop(hi2c, timeout, tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); |
|||
|
|||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); |
|||
|
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
hi2c->i2c_mode = I2C_MODE_NONE; |
|||
|
|||
hi2c->lock = 0; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* @brief Checks if target device is ready for communication. |
|||
* @note This function is used with Memory devices |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2C. |
|||
* @param dev_addr: Target device address |
|||
* @param trials: Number of trials |
|||
* @param timeout: timeout duration |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
int stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, |
|||
uint16_t dev_addr, uint32_t trials, |
|||
uint32_t timeout) |
|||
{ |
|||
uint32_t i2c_trials = 0U; |
|||
|
|||
if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { |
|||
return -EBUSY; |
|||
} |
|||
|
|||
if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) != |
|||
0U) { |
|||
return -EBUSY; |
|||
} |
|||
|
|||
hi2c->lock = 1; |
|||
|
|||
hi2c->i2c_state = I2C_STATE_BUSY; |
|||
hi2c->i2c_err = I2C_ERROR_NONE; |
|||
|
|||
do { |
|||
uint32_t tickstart; |
|||
|
|||
/* Generate Start */ |
|||
if (hi2c->i2c_init.addressing_mode == I2C_ADDRESSINGMODE_7BIT) { |
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, |
|||
(((uint32_t)dev_addr & I2C_CR2_SADD) | |
|||
I2C_CR2_START | I2C_CR2_AUTOEND) & |
|||
~I2C_CR2_RD_WRN); |
|||
} else { |
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, |
|||
(((uint32_t)dev_addr & I2C_CR2_SADD) | |
|||
I2C_CR2_START | I2C_CR2_ADD10) & |
|||
~I2C_CR2_RD_WRN); |
|||
} |
|||
|
|||
/*
|
|||
* No need to Check TC flag, with AUTOEND mode the stop |
|||
* is automatically generated |
|||
* Wait until STOPF flag is set or a NACK flag is set |
|||
*/ |
|||
tickstart = (uint32_t)read_cntpct_el0(); |
|||
while (((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & |
|||
(I2C_FLAG_STOPF | I2C_FLAG_AF)) == 0U) && |
|||
(hi2c->i2c_state != I2C_STATE_TIMEOUT)) { |
|||
if (timeout != MAX_DELAY) { |
|||
if ((((uint32_t)read_cntpct_el0() - tickstart) > |
|||
timeout) || (timeout == 0U)) { |
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
|
|||
hi2c->i2c_err |= |
|||
I2C_ERROR_TIMEOUT; |
|||
|
|||
hi2c->lock = 0; |
|||
|
|||
return -EIO; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* Check if the NACKF flag has not been set */ |
|||
if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & |
|||
I2C_FLAG_AF) == 0U) { |
|||
if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout, |
|||
tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, |
|||
I2C_FLAG_STOPF); |
|||
|
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
|
|||
hi2c->lock = 0; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout, |
|||
tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); |
|||
|
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); |
|||
|
|||
if (i2c_trials == trials) { |
|||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, |
|||
I2C_CR2_STOP); |
|||
|
|||
if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout, |
|||
tickstart) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, |
|||
I2C_FLAG_STOPF); |
|||
} |
|||
|
|||
i2c_trials++; |
|||
} while (i2c_trials < trials); |
|||
|
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
|
|||
hi2c->i2c_err |= I2C_ERROR_TIMEOUT; |
|||
|
|||
hi2c->lock = 0; |
|||
|
|||
return -EIO; |
|||
} |
|||
|
|||
/*
|
|||
* @brief Master sends target device address followed by internal memory |
|||
* address for write request. |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2C. |
|||
* @param dev_addr: Target device address |
|||
* @param mem_addr: Internal memory address |
|||
* @param mem_add_size: size of internal memory address |
|||
* @param timeout: timeout duration |
|||
* @param tick_start Tick start value |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
static int i2c_request_memory_write(struct i2c_handle_s *hi2c, |
|||
uint16_t dev_addr, uint16_t mem_addr, |
|||
uint16_t mem_add_size, uint32_t timeout, |
|||
uint32_t tick_start) |
|||
{ |
|||
i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE, |
|||
I2C_GENERATE_START_WRITE); |
|||
|
|||
if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { |
|||
/* Send Memory Address */ |
|||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, |
|||
(uint8_t)(mem_addr & 0x00FFU)); |
|||
} else { |
|||
/* Send MSB of Memory Address */ |
|||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, |
|||
(uint8_t)((mem_addr & 0xFF00U) >> 8)); |
|||
|
|||
/* Wait until TXIS flag is set */ |
|||
if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
/* Send LSB of Memory Address */ |
|||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, |
|||
(uint8_t)(mem_addr & 0x00FFU)); |
|||
} |
|||
|
|||
if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout, tick_start) != |
|||
0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* @brief Master sends target device address followed by internal memory |
|||
* address for read request. |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2C. |
|||
* @param dev_addr: Target device address |
|||
* @param mem_addr: Internal memory address |
|||
* @param mem_add_size: size of internal memory address |
|||
* @param timeout: timeout duration |
|||
* @param tick_start Tick start value |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, |
|||
uint16_t mem_addr, uint16_t mem_add_size, |
|||
uint32_t timeout, uint32_t tick_start) |
|||
{ |
|||
i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE, |
|||
I2C_GENERATE_START_WRITE); |
|||
|
|||
if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { |
|||
/* Send Memory Address */ |
|||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, |
|||
(uint8_t)(mem_addr & 0x00FFU)); |
|||
} else { |
|||
/* Send MSB of Memory Address */ |
|||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, |
|||
(uint8_t)((mem_addr & 0xFF00U) >> 8)); |
|||
|
|||
/* Wait until TXIS flag is set */ |
|||
if (i2c_wait_txis(hi2c, timeout, tick_start) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
/* Send LSB of Memory Address */ |
|||
mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, |
|||
(uint8_t)(mem_addr & 0x00FFU)); |
|||
} |
|||
|
|||
if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout, tick_start) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* @brief I2C Tx data register flush process. |
|||
* @param hi2c: I2C handle. |
|||
* @retval None |
|||
*/ |
|||
static void i2c_flush_txdr(struct i2c_handle_s *hi2c) |
|||
{ |
|||
/*
|
|||
* If a pending TXIS flag is set, |
|||
* write a dummy data in TXDR to clear it. |
|||
*/ |
|||
if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) != |
|||
0U) { |
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0); |
|||
} |
|||
|
|||
/* Flush TX register if not empty */ |
|||
if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) == |
|||
0U) { |
|||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR, |
|||
I2C_FLAG_TXE); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* @brief This function handles I2C Communication timeout. |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2C. |
|||
* @param flag: Specifies the I2C flag to check. |
|||
* @param awaited_value: The awaited bit value for the flag (0 or 1). |
|||
* @param timeout: timeout duration |
|||
* @param tick_start: Tick start value |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, |
|||
uint8_t awaited_value, uint32_t timeout, |
|||
uint32_t tick_start) |
|||
{ |
|||
uint8_t flag_check; |
|||
|
|||
do { |
|||
flag_check = ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & |
|||
flag) == flag) ? 1U : 0U; |
|||
|
|||
if (timeout != MAX_DELAY) { |
|||
if ((((uint32_t)read_cntpct_el0() - tick_start) > |
|||
timeout) || (timeout == 0U)) { |
|||
hi2c->i2c_err |= I2C_ERROR_TIMEOUT; |
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
hi2c->i2c_mode = I2C_MODE_NONE; |
|||
|
|||
hi2c->lock = 0; |
|||
return -EIO; |
|||
} |
|||
} |
|||
} while (flag_check == awaited_value); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* @brief This function handles I2C Communication timeout for specific usage |
|||
* of TXIS flag. |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2C. |
|||
* @param timeout: timeout duration |
|||
* @param tick_start: Tick start value |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint32_t timeout, |
|||
uint32_t tick_start) |
|||
{ |
|||
while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & |
|||
I2C_FLAG_TXIS) == 0U) { |
|||
if (i2c_ack_failed(hi2c, timeout, tick_start) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
if (timeout != MAX_DELAY) { |
|||
if ((((uint32_t)read_cntpct_el0() - tick_start) > |
|||
timeout) || (timeout == 0U)) { |
|||
hi2c->i2c_err |= I2C_ERROR_TIMEOUT; |
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
hi2c->i2c_mode = I2C_MODE_NONE; |
|||
|
|||
hi2c->lock = 0; |
|||
|
|||
return -EIO; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* @brief This function handles I2C Communication timeout for specific |
|||
* usage of STOP flag. |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2C. |
|||
* @param timeout: timeout duration |
|||
* @param tick_start: Tick start value |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout, |
|||
uint32_t tick_start) |
|||
{ |
|||
while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & |
|||
I2C_FLAG_STOPF) == 0U) { |
|||
if (i2c_ack_failed(hi2c, timeout, tick_start) != 0) { |
|||
return -EIO; |
|||
} |
|||
|
|||
if ((((uint32_t)read_cntpct_el0() - tick_start) > timeout) || |
|||
(timeout == 0U)) { |
|||
hi2c->i2c_err |= I2C_ERROR_TIMEOUT; |
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
hi2c->i2c_mode = I2C_MODE_NONE; |
|||
|
|||
hi2c->lock = 0; |
|||
|
|||
return -EIO; |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* @brief This function handles Acknowledge failed detection during |
|||
* an I2C Communication. |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2C. |
|||
* @param timeout: timeout duration |
|||
* @param tick_start: Tick start value |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout, |
|||
uint32_t tick_start) |
|||
{ |
|||
if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) { |
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* Wait until STOP Flag is reset. |
|||
* AutoEnd should be initiate after AF. |
|||
*/ |
|||
while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & |
|||
I2C_FLAG_STOPF) == 0U) { |
|||
if (timeout != MAX_DELAY) { |
|||
if ((((uint32_t)read_cntpct_el0() - tick_start) > |
|||
timeout) || (timeout == 0U)) { |
|||
hi2c->i2c_err |= I2C_ERROR_TIMEOUT; |
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
hi2c->i2c_mode = I2C_MODE_NONE; |
|||
|
|||
hi2c->lock = 0; |
|||
|
|||
return -EIO; |
|||
} |
|||
} |
|||
} |
|||
|
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); |
|||
|
|||
mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); |
|||
|
|||
i2c_flush_txdr(hi2c); |
|||
|
|||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); |
|||
|
|||
hi2c->i2c_err |= I2C_ERROR_AF; |
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
hi2c->i2c_mode = I2C_MODE_NONE; |
|||
|
|||
hi2c->lock = 0; |
|||
|
|||
return -EIO; |
|||
} |
|||
|
|||
/*
|
|||
* @brief Handles I2Cx communication when starting transfer or during transfer |
|||
* (TC or TCR flag are set). |
|||
* @param hi2c: I2C handle. |
|||
* @param dev_addr: Specifies the slave address to be programmed. |
|||
* @param size: Specifies the number of bytes to be programmed. |
|||
* This parameter must be a value between 0 and 255. |
|||
* @param i2c_mode: New state of the I2C START condition generation. |
|||
* This parameter can be one of the following values: |
|||
* @arg @ref I2C_RELOAD_MODE: Enable Reload mode . |
|||
* @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode. |
|||
* @arg @ref I2C_SOFTEND_MODE: Enable Software end mode. |
|||
* @param request: New state of the I2C START condition generation. |
|||
* This parameter can be one of the following values: |
|||
* @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition. |
|||
* @arg @ref I2C_GENERATE_STOP: Generate stop condition |
|||
* (size should be set to 0). |
|||
* @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request. |
|||
* @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request. |
|||
* @retval None |
|||
*/ |
|||
static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, |
|||
uint16_t size, uint32_t i2c_mode, |
|||
uint32_t request) |
|||
{ |
|||
uint32_t clr_value, set_value; |
|||
|
|||
clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | |
|||
I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) | |
|||
(I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET))); |
|||
|
|||
set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) | |
|||
(((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) | |
|||
i2c_mode | request; |
|||
|
|||
mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value); |
|||
} |
|||
|
|||
/*
|
|||
* @brief Configure I2C Analog noise filter. |
|||
* @param hi2c: Pointer to a struct i2c_handle_s structure that contains |
|||
* the configuration information for the specified I2Cx peripheral |
|||
* @param analog_filter: New state of the Analog filter. |
|||
* @retval 0 if OK, negative value else |
|||
*/ |
|||
int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c, |
|||
uint32_t analog_filter) |
|||
{ |
|||
if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { |
|||
return -EBUSY; |
|||
} |
|||
|
|||
hi2c->lock = 1; |
|||
|
|||
hi2c->i2c_state = I2C_STATE_BUSY; |
|||
|
|||
/* Disable the selected I2C peripheral */ |
|||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); |
|||
|
|||
/* Reset I2Cx ANOFF bit */ |
|||
mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF); |
|||
|
|||
/* Set analog filter bit*/ |
|||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter); |
|||
|
|||
/* Enable the selected I2C peripheral */ |
|||
mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); |
|||
|
|||
hi2c->i2c_state = I2C_STATE_READY; |
|||
|
|||
hi2c->lock = 0; |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,346 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <debug.h> |
|||
#include <delay_timer.h> |
|||
#include <errno.h> |
|||
#include <libfdt.h> |
|||
#include <mmio.h> |
|||
#include <mmio.h> |
|||
#include <platform_def.h> |
|||
#include <stdbool.h> |
|||
#include <stm32_gpio.h> |
|||
#include <stm32mp1_clk.h> |
|||
#include <stm32mp1_dt.h> |
|||
#include <stm32mp1_pmic.h> |
|||
#include <stpmu1.h> |
|||
#include <utils_def.h> |
|||
|
|||
/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */ |
|||
#define I2C_TIMING 0x10D07DB5 |
|||
|
|||
#define I2C_TIMEOUT 0xFFFFF |
|||
|
|||
#define MASK_RESET_BUCK3 BIT(2) |
|||
|
|||
#define STPMU1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2)) |
|||
#define STPMU1_LDO12356_OUTPUT_SHIFT 2 |
|||
#define STPMU1_LDO3_MODE (uint8_t)(BIT(7)) |
|||
#define STPMU1_LDO3_DDR_SEL 31U |
|||
#define STPMU1_LDO3_1800000 (9U << STPMU1_LDO12356_OUTPUT_SHIFT) |
|||
|
|||
#define STPMU1_BUCK_OUTPUT_SHIFT 2 |
|||
#define STPMU1_BUCK3_1V8 (39U << STPMU1_BUCK_OUTPUT_SHIFT) |
|||
|
|||
#define STPMU1_DEFAULT_START_UP_DELAY_MS 1 |
|||
|
|||
static struct i2c_handle_s i2c_handle; |
|||
static uint32_t pmic_i2c_addr; |
|||
|
|||
static int dt_get_pmic_node(void *fdt) |
|||
{ |
|||
return fdt_node_offset_by_compatible(fdt, -1, "st,stpmu1"); |
|||
} |
|||
|
|||
bool dt_check_pmic(void) |
|||
{ |
|||
int node; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return false; |
|||
} |
|||
|
|||
node = dt_get_pmic_node(fdt); |
|||
if (node < 0) { |
|||
VERBOSE("%s: No PMIC node found in DT\n", __func__); |
|||
return false; |
|||
} |
|||
|
|||
return fdt_check_status(node); |
|||
} |
|||
|
|||
static int dt_pmic_i2c_config(struct dt_node_info *i2c_info) |
|||
{ |
|||
int pmic_node, i2c_node; |
|||
void *fdt; |
|||
const fdt32_t *cuint; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return -ENOENT; |
|||
} |
|||
|
|||
pmic_node = dt_get_pmic_node(fdt); |
|||
if (pmic_node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); |
|||
if (cuint == NULL) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; |
|||
if (pmic_i2c_addr > UINT16_MAX) { |
|||
return -EINVAL; |
|||
} |
|||
|
|||
i2c_node = fdt_parent_offset(fdt, pmic_node); |
|||
if (i2c_node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
dt_fill_device_info(i2c_info, i2c_node); |
|||
if (i2c_info->base == 0U) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
return dt_set_pinctrl_config(i2c_node); |
|||
} |
|||
|
|||
int dt_pmic_enable_boot_on_regulators(void) |
|||
{ |
|||
int pmic_node, regulators_node, regulator_node; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return -ENOENT; |
|||
} |
|||
|
|||
pmic_node = dt_get_pmic_node(fdt); |
|||
if (pmic_node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); |
|||
|
|||
fdt_for_each_subnode(regulator_node, fdt, regulators_node) { |
|||
const fdt32_t *cuint; |
|||
const char *node_name; |
|||
uint16_t voltage; |
|||
|
|||
if (fdt_getprop(fdt, regulator_node, "regulator-boot-on", |
|||
NULL) == NULL) { |
|||
continue; |
|||
} |
|||
|
|||
cuint = fdt_getprop(fdt, regulator_node, |
|||
"regulator-min-microvolt", NULL); |
|||
if (cuint == NULL) { |
|||
continue; |
|||
} |
|||
|
|||
/* DT uses microvolts, whereas driver awaits millivolts */ |
|||
voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); |
|||
node_name = fdt_get_name(fdt, regulator_node, NULL); |
|||
|
|||
if (stpmu1_is_regulator_enabled(node_name) == 0U) { |
|||
int status; |
|||
|
|||
status = stpmu1_regulator_voltage_set(node_name, |
|||
voltage); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
status = stpmu1_regulator_enable(node_name); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void initialize_pmic_i2c(void) |
|||
{ |
|||
int ret; |
|||
struct dt_node_info i2c_info; |
|||
|
|||
if (dt_pmic_i2c_config(&i2c_info) != 0) { |
|||
ERROR("I2C configuration failed\n"); |
|||
panic(); |
|||
} |
|||
|
|||
if (stm32mp1_clk_enable((uint32_t)i2c_info.clock) < 0) { |
|||
ERROR("I2C clock enable failed\n"); |
|||
panic(); |
|||
} |
|||
|
|||
/* Initialize PMIC I2C */ |
|||
i2c_handle.i2c_base_addr = i2c_info.base; |
|||
i2c_handle.i2c_init.timing = I2C_TIMING; |
|||
i2c_handle.i2c_init.own_address1 = pmic_i2c_addr; |
|||
i2c_handle.i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; |
|||
i2c_handle.i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; |
|||
i2c_handle.i2c_init.own_address2 = 0; |
|||
i2c_handle.i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK; |
|||
i2c_handle.i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE; |
|||
i2c_handle.i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE; |
|||
|
|||
ret = stm32_i2c_init(&i2c_handle); |
|||
if (ret != 0) { |
|||
ERROR("Cannot initialize I2C %x (%d)\n", |
|||
i2c_handle.i2c_base_addr, ret); |
|||
panic(); |
|||
} |
|||
|
|||
ret = stm32_i2c_config_analog_filter(&i2c_handle, |
|||
I2C_ANALOGFILTER_ENABLE); |
|||
if (ret != 0) { |
|||
ERROR("Cannot initialize I2C analog filter (%d)\n", ret); |
|||
panic(); |
|||
} |
|||
|
|||
ret = stm32_i2c_is_device_ready(&i2c_handle, (uint16_t)pmic_i2c_addr, 1, |
|||
I2C_TIMEOUT); |
|||
if (ret != 0) { |
|||
ERROR("I2C device not ready (%d)\n", ret); |
|||
panic(); |
|||
} |
|||
|
|||
stpmu1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr); |
|||
} |
|||
|
|||
void initialize_pmic(void) |
|||
{ |
|||
int status; |
|||
uint8_t read_val; |
|||
|
|||
initialize_pmic_i2c(); |
|||
|
|||
status = stpmu1_register_read(VERSION_STATUS_REG, &read_val); |
|||
if (status != 0) { |
|||
panic(); |
|||
} |
|||
|
|||
INFO("PMIC version = 0x%x\n", read_val); |
|||
|
|||
/* Keep VDD on during the reset cycle */ |
|||
status = stpmu1_register_update(MASK_RESET_BUCK_REG, |
|||
MASK_RESET_BUCK3, |
|||
MASK_RESET_BUCK3); |
|||
if (status != 0) { |
|||
panic(); |
|||
} |
|||
} |
|||
|
|||
int pmic_ddr_power_init(enum ddr_type ddr_type) |
|||
{ |
|||
bool buck3_at_1v8 = false; |
|||
uint8_t read_val; |
|||
int status; |
|||
|
|||
switch (ddr_type) { |
|||
case STM32MP_DDR3: |
|||
/* Set LDO3 to sync mode */ |
|||
status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
read_val &= ~STPMU1_LDO3_MODE; |
|||
read_val &= ~STPMU1_LDO12356_OUTPUT_MASK; |
|||
read_val |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT; |
|||
|
|||
status = stpmu1_register_write(LDO3_CONTROL_REG, read_val); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
status = stpmu1_regulator_voltage_set("buck2", 1350); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
status = stpmu1_regulator_enable("buck2"); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); |
|||
|
|||
status = stpmu1_regulator_enable("vref_ddr"); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); |
|||
|
|||
status = stpmu1_regulator_enable("ldo3"); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); |
|||
break; |
|||
|
|||
case STM32MP_LPDDR2: |
|||
/*
|
|||
* Set LDO3 to 1.8V |
|||
* Set LDO3 to bypass mode if BUCK3 = 1.8V |
|||
* Set LDO3 to normal mode if BUCK3 != 1.8V |
|||
*/ |
|||
status = stpmu1_register_read(BUCK3_CONTROL_REG, &read_val); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
if ((read_val & STPMU1_BUCK3_1V8) == STPMU1_BUCK3_1V8) { |
|||
buck3_at_1v8 = true; |
|||
} |
|||
|
|||
status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
read_val &= ~STPMU1_LDO3_MODE; |
|||
read_val &= ~STPMU1_LDO12356_OUTPUT_MASK; |
|||
read_val |= STPMU1_LDO3_1800000; |
|||
if (buck3_at_1v8) { |
|||
read_val |= STPMU1_LDO3_MODE; |
|||
} |
|||
|
|||
status = stpmu1_register_write(LDO3_CONTROL_REG, read_val); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
status = stpmu1_regulator_voltage_set("buck2", 1200); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
status = stpmu1_regulator_enable("ldo3"); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); |
|||
|
|||
status = stpmu1_regulator_enable("buck2"); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); |
|||
|
|||
status = stpmu1_regulator_enable("vref_ddr"); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); |
|||
break; |
|||
|
|||
default: |
|||
break; |
|||
}; |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,600 @@ |
|||
/*
|
|||
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <debug.h> |
|||
#include <platform.h> |
|||
#include <stpmu1.h> |
|||
#include <string.h> |
|||
|
|||
struct regul_struct { |
|||
const char *dt_node_name; |
|||
const uint16_t *voltage_table; |
|||
uint8_t voltage_table_size; |
|||
uint8_t control_reg; |
|||
uint8_t low_power_reg; |
|||
}; |
|||
|
|||
static struct i2c_handle_s *stpmu_i2c_handle; |
|||
static uint16_t stpmu_i2c_addr; |
|||
|
|||
/* Voltage tables in mV */ |
|||
static const uint16_t buck1_voltage_table[] = { |
|||
600, |
|||
625, |
|||
650, |
|||
675, |
|||
700, |
|||
725, |
|||
750, |
|||
775, |
|||
800, |
|||
825, |
|||
850, |
|||
875, |
|||
900, |
|||
925, |
|||
950, |
|||
975, |
|||
1000, |
|||
1025, |
|||
1050, |
|||
1075, |
|||
1100, |
|||
1125, |
|||
1150, |
|||
1175, |
|||
1200, |
|||
1225, |
|||
1250, |
|||
1275, |
|||
1300, |
|||
1325, |
|||
1350, |
|||
1350, |
|||
}; |
|||
|
|||
static const uint16_t buck2_voltage_table[] = { |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1050, |
|||
1050, |
|||
1100, |
|||
1100, |
|||
1150, |
|||
1150, |
|||
1200, |
|||
1200, |
|||
1250, |
|||
1250, |
|||
1300, |
|||
1300, |
|||
1350, |
|||
1350, |
|||
1400, |
|||
1400, |
|||
1450, |
|||
1450, |
|||
1500, |
|||
}; |
|||
|
|||
static const uint16_t buck3_voltage_table[] = { |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1000, |
|||
1100, |
|||
1100, |
|||
1100, |
|||
1100, |
|||
1200, |
|||
1200, |
|||
1200, |
|||
1200, |
|||
1300, |
|||
1300, |
|||
1300, |
|||
1300, |
|||
1400, |
|||
1400, |
|||
1400, |
|||
1400, |
|||
1500, |
|||
1600, |
|||
1700, |
|||
1800, |
|||
1900, |
|||
2000, |
|||
2100, |
|||
2200, |
|||
2300, |
|||
2400, |
|||
2500, |
|||
2600, |
|||
2700, |
|||
2800, |
|||
2900, |
|||
3000, |
|||
3100, |
|||
3200, |
|||
3300, |
|||
3400, |
|||
}; |
|||
|
|||
static const uint16_t buck4_voltage_table[] = { |
|||
600, |
|||
625, |
|||
650, |
|||
675, |
|||
700, |
|||
725, |
|||
750, |
|||
775, |
|||
800, |
|||
825, |
|||
850, |
|||
875, |
|||
900, |
|||
925, |
|||
950, |
|||
975, |
|||
1000, |
|||
1025, |
|||
1050, |
|||
1075, |
|||
1100, |
|||
1125, |
|||
1150, |
|||
1175, |
|||
1200, |
|||
1225, |
|||
1250, |
|||
1275, |
|||
1300, |
|||
1300, |
|||
1350, |
|||
1350, |
|||
1400, |
|||
1400, |
|||
1450, |
|||
1450, |
|||
1500, |
|||
1600, |
|||
1700, |
|||
1800, |
|||
1900, |
|||
2000, |
|||
2100, |
|||
2200, |
|||
2300, |
|||
2400, |
|||
2500, |
|||
2600, |
|||
2700, |
|||
2800, |
|||
2900, |
|||
3000, |
|||
3100, |
|||
3200, |
|||
3300, |
|||
3400, |
|||
3500, |
|||
3600, |
|||
3700, |
|||
3800, |
|||
3900, |
|||
}; |
|||
|
|||
static const uint16_t ldo1_voltage_table[] = { |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1800, |
|||
1900, |
|||
2000, |
|||
2100, |
|||
2200, |
|||
2300, |
|||
2400, |
|||
2500, |
|||
2600, |
|||
2700, |
|||
2800, |
|||
2900, |
|||
3000, |
|||
3100, |
|||
3200, |
|||
3300, |
|||
}; |
|||
|
|||
static const uint16_t ldo2_voltage_table[] = { |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1800, |
|||
1900, |
|||
2000, |
|||
2100, |
|||
2200, |
|||
2300, |
|||
2400, |
|||
2500, |
|||
2600, |
|||
2700, |
|||
2800, |
|||
2900, |
|||
3000, |
|||
3100, |
|||
3200, |
|||
3300, |
|||
}; |
|||
|
|||
static const uint16_t ldo3_voltage_table[] = { |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1800, |
|||
1900, |
|||
2000, |
|||
2100, |
|||
2200, |
|||
2300, |
|||
2400, |
|||
2500, |
|||
2600, |
|||
2700, |
|||
2800, |
|||
2900, |
|||
3000, |
|||
3100, |
|||
3200, |
|||
3300, |
|||
3300, |
|||
3300, |
|||
3300, |
|||
3300, |
|||
3300, |
|||
3300, |
|||
0xFFFF, /* VREFDDR */ |
|||
}; |
|||
|
|||
static const uint16_t ldo5_voltage_table[] = { |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1700, |
|||
1800, |
|||
1900, |
|||
2000, |
|||
2100, |
|||
2200, |
|||
2300, |
|||
2400, |
|||
2500, |
|||
2600, |
|||
2700, |
|||
2800, |
|||
2900, |
|||
3000, |
|||
3100, |
|||
3200, |
|||
3300, |
|||
3400, |
|||
3500, |
|||
3600, |
|||
3700, |
|||
3800, |
|||
3900, |
|||
}; |
|||
|
|||
static const uint16_t ldo6_voltage_table[] = { |
|||
900, |
|||
1000, |
|||
1100, |
|||
1200, |
|||
1300, |
|||
1400, |
|||
1500, |
|||
1600, |
|||
1700, |
|||
1800, |
|||
1900, |
|||
2000, |
|||
2100, |
|||
2200, |
|||
2300, |
|||
2400, |
|||
2500, |
|||
2600, |
|||
2700, |
|||
2800, |
|||
2900, |
|||
3000, |
|||
3100, |
|||
3200, |
|||
3300, |
|||
}; |
|||
|
|||
static const uint16_t ldo4_voltage_table[] = { |
|||
3300, |
|||
}; |
|||
|
|||
static const uint16_t vref_ddr_voltage_table[] = { |
|||
3300, |
|||
}; |
|||
|
|||
/* Table of Regulators in PMIC SoC */ |
|||
static const struct regul_struct regulators_table[] = { |
|||
{ |
|||
.dt_node_name = "buck1", |
|||
.voltage_table = buck1_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(buck1_voltage_table), |
|||
.control_reg = BUCK1_CONTROL_REG, |
|||
.low_power_reg = BUCK1_PWRCTRL_REG, |
|||
}, |
|||
{ |
|||
.dt_node_name = "buck2", |
|||
.voltage_table = buck2_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(buck2_voltage_table), |
|||
.control_reg = BUCK2_CONTROL_REG, |
|||
.low_power_reg = BUCK2_PWRCTRL_REG, |
|||
}, |
|||
{ |
|||
.dt_node_name = "buck3", |
|||
.voltage_table = buck3_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(buck3_voltage_table), |
|||
.control_reg = BUCK3_CONTROL_REG, |
|||
.low_power_reg = BUCK3_PWRCTRL_REG, |
|||
}, |
|||
{ |
|||
.dt_node_name = "buck4", |
|||
.voltage_table = buck4_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(buck4_voltage_table), |
|||
.control_reg = BUCK4_CONTROL_REG, |
|||
.low_power_reg = BUCK4_PWRCTRL_REG, |
|||
}, |
|||
{ |
|||
.dt_node_name = "ldo1", |
|||
.voltage_table = ldo1_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), |
|||
.control_reg = LDO1_CONTROL_REG, |
|||
.low_power_reg = LDO1_PWRCTRL_REG, |
|||
}, |
|||
{ |
|||
.dt_node_name = "ldo2", |
|||
.voltage_table = ldo2_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), |
|||
.control_reg = LDO2_CONTROL_REG, |
|||
.low_power_reg = LDO2_PWRCTRL_REG, |
|||
}, |
|||
{ |
|||
.dt_node_name = "ldo3", |
|||
.voltage_table = ldo3_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), |
|||
.control_reg = LDO3_CONTROL_REG, |
|||
.low_power_reg = LDO3_PWRCTRL_REG, |
|||
}, |
|||
{ |
|||
.dt_node_name = "ldo4", |
|||
.voltage_table = ldo4_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), |
|||
.control_reg = LDO4_CONTROL_REG, |
|||
.low_power_reg = LDO4_PWRCTRL_REG, |
|||
}, |
|||
{ |
|||
.dt_node_name = "ldo5", |
|||
.voltage_table = ldo5_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), |
|||
.control_reg = LDO5_CONTROL_REG, |
|||
.low_power_reg = LDO5_PWRCTRL_REG, |
|||
}, |
|||
{ |
|||
.dt_node_name = "ldo6", |
|||
.voltage_table = ldo6_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), |
|||
.control_reg = LDO6_CONTROL_REG, |
|||
.low_power_reg = LDO6_PWRCTRL_REG, |
|||
}, |
|||
{ |
|||
.dt_node_name = "vref_ddr", |
|||
.voltage_table = vref_ddr_voltage_table, |
|||
.voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table), |
|||
.control_reg = VREF_DDR_CONTROL_REG, |
|||
.low_power_reg = VREF_DDR_PWRCTRL_REG, |
|||
}, |
|||
}; |
|||
|
|||
#define MAX_REGUL ARRAY_SIZE(regulators_table) |
|||
|
|||
static const struct regul_struct *stpmu1_get_regulator_data(const char *name) |
|||
{ |
|||
uint8_t i; |
|||
|
|||
for (i = 0 ; i < MAX_REGUL ; i++) { |
|||
if (strncmp(name, regulators_table[i].dt_node_name, |
|||
strlen(regulators_table[i].dt_node_name)) == 0) { |
|||
return ®ulators_table[i]; |
|||
} |
|||
} |
|||
|
|||
/* Regulator not found */ |
|||
panic(); |
|||
return NULL; |
|||
} |
|||
|
|||
static uint8_t stpmu1_voltage_find_index(const char *name, |
|||
uint16_t millivolts) |
|||
{ |
|||
const struct regul_struct *regul = stpmu1_get_regulator_data(name); |
|||
uint8_t i; |
|||
|
|||
for (i = 0 ; i < regul->voltage_table_size ; i++) { |
|||
if (regul->voltage_table[i] == millivolts) { |
|||
return i; |
|||
} |
|||
} |
|||
|
|||
/* Voltage not found */ |
|||
panic(); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int stpmu1_switch_off(void) |
|||
{ |
|||
return stpmu1_register_update(MAIN_CONTROL_REG, 1, |
|||
SOFTWARE_SWITCH_OFF_ENABLED); |
|||
} |
|||
|
|||
int stpmu1_regulator_enable(const char *name) |
|||
{ |
|||
const struct regul_struct *regul = stpmu1_get_regulator_data(name); |
|||
|
|||
return stpmu1_register_update(regul->control_reg, BIT(0), BIT(0)); |
|||
} |
|||
|
|||
int stpmu1_regulator_disable(const char *name) |
|||
{ |
|||
const struct regul_struct *regul = stpmu1_get_regulator_data(name); |
|||
|
|||
return stpmu1_register_update(regul->control_reg, 0, BIT(0)); |
|||
} |
|||
|
|||
uint8_t stpmu1_is_regulator_enabled(const char *name) |
|||
{ |
|||
uint8_t val; |
|||
const struct regul_struct *regul = stpmu1_get_regulator_data(name); |
|||
|
|||
if (stpmu1_register_read(regul->control_reg, &val) != 0) { |
|||
panic(); |
|||
} |
|||
|
|||
return (val & 0x1U); |
|||
} |
|||
|
|||
int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts) |
|||
{ |
|||
uint8_t voltage_index = stpmu1_voltage_find_index(name, millivolts); |
|||
const struct regul_struct *regul = stpmu1_get_regulator_data(name); |
|||
|
|||
return stpmu1_register_update(regul->control_reg, voltage_index << 2, |
|||
0xFC); |
|||
} |
|||
|
|||
int stpmu1_register_read(uint8_t register_id, uint8_t *value) |
|||
{ |
|||
return stm32_i2c_mem_read(stpmu_i2c_handle, stpmu_i2c_addr, |
|||
(uint16_t)register_id, I2C_MEMADD_SIZE_8BIT, |
|||
value, 1, 100000); |
|||
} |
|||
|
|||
int stpmu1_register_write(uint8_t register_id, uint8_t value) |
|||
{ |
|||
int status; |
|||
|
|||
status = stm32_i2c_mem_write(stpmu_i2c_handle, stpmu_i2c_addr, |
|||
(uint16_t)register_id, |
|||
I2C_MEMADD_SIZE_8BIT, &value, 1, 100000); |
|||
|
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) { |
|||
uint8_t readval; |
|||
|
|||
status = stpmu1_register_read(register_id, &readval); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
if (readval != value) { |
|||
return -1; |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask) |
|||
{ |
|||
int status; |
|||
uint8_t val; |
|||
|
|||
status = stpmu1_register_read(register_id, &val); |
|||
if (status != 0) { |
|||
return status; |
|||
} |
|||
|
|||
/* Clear bits to update */ |
|||
val &= ~mask; |
|||
|
|||
/* Update appropriate bits*/ |
|||
val |= (value & mask); |
|||
|
|||
/* Send new value on I2C Bus */ |
|||
return stpmu1_register_write(register_id, val); |
|||
} |
|||
|
|||
void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr) |
|||
{ |
|||
stpmu_i2c_handle = i2c_handle; |
|||
stpmu_i2c_addr = i2c_addr; |
|||
} |
@ -0,0 +1,39 @@ |
|||
/*
|
|||
* Copyright (c) 2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <bl_common.h> |
|||
#include <debug.h> |
|||
#include <limits.h> |
|||
#include <mmio.h> |
|||
#include <platform_def.h> |
|||
#include <stm32mp1_rcc.h> |
|||
#include <stm32mp1_reset.h> |
|||
#include <utils_def.h> |
|||
|
|||
#define RST_CLR_OFFSET 4U |
|||
|
|||
void stm32mp1_reset_assert(uint32_t id) |
|||
{ |
|||
uint32_t offset = (id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t); |
|||
uint32_t bit = id % (uint32_t)__LONG_BIT; |
|||
|
|||
mmio_write_32(RCC_BASE + offset, BIT(bit)); |
|||
while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) == 0U) { |
|||
; |
|||
} |
|||
} |
|||
|
|||
void stm32mp1_reset_deassert(uint32_t id) |
|||
{ |
|||
uint32_t offset = ((id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t)) + |
|||
RST_CLR_OFFSET; |
|||
uint32_t bit = id % (uint32_t)__LONG_BIT; |
|||
|
|||
mmio_write_32(RCC_BASE + offset, BIT(bit)); |
|||
while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) != 0U) { |
|||
; |
|||
} |
|||
} |
@ -0,0 +1,184 @@ |
|||
/* |
|||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
#include <asm_macros.S> |
|||
|
|||
#define USART_TIMEOUT 0x1000 |
|||
|
|||
#define USART_CR1 0x00 |
|||
#define USART_CR1_UE 0x00000001 |
|||
#define USART_CR1_TE 0x00000008 |
|||
#define USART_CR1_FIFOEN 0x20000000 |
|||
|
|||
#define USART_CR2 0x04 |
|||
#define USART_CR2_STOP 0x00003000 |
|||
|
|||
#define USART_BRR 0x0C |
|||
|
|||
#define USART_ISR 0x1C |
|||
#define USART_ISR_TC 0x00000040 |
|||
#define USART_ISR_TXE 0x00000080 |
|||
#define USART_ISR_TEACK 0x00200000 |
|||
|
|||
#define USART_TDR 0x28 |
|||
|
|||
.globl console_core_init |
|||
.globl console_core_putc |
|||
.globl console_core_getc |
|||
.globl console_core_flush |
|||
|
|||
/* ----------------------------------------------------------------- |
|||
* int console_core_init(uintptr_t base_addr, |
|||
* unsigned int uart_clk, |
|||
* unsigned int baud_rate) |
|||
* |
|||
* Function to initialize the console without a C Runtime to print |
|||
* debug information. This function will be accessed by console_init |
|||
* and crash reporting. |
|||
* |
|||
* In: r0 - console base address |
|||
* r1 - Uart clock in Hz |
|||
* r2 - Baud rate |
|||
* Out: return 1 on success else 0 on error |
|||
* Clobber list : r1, r2, r3 |
|||
* ----------------------------------------------------------------- |
|||
*/ |
|||
func console_core_init |
|||
/* Check the input base address */ |
|||
cmp r0, #0 |
|||
beq core_init_fail |
|||
#if defined(IMAGE_BL2) |
|||
/* Check baud rate and uart clock for sanity */ |
|||
cmp r1, #0 |
|||
beq core_init_fail |
|||
cmp r2, #0 |
|||
beq core_init_fail |
|||
/* Disable UART */ |
|||
ldr r3, [r0, #USART_CR1] |
|||
bic r3, r3, #USART_CR1_UE |
|||
str r3, [r0, #USART_CR1] |
|||
/* Configure UART */ |
|||
orr r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN) |
|||
str r3, [r0, #USART_CR1] |
|||
ldr r3, [r0, #USART_CR2] |
|||
bic r3, r3, #USART_CR2_STOP |
|||
str r3, [r0, #USART_CR2] |
|||
/* Divisor = (Uart clock + (baudrate / 2)) / baudrate */ |
|||
lsl r3, r2, #1 |
|||
add r3, r1, r3 |
|||
udiv r3, r3, r2 |
|||
str r3, [r0, #USART_BRR] |
|||
/* Enable UART */ |
|||
ldr r3, [r0, #USART_CR1] |
|||
orr r3, r3, #USART_CR1_UE |
|||
str r3, [r0, #USART_CR1] |
|||
/* Check TEACK bit */ |
|||
mov r2, #USART_TIMEOUT |
|||
teack_loop: |
|||
subs r2, r2, #1 |
|||
beq core_init_fail |
|||
ldr r3, [r0, #USART_ISR] |
|||
tst r3, #USART_ISR_TEACK |
|||
beq teack_loop |
|||
#endif /* IMAGE_BL2 */ |
|||
mov r0, #1 |
|||
bx lr |
|||
core_init_fail: |
|||
mov r0, #0 |
|||
bx lr |
|||
endfunc console_core_init |
|||
|
|||
/* --------------------------------------------------------------- |
|||
* int console_core_putc(int c, uintptr_t base_addr) |
|||
* |
|||
* Function to output a character over the console. It returns the |
|||
* character printed on success or -1 on error. |
|||
* |
|||
* In : r0 - character to be printed |
|||
* r1 - console base address |
|||
* Out : return -1 on error else return character. |
|||
* Clobber list : r2 |
|||
* --------------------------------------------------------------- |
|||
*/ |
|||
func console_core_putc |
|||
/* Check the input parameter */ |
|||
cmp r1, #0 |
|||
beq putc_error |
|||
/* Prepend '\r' to '\n' */ |
|||
cmp r0, #0xA |
|||
bne 2f |
|||
1: |
|||
/* Check Transmit Data Register Empty */ |
|||
txe_loop_1: |
|||
ldr r2, [r1, #USART_ISR] |
|||
tst r2, #USART_ISR_TXE |
|||
beq txe_loop_1 |
|||
mov r2, #0xD |
|||
str r2, [r1, #USART_TDR] |
|||
/* Check transmit complete flag */ |
|||
tc_loop_1: |
|||
ldr r2, [r1, #USART_ISR] |
|||
tst r2, #USART_ISR_TC |
|||
beq tc_loop_1 |
|||
2: |
|||
/* Check Transmit Data Register Empty */ |
|||
txe_loop_2: |
|||
ldr r2, [r1, #USART_ISR] |
|||
tst r2, #USART_ISR_TXE |
|||
beq txe_loop_2 |
|||
str r0, [r1, #USART_TDR] |
|||
/* Check transmit complete flag */ |
|||
tc_loop_2: |
|||
ldr r2, [r1, #USART_ISR] |
|||
tst r2, #USART_ISR_TC |
|||
beq tc_loop_2 |
|||
bx lr |
|||
putc_error: |
|||
mov r0, #-1 |
|||
bx lr |
|||
endfunc console_core_putc |
|||
|
|||
/* ----------------------------------------------------------- |
|||
* int console_core_getc(uintptr_t base_addr) |
|||
* |
|||
* Function to get a character from the console. |
|||
* It returns the character grabbed on success or -1 on error. |
|||
* |
|||
* In : r0 - console base address |
|||
* Out : return -1. |
|||
* Clobber list : r0, r1 |
|||
* ----------------------------------------------------------- |
|||
*/ |
|||
func console_core_getc |
|||
/* Not supported */ |
|||
mov r0, #-1 |
|||
bx lr |
|||
endfunc console_core_getc |
|||
|
|||
/* --------------------------------------------------------------- |
|||
* int console_core_flush(uintptr_t base_addr) |
|||
* |
|||
* Function to force a write of all buffered data that hasn't been |
|||
* output. |
|||
* |
|||
* In : r0 - console base address |
|||
* Out : return -1 on error else return 0. |
|||
* Clobber list : r0, r1 |
|||
* --------------------------------------------------------------- |
|||
*/ |
|||
func console_core_flush |
|||
cmp r0, #0 |
|||
beq flush_error |
|||
/* Check Transmit Data Register Empty */ |
|||
txe_loop_3: |
|||
ldr r1, [r0, #USART_ISR] |
|||
tst r1, #USART_ISR_TXE |
|||
beq txe_loop_3 |
|||
mov r0, #0 |
|||
bx lr |
|||
flush_error: |
|||
mov r0, #-1 |
|||
bx lr |
|||
endfunc console_core_flush |
@ -0,0 +1,153 @@ |
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
|||
/* |
|||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved |
|||
*/ |
|||
|
|||
/ { |
|||
soc { |
|||
ddr: ddr@0x5A003000{ |
|||
|
|||
compatible = "st,stm32mp1-ddr"; |
|||
|
|||
reg = <0x5A003000 0x550 |
|||
0x5A004000 0x234>; |
|||
|
|||
clocks = <&rcc AXIDCG>, |
|||
<&rcc DDRC1>, |
|||
<&rcc DDRC2>, |
|||
<&rcc DDRPHYC>, |
|||
<&rcc DDRCAPB>, |
|||
<&rcc DDRPHYCAPB>; |
|||
|
|||
clock-names = "axidcg", |
|||
"ddrc1", |
|||
"ddrc2", |
|||
"ddrphyc", |
|||
"ddrcapb", |
|||
"ddrphycapb"; |
|||
|
|||
st,mem-name = DDR_MEM_NAME; |
|||
st,mem-speed = <DDR_MEM_SPEED>; |
|||
st,mem-size = <DDR_MEM_SIZE>; |
|||
|
|||
st,ctl-reg = < |
|||
DDR_MSTR |
|||
DDR_MRCTRL0 |
|||
DDR_MRCTRL1 |
|||
DDR_DERATEEN |
|||
DDR_DERATEINT |
|||
DDR_PWRCTL |
|||
DDR_PWRTMG |
|||
DDR_HWLPCTL |
|||
DDR_RFSHCTL0 |
|||
DDR_RFSHCTL3 |
|||
DDR_CRCPARCTL0 |
|||
DDR_ZQCTL0 |
|||
DDR_DFITMG0 |
|||
DDR_DFITMG1 |
|||
DDR_DFILPCFG0 |
|||
DDR_DFIUPD0 |
|||
DDR_DFIUPD1 |
|||
DDR_DFIUPD2 |
|||
DDR_DFIPHYMSTR |
|||
DDR_ODTMAP |
|||
DDR_DBG0 |
|||
DDR_DBG1 |
|||
DDR_DBGCMD |
|||
DDR_POISONCFG |
|||
DDR_PCCFG |
|||
>; |
|||
|
|||
st,ctl-timing = < |
|||
DDR_RFSHTMG |
|||
DDR_DRAMTMG0 |
|||
DDR_DRAMTMG1 |
|||
DDR_DRAMTMG2 |
|||
DDR_DRAMTMG3 |
|||
DDR_DRAMTMG4 |
|||
DDR_DRAMTMG5 |
|||
DDR_DRAMTMG6 |
|||
DDR_DRAMTMG7 |
|||
DDR_DRAMTMG8 |
|||
DDR_DRAMTMG14 |
|||
DDR_ODTCFG |
|||
>; |
|||
|
|||
st,ctl-map = < |
|||
DDR_ADDRMAP1 |
|||
DDR_ADDRMAP2 |
|||
DDR_ADDRMAP3 |
|||
DDR_ADDRMAP4 |
|||
DDR_ADDRMAP5 |
|||
DDR_ADDRMAP6 |
|||
DDR_ADDRMAP9 |
|||
DDR_ADDRMAP10 |
|||
DDR_ADDRMAP11 |
|||
>; |
|||
|
|||
st,ctl-perf = < |
|||
DDR_SCHED |
|||
DDR_SCHED1 |
|||
DDR_PERFHPR1 |
|||
DDR_PERFLPR1 |
|||
DDR_PERFWR1 |
|||
DDR_PCFGR_0 |
|||
DDR_PCFGW_0 |
|||
DDR_PCFGQOS0_0 |
|||
DDR_PCFGQOS1_0 |
|||
DDR_PCFGWQOS0_0 |
|||
DDR_PCFGWQOS1_0 |
|||
DDR_PCFGR_1 |
|||
DDR_PCFGW_1 |
|||
DDR_PCFGQOS0_1 |
|||
DDR_PCFGQOS1_1 |
|||
DDR_PCFGWQOS0_1 |
|||
DDR_PCFGWQOS1_1 |
|||
>; |
|||
|
|||
st,phy-reg = < |
|||
DDR_PGCR |
|||
DDR_ACIOCR |
|||
DDR_DXCCR |
|||
DDR_DSGCR |
|||
DDR_DCR |
|||
DDR_ODTCR |
|||
DDR_ZQ0CR1 |
|||
DDR_DX0GCR |
|||
DDR_DX1GCR |
|||
DDR_DX2GCR |
|||
DDR_DX3GCR |
|||
>; |
|||
|
|||
st,phy-timing = < |
|||
DDR_PTR0 |
|||
DDR_PTR1 |
|||
DDR_PTR2 |
|||
DDR_DTPR0 |
|||
DDR_DTPR1 |
|||
DDR_DTPR2 |
|||
DDR_MR0 |
|||
DDR_MR1 |
|||
DDR_MR2 |
|||
DDR_MR3 |
|||
>; |
|||
|
|||
st,phy-cal = < |
|||
DDR_DX0DLLCR |
|||
DDR_DX0DQTR |
|||
DDR_DX0DQSTR |
|||
DDR_DX1DLLCR |
|||
DDR_DX1DQTR |
|||
DDR_DX1DQSTR |
|||
DDR_DX2DLLCR |
|||
DDR_DX2DQTR |
|||
DDR_DX2DQSTR |
|||
DDR_DX3DLLCR |
|||
DDR_DX3DQTR |
|||
DDR_DX3DQSTR |
|||
>; |
|||
|
|||
status = "okay"; |
|||
}; |
|||
}; |
|||
}; |
@ -0,0 +1,121 @@ |
|||
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
|||
/* |
|||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved |
|||
*/ |
|||
|
|||
/* STM32MP157C ED1 and ED2 BOARD configuration |
|||
* 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology. |
|||
* Reference used NT5CC256M16DP-DI from NANYA |
|||
* |
|||
* DDR type / Platform DDR3/3L |
|||
* freq 533MHz |
|||
* width 32 |
|||
* datasheet 0 = MT41J256M16-187 / DDR3-1066 bin G |
|||
* DDR density 8 |
|||
* timing mode optimized |
|||
* Scheduling/QoS options : type = 2 |
|||
* address mapping : RBC |
|||
*/ |
|||
|
|||
#define DDR_MEM_NAME "DDR3-1066 bin G 2x4Gb 533MHz v1.39" |
|||
#define DDR_MEM_SPEED 533 |
|||
#define DDR_MEM_SIZE 0x40000000 |
|||
|
|||
#define DDR_MSTR 0x00040401 |
|||
#define DDR_MRCTRL0 0x00000010 |
|||
#define DDR_MRCTRL1 0x00000000 |
|||
#define DDR_DERATEEN 0x00000000 |
|||
#define DDR_DERATEINT 0x00800000 |
|||
#define DDR_PWRCTL 0x00000000 |
|||
#define DDR_PWRTMG 0x00400010 |
|||
#define DDR_HWLPCTL 0x00000000 |
|||
#define DDR_RFSHCTL0 0x00210000 |
|||
#define DDR_RFSHCTL3 0x00000000 |
|||
#define DDR_RFSHTMG 0x0081008B |
|||
#define DDR_CRCPARCTL0 0x00000000 |
|||
#define DDR_DRAMTMG0 0x121B2414 |
|||
#define DDR_DRAMTMG1 0x000A041C |
|||
#define DDR_DRAMTMG2 0x0608090F |
|||
#define DDR_DRAMTMG3 0x0050400C |
|||
#define DDR_DRAMTMG4 0x08040608 |
|||
#define DDR_DRAMTMG5 0x06060403 |
|||
#define DDR_DRAMTMG6 0x02020002 |
|||
#define DDR_DRAMTMG7 0x00000202 |
|||
#define DDR_DRAMTMG8 0x00001005 |
|||
#define DDR_DRAMTMG14 0x000000A0 |
|||
#define DDR_ZQCTL0 0xC2000040 |
|||
#define DDR_DFITMG0 0x02060105 |
|||
#define DDR_DFITMG1 0x00000202 |
|||
#define DDR_DFILPCFG0 0x07000000 |
|||
#define DDR_DFIUPD0 0xC0400003 |
|||
#define DDR_DFIUPD1 0x00000000 |
|||
#define DDR_DFIUPD2 0x00000000 |
|||
#define DDR_DFIPHYMSTR 0x00000000 |
|||
#define DDR_ADDRMAP1 0x00080808 |
|||
#define DDR_ADDRMAP2 0x00000000 |
|||
#define DDR_ADDRMAP3 0x00000000 |
|||
#define DDR_ADDRMAP4 0x00001F1F |
|||
#define DDR_ADDRMAP5 0x07070707 |
|||
#define DDR_ADDRMAP6 0x0F070707 |
|||
#define DDR_ADDRMAP9 0x00000000 |
|||
#define DDR_ADDRMAP10 0x00000000 |
|||
#define DDR_ADDRMAP11 0x00000000 |
|||
#define DDR_ODTCFG 0x06000600 |
|||
#define DDR_ODTMAP 0x00000001 |
|||
#define DDR_SCHED 0x00001201 |
|||
#define DDR_SCHED1 0x00000000 |
|||
#define DDR_PERFHPR1 0x01000001 |
|||
#define DDR_PERFLPR1 0x08000200 |
|||
#define DDR_PERFWR1 0x08000400 |
|||
#define DDR_DBG0 0x00000000 |
|||
#define DDR_DBG1 0x00000000 |
|||
#define DDR_DBGCMD 0x00000000 |
|||
#define DDR_POISONCFG 0x00000000 |
|||
#define DDR_PCCFG 0x00000010 |
|||
#define DDR_PCFGR_0 0x00010000 |
|||
#define DDR_PCFGW_0 0x00000000 |
|||
#define DDR_PCFGQOS0_0 0x02100B03 |
|||
#define DDR_PCFGQOS1_0 0x00800100 |
|||
#define DDR_PCFGWQOS0_0 0x01100B03 |
|||
#define DDR_PCFGWQOS1_0 0x01000200 |
|||
#define DDR_PCFGR_1 0x00010000 |
|||
#define DDR_PCFGW_1 0x00000000 |
|||
#define DDR_PCFGQOS0_1 0x02100B03 |
|||
#define DDR_PCFGQOS1_1 0x00800000 |
|||
#define DDR_PCFGWQOS0_1 0x01100B03 |
|||
#define DDR_PCFGWQOS1_1 0x01000200 |
|||
#define DDR_PGCR 0x01442E02 |
|||
#define DDR_PTR0 0x0022AA5B |
|||
#define DDR_PTR1 0x04841104 |
|||
#define DDR_PTR2 0x042DA068 |
|||
#define DDR_ACIOCR 0x10400812 |
|||
#define DDR_DXCCR 0x00000C40 |
|||
#define DDR_DSGCR 0xF200001F |
|||
#define DDR_DCR 0x0000000B |
|||
#define DDR_DTPR0 0x38D488D0 |
|||
#define DDR_DTPR1 0x098B00D8 |
|||
#define DDR_DTPR2 0x10023600 |
|||
#define DDR_MR0 0x00000840 |
|||
#define DDR_MR1 0x00000000 |
|||
#define DDR_MR2 0x00000208 |
|||
#define DDR_MR3 0x00000000 |
|||
#define DDR_ODTCR 0x00010000 |
|||
#define DDR_ZQ0CR1 0x00000038 |
|||
#define DDR_DX0GCR 0x0000CE81 |
|||
#define DDR_DX0DLLCR 0x40000000 |
|||
#define DDR_DX0DQTR 0xFFFFFFFF |
|||
#define DDR_DX0DQSTR 0x3DB02000 |
|||
#define DDR_DX1GCR 0x0000CE81 |
|||
#define DDR_DX1DLLCR 0x40000000 |
|||
#define DDR_DX1DQTR 0xFFFFFFFF |
|||
#define DDR_DX1DQSTR 0x3DB02000 |
|||
#define DDR_DX2GCR 0x0000CE81 |
|||
#define DDR_DX2DLLCR 0x40000000 |
|||
#define DDR_DX2DQTR 0xFFFFFFFF |
|||
#define DDR_DX2DQSTR 0x3DB02000 |
|||
#define DDR_DX3GCR 0x0000CE81 |
|||
#define DDR_DX3DLLCR 0x40000000 |
|||
#define DDR_DX3DQTR 0xFFFFFFFF |
|||
#define DDR_DX3DQSTR 0x3DB02000 |
|||
|
|||
#include "stm32mp15-ddr.dtsi" |
@ -0,0 +1,250 @@ |
|||
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
|||
/* |
|||
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved |
|||
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics. |
|||
*/ |
|||
|
|||
#include <dt-bindings/pinctrl/stm32-pinfunc.h> |
|||
/ { |
|||
soc { |
|||
pinctrl: pin-controller { |
|||
#address-cells = <1>; |
|||
#size-cells = <1>; |
|||
ranges = <0 0x50002000 0xa400>; |
|||
pins-are-numbered; |
|||
|
|||
gpioa: gpio@50002000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0x0 0x400>; |
|||
clocks = <&rcc GPIOA>; |
|||
st,bank-name = "GPIOA"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
gpiob: gpio@50003000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0x1000 0x400>; |
|||
clocks = <&rcc GPIOB>; |
|||
st,bank-name = "GPIOB"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
gpioc: gpio@50004000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0x2000 0x400>; |
|||
clocks = <&rcc GPIOC>; |
|||
st,bank-name = "GPIOC"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
gpiod: gpio@50005000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0x3000 0x400>; |
|||
clocks = <&rcc GPIOD>; |
|||
st,bank-name = "GPIOD"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
gpioe: gpio@50006000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0x4000 0x400>; |
|||
clocks = <&rcc GPIOE>; |
|||
st,bank-name = "GPIOE"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
gpiof: gpio@50007000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0x5000 0x400>; |
|||
clocks = <&rcc GPIOF>; |
|||
st,bank-name = "GPIOF"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
gpiog: gpio@50008000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0x6000 0x400>; |
|||
clocks = <&rcc GPIOG>; |
|||
st,bank-name = "GPIOG"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
gpioh: gpio@50009000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0x7000 0x400>; |
|||
clocks = <&rcc GPIOH>; |
|||
st,bank-name = "GPIOH"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
gpioi: gpio@5000a000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0x8000 0x400>; |
|||
clocks = <&rcc GPIOI>; |
|||
st,bank-name = "GPIOI"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
gpioj: gpio@5000b000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0x9000 0x400>; |
|||
clocks = <&rcc GPIOJ>; |
|||
st,bank-name = "GPIOJ"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
gpiok: gpio@5000c000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0xa000 0x400>; |
|||
clocks = <&rcc GPIOK>; |
|||
st,bank-name = "GPIOK"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
uart4_pins_a: uart4@0 { |
|||
pins1 { |
|||
pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */ |
|||
bias-disable; |
|||
drive-push-pull; |
|||
slew-rate = <0>; |
|||
}; |
|||
pins2 { |
|||
pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */ |
|||
bias-disable; |
|||
}; |
|||
}; |
|||
|
|||
usart3_pins_a: usart3@0 { |
|||
pins1 { |
|||
pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */ |
|||
<STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */ |
|||
bias-disable; |
|||
drive-push-pull; |
|||
slew-rate = <0>; |
|||
}; |
|||
pins2 { |
|||
pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */ |
|||
<STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */ |
|||
bias-disable; |
|||
}; |
|||
}; |
|||
|
|||
sdmmc1_b4_pins_a: sdmmc1-b4@0 { |
|||
pins { |
|||
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */ |
|||
<STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */ |
|||
<STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */ |
|||
<STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */ |
|||
<STM32_PINMUX('C', 12, AF12)>, /* SDMMC1_CK */ |
|||
<STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */ |
|||
slew-rate = <3>; |
|||
drive-push-pull; |
|||
bias-disable; |
|||
}; |
|||
}; |
|||
|
|||
sdmmc1_dir_pins_a: sdmmc1-dir@0 { |
|||
pins1 { |
|||
pinmux = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */ |
|||
<STM32_PINMUX('C', 7, AF8)>, /* SDMMC1_D123DIR */ |
|||
<STM32_PINMUX('B', 9, AF11)>; /* SDMMC1_CDIR */ |
|||
slew-rate = <3>; |
|||
drive-push-pull; |
|||
bias-pull-up; |
|||
}; |
|||
pins2{ |
|||
pinmux = <STM32_PINMUX('E', 4, AF8)>; /* SDMMC1_CKIN */ |
|||
bias-pull-up; |
|||
}; |
|||
}; |
|||
|
|||
sdmmc2_b4_pins_a: sdmmc2-b4@0 { |
|||
pins { |
|||
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */ |
|||
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */ |
|||
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */ |
|||
<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */ |
|||
<STM32_PINMUX('E', 3, AF9)>, /* SDMMC2_CK */ |
|||
<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */ |
|||
slew-rate = <3>; |
|||
drive-push-pull; |
|||
bias-pull-up; |
|||
}; |
|||
}; |
|||
|
|||
sdmmc2_d47_pins_a: sdmmc2-d47@0 { |
|||
pins { |
|||
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */ |
|||
<STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */ |
|||
<STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */ |
|||
<STM32_PINMUX('D', 3, AF9)>; /* SDMMC2_D7 */ |
|||
slew-rate = <3>; |
|||
drive-push-pull; |
|||
bias-pull-up; |
|||
}; |
|||
}; |
|||
}; |
|||
|
|||
pinctrl_z: pin-controller-z { |
|||
#address-cells = <1>; |
|||
#size-cells = <1>; |
|||
ranges = <0 0x54004000 0x400>; |
|||
pins-are-numbered; |
|||
|
|||
gpioz: gpio@54004000 { |
|||
gpio-controller; |
|||
#gpio-cells = <2>; |
|||
interrupt-controller; |
|||
#interrupt-cells = <2>; |
|||
reg = <0 0x400>; |
|||
clocks = <&rcc GPIOZ>; |
|||
st,bank-name = "GPIOZ"; |
|||
st,bank-ioport = <11>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
i2c4_pins_a: i2c4@0 { |
|||
pins { |
|||
pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */ |
|||
<STM32_PINMUX('Z', 5, AF6)>; /* I2C4_SDA */ |
|||
bias-disable; |
|||
drive-open-drain; |
|||
slew-rate = <0>; |
|||
}; |
|||
}; |
|||
}; |
|||
}; |
|||
}; |
@ -0,0 +1,246 @@ |
|||
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
|||
/* |
|||
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved |
|||
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics. |
|||
*/ |
|||
|
|||
/dts-v1/; |
|||
|
|||
#include "stm32mp157c.dtsi" |
|||
#include "stm32mp157caa-pinctrl.dtsi" |
|||
|
|||
/ { |
|||
model = "STMicroelectronics STM32MP157C-ED1 pmic eval daughter"; |
|||
compatible = "st,stm32mp157c-ed1", "st,stm32mp157"; |
|||
|
|||
chosen { |
|||
bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram"; |
|||
stdout-path = "serial3:115200n8"; |
|||
}; |
|||
}; |
|||
|
|||
&i2c4 { |
|||
pinctrl-names = "default"; |
|||
pinctrl-0 = <&i2c4_pins_a>; |
|||
i2c-scl-rising-time-ns = <185>; |
|||
i2c-scl-falling-time-ns = <20>; |
|||
status = "okay"; |
|||
|
|||
pmic: stpmu1@33 { |
|||
compatible = "st,stpmu1"; |
|||
reg = <0x33>; |
|||
status = "okay"; |
|||
|
|||
st,main_control_register = <0x04>; |
|||
st,vin_control_register = <0xc0>; |
|||
st,usb_control_register = <0x30>; |
|||
|
|||
regulators { |
|||
compatible = "st,stpmu1-regulators"; |
|||
|
|||
v3v3: buck4 { |
|||
regulator-name = "v3v3"; |
|||
regulator-min-microvolt = <3300000>; |
|||
regulator-max-microvolt = <3300000>; |
|||
regulator-boot-on; |
|||
regulator-over-current-protection; |
|||
regulator-initial-mode = <8>; |
|||
|
|||
regulator-state-standby { |
|||
regulator-suspend-microvolt = <3300000>; |
|||
regulator-unchanged-in-suspend; |
|||
regulator-mode = <8>; |
|||
}; |
|||
regulator-state-mem { |
|||
regulator-off-in-suspend; |
|||
}; |
|||
regulator-state-disk { |
|||
regulator-off-in-suspend; |
|||
}; |
|||
}; |
|||
|
|||
vdd_sd: ldo5 { |
|||
regulator-name = "vdd_sd"; |
|||
regulator-min-microvolt = <2900000>; |
|||
regulator-max-microvolt = <2900000>; |
|||
regulator-boot-on; |
|||
|
|||
regulator-state-standby { |
|||
regulator-suspend-microvolt = <2900000>; |
|||
regulator-unchanged-in-suspend; |
|||
}; |
|||
regulator-state-mem { |
|||
regulator-off-in-suspend; |
|||
}; |
|||
regulator-state-disk { |
|||
regulator-off-in-suspend; |
|||
}; |
|||
}; |
|||
}; |
|||
}; |
|||
}; |
|||
|
|||
&iwdg2 { |
|||
instance = <2>; |
|||
timeout-sec = <32>; |
|||
status = "okay"; |
|||
}; |
|||
|
|||
&rng1 { |
|||
status = "okay"; |
|||
}; |
|||
|
|||
&sdmmc1 { |
|||
pinctrl-names = "default"; |
|||
pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; |
|||
broken-cd; |
|||
st,dirpol; |
|||
st,negedge; |
|||
st,pin-ckin; |
|||
bus-width = <4>; |
|||
sd-uhs-sdr12; |
|||
sd-uhs-sdr25; |
|||
sd-uhs-sdr50; |
|||
sd-uhs-ddr50; |
|||
sd-uhs-sdr104; |
|||
status = "okay"; |
|||
}; |
|||
|
|||
&sdmmc2 { |
|||
pinctrl-names = "default"; |
|||
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; |
|||
non-removable; |
|||
no-sd; |
|||
no-sdio; |
|||
st,dirpol; |
|||
st,negedge; |
|||
bus-width = <8>; |
|||
status = "okay"; |
|||
}; |
|||
|
|||
&uart4 { |
|||
pinctrl-names = "default"; |
|||
pinctrl-0 = <&uart4_pins_a>; |
|||
resets = <&rcc UART4_R>; |
|||
status = "okay"; |
|||
}; |
|||
|
|||
/* ATF Specific */ |
|||
#include <dt-bindings/clock/stm32mp1-clksrc.h> |
|||
#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" |
|||
|
|||
/ { |
|||
aliases { |
|||
gpio0 = &gpioa; |
|||
gpio1 = &gpiob; |
|||
gpio2 = &gpioc; |
|||
gpio3 = &gpiod; |
|||
gpio4 = &gpioe; |
|||
gpio5 = &gpiof; |
|||
gpio6 = &gpiog; |
|||
gpio7 = &gpioh; |
|||
gpio8 = &gpioi; |
|||
gpio9 = &gpioj; |
|||
gpio10 = &gpiok; |
|||
gpio25 = &gpioz; |
|||
i2c3 = &i2c4; |
|||
}; |
|||
|
|||
soc { |
|||
stgen: stgen@5C008000 { |
|||
compatible = "st,stm32-stgen"; |
|||
reg = <0x5C008000 0x1000>; |
|||
status = "okay"; |
|||
}; |
|||
}; |
|||
}; |
|||
|
|||
/* CLOCK init */ |
|||
&rcc { |
|||
st,clksrc = < |
|||
CLK_MPU_PLL1P |
|||
CLK_AXI_PLL2P |
|||
CLK_PLL12_HSE |
|||
CLK_PLL3_HSE |
|||
CLK_PLL4_HSE |
|||
CLK_RTC_LSE |
|||
CLK_MCO1_DISABLED |
|||
CLK_MCO2_DISABLED |
|||
>; |
|||
|
|||
st,clkdiv = < |
|||
1 /*MPU*/ |
|||
0 /*AXI*/ |
|||
1 /*APB1*/ |
|||
1 /*APB2*/ |
|||
1 /*APB3*/ |
|||
1 /*APB4*/ |
|||
2 /*APB5*/ |
|||
23 /*RTC*/ |
|||
0 /*MCO1*/ |
|||
0 /*MCO2*/ |
|||
>; |
|||
|
|||
st,pkcs = < |
|||
CLK_CKPER_HSE |
|||
CLK_FMC_ACLK |
|||
CLK_QSPI_ACLK |
|||
CLK_ETH_DISABLED |
|||
CLK_SDMMC12_PLL3R |
|||
CLK_DSI_DSIPLL |
|||
CLK_STGEN_HSE |
|||
CLK_USBPHY_HSE |
|||
CLK_SPI2S1_PLL3Q |
|||
CLK_SPI2S23_PLL3Q |
|||
CLK_SPI45_HSI |
|||
CLK_SPI6_HSI |
|||
CLK_I2C46_HSI |
|||
CLK_SDMMC3_PLL3R |
|||
CLK_USBO_USBPHY |
|||
CLK_ADC_CKPER |
|||
CLK_CEC_LSE |
|||
CLK_I2C12_HSI |
|||
CLK_I2C35_HSI |
|||
CLK_UART1_HSI |
|||
CLK_UART24_HSI |
|||
CLK_UART35_HSI |
|||
CLK_UART6_HSI |
|||
CLK_UART78_HSI |
|||
CLK_SPDIF_PLL3Q |
|||
CLK_FDCAN_PLL4Q |
|||
CLK_SAI1_PLL3Q |
|||
CLK_SAI2_PLL3Q |
|||
CLK_SAI3_PLL3Q |
|||
CLK_SAI4_PLL3Q |
|||
CLK_RNG1_CSI |
|||
CLK_RNG2_CSI |
|||
CLK_LPTIM1_PCLK1 |
|||
CLK_LPTIM23_PCLK3 |
|||
CLK_LPTIM45_PCLK3 |
|||
>; |
|||
|
|||
/* VCO = 1300.0 MHz => P = 650 (CPU) */ |
|||
pll1: st,pll@0 { |
|||
cfg = < 2 80 0 0 0 PQR(1,0,0) >; |
|||
frac = < 0x800 >; |
|||
}; |
|||
|
|||
/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ |
|||
pll2: st,pll@1 { |
|||
cfg = < 2 65 1 0 0 PQR(1,1,1) >; |
|||
frac = < 0x1400 >; |
|||
}; |
|||
|
|||
/* VCO = 786.4 MHz => P = 197, Q = 49, R = 98 */ |
|||
pll3: st,pll@2 { |
|||
cfg = < 2 97 3 15 7 PQR(1,1,1) >; |
|||
frac = < 0x9ba >; |
|||
}; |
|||
|
|||
/* VCO = 508.0 MHz => P = 56, Q = 56, R = 56 */ |
|||
pll4: st,pll@3 { |
|||
cfg = < 5 126 8 8 8 PQR(1,1,1) >; |
|||
}; |
|||
}; |
|||
|
|||
/delete-node/ &clk_csi; |
@ -0,0 +1,25 @@ |
|||
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
|||
/* |
|||
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved |
|||
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics. |
|||
*/ |
|||
|
|||
/dts-v1/; |
|||
#include "stm32mp157c-ed1.dts" |
|||
|
|||
/ { |
|||
model = "STMicroelectronics STM32MP157C-EV1 pmic eval daughter on eval mother"; |
|||
compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; |
|||
|
|||
chosen { |
|||
bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram"; |
|||
stdout-path = "serial3:115200n8"; |
|||
}; |
|||
}; |
|||
|
|||
&usart3 { |
|||
pinctrl-names = "default"; |
|||
pinctrl-0 = <&usart3_pins_a>; |
|||
resets = <&rcc USART3_R>; |
|||
status = "disabled"; |
|||
}; |
@ -0,0 +1,240 @@ |
|||
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
|||
/* |
|||
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved |
|||
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics. |
|||
*/ |
|||
|
|||
#include <dt-bindings/clock/stm32mp1-clks.h> |
|||
#include <dt-bindings/reset/stm32mp1-resets.h> |
|||
|
|||
/ { |
|||
#address-cells = <1>; |
|||
#size-cells = <1>; |
|||
|
|||
aliases { |
|||
serial0 = &usart1; |
|||
serial1 = &usart2; |
|||
serial2 = &usart3; |
|||
serial3 = &uart4; |
|||
serial4 = &uart5; |
|||
serial5 = &usart6; |
|||
serial6 = &uart7; |
|||
serial7 = &uart8; |
|||
}; |
|||
|
|||
clocks { |
|||
clk_hse: clk-hse { |
|||
#clock-cells = <0>; |
|||
compatible = "fixed-clock"; |
|||
clock-frequency = <24000000>; |
|||
}; |
|||
|
|||
clk_hsi: clk-hsi { |
|||
#clock-cells = <0>; |
|||
compatible = "fixed-clock"; |
|||
clock-frequency = <64000000>; |
|||
}; |
|||
|
|||
clk_lse: clk-lse { |
|||
#clock-cells = <0>; |
|||
compatible = "fixed-clock"; |
|||
clock-frequency = <32768>; |
|||
}; |
|||
|
|||
clk_lsi: clk-lsi { |
|||
#clock-cells = <0>; |
|||
compatible = "fixed-clock"; |
|||
clock-frequency = <32000>; |
|||
}; |
|||
|
|||
clk_csi: clk-csi { |
|||
#clock-cells = <0>; |
|||
compatible = "fixed-clock"; |
|||
clock-frequency = <4000000>; |
|||
}; |
|||
|
|||
clk_i2s_ckin: i2s_ckin { |
|||
#clock-cells = <0>; |
|||
compatible = "fixed-clock"; |
|||
clock-frequency = <64000000>; |
|||
}; |
|||
|
|||
clk_dsi_phy: ck_dsi_phy { |
|||
#clock-cells = <0>; |
|||
compatible = "fixed-clock"; |
|||
clock-frequency = <0>; |
|||
}; |
|||
|
|||
clk_usbo_48m: ck_usbo_48m { |
|||
#clock-cells = <0>; |
|||
compatible = "fixed-clock"; |
|||
clock-frequency = <48000000>; |
|||
}; |
|||
}; |
|||
|
|||
soc { |
|||
compatible = "simple-bus"; |
|||
#address-cells = <1>; |
|||
#size-cells = <1>; |
|||
ranges; |
|||
|
|||
usart2: serial@4000e000 { |
|||
compatible = "st,stm32h7-usart"; |
|||
reg = <0x4000e000 0x400>; |
|||
clocks = <&rcc USART2_K>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
usart3: serial@4000f000 { |
|||
compatible = "st,stm32h7-usart"; |
|||
reg = <0x4000f000 0x400>; |
|||
clocks = <&rcc USART3_K>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
uart4: serial@40010000 { |
|||
compatible = "st,stm32h7-uart"; |
|||
reg = <0x40010000 0x400>; |
|||
clocks = <&rcc UART4_K>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
uart5: serial@40011000 { |
|||
compatible = "st,stm32h7-uart"; |
|||
reg = <0x40011000 0x400>; |
|||
clocks = <&rcc UART5_K>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
|
|||
uart7: serial@40018000 { |
|||
compatible = "st,stm32h7-uart"; |
|||
reg = <0x40018000 0x400>; |
|||
clocks = <&rcc UART7_K>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
uart8: serial@40019000 { |
|||
compatible = "st,stm32h7-uart"; |
|||
reg = <0x40019000 0x400>; |
|||
clocks = <&rcc UART8_K>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
usart6: serial@44003000 { |
|||
compatible = "st,stm32h7-usart"; |
|||
reg = <0x44003000 0x400>; |
|||
clocks = <&rcc USART6_K>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
sdmmc3: sdmmc@48004000 { |
|||
compatible = "st,stm32-sdmmc2"; |
|||
reg = <0x48004000 0x400>, <0x48005000 0x400>; |
|||
reg-names = "sdmmc", "delay"; |
|||
clocks = <&rcc SDMMC3_K>; |
|||
resets = <&rcc SDMMC3_R>; |
|||
cap-sd-highspeed; |
|||
cap-mmc-highspeed; |
|||
max-frequency = <120000000>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
rcc: rcc@50000000 { |
|||
compatible = "syscon", "st,stm32mp1-rcc"; |
|||
#clock-cells = <1>; |
|||
#reset-cells = <1>; |
|||
reg = <0x50000000 0x1000>; |
|||
}; |
|||
|
|||
rcc_reboot: rcc-reboot@50000000 { |
|||
compatible = "syscon-reboot"; |
|||
regmap = <&rcc>; |
|||
offset = <0x404>; |
|||
mask = <0x1>; |
|||
}; |
|||
|
|||
rng1: rng@54003000 { |
|||
compatible = "st,stm32-rng"; |
|||
reg = <0x54003000 0x400>; |
|||
clocks = <&rcc RNG1_K>; |
|||
resets = <&rcc RNG1_R>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
fmc_nand: fmc_nand@58002000 { |
|||
compatible = "st,stm32mp1-fmc"; |
|||
reg = <0x58002000 0x1000>, |
|||
<0x80000000 0x40000>, |
|||
<0x81000000 0x40000>, |
|||
<0x88000000 0x40000>, |
|||
<0x89000000 0x40000>; |
|||
clocks = <&rcc FMC_K>; |
|||
resets = <&rcc FMC_R>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
qspi: qspi@58003000 { |
|||
compatible = "st,stm32f469-qspi"; |
|||
reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; |
|||
clocks = <&rcc QSPI_K>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
sdmmc1: sdmmc@58005000 { |
|||
compatible = "st,stm32-sdmmc2"; |
|||
reg = <0x58005000 0x1000>, <0x58006000 0x1000>; |
|||
reg-names = "sdmmc", "delay"; |
|||
clocks = <&rcc SDMMC1_K>; |
|||
resets = <&rcc SDMMC1_R>; |
|||
cap-sd-highspeed; |
|||
cap-mmc-highspeed; |
|||
max-frequency = <120000000>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
sdmmc2: sdmmc@58007000 { |
|||
compatible = "st,stm32-sdmmc2"; |
|||
reg = <0x58007000 0x1000>, <0x58008000 0x1000>; |
|||
reg-names = "sdmmc", "delay"; |
|||
clocks = <&rcc SDMMC2_K>; |
|||
resets = <&rcc SDMMC2_R>; |
|||
cap-sd-highspeed; |
|||
cap-mmc-highspeed; |
|||
max-frequency = <120000000>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
iwdg2: iwdg@5a002000 { |
|||
compatible = "st,stm32mp1-iwdg"; |
|||
reg = <0x5a002000 0x400>; |
|||
clocks = <&rcc IWDG2>, <&rcc CK_LSI>; |
|||
clock-names = "pclk", "lsi"; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
usart1: serial@5c000000 { |
|||
compatible = "st,stm32h7-usart"; |
|||
reg = <0x5c000000 0x400>; |
|||
clocks = <&rcc USART1_K>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
i2c4: i2c@5c002000 { |
|||
compatible = "st,stm32f7-i2c"; |
|||
reg = <0x5c002000 0x400>; |
|||
clocks = <&rcc I2C4_K>; |
|||
resets = <&rcc I2C4_R>; |
|||
#address-cells = <1>; |
|||
#size-cells = <0>; |
|||
status = "disabled"; |
|||
}; |
|||
|
|||
rtc: rtc@5c004000 { |
|||
compatible = "st,stm32mp1-rtc"; |
|||
reg = <0x5c004000 0x400>; |
|||
clocks = <&rcc RTCAPB>, <&rcc RTC>; |
|||
clock-names = "pclk", "rtc_ck"; |
|||
}; |
|||
}; |
|||
}; |
@ -0,0 +1,90 @@ |
|||
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
|||
/* |
|||
* Copyright (C) STMicroelectronics 2018 - All Rights Reserved |
|||
* Author: Alexandre Torgue <alexandre.torgue@st.com> |
|||
*/ |
|||
|
|||
#include "stm32mp157-pinctrl.dtsi" |
|||
/ { |
|||
soc { |
|||
pinctrl: pin-controller { |
|||
compatible = "st,stm32mp157caa-pinctrl"; |
|||
|
|||
gpioa: gpio@50002000 { |
|||
status = "okay"; |
|||
ngpios = <16>; |
|||
gpio-ranges = <&pinctrl 0 0 16>; |
|||
}; |
|||
|
|||
gpiob: gpio@50003000 { |
|||
status = "okay"; |
|||
ngpios = <16>; |
|||
gpio-ranges = <&pinctrl 0 16 16>; |
|||
}; |
|||
|
|||
gpioc: gpio@50004000 { |
|||
status = "okay"; |
|||
ngpios = <16>; |
|||
gpio-ranges = <&pinctrl 0 32 16>; |
|||
}; |
|||
|
|||
gpiod: gpio@50005000 { |
|||
status = "okay"; |
|||
ngpios = <16>; |
|||
gpio-ranges = <&pinctrl 0 48 16>; |
|||
}; |
|||
|
|||
gpioe: gpio@50006000 { |
|||
status = "okay"; |
|||
ngpios = <16>; |
|||
gpio-ranges = <&pinctrl 0 64 16>; |
|||
}; |
|||
|
|||
gpiof: gpio@50007000 { |
|||
status = "okay"; |
|||
ngpios = <16>; |
|||
gpio-ranges = <&pinctrl 0 80 16>; |
|||
}; |
|||
|
|||
gpiog: gpio@50008000 { |
|||
status = "okay"; |
|||
ngpios = <16>; |
|||
gpio-ranges = <&pinctrl 0 96 16>; |
|||
}; |
|||
|
|||
gpioh: gpio@50009000 { |
|||
status = "okay"; |
|||
ngpios = <16>; |
|||
gpio-ranges = <&pinctrl 0 112 16>; |
|||
}; |
|||
|
|||
gpioi: gpio@5000a000 { |
|||
status = "okay"; |
|||
ngpios = <16>; |
|||
gpio-ranges = <&pinctrl 0 128 16>; |
|||
}; |
|||
|
|||
gpioj: gpio@5000b000 { |
|||
status = "okay"; |
|||
ngpios = <16>; |
|||
gpio-ranges = <&pinctrl 0 144 16>; |
|||
}; |
|||
|
|||
gpiok: gpio@5000c000 { |
|||
status = "okay"; |
|||
ngpios = <8>; |
|||
gpio-ranges = <&pinctrl 0 160 8>; |
|||
}; |
|||
}; |
|||
|
|||
pinctrl_z: pin-controller-z { |
|||
compatible = "st,stm32mp157caa-z-pinctrl"; |
|||
|
|||
gpioz: gpio@54004000 { |
|||
status = "okay"; |
|||
ngpios = <8>; |
|||
gpio-ranges = <&pinctrl_z 0 400 8>; |
|||
}; |
|||
}; |
|||
}; |
|||
}; |
@ -0,0 +1,101 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __PLAT_GPIO_H__ |
|||
#define __PLAT_GPIO_H__ |
|||
|
|||
#include <utils_def.h> |
|||
|
|||
#define STM32_GPIOA_BANK U(0x50002000) |
|||
#define STM32_GPIOZ_BANK U(0x54004000) |
|||
#define STM32_GPIO_BANK_OFFSET U(0x1000) |
|||
|
|||
#define GPIO_MODE_OFFSET U(0x00) |
|||
#define GPIO_TYPE_OFFSET U(0x04) |
|||
#define GPIO_SPEED_OFFSET U(0x08) |
|||
#define GPIO_PUPD_OFFSET U(0x0C) |
|||
#define GPIO_BSRR_OFFSET U(0x18) |
|||
#define GPIO_AFRL_OFFSET U(0x20) |
|||
#define GPIO_AFRH_OFFSET U(0x24) |
|||
|
|||
#define GPIO_ALT_LOWER_LIMIT U(0x08) |
|||
|
|||
#define GPIO_BANK_A U(0x00) |
|||
#define GPIO_BANK_B U(0x01) |
|||
#define GPIO_BANK_C U(0x02) |
|||
#define GPIO_BANK_D U(0x03) |
|||
#define GPIO_BANK_E U(0x04) |
|||
#define GPIO_BANK_F U(0x05) |
|||
#define GPIO_BANK_G U(0x06) |
|||
#define GPIO_BANK_H U(0x07) |
|||
#define GPIO_BANK_I U(0x08) |
|||
#define GPIO_BANK_J U(0x09) |
|||
#define GPIO_BANK_K U(0x0A) |
|||
#define GPIO_BANK_Z U(0x19) |
|||
|
|||
#define GPIO_PIN_0 U(0x00) |
|||
#define GPIO_PIN_1 U(0x01) |
|||
#define GPIO_PIN_2 U(0x02) |
|||
#define GPIO_PIN_3 U(0x03) |
|||
#define GPIO_PIN_4 U(0x04) |
|||
#define GPIO_PIN_5 U(0x05) |
|||
#define GPIO_PIN_6 U(0x06) |
|||
#define GPIO_PIN_7 U(0x07) |
|||
#define GPIO_PIN_8 U(0x08) |
|||
#define GPIO_PIN_9 U(0x09) |
|||
#define GPIO_PIN_10 U(0x0A) |
|||
#define GPIO_PIN_11 U(0x0B) |
|||
#define GPIO_PIN_12 U(0x0C) |
|||
#define GPIO_PIN_13 U(0x0D) |
|||
#define GPIO_PIN_14 U(0x0E) |
|||
#define GPIO_PIN_15 U(0x0F) |
|||
#define GPIO_PIN_MAX GPIO_PIN_15 |
|||
|
|||
#define GPIO_ALTERNATE_0 0x00 |
|||
#define GPIO_ALTERNATE_1 0x01 |
|||
#define GPIO_ALTERNATE_2 0x02 |
|||
#define GPIO_ALTERNATE_3 0x03 |
|||
#define GPIO_ALTERNATE_4 0x04 |
|||
#define GPIO_ALTERNATE_5 0x05 |
|||
#define GPIO_ALTERNATE_6 0x06 |
|||
#define GPIO_ALTERNATE_7 0x07 |
|||
#define GPIO_ALTERNATE_8 0x08 |
|||
#define GPIO_ALTERNATE_9 0x09 |
|||
#define GPIO_ALTERNATE_10 0x0A |
|||
#define GPIO_ALTERNATE_11 0x0B |
|||
#define GPIO_ALTERNATE_12 0x0C |
|||
#define GPIO_ALTERNATE_13 0x0D |
|||
#define GPIO_ALTERNATE_14 0x0E |
|||
#define GPIO_ALTERNATE_15 0x0F |
|||
#define GPIO_ALTERNATE_MASK U(0x0F) |
|||
|
|||
#define GPIO_MODE_INPUT 0x00 |
|||
#define GPIO_MODE_OUTPUT 0x01 |
|||
#define GPIO_MODE_ALTERNATE 0x02 |
|||
#define GPIO_MODE_ANALOG 0x03 |
|||
#define GPIO_MODE_MASK U(0x03) |
|||
|
|||
#define GPIO_OPEN_DRAIN U(0x10) |
|||
|
|||
#define GPIO_SPEED_LOW 0x00 |
|||
#define GPIO_SPEED_MEDIUM 0x01 |
|||
#define GPIO_SPEED_FAST 0x02 |
|||
#define GPIO_SPEED_HIGH 0x03 |
|||
#define GPIO_SPEED_MASK U(0x03) |
|||
|
|||
#define GPIO_NO_PULL 0x00 |
|||
#define GPIO_PULL_UP 0x01 |
|||
#define GPIO_PULL_DOWN 0x02 |
|||
#define GPIO_PULL_MASK U(0x03) |
|||
|
|||
#ifndef __ASSEMBLY__ |
|||
#include <stdint.h> |
|||
|
|||
void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, |
|||
uint32_t pull, uint32_t alternate); |
|||
#endif /*__ASSEMBLY__*/ |
|||
|
|||
#endif /*__PLAT_GPIO_H__*/ |
@ -0,0 +1,300 @@ |
|||
/*
|
|||
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_I2C_H |
|||
#define __STM32MP1_I2C_H |
|||
|
|||
#include <stdint.h> |
|||
#include <utils_def.h> |
|||
|
|||
/* Bit definition for I2C_CR1 register */ |
|||
#define I2C_CR1_PE BIT(0) |
|||
#define I2C_CR1_TXIE BIT(1) |
|||
#define I2C_CR1_RXIE BIT(2) |
|||
#define I2C_CR1_ADDRIE BIT(3) |
|||
#define I2C_CR1_NACKIE BIT(4) |
|||
#define I2C_CR1_STOPIE BIT(5) |
|||
#define I2C_CR1_TCIE BIT(6) |
|||
#define I2C_CR1_ERRIE BIT(7) |
|||
#define I2C_CR1_DNF GENMASK(11, 8) |
|||
#define I2C_CR1_ANFOFF BIT(12) |
|||
#define I2C_CR1_SWRST BIT(13) |
|||
#define I2C_CR1_TXDMAEN BIT(14) |
|||
#define I2C_CR1_RXDMAEN BIT(15) |
|||
#define I2C_CR1_SBC BIT(16) |
|||
#define I2C_CR1_NOSTRETCH BIT(17) |
|||
#define I2C_CR1_WUPEN BIT(18) |
|||
#define I2C_CR1_GCEN BIT(19) |
|||
#define I2C_CR1_SMBHEN BIT(22) |
|||
#define I2C_CR1_SMBDEN BIT(21) |
|||
#define I2C_CR1_ALERTEN BIT(22) |
|||
#define I2C_CR1_PECEN BIT(23) |
|||
|
|||
/* Bit definition for I2C_CR2 register */ |
|||
#define I2C_CR2_SADD GENMASK(9, 0) |
|||
#define I2C_CR2_RD_WRN BIT(10) |
|||
#define I2C_CR2_RD_WRN_OFFSET 10U |
|||
#define I2C_CR2_ADD10 BIT(11) |
|||
#define I2C_CR2_HEAD10R BIT(12) |
|||
#define I2C_CR2_START BIT(13) |
|||
#define I2C_CR2_STOP BIT(14) |
|||
#define I2C_CR2_NACK BIT(15) |
|||
#define I2C_CR2_NBYTES GENMASK(23, 16) |
|||
#define I2C_CR2_NBYTES_OFFSET 16U |
|||
#define I2C_CR2_RELOAD BIT(24) |
|||
#define I2C_CR2_AUTOEND BIT(25) |
|||
#define I2C_CR2_PECBYTE BIT(26) |
|||
|
|||
/* Bit definition for I2C_OAR1 register */ |
|||
#define I2C_OAR1_OA1 GENMASK(9, 0) |
|||
#define I2C_OAR1_OA1MODE BIT(10) |
|||
#define I2C_OAR1_OA1EN BIT(15) |
|||
|
|||
/* Bit definition for I2C_OAR2 register */ |
|||
#define I2C_OAR2_OA2 GENMASK(7, 1) |
|||
#define I2C_OAR2_OA2MSK GENMASK(10, 8) |
|||
#define I2C_OAR2_OA2NOMASK 0 |
|||
#define I2C_OAR2_OA2MASK01 BIT(8) |
|||
#define I2C_OAR2_OA2MASK02 BIT(9) |
|||
#define I2C_OAR2_OA2MASK03 GENMASK(9, 8) |
|||
#define I2C_OAR2_OA2MASK04 BIT(10) |
|||
#define I2C_OAR2_OA2MASK05 (BIT(8) | BIT(10)) |
|||
#define I2C_OAR2_OA2MASK06 (BIT(9) | BIT(10)) |
|||
#define I2C_OAR2_OA2MASK07 GENMASK(10, 8) |
|||
#define I2C_OAR2_OA2EN BIT(15) |
|||
|
|||
/* Bit definition for I2C_TIMINGR register */ |
|||
#define I2C_TIMINGR_SCLL GENMASK(7, 0) |
|||
#define I2C_TIMINGR_SCLH GENMASK(15, 8) |
|||
#define I2C_TIMINGR_SDADEL GENMASK(19, 16) |
|||
#define I2C_TIMINGR_SCLDEL GENMASK(23, 20) |
|||
#define I2C_TIMINGR_PRESC GENMASK(31, 28) |
|||
|
|||
/* Bit definition for I2C_TIMEOUTR register */ |
|||
#define I2C_TIMEOUTR_TIMEOUTA GENMASK(11, 0) |
|||
#define I2C_TIMEOUTR_TIDLE BIT(12) |
|||
#define I2C_TIMEOUTR_TIMOUTEN BIT(15) |
|||
#define I2C_TIMEOUTR_TIMEOUTB GENMASK(27, 16) |
|||
#define I2C_TIMEOUTR_TEXTEN BIT(31) |
|||
|
|||
/* Bit definition for I2C_ISR register */ |
|||
#define I2C_ISR_TXE BIT(0) |
|||
#define I2C_ISR_TXIS BIT(1) |
|||
#define I2C_ISR_RXNE BIT(2) |
|||
#define I2C_ISR_ADDR BIT(3) |
|||
#define I2C_ISR_NACKF BIT(4) |
|||
#define I2C_ISR_STOPF BIT(5) |
|||
#define I2C_ISR_TC BIT(6) |
|||
#define I2C_ISR_TCR BIT(7) |
|||
#define I2C_ISR_BERR BIT(8) |
|||
#define I2C_ISR_ARLO BIT(9) |
|||
#define I2C_ISR_OVR BIT(10) |
|||
#define I2C_ISR_PECERR BIT(11) |
|||
#define I2C_ISR_TIMEOUT BIT(12) |
|||
#define I2C_ISR_ALERT BIT(13) |
|||
#define I2C_ISR_BUSY BIT(15) |
|||
#define I2C_ISR_DIR BIT(16) |
|||
#define I2C_ISR_ADDCODE GENMASK(23, 17) |
|||
|
|||
/* Bit definition for I2C_ICR register */ |
|||
#define I2C_ICR_ADDRCF BIT(3) |
|||
#define I2C_ICR_NACKCF BIT(4) |
|||
#define I2C_ICR_STOPCF BIT(5) |
|||
#define I2C_ICR_BERRCF BIT(8) |
|||
#define I2C_ICR_ARLOCF BIT(9) |
|||
#define I2C_ICR_OVRCF BIT(10) |
|||
#define I2C_ICR_PECCF BIT(11) |
|||
#define I2C_ICR_TIMOUTCF BIT(12) |
|||
#define I2C_ICR_ALERTCF BIT(13) |
|||
|
|||
struct stm32_i2c_init_s { |
|||
uint32_t timing; /* Specifies the I2C_TIMINGR_register value
|
|||
* This parameter is calculated by referring |
|||
* to I2C initialization section in Reference |
|||
* manual. |
|||
*/ |
|||
|
|||
uint32_t own_address1; /* Specifies the first device own address.
|
|||
* This parameter can be a 7-bit or 10-bit |
|||
* address. |
|||
*/ |
|||
|
|||
uint32_t addressing_mode; /* Specifies if 7-bit or 10-bit addressing
|
|||
* mode is selected. |
|||
* This parameter can be a value of @ref |
|||
* I2C_ADDRESSING_MODE. |
|||
*/ |
|||
|
|||
uint32_t dual_address_mode; /* Specifies if dual addressing mode is
|
|||
* selected. |
|||
* This parameter can be a value of @ref |
|||
* I2C_DUAL_ADDRESSING_MODE. |
|||
*/ |
|||
|
|||
uint32_t own_address2; /* Specifies the second device own address
|
|||
* if dual addressing mode is selected. |
|||
* This parameter can be a 7-bit address. |
|||
*/ |
|||
|
|||
uint32_t own_address2_masks; /* Specifies the acknowledge mask address
|
|||
* second device own address if dual |
|||
* addressing mode is selected. |
|||
* This parameter can be a value of @ref |
|||
* I2C_OWN_ADDRESS2_MASKS. |
|||
*/ |
|||
|
|||
uint32_t general_call_mode; /* Specifies if general call mode is
|
|||
* selected. |
|||
* This parameter can be a value of @ref |
|||
* I2C_GENERAL_CALL_ADDRESSING_MODE. |
|||
*/ |
|||
|
|||
uint32_t no_stretch_mode; /* Specifies if nostretch mode is
|
|||
* selected. |
|||
* This parameter can be a value of @ref |
|||
* I2C_NOSTRETCH_MODE. |
|||
*/ |
|||
|
|||
}; |
|||
|
|||
enum i2c_state_e { |
|||
I2C_STATE_RESET = 0x00U, /* Peripheral is not yet
|
|||
* initialized. |
|||
*/ |
|||
I2C_STATE_READY = 0x20U, /* Peripheral Initialized
|
|||
* and ready for use. |
|||
*/ |
|||
I2C_STATE_BUSY = 0x24U, /* An internal process is
|
|||
* ongoing. |
|||
*/ |
|||
I2C_STATE_BUSY_TX = 0x21U, /* Data Transmission process
|
|||
* is ongoing. |
|||
*/ |
|||
I2C_STATE_BUSY_RX = 0x22U, /* Data Reception process
|
|||
* is ongoing. |
|||
*/ |
|||
I2C_STATE_LISTEN = 0x28U, /* Address Listen Mode is
|
|||
* ongoing. |
|||
*/ |
|||
I2C_STATE_BUSY_TX_LISTEN = 0x29U, /* Address Listen Mode
|
|||
* and Data Transmission |
|||
* process is ongoing. |
|||
*/ |
|||
I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /* Address Listen Mode
|
|||
* and Data Reception |
|||
* process is ongoing. |
|||
*/ |
|||
I2C_STATE_ABORT = 0x60U, /* Abort user request ongoing. */ |
|||
I2C_STATE_TIMEOUT = 0xA0U, /* Timeout state. */ |
|||
I2C_STATE_ERROR = 0xE0U /* Error. */ |
|||
|
|||
}; |
|||
|
|||
enum i2c_mode_e { |
|||
I2C_MODE_NONE = 0x00U, /* No I2C communication on going. */ |
|||
I2C_MODE_MASTER = 0x10U, /* I2C communication is in Master Mode. */ |
|||
I2C_MODE_SLAVE = 0x20U, /* I2C communication is in Slave Mode. */ |
|||
I2C_MODE_MEM = 0x40U /* I2C communication is in Memory Mode. */ |
|||
|
|||
}; |
|||
|
|||
#define I2C_ERROR_NONE 0x00000000U /* No error */ |
|||
#define I2C_ERROR_BERR 0x00000001U /* BERR error */ |
|||
#define I2C_ERROR_ARLO 0x00000002U /* ARLO error */ |
|||
#define I2C_ERROR_AF 0x00000004U /* ACKF error */ |
|||
#define I2C_ERROR_OVR 0x00000008U /* OVR error */ |
|||
#define I2C_ERROR_DMA 0x00000010U /* DMA transfer error */ |
|||
#define I2C_ERROR_TIMEOUT 0x00000020U /* Timeout error */ |
|||
#define I2C_ERROR_SIZE 0x00000040U /* Size Management error */ |
|||
|
|||
struct i2c_handle_s { |
|||
uint32_t i2c_base_addr; /* Registers base address */ |
|||
|
|||
struct stm32_i2c_init_s i2c_init; /* Communication parameters */ |
|||
|
|||
uint8_t *p_buff; /* Pointer to transfer buffer */ |
|||
|
|||
uint16_t xfer_size; /* Transfer size */ |
|||
|
|||
uint16_t xfer_count; /* Transfer counter */ |
|||
|
|||
uint32_t prev_state; /* Communication previous
|
|||
* state |
|||
*/ |
|||
|
|||
uint8_t lock; /* Locking object */ |
|||
|
|||
enum i2c_state_e i2c_state; /* Communication state */ |
|||
|
|||
enum i2c_mode_e i2c_mode; /* Communication mode */ |
|||
|
|||
uint32_t i2c_err; /* Error code */ |
|||
}; |
|||
|
|||
#define I2C_ADDRESSINGMODE_7BIT 0x00000001U |
|||
#define I2C_ADDRESSINGMODE_10BIT 0x00000002U |
|||
|
|||
#define I2C_DUALADDRESS_DISABLE 0x00000000U |
|||
#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN |
|||
|
|||
#define I2C_GENERALCALL_DISABLE 0x00000000U |
|||
#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN |
|||
|
|||
#define I2C_NOSTRETCH_DISABLE 0x00000000U |
|||
#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH |
|||
|
|||
#define I2C_MEMADD_SIZE_8BIT 0x00000001U |
|||
#define I2C_MEMADD_SIZE_16BIT 0x00000002U |
|||
|
|||
#define I2C_RELOAD_MODE I2C_CR2_RELOAD |
|||
#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND |
|||
#define I2C_SOFTEND_MODE 0x00000000U |
|||
|
|||
#define I2C_NO_STARTSTOP 0x00000000U |
|||
#define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP) |
|||
#define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \ |
|||
I2C_CR2_RD_WRN) |
|||
#define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START) |
|||
|
|||
#define I2C_FLAG_TXE I2C_ISR_TXE |
|||
#define I2C_FLAG_TXIS I2C_ISR_TXIS |
|||
#define I2C_FLAG_RXNE I2C_ISR_RXNE |
|||
#define I2C_FLAG_ADDR I2C_ISR_ADDR |
|||
#define I2C_FLAG_AF I2C_ISR_NACKF |
|||
#define I2C_FLAG_STOPF I2C_ISR_STOPF |
|||
#define I2C_FLAG_TC I2C_ISR_TC |
|||
#define I2C_FLAG_TCR I2C_ISR_TCR |
|||
#define I2C_FLAG_BERR I2C_ISR_BERR |
|||
#define I2C_FLAG_ARLO I2C_ISR_ARLO |
|||
#define I2C_FLAG_OVR I2C_ISR_OVR |
|||
#define I2C_FLAG_PECERR I2C_ISR_PECERR |
|||
#define I2C_FLAG_TIMEOUT I2C_ISR_TIMEOUT |
|||
#define I2C_FLAG_ALERT I2C_ISR_ALERT |
|||
#define I2C_FLAG_BUSY I2C_ISR_BUSY |
|||
#define I2C_FLAG_DIR I2C_ISR_DIR |
|||
|
|||
#define I2C_RESET_CR2 (I2C_CR2_SADD | I2C_CR2_HEAD10R | \ |
|||
I2C_CR2_NBYTES | I2C_CR2_RELOAD | \ |
|||
I2C_CR2_RD_WRN) |
|||
|
|||
#define I2C_ANALOGFILTER_ENABLE ((uint32_t)0x00000000U) |
|||
#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF |
|||
|
|||
int stm32_i2c_init(struct i2c_handle_s *hi2c); |
|||
|
|||
int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, |
|||
uint16_t mem_addr, uint16_t mem_add_size, |
|||
uint8_t *p_data, uint16_t size, uint32_t timeout); |
|||
int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, |
|||
uint16_t mem_addr, uint16_t mem_add_size, |
|||
uint8_t *p_data, uint16_t size, uint32_t timeout); |
|||
int stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr, |
|||
uint32_t trials, uint32_t timeout); |
|||
|
|||
int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c, |
|||
uint32_t analog_filter); |
|||
|
|||
#endif /* __STM32MP1_I2C_H */ |
@ -0,0 +1,30 @@ |
|||
/*
|
|||
* Copyright (c) 2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_CLK_H__ |
|||
#define __STM32MP1_CLK_H__ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <stdbool.h> |
|||
|
|||
int stm32mp1_clk_probe(void); |
|||
int stm32mp1_clk_init(void); |
|||
bool stm32mp1_clk_is_enabled(unsigned long id); |
|||
int stm32mp1_clk_enable(unsigned long id); |
|||
int stm32mp1_clk_disable(unsigned long id); |
|||
unsigned long stm32mp1_clk_get_rate(unsigned long id); |
|||
void stm32mp1_stgen_increment(unsigned long long offset_in_ms); |
|||
|
|||
static inline uint32_t get_timer(uint32_t base) |
|||
{ |
|||
if (base == 0U) { |
|||
return (uint32_t)(~read_cntpct_el0()); |
|||
} |
|||
|
|||
return base - (uint32_t)(~read_cntpct_el0()); |
|||
} |
|||
|
|||
#endif /* __STM32MP1_CLK_H__ */ |
@ -0,0 +1,42 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_CLKFUNC_H__ |
|||
#define __STM32MP1_CLKFUNC_H__ |
|||
|
|||
#include <stdbool.h> |
|||
|
|||
enum stm32mp_osc_id { |
|||
_HSI, |
|||
_HSE, |
|||
_CSI, |
|||
_LSI, |
|||
_LSE, |
|||
_I2S_CKIN, |
|||
_USB_PHY_48, |
|||
NB_OSC, |
|||
_UNKNOWN_OSC_ID = 0xFF |
|||
}; |
|||
|
|||
extern const char *stm32mp_osc_node_label[NB_OSC]; |
|||
|
|||
int fdt_osc_read_freq(const char *name, uint32_t *freq); |
|||
bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name); |
|||
uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, |
|||
const char *prop_name, |
|||
uint32_t dflt_value); |
|||
|
|||
uint32_t fdt_rcc_read_addr(void); |
|||
int fdt_rcc_read_uint32_array(const char *prop_name, |
|||
uint32_t *array, uint32_t count); |
|||
int fdt_rcc_subnode_offset(const char *name); |
|||
const uint32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp); |
|||
bool fdt_get_rcc_secure_status(void); |
|||
|
|||
uintptr_t fdt_get_stgen_base(void); |
|||
int fdt_get_clock_id(int node); |
|||
|
|||
#endif /* __STM32MP1_CLKFUNC_H__ */ |
@ -0,0 +1,173 @@ |
|||
/*
|
|||
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef _STM32MP1_DDR_H |
|||
#define _STM32MP1_DDR_H |
|||
|
|||
#include <stdbool.h> |
|||
|
|||
#define DT_DDR_COMPAT "st,stm32mp1-ddr" |
|||
|
|||
struct stm32mp1_ddr_size { |
|||
uint64_t base; |
|||
uint64_t size; |
|||
}; |
|||
|
|||
/**
|
|||
* struct ddr_info |
|||
* |
|||
* @dev: pointer for the device |
|||
* @info: UCLASS RAM information |
|||
* @ctl: DDR controleur base address |
|||
* @phy: DDR PHY base address |
|||
* @syscfg: syscfg base address |
|||
*/ |
|||
struct ddr_info { |
|||
struct stm32mp1_ddr_size info; |
|||
struct stm32mp1_ddrctl *ctl; |
|||
struct stm32mp1_ddrphy *phy; |
|||
uintptr_t pwr; |
|||
uintptr_t rcc; |
|||
}; |
|||
|
|||
struct stm32mp1_ddrctrl_reg { |
|||
uint32_t mstr; |
|||
uint32_t mrctrl0; |
|||
uint32_t mrctrl1; |
|||
uint32_t derateen; |
|||
uint32_t derateint; |
|||
uint32_t pwrctl; |
|||
uint32_t pwrtmg; |
|||
uint32_t hwlpctl; |
|||
uint32_t rfshctl0; |
|||
uint32_t rfshctl3; |
|||
uint32_t crcparctl0; |
|||
uint32_t zqctl0; |
|||
uint32_t dfitmg0; |
|||
uint32_t dfitmg1; |
|||
uint32_t dfilpcfg0; |
|||
uint32_t dfiupd0; |
|||
uint32_t dfiupd1; |
|||
uint32_t dfiupd2; |
|||
uint32_t dfiphymstr; |
|||
uint32_t odtmap; |
|||
uint32_t dbg0; |
|||
uint32_t dbg1; |
|||
uint32_t dbgcmd; |
|||
uint32_t poisoncfg; |
|||
uint32_t pccfg; |
|||
}; |
|||
|
|||
struct stm32mp1_ddrctrl_timing { |
|||
uint32_t rfshtmg; |
|||
uint32_t dramtmg0; |
|||
uint32_t dramtmg1; |
|||
uint32_t dramtmg2; |
|||
uint32_t dramtmg3; |
|||
uint32_t dramtmg4; |
|||
uint32_t dramtmg5; |
|||
uint32_t dramtmg6; |
|||
uint32_t dramtmg7; |
|||
uint32_t dramtmg8; |
|||
uint32_t dramtmg14; |
|||
uint32_t odtcfg; |
|||
}; |
|||
|
|||
struct stm32mp1_ddrctrl_map { |
|||
uint32_t addrmap1; |
|||
uint32_t addrmap2; |
|||
uint32_t addrmap3; |
|||
uint32_t addrmap4; |
|||
uint32_t addrmap5; |
|||
uint32_t addrmap6; |
|||
uint32_t addrmap9; |
|||
uint32_t addrmap10; |
|||
uint32_t addrmap11; |
|||
}; |
|||
|
|||
struct stm32mp1_ddrctrl_perf { |
|||
uint32_t sched; |
|||
uint32_t sched1; |
|||
uint32_t perfhpr1; |
|||
uint32_t perflpr1; |
|||
uint32_t perfwr1; |
|||
uint32_t pcfgr_0; |
|||
uint32_t pcfgw_0; |
|||
uint32_t pcfgqos0_0; |
|||
uint32_t pcfgqos1_0; |
|||
uint32_t pcfgwqos0_0; |
|||
uint32_t pcfgwqos1_0; |
|||
uint32_t pcfgr_1; |
|||
uint32_t pcfgw_1; |
|||
uint32_t pcfgqos0_1; |
|||
uint32_t pcfgqos1_1; |
|||
uint32_t pcfgwqos0_1; |
|||
uint32_t pcfgwqos1_1; |
|||
}; |
|||
|
|||
struct stm32mp1_ddrphy_reg { |
|||
uint32_t pgcr; |
|||
uint32_t aciocr; |
|||
uint32_t dxccr; |
|||
uint32_t dsgcr; |
|||
uint32_t dcr; |
|||
uint32_t odtcr; |
|||
uint32_t zq0cr1; |
|||
uint32_t dx0gcr; |
|||
uint32_t dx1gcr; |
|||
uint32_t dx2gcr; |
|||
uint32_t dx3gcr; |
|||
}; |
|||
|
|||
struct stm32mp1_ddrphy_timing { |
|||
uint32_t ptr0; |
|||
uint32_t ptr1; |
|||
uint32_t ptr2; |
|||
uint32_t dtpr0; |
|||
uint32_t dtpr1; |
|||
uint32_t dtpr2; |
|||
uint32_t mr0; |
|||
uint32_t mr1; |
|||
uint32_t mr2; |
|||
uint32_t mr3; |
|||
}; |
|||
|
|||
struct stm32mp1_ddrphy_cal { |
|||
uint32_t dx0dllcr; |
|||
uint32_t dx0dqtr; |
|||
uint32_t dx0dqstr; |
|||
uint32_t dx1dllcr; |
|||
uint32_t dx1dqtr; |
|||
uint32_t dx1dqstr; |
|||
uint32_t dx2dllcr; |
|||
uint32_t dx2dqtr; |
|||
uint32_t dx2dqstr; |
|||
uint32_t dx3dllcr; |
|||
uint32_t dx3dqtr; |
|||
uint32_t dx3dqstr; |
|||
}; |
|||
|
|||
struct stm32mp1_ddr_info { |
|||
const char *name; |
|||
uint16_t speed; /* in MHZ */ |
|||
uint32_t size; /* Memory size in byte = col * row * width */ |
|||
}; |
|||
|
|||
struct stm32mp1_ddr_config { |
|||
struct stm32mp1_ddr_info info; |
|||
struct stm32mp1_ddrctrl_reg c_reg; |
|||
struct stm32mp1_ddrctrl_timing c_timing; |
|||
struct stm32mp1_ddrctrl_map c_map; |
|||
struct stm32mp1_ddrctrl_perf c_perf; |
|||
struct stm32mp1_ddrphy_reg p_reg; |
|||
struct stm32mp1_ddrphy_timing p_timing; |
|||
struct stm32mp1_ddrphy_cal p_cal; |
|||
}; |
|||
|
|||
int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed); |
|||
void stm32mp1_ddr_init(struct ddr_info *priv, |
|||
struct stm32mp1_ddr_config *config); |
|||
#endif /* _STM32MP1_DDR_H */ |
@ -0,0 +1,12 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_DDR_HELPERS_H__ |
|||
#define __STM32MP1_DDR_HELPERS_H__ |
|||
|
|||
void ddr_enable_clock(void); |
|||
|
|||
#endif /* __STM32MP1_DDR_HELPERS_H__ */ |
@ -0,0 +1,413 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef _RAM_STM32MP1_DDR_REGS_H |
|||
#define _RAM_STM32MP1_DDR_REGS_H |
|||
|
|||
#include <utils_def.h> |
|||
|
|||
/* DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL) registers */ |
|||
struct stm32mp1_ddrctl { |
|||
uint32_t mstr ; /* 0x0 Master */ |
|||
uint32_t stat; /* 0x4 Operating Mode Status */ |
|||
uint8_t reserved008[0x10 - 0x8]; |
|||
uint32_t mrctrl0; /* 0x10 Control 0 */ |
|||
uint32_t mrctrl1; /* 0x14 Control 1 */ |
|||
uint32_t mrstat; /* 0x18 Status */ |
|||
uint32_t reserved01c; /* 0x1c */ |
|||
uint32_t derateen; /* 0x20 Temperature Derate Enable */ |
|||
uint32_t derateint; /* 0x24 Temperature Derate Interval */ |
|||
uint8_t reserved028[0x30 - 0x28]; |
|||
uint32_t pwrctl; /* 0x30 Low Power Control */ |
|||
uint32_t pwrtmg; /* 0x34 Low Power Timing */ |
|||
uint32_t hwlpctl; /* 0x38 Hardware Low Power Control */ |
|||
uint8_t reserved03c[0x50 - 0x3C]; |
|||
uint32_t rfshctl0; /* 0x50 Refresh Control 0 */ |
|||
uint32_t reserved054; /* 0x54 Refresh Control 1 */ |
|||
uint32_t reserved058; /* 0x58 Refresh Control 2 */ |
|||
uint32_t reserved05C; |
|||
uint32_t rfshctl3; /* 0x60 Refresh Control 0 */ |
|||
uint32_t rfshtmg; /* 0x64 Refresh Timing */ |
|||
uint8_t reserved068[0xc0 - 0x68]; |
|||
uint32_t crcparctl0; /* 0xc0 CRC Parity Control0 */ |
|||
uint32_t reserved0c4; /* 0xc4 CRC Parity Control1 */ |
|||
uint32_t reserved0c8; /* 0xc8 CRC Parity Control2 */ |
|||
uint32_t crcparstat; /* 0xcc CRC Parity Status */ |
|||
uint32_t init0; /* 0xd0 SDRAM Initialization 0 */ |
|||
uint32_t init1; /* 0xd4 SDRAM Initialization 1 */ |
|||
uint32_t init2; /* 0xd8 SDRAM Initialization 2 */ |
|||
uint32_t init3; /* 0xdc SDRAM Initialization 3 */ |
|||
uint32_t init4; /* 0xe0 SDRAM Initialization 4 */ |
|||
uint32_t init5; /* 0xe4 SDRAM Initialization 5 */ |
|||
uint32_t reserved0e8; |
|||
uint32_t reserved0ec; |
|||
uint32_t dimmctl; /* 0xf0 DIMM Control */ |
|||
uint8_t reserved0f4[0x100 - 0xf4]; |
|||
uint32_t dramtmg0; /* 0x100 SDRAM Timing 0 */ |
|||
uint32_t dramtmg1; /* 0x104 SDRAM Timing 1 */ |
|||
uint32_t dramtmg2; /* 0x108 SDRAM Timing 2 */ |
|||
uint32_t dramtmg3; /* 0x10c SDRAM Timing 3 */ |
|||
uint32_t dramtmg4; /* 0x110 SDRAM Timing 4 */ |
|||
uint32_t dramtmg5; /* 0x114 SDRAM Timing 5 */ |
|||
uint32_t dramtmg6; /* 0x118 SDRAM Timing 6 */ |
|||
uint32_t dramtmg7; /* 0x11c SDRAM Timing 7 */ |
|||
uint32_t dramtmg8; /* 0x120 SDRAM Timing 8 */ |
|||
uint8_t reserved124[0x138 - 0x124]; |
|||
uint32_t dramtmg14; /* 0x138 SDRAM Timing 14 */ |
|||
uint32_t dramtmg15; /* 0x13C SDRAM Timing 15 */ |
|||
uint8_t reserved140[0x180 - 0x140]; |
|||
uint32_t zqctl0; /* 0x180 ZQ Control 0 */ |
|||
uint32_t zqctl1; /* 0x184 ZQ Control 1 */ |
|||
uint32_t zqctl2; /* 0x188 ZQ Control 2 */ |
|||
uint32_t zqstat; /* 0x18c ZQ Status */ |
|||
uint32_t dfitmg0; /* 0x190 DFI Timing 0 */ |
|||
uint32_t dfitmg1; /* 0x194 DFI Timing 1 */ |
|||
uint32_t dfilpcfg0; /* 0x198 DFI Low Power Configuration 0 */ |
|||
uint32_t reserved19c; |
|||
uint32_t dfiupd0; /* 0x1a0 DFI Update 0 */ |
|||
uint32_t dfiupd1; /* 0x1a4 DFI Update 1 */ |
|||
uint32_t dfiupd2; /* 0x1a8 DFI Update 2 */ |
|||
uint32_t reserved1ac; |
|||
uint32_t dfimisc; /* 0x1b0 DFI Miscellaneous Control */ |
|||
uint8_t reserved1b4[0x1bc - 0x1b4]; |
|||
uint32_t dfistat; /* 0x1bc DFI Miscellaneous Control */ |
|||
uint8_t reserved1c0[0x1c4 - 0x1c0]; |
|||
uint32_t dfiphymstr; /* 0x1c4 DFI PHY Master interface */ |
|||
uint8_t reserved1c8[0x204 - 0x1c8]; |
|||
uint32_t addrmap1; /* 0x204 Address Map 1 */ |
|||
uint32_t addrmap2; /* 0x208 Address Map 2 */ |
|||
uint32_t addrmap3; /* 0x20c Address Map 3 */ |
|||
uint32_t addrmap4; /* 0x210 Address Map 4 */ |
|||
uint32_t addrmap5; /* 0x214 Address Map 5 */ |
|||
uint32_t addrmap6; /* 0x218 Address Map 6 */ |
|||
uint8_t reserved21c[0x224 - 0x21c]; |
|||
uint32_t addrmap9; /* 0x224 Address Map 9 */ |
|||
uint32_t addrmap10; /* 0x228 Address Map 10 */ |
|||
uint32_t addrmap11; /* 0x22C Address Map 11 */ |
|||
uint8_t reserved230[0x240 - 0x230]; |
|||
uint32_t odtcfg; /* 0x240 ODT Configuration */ |
|||
uint32_t odtmap; /* 0x244 ODT/Rank Map */ |
|||
uint8_t reserved248[0x250 - 0x248]; |
|||
uint32_t sched; /* 0x250 Scheduler Control */ |
|||
uint32_t sched1; /* 0x254 Scheduler Control 1 */ |
|||
uint32_t reserved258; |
|||
uint32_t perfhpr1; /* 0x25c High Priority Read CAM 1 */ |
|||
uint32_t reserved260; |
|||
uint32_t perflpr1; /* 0x264 Low Priority Read CAM 1 */ |
|||
uint32_t reserved268; |
|||
uint32_t perfwr1; /* 0x26c Write CAM 1 */ |
|||
uint8_t reserved27c[0x300 - 0x270]; |
|||
uint32_t dbg0; /* 0x300 Debug 0 */ |
|||
uint32_t dbg1; /* 0x304 Debug 1 */ |
|||
uint32_t dbgcam; /* 0x308 CAM Debug */ |
|||
uint32_t dbgcmd; /* 0x30c Command Debug */ |
|||
uint32_t dbgstat; /* 0x310 Status Debug */ |
|||
uint8_t reserved314[0x320 - 0x314]; |
|||
uint32_t swctl; /* 0x320 Software Programming Control Enable */ |
|||
uint32_t swstat; /* 0x324 Software Programming Control Status */ |
|||
uint8_t reserved328[0x36c - 0x328]; |
|||
uint32_t poisoncfg; /* 0x36c AXI Poison Configuration Register */ |
|||
uint32_t poisonstat; /* 0x370 AXI Poison Status Register */ |
|||
uint8_t reserved374[0x3fc - 0x374]; |
|||
|
|||
/* Multi Port registers */ |
|||
uint32_t pstat; /* 0x3fc Port Status */ |
|||
uint32_t pccfg; /* 0x400 Port Common Configuration */ |
|||
|
|||
/* PORT 0 */ |
|||
uint32_t pcfgr_0; /* 0x404 Configuration Read */ |
|||
uint32_t pcfgw_0; /* 0x408 Configuration Write */ |
|||
uint8_t reserved40c[0x490 - 0x40c]; |
|||
uint32_t pctrl_0; /* 0x490 Port Control Register */ |
|||
uint32_t pcfgqos0_0; /* 0x494 Read QoS Configuration 0 */ |
|||
uint32_t pcfgqos1_0; /* 0x498 Read QoS Configuration 1 */ |
|||
uint32_t pcfgwqos0_0; /* 0x49c Write QoS Configuration 0 */ |
|||
uint32_t pcfgwqos1_0; /* 0x4a0 Write QoS Configuration 1 */ |
|||
uint8_t reserved4a4[0x4b4 - 0x4a4]; |
|||
|
|||
/* PORT 1 */ |
|||
uint32_t pcfgr_1; /* 0x4b4 Configuration Read */ |
|||
uint32_t pcfgw_1; /* 0x4b8 Configuration Write */ |
|||
uint8_t reserved4bc[0x540 - 0x4bc]; |
|||
uint32_t pctrl_1; /* 0x540 Port 2 Control Register */ |
|||
uint32_t pcfgqos0_1; /* 0x544 Read QoS Configuration 0 */ |
|||
uint32_t pcfgqos1_1; /* 0x548 Read QoS Configuration 1 */ |
|||
uint32_t pcfgwqos0_1; /* 0x54c Write QoS Configuration 0 */ |
|||
uint32_t pcfgwqos1_1; /* 0x550 Write QoS Configuration 1 */ |
|||
} __packed; |
|||
|
|||
/* DDR Physical Interface Control (DDRPHYC) registers*/ |
|||
struct stm32mp1_ddrphy { |
|||
uint32_t ridr; /* 0x00 R Revision Identification */ |
|||
uint32_t pir; /* 0x04 R/W PHY Initialization */ |
|||
uint32_t pgcr; /* 0x08 R/W PHY General Configuration */ |
|||
uint32_t pgsr; /* 0x0C PHY General Status */ |
|||
uint32_t dllgcr; /* 0x10 R/W DLL General Control */ |
|||
uint32_t acdllcr; /* 0x14 R/W AC DLL Control */ |
|||
uint32_t ptr0; /* 0x18 R/W PHY Timing 0 */ |
|||
uint32_t ptr1; /* 0x1C R/W PHY Timing 1 */ |
|||
uint32_t ptr2; /* 0x20 R/W PHY Timing 2 */ |
|||
uint32_t aciocr; /* 0x24 AC I/O Configuration */ |
|||
uint32_t dxccr; /* 0x28 DATX8 Common Configuration */ |
|||
uint32_t dsgcr; /* 0x2C DDR System General Configuration */ |
|||
uint32_t dcr; /* 0x30 DRAM Configuration */ |
|||
uint32_t dtpr0; /* 0x34 DRAM Timing Parameters0 */ |
|||
uint32_t dtpr1; /* 0x38 DRAM Timing Parameters1 */ |
|||
uint32_t dtpr2; /* 0x3C DRAM Timing Parameters2 */ |
|||
uint32_t mr0; /* 0x40 Mode 0 */ |
|||
uint32_t mr1; /* 0x44 Mode 1 */ |
|||
uint32_t mr2; /* 0x48 Mode 2 */ |
|||
uint32_t mr3; /* 0x4C Mode 3 */ |
|||
uint32_t odtcr; /* 0x50 ODT Configuration */ |
|||
uint32_t dtar; /* 0x54 data training address */ |
|||
uint32_t dtdr0; /* 0x58 */ |
|||
uint32_t dtdr1; /* 0x5c */ |
|||
uint8_t res1[0x0c0 - 0x060]; /* 0x60 */ |
|||
uint32_t dcuar; /* 0xc0 Address */ |
|||
uint32_t dcudr; /* 0xc4 DCU Data */ |
|||
uint32_t dcurr; /* 0xc8 DCU Run */ |
|||
uint32_t dculr; /* 0xcc DCU Loop */ |
|||
uint32_t dcugcr; /* 0xd0 DCU General Configuration */ |
|||
uint32_t dcutpr; /* 0xd4 DCU Timing Parameters */ |
|||
uint32_t dcusr0; /* 0xd8 DCU Status 0 */ |
|||
uint32_t dcusr1; /* 0xdc DCU Status 1 */ |
|||
uint8_t res2[0x100 - 0xe0]; /* 0xe0 */ |
|||
uint32_t bistrr; /* 0x100 BIST Run */ |
|||
uint32_t bistmskr0; /* 0x104 BIST Mask 0 */ |
|||
uint32_t bistmskr1; /* 0x108 BIST Mask 0 */ |
|||
uint32_t bistwcr; /* 0x10c BIST Word Count */ |
|||
uint32_t bistlsr; /* 0x110 BIST LFSR Seed */ |
|||
uint32_t bistar0; /* 0x114 BIST Address 0 */ |
|||
uint32_t bistar1; /* 0x118 BIST Address 1 */ |
|||
uint32_t bistar2; /* 0x11c BIST Address 2 */ |
|||
uint32_t bistupdr; /* 0x120 BIST User Data Pattern */ |
|||
uint32_t bistgsr; /* 0x124 BIST General Status */ |
|||
uint32_t bistwer; /* 0x128 BIST Word Error */ |
|||
uint32_t bistber0; /* 0x12c BIST Bit Error 0 */ |
|||
uint32_t bistber1; /* 0x130 BIST Bit Error 1 */ |
|||
uint32_t bistber2; /* 0x134 BIST Bit Error 2 */ |
|||
uint32_t bistwcsr; /* 0x138 BIST Word Count Status */ |
|||
uint32_t bistfwr0; /* 0x13c BIST Fail Word 0 */ |
|||
uint32_t bistfwr1; /* 0x140 BIST Fail Word 1 */ |
|||
uint8_t res3[0x178 - 0x144]; /* 0x144 */ |
|||
uint32_t gpr0; /* 0x178 General Purpose 0 (GPR0) */ |
|||
uint32_t gpr1; /* 0x17C General Purpose 1 (GPR1) */ |
|||
uint32_t zq0cr0; /* 0x180 zq 0 control 0 */ |
|||
uint32_t zq0cr1; /* 0x184 zq 0 control 1 */ |
|||
uint32_t zq0sr0; /* 0x188 zq 0 status 0 */ |
|||
uint32_t zq0sr1; /* 0x18C zq 0 status 1 */ |
|||
uint8_t res4[0x1C0 - 0x190]; /* 0x190 */ |
|||
uint32_t dx0gcr; /* 0x1c0 Byte lane 0 General Configuration */ |
|||
uint32_t dx0gsr0; /* 0x1c4 Byte lane 0 General Status 0 */ |
|||
uint32_t dx0gsr1; /* 0x1c8 Byte lane 0 General Status 1 */ |
|||
uint32_t dx0dllcr; /* 0x1cc Byte lane 0 DLL Control */ |
|||
uint32_t dx0dqtr; /* 0x1d0 Byte lane 0 DQ Timing */ |
|||
uint32_t dx0dqstr; /* 0x1d4 Byte lane 0 DQS Timing */ |
|||
uint8_t res5[0x200 - 0x1d8]; /* 0x1d8 */ |
|||
uint32_t dx1gcr; /* 0x200 Byte lane 1 General Configuration */ |
|||
uint32_t dx1gsr0; /* 0x204 Byte lane 1 General Status 0 */ |
|||
uint32_t dx1gsr1; /* 0x208 Byte lane 1 General Status 1 */ |
|||
uint32_t dx1dllcr; /* 0x20c Byte lane 1 DLL Control */ |
|||
uint32_t dx1dqtr; /* 0x210 Byte lane 1 DQ Timing */ |
|||
uint32_t dx1dqstr; /* 0x214 Byte lane 1 QS Timing */ |
|||
uint8_t res6[0x240 - 0x218]; /* 0x218 */ |
|||
uint32_t dx2gcr; /* 0x240 Byte lane 2 General Configuration */ |
|||
uint32_t dx2gsr0; /* 0x244 Byte lane 2 General Status 0 */ |
|||
uint32_t dx2gsr1; /* 0x248 Byte lane 2 General Status 1 */ |
|||
uint32_t dx2dllcr; /* 0x24c Byte lane 2 DLL Control */ |
|||
uint32_t dx2dqtr; /* 0x250 Byte lane 2 DQ Timing */ |
|||
uint32_t dx2dqstr; /* 0x254 Byte lane 2 QS Timing */ |
|||
uint8_t res7[0x280 - 0x258]; /* 0x258 */ |
|||
uint32_t dx3gcr; /* 0x280 Byte lane 3 General Configuration */ |
|||
uint32_t dx3gsr0; /* 0x284 Byte lane 3 General Status 0 */ |
|||
uint32_t dx3gsr1; /* 0x288 Byte lane 3 General Status 1 */ |
|||
uint32_t dx3dllcr; /* 0x28c Byte lane 3 DLL Control */ |
|||
uint32_t dx3dqtr; /* 0x290 Byte lane 3 DQ Timing */ |
|||
uint32_t dx3dqstr; /* 0x294 Byte lane 3 QS Timing */ |
|||
} __packed; |
|||
|
|||
/* DDR Controller registers offsets */ |
|||
#define DDRCTRL_MSTR 0x000 |
|||
#define DDRCTRL_STAT 0x004 |
|||
#define DDRCTRL_MRCTRL0 0x010 |
|||
#define DDRCTRL_MRSTAT 0x018 |
|||
#define DDRCTRL_PWRCTL 0x030 |
|||
#define DDRCTRL_PWRTMG 0x034 |
|||
#define DDRCTRL_HWLPCTL 0x038 |
|||
#define DDRCTRL_RFSHCTL3 0x060 |
|||
#define DDRCTRL_RFSHTMG 0x064 |
|||
#define DDRCTRL_INIT0 0x0D0 |
|||
#define DDRCTRL_DFIMISC 0x1B0 |
|||
#define DDRCTRL_DBG1 0x304 |
|||
#define DDRCTRL_DBGCAM 0x308 |
|||
#define DDRCTRL_DBGCMD 0x30C |
|||
#define DDRCTRL_DBGSTAT 0x310 |
|||
#define DDRCTRL_SWCTL 0x320 |
|||
#define DDRCTRL_SWSTAT 0x324 |
|||
#define DDRCTRL_PCTRL_0 0x490 |
|||
#define DDRCTRL_PCTRL_1 0x540 |
|||
|
|||
/* DDR Controller Register fields */ |
|||
#define DDRCTRL_MSTR_DDR3 BIT(0) |
|||
#define DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK GENMASK(13, 12) |
|||
#define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL 0 |
|||
#define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF BIT(12) |
|||
#define DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER BIT(13) |
|||
#define DDRCTRL_MSTR_DLL_OFF_MODE BIT(15) |
|||
|
|||
#define DDRCTRL_STAT_OPERATING_MODE_MASK GENMASK(2, 0) |
|||
#define DDRCTRL_STAT_OPERATING_MODE_NORMAL BIT(0) |
|||
#define DDRCTRL_STAT_OPERATING_MODE_SR (BIT(0) | BIT(1)) |
|||
#define DDRCTRL_STAT_SELFREF_TYPE_MASK GENMASK(5, 4) |
|||
#define DDRCTRL_STAT_SELFREF_TYPE_ASR (BIT(4) | BIT(5)) |
|||
#define DDRCTRL_STAT_SELFREF_TYPE_SR BIT(5) |
|||
|
|||
#define DDRCTRL_MRCTRL0_MR_TYPE_WRITE U(0) |
|||
/* Only one rank supported */ |
|||
#define DDRCTRL_MRCTRL0_MR_RANK_SHIFT 4 |
|||
#define DDRCTRL_MRCTRL0_MR_RANK_ALL \ |
|||
(0x1U << DDRCTRL_MRCTRL0_MR_RANK_SHIFT) |
|||
#define DDRCTRL_MRCTRL0_MR_ADDR_SHIFT 12 |
|||
#define DDRCTRL_MRCTRL0_MR_ADDR_MASK GENMASK(15, 12) |
|||
#define DDRCTRL_MRCTRL0_MR_WR BIT(31) |
|||
|
|||
#define DDRCTRL_MRSTAT_MR_WR_BUSY BIT(0) |
|||
|
|||
#define DDRCTRL_PWRCTL_SELFREF_EN BIT(0) |
|||
#define DDRCTRL_PWRCTL_POWERDOWN_EN BIT(1) |
|||
#define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE BIT(3) |
|||
#define DDRCTRL_PWRCTL_SELFREF_SW BIT(5) |
|||
|
|||
#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(19, 12) |
|||
#define DDRCTRL_PWRTMG_SELFREF_TO_X32_0 BIT(16) |
|||
|
|||
#define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH BIT(0) |
|||
|
|||
#define DDRCTRL_HWLPCTL_HW_LP_EN BIT(0) |
|||
|
|||
#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK GENMASK(27, 16) |
|||
#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT 16 |
|||
|
|||
#define DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK GENMASK(31, 30) |
|||
#define DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL BIT(30) |
|||
|
|||
#define DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0) |
|||
|
|||
#define DDRCTRL_DBG1_DIS_HIF BIT(1) |
|||
|
|||
#define DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY BIT(29) |
|||
#define DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY BIT(28) |
|||
#define DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY BIT(26) |
|||
#define DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH GENMASK(12, 8) |
|||
#define DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH GENMASK(4, 0) |
|||
#define DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY \ |
|||
(DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY | \ |
|||
DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY) |
|||
#define DDRCTRL_DBGCAM_DBG_Q_DEPTH \ |
|||
(DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY | \ |
|||
DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH | \ |
|||
DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH) |
|||
|
|||
#define DDRCTRL_DBGCMD_RANK0_REFRESH BIT(0) |
|||
|
|||
#define DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY BIT(0) |
|||
|
|||
#define DDRCTRL_SWCTL_SW_DONE BIT(0) |
|||
|
|||
#define DDRCTRL_SWSTAT_SW_DONE_ACK BIT(0) |
|||
|
|||
#define DDRCTRL_PCTRL_N_PORT_EN BIT(0) |
|||
|
|||
/* DDR PHY registers offsets */ |
|||
#define DDRPHYC_PIR 0x004 |
|||
#define DDRPHYC_PGCR 0x008 |
|||
#define DDRPHYC_PGSR 0x00C |
|||
#define DDRPHYC_DLLGCR 0x010 |
|||
#define DDRPHYC_ACDLLCR 0x014 |
|||
#define DDRPHYC_PTR0 0x018 |
|||
#define DDRPHYC_ACIOCR 0x024 |
|||
#define DDRPHYC_DXCCR 0x028 |
|||
#define DDRPHYC_DSGCR 0x02C |
|||
#define DDRPHYC_ZQ0CR0 0x180 |
|||
#define DDRPHYC_DX0GCR 0x1C0 |
|||
#define DDRPHYC_DX0DLLCR 0x1CC |
|||
#define DDRPHYC_DX1GCR 0x200 |
|||
#define DDRPHYC_DX1DLLCR 0x20C |
|||
#define DDRPHYC_DX2GCR 0x240 |
|||
#define DDRPHYC_DX2DLLCR 0x24C |
|||
#define DDRPHYC_DX3GCR 0x280 |
|||
#define DDRPHYC_DX3DLLCR 0x28C |
|||
|
|||
/* DDR PHY Register fields */ |
|||
#define DDRPHYC_PIR_INIT BIT(0) |
|||
#define DDRPHYC_PIR_DLLSRST BIT(1) |
|||
#define DDRPHYC_PIR_DLLLOCK BIT(2) |
|||
#define DDRPHYC_PIR_ZCAL BIT(3) |
|||
#define DDRPHYC_PIR_ITMSRST BIT(4) |
|||
#define DDRPHYC_PIR_DRAMRST BIT(5) |
|||
#define DDRPHYC_PIR_DRAMINIT BIT(6) |
|||
#define DDRPHYC_PIR_QSTRN BIT(7) |
|||
#define DDRPHYC_PIR_ICPC BIT(16) |
|||
#define DDRPHYC_PIR_ZCALBYP BIT(30) |
|||
#define DDRPHYC_PIR_INITSTEPS_MASK GENMASK(31, 7) |
|||
|
|||
#define DDRPHYC_PGCR_DFTCMP BIT(2) |
|||
#define DDRPHYC_PGCR_PDDISDX BIT(24) |
|||
#define DDRPHYC_PGCR_RFSHDT_MASK GENMASK(28, 25) |
|||
|
|||
#define DDRPHYC_PGSR_IDONE BIT(0) |
|||
#define DDRPHYC_PGSR_DTERR BIT(5) |
|||
#define DDRPHYC_PGSR_DTIERR BIT(6) |
|||
#define DDRPHYC_PGSR_DFTERR BIT(7) |
|||
#define DDRPHYC_PGSR_RVERR BIT(8) |
|||
#define DDRPHYC_PGSR_RVEIRR BIT(9) |
|||
|
|||
#define DDRPHYC_DLLGCR_BPS200 BIT(23) |
|||
|
|||
#define DDRPHYC_ACDLLCR_DLLDIS BIT(31) |
|||
|
|||
#define DDRPHYC_PTR0_TDLLSRST_OFFSET 0 |
|||
#define DDRPHYC_PTR0_TDLLSRST_MASK GENMASK(5, 0) |
|||
#define DDRPHYC_PTR0_TDLLLOCK_OFFSET 6 |
|||
#define DDRPHYC_PTR0_TDLLLOCK_MASK GENMASK(17, 6) |
|||
#define DDRPHYC_PTR0_TITMSRST_OFFSET 18 |
|||
#define DDRPHYC_PTR0_TITMSRST_MASK GENMASK(21, 18) |
|||
|
|||
#define DDRPHYC_ACIOCR_ACPDD BIT(3) |
|||
#define DDRPHYC_ACIOCR_ACPDR BIT(4) |
|||
#define DDRPHYC_ACIOCR_CKPDD_MASK GENMASK(10, 8) |
|||
#define DDRPHYC_ACIOCR_CKPDD_0 BIT(8) |
|||
#define DDRPHYC_ACIOCR_CKPDR_MASK GENMASK(13, 11) |
|||
#define DDRPHYC_ACIOCR_CKPDR_0 BIT(11) |
|||
#define DDRPHYC_ACIOCR_CSPDD_MASK GENMASK(21, 18) |
|||
#define DDRPHYC_ACIOCR_CSPDD_0 BIT(18) |
|||
#define DDRPHYC_ACIOCR_RSTPDD BIT(27) |
|||
#define DDRPHYC_ACIOCR_RSTPDR BIT(28) |
|||
|
|||
#define DDRPHYC_DXCCR_DXPDD BIT(2) |
|||
#define DDRPHYC_DXCCR_DXPDR BIT(3) |
|||
|
|||
#define DDRPHYC_DSGCR_CKEPDD_MASK GENMASK(19, 16) |
|||
#define DDRPHYC_DSGCR_CKEPDD_0 BIT(16) |
|||
#define DDRPHYC_DSGCR_ODTPDD_MASK GENMASK(23, 20) |
|||
#define DDRPHYC_DSGCR_ODTPDD_0 BIT(20) |
|||
#define DDRPHYC_DSGCR_NL2PD BIT(24) |
|||
|
|||
#define DDRPHYC_ZQ0CRN_ZDATA_MASK GENMASK(27, 0) |
|||
#define DDRPHYC_ZQ0CRN_ZDATA_SHIFT 0 |
|||
#define DDRPHYC_ZQ0CRN_ZDEN BIT(28) |
|||
#define DDRPHYC_ZQ0CRN_ZQPD BIT(31) |
|||
|
|||
#define DDRPHYC_DXNGCR_DXEN BIT(0) |
|||
|
|||
#define DDRPHYC_DXNDLLCR_DLLSRST BIT(30) |
|||
#define DDRPHYC_DXNDLLCR_DLLDIS BIT(31) |
|||
#define DDRPHYC_DXNDLLCR_SDPHASE_MASK GENMASK(17, 14) |
|||
#define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT 14 |
|||
|
|||
void ddr_enable_clock(void); |
|||
|
|||
#endif /* _RAM_STM32MP1_DDR_REGS_H */ |
@ -0,0 +1,18 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_PMIC_H__ |
|||
#define __STM32MP1_PMIC_H__ |
|||
|
|||
#include <stdbool.h> |
|||
|
|||
bool dt_check_pmic(void); |
|||
int dt_pmic_enable_boot_on_regulators(void); |
|||
void initialize_pmic_i2c(void); |
|||
void initialize_pmic(void); |
|||
int pmic_ddr_power_init(enum ddr_type ddr_type); |
|||
|
|||
#endif /* __STM32MP1_PMIC_H__ */ |
@ -0,0 +1,32 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_PWR_H__ |
|||
#define __STM32MP1_PWR_H__ |
|||
|
|||
#include <utils_def.h> |
|||
|
|||
#define PWR_CR1 U(0x00) |
|||
#define PWR_CR2 U(0x08) |
|||
#define PWR_CR3 U(0x0C) |
|||
#define PWR_MPUCR U(0x10) |
|||
#define PWR_WKUPCR U(0x20) |
|||
#define PWR_MPUWKUPENR U(0x28) |
|||
|
|||
#define PWR_CR1_LPDS BIT(0) |
|||
#define PWR_CR1_LPCFG BIT(1) |
|||
#define PWR_CR1_LVDS BIT(2) |
|||
#define PWR_CR1_DBP BIT(8) |
|||
|
|||
#define PWR_CR3_DDRSREN BIT(10) |
|||
#define PWR_CR3_DDRSRDIS BIT(11) |
|||
#define PWR_CR3_DDRRETEN BIT(12) |
|||
|
|||
#define PWR_MPUCR_PDDS BIT(0) |
|||
#define PWR_MPUCR_CSTDBYDIS BIT(3) |
|||
#define PWR_MPUCR_CSSF BIT(9) |
|||
|
|||
#endif /* __STM32MP1_PWR_H__ */ |
@ -0,0 +1,12 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef _STM32MP1_RAM_H |
|||
#define _STM32MP1_RAM_H |
|||
|
|||
int stm32mp1_ddr_probe(void); |
|||
|
|||
#endif /* _STM32MP1_RAM_H */ |
@ -0,0 +1,368 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_RCC_H__ |
|||
#define __STM32MP1_RCC_H__ |
|||
|
|||
#include <utils_def.h> |
|||
|
|||
#define RCC_TZCR U(0x00) |
|||
#define RCC_OCENSETR U(0x0C) |
|||
#define RCC_OCENCLRR U(0x10) |
|||
#define RCC_HSICFGR U(0x18) |
|||
#define RCC_CSICFGR U(0x1C) |
|||
#define RCC_MPCKSELR U(0x20) |
|||
#define RCC_ASSCKSELR U(0x24) |
|||
#define RCC_RCK12SELR U(0x28) |
|||
#define RCC_MPCKDIVR U(0x2C) |
|||
#define RCC_AXIDIVR U(0x30) |
|||
#define RCC_APB4DIVR U(0x3C) |
|||
#define RCC_APB5DIVR U(0x40) |
|||
#define RCC_RTCDIVR U(0x44) |
|||
#define RCC_MSSCKSELR U(0x48) |
|||
#define RCC_PLL1CR U(0x80) |
|||
#define RCC_PLL1CFGR1 U(0x84) |
|||
#define RCC_PLL1CFGR2 U(0x88) |
|||
#define RCC_PLL1FRACR U(0x8C) |
|||
#define RCC_PLL1CSGR U(0x90) |
|||
#define RCC_PLL2CR U(0x94) |
|||
#define RCC_PLL2CFGR1 U(0x98) |
|||
#define RCC_PLL2CFGR2 U(0x9C) |
|||
#define RCC_PLL2FRACR U(0xA0) |
|||
#define RCC_PLL2CSGR U(0xA4) |
|||
#define RCC_I2C46CKSELR U(0xC0) |
|||
#define RCC_SPI6CKSELR U(0xC4) |
|||
#define RCC_UART1CKSELR U(0xC8) |
|||
#define RCC_RNG1CKSELR U(0xCC) |
|||
#define RCC_CPERCKSELR U(0xD0) |
|||
#define RCC_STGENCKSELR U(0xD4) |
|||
#define RCC_DDRITFCR U(0xD8) |
|||
#define RCC_MP_BOOTCR U(0x100) |
|||
#define RCC_MP_SREQSETR U(0x104) |
|||
#define RCC_MP_SREQCLRR U(0x108) |
|||
#define RCC_MP_GCR U(0x10C) |
|||
#define RCC_MP_APRSTCR U(0x110) |
|||
#define RCC_MP_APRSTSR U(0x114) |
|||
#define RCC_BDCR U(0x140) |
|||
#define RCC_RDLSICR U(0x144) |
|||
#define RCC_APB4RSTSETR U(0x180) |
|||
#define RCC_APB4RSTCLRR U(0x184) |
|||
#define RCC_APB5RSTSETR U(0x188) |
|||
#define RCC_APB5RSTCLRR U(0x18C) |
|||
#define RCC_AHB5RSTSETR U(0x190) |
|||
#define RCC_AHB5RSTCLRR U(0x194) |
|||
#define RCC_AHB6RSTSETR U(0x198) |
|||
#define RCC_AHB6RSTCLRR U(0x19C) |
|||
#define RCC_TZAHB6RSTSETR U(0x1A0) |
|||
#define RCC_TZAHB6RSTCLRR U(0x1A4) |
|||
#define RCC_MP_APB4ENSETR U(0x200) |
|||
#define RCC_MP_APB4ENCLRR U(0x204) |
|||
#define RCC_MP_APB5ENSETR U(0x208) |
|||
#define RCC_MP_APB5ENCLRR U(0x20C) |
|||
#define RCC_MP_AHB5ENSETR U(0x210) |
|||
#define RCC_MP_AHB5ENCLRR U(0x214) |
|||
#define RCC_MP_AHB6ENSETR U(0x218) |
|||
#define RCC_MP_AHB6ENCLRR U(0x21C) |
|||
#define RCC_MP_TZAHB6ENSETR U(0x220) |
|||
#define RCC_MP_TZAHB6ENCLRR U(0x224) |
|||
#define RCC_MP_APB4LPENSETR U(0x300) |
|||
#define RCC_MP_APB4LPENCLRR U(0x304) |
|||
#define RCC_MP_APB5LPENSETR U(0x308) |
|||
#define RCC_MP_APB5LPENCLRR U(0x30C) |
|||
#define RCC_MP_AHB5LPENSETR U(0x310) |
|||
#define RCC_MP_AHB5LPENCLRR U(0x314) |
|||
#define RCC_MP_AHB6LPENSETR U(0x318) |
|||
#define RCC_MP_AHB6LPENCLRR U(0x31C) |
|||
#define RCC_MP_TZAHB6LPENSETR U(0x320) |
|||
#define RCC_MP_TZAHB6LPENCLRR U(0x324) |
|||
#define RCC_BR_RSTSCLRR U(0x400) |
|||
#define RCC_MP_GRSTCSETR U(0x404) |
|||
#define RCC_MP_RSTSCLRR U(0x408) |
|||
#define RCC_MP_IWDGFZSETR U(0x40C) |
|||
#define RCC_MP_IWDGFZCLRR U(0x410) |
|||
#define RCC_MP_CIER U(0x414) |
|||
#define RCC_MP_CIFR U(0x418) |
|||
#define RCC_PWRLPDLYCR U(0x41C) |
|||
#define RCC_MP_RSTSSETR U(0x420) |
|||
#define RCC_MCO1CFGR U(0x800) |
|||
#define RCC_MCO2CFGR U(0x804) |
|||
#define RCC_OCRDYR U(0x808) |
|||
#define RCC_DBGCFGR U(0x80C) |
|||
#define RCC_RCK3SELR U(0x820) |
|||
#define RCC_RCK4SELR U(0x824) |
|||
#define RCC_TIMG1PRER U(0x828) |
|||
#define RCC_TIMG2PRER U(0x82C) |
|||
#define RCC_APB1DIVR U(0x834) |
|||
#define RCC_APB2DIVR U(0x838) |
|||
#define RCC_APB3DIVR U(0x83C) |
|||
#define RCC_PLL3CR U(0x880) |
|||
#define RCC_PLL3CFGR1 U(0x884) |
|||
#define RCC_PLL3CFGR2 U(0x888) |
|||
#define RCC_PLL3FRACR U(0x88C) |
|||
#define RCC_PLL3CSGR U(0x890) |
|||
#define RCC_PLL4CR U(0x894) |
|||
#define RCC_PLL4CFGR1 U(0x898) |
|||
#define RCC_PLL4CFGR2 U(0x89C) |
|||
#define RCC_PLL4FRACR U(0x8A0) |
|||
#define RCC_PLL4CSGR U(0x8A4) |
|||
#define RCC_I2C12CKSELR U(0x8C0) |
|||
#define RCC_I2C35CKSELR U(0x8C4) |
|||
#define RCC_SAI1CKSELR U(0x8C8) |
|||
#define RCC_SAI2CKSELR U(0x8CC) |
|||
#define RCC_SAI3CKSELR U(0x8D0) |
|||
#define RCC_SAI4CKSELR U(0x8D4) |
|||
#define RCC_SPI2S1CKSELR U(0x8D8) |
|||
#define RCC_SPI2S23CKSELR U(0x8DC) |
|||
#define RCC_SPI45CKSELR U(0x8E0) |
|||
#define RCC_UART6CKSELR U(0x8E4) |
|||
#define RCC_UART24CKSELR U(0x8E8) |
|||
#define RCC_UART35CKSELR U(0x8EC) |
|||
#define RCC_UART78CKSELR U(0x8F0) |
|||
#define RCC_SDMMC12CKSELR U(0x8F4) |
|||
#define RCC_SDMMC3CKSELR U(0x8F8) |
|||
#define RCC_ETHCKSELR U(0x8FC) |
|||
#define RCC_QSPICKSELR U(0x900) |
|||
#define RCC_FMCCKSELR U(0x904) |
|||
#define RCC_FDCANCKSELR U(0x90C) |
|||
#define RCC_SPDIFCKSELR U(0x914) |
|||
#define RCC_CECCKSELR U(0x918) |
|||
#define RCC_USBCKSELR U(0x91C) |
|||
#define RCC_RNG2CKSELR U(0x920) |
|||
#define RCC_DSICKSELR U(0x924) |
|||
#define RCC_ADCCKSELR U(0x928) |
|||
#define RCC_LPTIM45CKSELR U(0x92C) |
|||
#define RCC_LPTIM23CKSELR U(0x930) |
|||
#define RCC_LPTIM1CKSELR U(0x934) |
|||
#define RCC_APB1RSTSETR U(0x980) |
|||
#define RCC_APB1RSTCLRR U(0x984) |
|||
#define RCC_APB2RSTSETR U(0x988) |
|||
#define RCC_APB2RSTCLRR U(0x98C) |
|||
#define RCC_APB3RSTSETR U(0x990) |
|||
#define RCC_APB3RSTCLRR U(0x994) |
|||
#define RCC_AHB2RSTSETR U(0x998) |
|||
#define RCC_AHB2RSTCLRR U(0x99C) |
|||
#define RCC_AHB3RSTSETR U(0x9A0) |
|||
#define RCC_AHB3RSTCLRR U(0x9A4) |
|||
#define RCC_AHB4RSTSETR U(0x9A8) |
|||
#define RCC_AHB4RSTCLRR U(0x9AC) |
|||
#define RCC_MP_APB1ENSETR U(0xA00) |
|||
#define RCC_MP_APB1ENCLRR U(0xA04) |
|||
#define RCC_MP_APB2ENSETR U(0xA08) |
|||
#define RCC_MP_APB2ENCLRR U(0xA0C) |
|||
#define RCC_MP_APB3ENSETR U(0xA10) |
|||
#define RCC_MP_APB3ENCLRR U(0xA14) |
|||
#define RCC_MP_AHB2ENSETR U(0xA18) |
|||
#define RCC_MP_AHB2ENCLRR U(0xA1C) |
|||
#define RCC_MP_AHB3ENSETR U(0xA20) |
|||
#define RCC_MP_AHB3ENCLRR U(0xA24) |
|||
#define RCC_MP_AHB4ENSETR U(0xA28) |
|||
#define RCC_MP_AHB4ENCLRR U(0xA2C) |
|||
#define RCC_MP_MLAHBENSETR U(0xA38) |
|||
#define RCC_MP_MLAHBENCLRR U(0xA3C) |
|||
#define RCC_MP_APB1LPENSETR U(0xB00) |
|||
#define RCC_MP_APB1LPENCLRR U(0xB04) |
|||
#define RCC_MP_APB2LPENSETR U(0xB08) |
|||
#define RCC_MP_APB2LPENCLRR U(0xB0C) |
|||
#define RCC_MP_APB3LPENSETR U(0xB10) |
|||
#define RCC_MP_APB3LPENCLRR U(0xB14) |
|||
#define RCC_MP_AHB2LPENSETR U(0xB18) |
|||
#define RCC_MP_AHB2LPENCLRR U(0xB1C) |
|||
#define RCC_MP_AHB3LPENSETR U(0xB20) |
|||
#define RCC_MP_AHB3LPENCLRR U(0xB24) |
|||
#define RCC_MP_AHB4LPENSETR U(0xB28) |
|||
#define RCC_MP_AHB4LPENCLRR U(0xB2C) |
|||
#define RCC_MP_AXIMLPENSETR U(0xB30) |
|||
#define RCC_MP_AXIMLPENCLRR U(0xB34) |
|||
#define RCC_MP_MLAHBLPENSETR U(0xB38) |
|||
#define RCC_MP_MLAHBLPENCLRR U(0xB3C) |
|||
#define RCC_VERR U(0xFF4) |
|||
#define RCC_IDR U(0xFF8) |
|||
#define RCC_SIDR U(0xFFC) |
|||
|
|||
/* Values for RCC_TZCR register */ |
|||
#define RCC_TZCR_TZEN BIT(0) |
|||
|
|||
/* Used for most of RCC_<x>SELR registers */ |
|||
#define RCC_SELR_SRC_MASK GENMASK(2, 0) |
|||
#define RCC_SELR_REFCLK_SRC_MASK GENMASK(1, 0) |
|||
#define RCC_SELR_SRCRDY BIT(31) |
|||
|
|||
/* Values of RCC_MPCKSELR register */ |
|||
#define RCC_MPCKSELR_HSI 0x00000000 |
|||
#define RCC_MPCKSELR_HSE 0x00000001 |
|||
#define RCC_MPCKSELR_PLL 0x00000002 |
|||
#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 |
|||
|
|||
/* Values of RCC_ASSCKSELR register */ |
|||
#define RCC_ASSCKSELR_HSI 0x00000000 |
|||
#define RCC_ASSCKSELR_HSE 0x00000001 |
|||
#define RCC_ASSCKSELR_PLL 0x00000002 |
|||
|
|||
/* Values of RCC_MSSCKSELR register */ |
|||
#define RCC_MSSCKSELR_HSI 0x00000000 |
|||
#define RCC_MSSCKSELR_HSE 0x00000001 |
|||
#define RCC_MSSCKSELR_CSI 0x00000002 |
|||
#define RCC_MSSCKSELR_PLL 0x00000003 |
|||
|
|||
/* Values of RCC_CPERCKSELR register */ |
|||
#define RCC_CPERCKSELR_HSI 0x00000000 |
|||
#define RCC_CPERCKSELR_CSI 0x00000001 |
|||
#define RCC_CPERCKSELR_HSE 0x00000002 |
|||
|
|||
/* Used for most of DIVR register: max div for RTC */ |
|||
#define RCC_DIVR_DIV_MASK GENMASK(5, 0) |
|||
#define RCC_DIVR_DIVRDY BIT(31) |
|||
|
|||
/* Masks for specific DIVR registers */ |
|||
#define RCC_APBXDIV_MASK GENMASK(2, 0) |
|||
#define RCC_MPUDIV_MASK GENMASK(2, 0) |
|||
#define RCC_AXIDIV_MASK GENMASK(2, 0) |
|||
|
|||
/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ |
|||
#define RCC_MP_ENCLRR_OFFSET U(4) |
|||
|
|||
/* Fields of RCC_BDCR register */ |
|||
#define RCC_BDCR_LSEON BIT(0) |
|||
#define RCC_BDCR_LSEBYP BIT(1) |
|||
#define RCC_BDCR_LSERDY BIT(2) |
|||
#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) |
|||
#define RCC_BDCR_LSEDRV_SHIFT 4 |
|||
#define RCC_BDCR_LSECSSON BIT(8) |
|||
#define RCC_BDCR_RTCCKEN BIT(20) |
|||
#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) |
|||
#define RCC_BDCR_RTCSRC_SHIFT 16 |
|||
#define RCC_BDCR_VSWRST BIT(31) |
|||
|
|||
/* Fields of RCC_RDLSICR register */ |
|||
#define RCC_RDLSICR_LSION BIT(0) |
|||
#define RCC_RDLSICR_LSIRDY BIT(1) |
|||
|
|||
/* Used for all RCC_PLL<n>CR registers */ |
|||
#define RCC_PLLNCR_PLLON BIT(0) |
|||
#define RCC_PLLNCR_PLLRDY BIT(1) |
|||
#define RCC_PLLNCR_DIVPEN BIT(4) |
|||
#define RCC_PLLNCR_DIVQEN BIT(5) |
|||
#define RCC_PLLNCR_DIVREN BIT(6) |
|||
#define RCC_PLLNCR_DIVEN_SHIFT 4 |
|||
|
|||
/* Used for all RCC_PLL<n>CFGR1 registers */ |
|||
#define RCC_PLLNCFGR1_DIVM_SHIFT 16 |
|||
#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16) |
|||
#define RCC_PLLNCFGR1_DIVN_SHIFT 0 |
|||
#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0) |
|||
/* Only for PLL3 and PLL4 */ |
|||
#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 |
|||
#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24) |
|||
|
|||
/* Used for all RCC_PLL<n>CFGR2 registers */ |
|||
#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0) |
|||
#define RCC_PLLNCFGR2_DIVP_SHIFT 0 |
|||
#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0) |
|||
#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 |
|||
#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8) |
|||
#define RCC_PLLNCFGR2_DIVR_SHIFT 16 |
|||
#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16) |
|||
|
|||
/* Used for all RCC_PLL<n>FRACR registers */ |
|||
#define RCC_PLLNFRACR_FRACV_SHIFT 3 |
|||
#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3) |
|||
#define RCC_PLLNFRACR_FRACLE BIT(16) |
|||
|
|||
/* Used for all RCC_PLL<n>CSGR registers */ |
|||
#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 |
|||
#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16) |
|||
#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 |
|||
#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0) |
|||
#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 |
|||
#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) |
|||
|
|||
/* Used for RCC_OCENSETR and RCC_OCENCLRR registers */ |
|||
#define RCC_OCENR_HSION BIT(0) |
|||
#define RCC_OCENR_CSION BIT(4) |
|||
#define RCC_OCENR_HSEON BIT(8) |
|||
#define RCC_OCENR_HSEBYP BIT(10) |
|||
#define RCC_OCENR_HSECSSON BIT(11) |
|||
|
|||
/* Fields of RCC_OCRDYR register */ |
|||
#define RCC_OCRDYR_HSIRDY BIT(0) |
|||
#define RCC_OCRDYR_HSIDIVRDY BIT(2) |
|||
#define RCC_OCRDYR_CSIRDY BIT(4) |
|||
#define RCC_OCRDYR_HSERDY BIT(8) |
|||
|
|||
/* Fields of RCC_DDRITFCR register */ |
|||
#define RCC_DDRITFCR_DDRC1EN BIT(0) |
|||
#define RCC_DDRITFCR_DDRC1LPEN BIT(1) |
|||
#define RCC_DDRITFCR_DDRC2EN BIT(2) |
|||
#define RCC_DDRITFCR_DDRC2LPEN BIT(3) |
|||
#define RCC_DDRITFCR_DDRPHYCEN BIT(4) |
|||
#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) |
|||
#define RCC_DDRITFCR_DDRCAPBEN BIT(6) |
|||
#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) |
|||
#define RCC_DDRITFCR_AXIDCGEN BIT(8) |
|||
#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) |
|||
#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) |
|||
#define RCC_DDRITFCR_DDRCAPBRST BIT(14) |
|||
#define RCC_DDRITFCR_DDRCAXIRST BIT(15) |
|||
#define RCC_DDRITFCR_DDRCORERST BIT(16) |
|||
#define RCC_DDRITFCR_DPHYAPBRST BIT(17) |
|||
#define RCC_DDRITFCR_DPHYRST BIT(18) |
|||
#define RCC_DDRITFCR_DPHYCTLRST BIT(19) |
|||
#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) |
|||
#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 |
|||
#define RCC_DDRITFCR_DDRCKMOD_SSR 0 |
|||
#define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) |
|||
#define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) |
|||
#define RCC_DDRITFCR_GSKPCTRL BIT(24) |
|||
|
|||
/* Fields of RCC_HSICFGR register */ |
|||
#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) |
|||
|
|||
/* Used for RCC_MCO related operations */ |
|||
#define RCC_MCOCFG_MCOON BIT(12) |
|||
#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4) |
|||
#define RCC_MCOCFG_MCODIV_SHIFT 4 |
|||
#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0) |
|||
|
|||
/* Fields of RCC_DBGCFGR register */ |
|||
#define RCC_DBGCFGR_DBGCKEN BIT(8) |
|||
|
|||
/* RCC register fields for reset reasons */ |
|||
#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) |
|||
#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) |
|||
#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) |
|||
#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) |
|||
#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) |
|||
#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) |
|||
#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) |
|||
#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) |
|||
#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) |
|||
#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) |
|||
|
|||
/* Global Reset Register */ |
|||
#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) |
|||
|
|||
/* Clock Source Interrupt Flag Register */ |
|||
#define RCC_MP_CIFR_MASK U(0x110F1F) |
|||
#define RCC_MP_CIFR_WKUPF BIT(20) |
|||
|
|||
/* Stop Request Set Register */ |
|||
#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) |
|||
#define RCC_MP_SREQSETR_STPREQ_P1 BIT(1) |
|||
|
|||
/* Stop Request Clear Register */ |
|||
#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) |
|||
#define RCC_MP_SREQCLRR_STPREQ_P1 BIT(1) |
|||
|
|||
/* Values of RCC_UART24CKSELR register */ |
|||
#define RCC_UART24CKSELR_HSI 0x00000002 |
|||
|
|||
/* Values of RCC_MP_APB1ENSETR register */ |
|||
#define RCC_MP_APB1ENSETR_UART4EN BIT(16) |
|||
|
|||
/* Values of RCC_MP_AHB4ENSETR register */ |
|||
#define RCC_MP_AHB4ENSETR_GPIOGEN BIT(6) |
|||
|
|||
#endif /* __STM32MP1_RCC_H__ */ |
@ -0,0 +1,15 @@ |
|||
/*
|
|||
* Copyright (c) 2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_RESET_H__ |
|||
#define __STM32MP1_RESET_H__ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
void stm32mp1_reset_assert(uint32_t reset_id); |
|||
void stm32mp1_reset_deassert(uint32_t reset_id); |
|||
|
|||
#endif /* __STM32MP1_RESET_H__ */ |
@ -0,0 +1,141 @@ |
|||
/*
|
|||
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
|
|||
#ifndef __STPMU1_H__ |
|||
#define __STPMU1_H__ |
|||
|
|||
#include <stm32_i2c.h> |
|||
#include <utils_def.h> |
|||
|
|||
#define TURN_ON_REG 0x1U |
|||
#define TURN_OFF_REG 0x2U |
|||
#define ICC_LDO_TURN_OFF_REG 0x3U |
|||
#define ICC_BUCK_TURN_OFF_REG 0x4U |
|||
#define RESET_STATUS_REG 0x5U |
|||
#define VERSION_STATUS_REG 0x6U |
|||
#define MAIN_CONTROL_REG 0x10U |
|||
#define PADS_PULL_REG 0x11U |
|||
#define BUCK_PULL_DOWN_REG 0x12U |
|||
#define LDO14_PULL_DOWN_REG 0x13U |
|||
#define LDO56_PULL_DOWN_REG 0x14U |
|||
#define VIN_CONTROL_REG 0x15U |
|||
#define PONKEY_TIMER_REG 0x16U |
|||
#define MASK_RANK_BUCK_REG 0x17U |
|||
#define MASK_RESET_BUCK_REG 0x18U |
|||
#define MASK_RANK_LDO_REG 0x19U |
|||
#define MASK_RESET_LDO_REG 0x1AU |
|||
#define WATCHDOG_CONTROL_REG 0x1BU |
|||
#define WATCHDOG_TIMER_REG 0x1CU |
|||
#define BUCK_ICC_TURNOFF_REG 0x1DU |
|||
#define LDO_ICC_TURNOFF_REG 0x1EU |
|||
#define BUCK_APM_CONTROL_REG 0x1FU |
|||
#define BUCK1_CONTROL_REG 0x20U |
|||
#define BUCK2_CONTROL_REG 0x21U |
|||
#define BUCK3_CONTROL_REG 0x22U |
|||
#define BUCK4_CONTROL_REG 0x23U |
|||
#define VREF_DDR_CONTROL_REG 0x24U |
|||
#define LDO1_CONTROL_REG 0x25U |
|||
#define LDO2_CONTROL_REG 0x26U |
|||
#define LDO3_CONTROL_REG 0x27U |
|||
#define LDO4_CONTROL_REG 0x28U |
|||
#define LDO5_CONTROL_REG 0x29U |
|||
#define LDO6_CONTROL_REG 0x2AU |
|||
#define BUCK1_PWRCTRL_REG 0x30U |
|||
#define BUCK2_PWRCTRL_REG 0x31U |
|||
#define BUCK3_PWRCTRL_REG 0x32U |
|||
#define BUCK4_PWRCTRL_REG 0x33U |
|||
#define VREF_DDR_PWRCTRL_REG 0x34U |
|||
#define LDO1_PWRCTRL_REG 0x35U |
|||
#define LDO2_PWRCTRL_REG 0x36U |
|||
#define LDO3_PWRCTRL_REG 0x37U |
|||
#define LDO4_PWRCTRL_REG 0x38U |
|||
#define LDO5_PWRCTRL_REG 0x39U |
|||
#define LDO6_PWRCTRL_REG 0x3AU |
|||
#define FREQUENCY_SPREADING_REG 0x3BU |
|||
#define USB_CONTROL_REG 0x40U |
|||
#define ITLATCH1_REG 0x50U |
|||
#define ITLATCH2_REG 0x51U |
|||
#define ITLATCH3_REG 0x52U |
|||
#define ITLATCH4_REG 0x53U |
|||
#define ITSETLATCH1_REG 0x60U |
|||
#define ITSETLATCH2_REG 0x61U |
|||
#define ITSETLATCH3_REG 0x62U |
|||
#define ITSETLATCH4_REG 0x63U |
|||
#define ITCLEARLATCH1_REG 0x70U |
|||
#define ITCLEARLATCH2_REG 0x71U |
|||
#define ITCLEARLATCH3_REG 0x72U |
|||
#define ITCLEARLATCH4_REG 0x73U |
|||
#define ITMASK1_REG 0x80U |
|||
#define ITMASK2_REG 0x81U |
|||
#define ITMASK3_REG 0x82U |
|||
#define ITMASK4_REG 0x83U |
|||
#define ITSETMASK1_REG 0x90U |
|||
#define ITSETMASK2_REG 0x91U |
|||
#define ITSETMASK3_REG 0x92U |
|||
#define ITSETMASK4_REG 0x93U |
|||
#define ITCLEARMASK1_REG 0xA0U |
|||
#define ITCLEARMASK2_REG 0xA1U |
|||
#define ITCLEARMASK3_REG 0xA2U |
|||
#define ITCLEARMASK4_REG 0xA3U |
|||
#define ITSOURCE1_REG 0xB0U |
|||
#define ITSOURCE2_REG 0xB1U |
|||
#define ITSOURCE3_REG 0xB2U |
|||
#define ITSOURCE4_REG 0xB3U |
|||
#define LDO_VOLTAGE_MASK 0x7CU |
|||
#define BUCK_VOLTAGE_MASK 0xFCU |
|||
#define LDO_BUCK_VOLTAGE_SHIFT 2 |
|||
#define LDO_ENABLE_MASK 0x01U |
|||
#define BUCK_ENABLE_MASK 0x01U |
|||
#define BUCK_HPLP_ENABLE_MASK 0x02U |
|||
#define LDO_HPLP_ENABLE_MASK 0x02U |
|||
#define LDO_BUCK_HPLP_SHIFT 1 |
|||
#define LDO_BUCK_RANK_MASK 0x01U |
|||
#define LDO_BUCK_RESET_MASK 0x01U |
|||
#define LDO_BUCK_PULL_DOWN_MASK 0x03U |
|||
|
|||
/* Main PMIC Control Register (MAIN_CONTROL_REG) */ |
|||
#define ICC_EVENT_ENABLED BIT(4) |
|||
#define PWRCTRL_POLARITY_HIGH BIT(3) |
|||
#define PWRCTRL_PIN_VALID BIT(2) |
|||
#define RESTART_REQUEST_ENABLED BIT(1) |
|||
#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0) |
|||
|
|||
/* Main PMIC PADS Control Register (PADS_PULL_REG) */ |
|||
#define WAKEUP_DETECTOR_DISABLED BIT(4) |
|||
#define PWRCTRL_PD_ACTIVE BIT(3) |
|||
#define PWRCTRL_PU_ACTIVE BIT(2) |
|||
#define WAKEUP_PD_ACTIVE BIT(1) |
|||
#define PONKEY_PU_ACTIVE BIT(0) |
|||
|
|||
/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */ |
|||
#define SWIN_DETECTOR_ENABLED BIT(7) |
|||
#define SWOUT_DETECTOR_ENABLED BIT(6) |
|||
#define VINLOW_HYST_MASK 0x3 |
|||
#define VINLOW_HYST_SHIFT 4 |
|||
#define VINLOW_THRESHOLD_MASK 0x7 |
|||
#define VINLOW_THRESHOLD_SHIFT 1 |
|||
#define VINLOW_ENABLED 0x01 |
|||
#define VINLOW_CTRL_REG_MASK 0xFF |
|||
|
|||
/* USB Control Register */ |
|||
#define BOOST_OVP_DISABLED BIT(7) |
|||
#define VBUS_OTG_DETECTION_DISABLED BIT(6) |
|||
#define OCP_LIMIT_HIGH BIT(3) |
|||
#define SWIN_SWOUT_ENABLED BIT(2) |
|||
#define USBSW_OTG_SWITCH_ENABLED BIT(1) |
|||
|
|||
int stpmu1_switch_off(void); |
|||
int stpmu1_register_read(uint8_t register_id, uint8_t *value); |
|||
int stpmu1_register_write(uint8_t register_id, uint8_t value); |
|||
int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); |
|||
int stpmu1_regulator_enable(const char *name); |
|||
int stpmu1_regulator_disable(const char *name); |
|||
uint8_t stpmu1_is_regulator_enabled(const char *name); |
|||
int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts); |
|||
void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); |
|||
|
|||
#endif /* __STPMU1_H__ */ |
@ -0,0 +1,251 @@ |
|||
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ |
|||
/*
|
|||
* Copyright (C) STMicroelectronics 2018 - All Rights Reserved |
|||
* Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics. |
|||
*/ |
|||
|
|||
#ifndef _DT_BINDINGS_STM32MP1_CLKS_H_ |
|||
#define _DT_BINDINGS_STM32MP1_CLKS_H_ |
|||
|
|||
/* OSCILLATOR clocks */ |
|||
#define CK_HSE 0 |
|||
#define CK_CSI 1 |
|||
#define CK_LSI 2 |
|||
#define CK_LSE 3 |
|||
#define CK_HSI 4 |
|||
#define CK_HSE_DIV2 5 |
|||
|
|||
/* Bus clocks */ |
|||
#define TIM2 6 |
|||
#define TIM3 7 |
|||
#define TIM4 8 |
|||
#define TIM5 9 |
|||
#define TIM6 10 |
|||
#define TIM7 11 |
|||
#define TIM12 12 |
|||
#define TIM13 13 |
|||
#define TIM14 14 |
|||
#define LPTIM1 15 |
|||
#define SPI2 16 |
|||
#define SPI3 17 |
|||
#define USART2 18 |
|||
#define USART3 19 |
|||
#define UART4 20 |
|||
#define UART5 21 |
|||
#define UART7 22 |
|||
#define UART8 23 |
|||
#define I2C1 24 |
|||
#define I2C2 25 |
|||
#define I2C3 26 |
|||
#define I2C5 27 |
|||
#define SPDIF 28 |
|||
#define CEC 29 |
|||
#define DAC12 30 |
|||
#define MDIO 31 |
|||
#define TIM1 32 |
|||
#define TIM8 33 |
|||
#define TIM15 34 |
|||
#define TIM16 35 |
|||
#define TIM17 36 |
|||
#define SPI1 37 |
|||
#define SPI4 38 |
|||
#define SPI5 39 |
|||
#define USART6 40 |
|||
#define SAI1 41 |
|||
#define SAI2 42 |
|||
#define SAI3 43 |
|||
#define DFSDM 44 |
|||
#define FDCAN 45 |
|||
#define LPTIM2 46 |
|||
#define LPTIM3 47 |
|||
#define LPTIM4 48 |
|||
#define LPTIM5 49 |
|||
#define SAI4 50 |
|||
#define SYSCFG 51 |
|||
#define VREF 52 |
|||
#define TMPSENS 53 |
|||
#define PMBCTRL 54 |
|||
#define HDP 55 |
|||
#define LTDC 56 |
|||
#define DSI 57 |
|||
#define IWDG2 58 |
|||
#define USBPHY 59 |
|||
#define STGENRO 60 |
|||
#define SPI6 61 |
|||
#define I2C4 62 |
|||
#define I2C6 63 |
|||
#define USART1 64 |
|||
#define RTCAPB 65 |
|||
#define TZC1 66 |
|||
#define TZPC 67 |
|||
#define IWDG1 68 |
|||
#define BSEC 69 |
|||
#define STGEN 70 |
|||
#define DMA1 71 |
|||
#define DMA2 72 |
|||
#define DMAMUX 73 |
|||
#define ADC12 74 |
|||
#define USBO 75 |
|||
#define SDMMC3 76 |
|||
#define DCMI 77 |
|||
#define CRYP2 78 |
|||
#define HASH2 79 |
|||
#define RNG2 80 |
|||
#define CRC2 81 |
|||
#define HSEM 82 |
|||
#define IPCC 83 |
|||
#define GPIOA 84 |
|||
#define GPIOB 85 |
|||
#define GPIOC 86 |
|||
#define GPIOD 87 |
|||
#define GPIOE 88 |
|||
#define GPIOF 89 |
|||
#define GPIOG 90 |
|||
#define GPIOH 91 |
|||
#define GPIOI 92 |
|||
#define GPIOJ 93 |
|||
#define GPIOK 94 |
|||
#define GPIOZ 95 |
|||
#define CRYP1 96 |
|||
#define HASH1 97 |
|||
#define RNG1 98 |
|||
#define BKPSRAM 99 |
|||
#define MDMA 100 |
|||
#define GPU 101 |
|||
#define ETHCK 102 |
|||
#define ETHTX 103 |
|||
#define ETHRX 104 |
|||
#define ETHMAC 105 |
|||
#define FMC 106 |
|||
#define QSPI 107 |
|||
#define SDMMC1 108 |
|||
#define SDMMC2 109 |
|||
#define CRC1 110 |
|||
#define USBH 111 |
|||
#define ETHSTP 112 |
|||
#define TZC2 113 |
|||
|
|||
/* Kernel clocks */ |
|||
#define SDMMC1_K 118 |
|||
#define SDMMC2_K 119 |
|||
#define SDMMC3_K 120 |
|||
#define FMC_K 121 |
|||
#define QSPI_K 122 |
|||
#define ETHCK_K 123 |
|||
#define RNG1_K 124 |
|||
#define RNG2_K 125 |
|||
#define GPU_K 126 |
|||
#define USBPHY_K 127 |
|||
#define STGEN_K 128 |
|||
#define SPDIF_K 129 |
|||
#define SPI1_K 130 |
|||
#define SPI2_K 131 |
|||
#define SPI3_K 132 |
|||
#define SPI4_K 133 |
|||
#define SPI5_K 134 |
|||
#define SPI6_K 135 |
|||
#define CEC_K 136 |
|||
#define I2C1_K 137 |
|||
#define I2C2_K 138 |
|||
#define I2C3_K 139 |
|||
#define I2C4_K 140 |
|||
#define I2C5_K 141 |
|||
#define I2C6_K 142 |
|||
#define LPTIM1_K 143 |
|||
#define LPTIM2_K 144 |
|||
#define LPTIM3_K 145 |
|||
#define LPTIM4_K 146 |
|||
#define LPTIM5_K 147 |
|||
#define USART1_K 148 |
|||
#define USART2_K 149 |
|||
#define USART3_K 150 |
|||
#define UART4_K 151 |
|||
#define UART5_K 152 |
|||
#define USART6_K 153 |
|||
#define UART7_K 154 |
|||
#define UART8_K 155 |
|||
#define DFSDM_K 156 |
|||
#define FDCAN_K 157 |
|||
#define SAI1_K 158 |
|||
#define SAI2_K 159 |
|||
#define SAI3_K 160 |
|||
#define SAI4_K 161 |
|||
#define ADC12_K 162 |
|||
#define DSI_K 163 |
|||
#define DSI_PX 164 |
|||
#define ADFSDM_K 165 |
|||
#define USBO_K 166 |
|||
#define LTDC_PX 167 |
|||
#define DAC12_K 168 |
|||
#define ETHPTP_K 169 |
|||
|
|||
/* PLL */ |
|||
#define PLL1 176 |
|||
#define PLL2 177 |
|||
#define PLL3 178 |
|||
#define PLL4 179 |
|||
|
|||
/* ODF */ |
|||
#define PLL1_P 180 |
|||
#define PLL1_Q 181 |
|||
#define PLL1_R 182 |
|||
#define PLL2_P 183 |
|||
#define PLL2_Q 184 |
|||
#define PLL2_R 185 |
|||
#define PLL3_P 186 |
|||
#define PLL3_Q 187 |
|||
#define PLL3_R 188 |
|||
#define PLL4_P 189 |
|||
#define PLL4_Q 190 |
|||
#define PLL4_R 191 |
|||
|
|||
/* AUX */ |
|||
#define RTC 192 |
|||
|
|||
/* MCLK */ |
|||
#define CK_PER 193 |
|||
#define CK_MPU 194 |
|||
#define CK_AXI 195 |
|||
#define CK_MCU 196 |
|||
|
|||
/* Time base */ |
|||
#define TIM2_K 197 |
|||
#define TIM3_K 198 |
|||
#define TIM4_K 199 |
|||
#define TIM5_K 200 |
|||
#define TIM6_K 201 |
|||
#define TIM7_K 202 |
|||
#define TIM12_K 203 |
|||
#define TIM13_K 204 |
|||
#define TIM14_K 205 |
|||
#define TIM1_K 206 |
|||
#define TIM8_K 207 |
|||
#define TIM15_K 208 |
|||
#define TIM16_K 209 |
|||
#define TIM17_K 210 |
|||
|
|||
/* MCO clocks */ |
|||
#define CK_MCO1 211 |
|||
#define CK_MCO2 212 |
|||
|
|||
/* TRACE & DEBUG clocks */ |
|||
#define CK_DBG 214 |
|||
#define CK_TRACE 215 |
|||
|
|||
/* DDR */ |
|||
#define DDRC1 220 |
|||
#define DDRC1LP 221 |
|||
#define DDRC2 222 |
|||
#define DDRC2LP 223 |
|||
#define DDRPHYC 224 |
|||
#define DDRPHYCLP 225 |
|||
#define DDRCAPB 226 |
|||
#define DDRCAPBLP 227 |
|||
#define AXIDCG 228 |
|||
#define DDRPHYCAPB 229 |
|||
#define DDRPHYCAPBLP 230 |
|||
#define DDRPERFM 231 |
|||
|
|||
#define STM32MP1_LAST_CLK 232 |
|||
|
|||
#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ |
@ -0,0 +1,283 @@ |
|||
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ |
|||
/*
|
|||
* Copyright (C) 2017, STMicroelectronics - All Rights Reserved |
|||
*/ |
|||
|
|||
#ifndef _DT_BINDINGS_CLOCK_STM32MP1_CLKSRC_H_ |
|||
#define _DT_BINDINGS_CLOCK_STM32MP1_CLKSRC_H_ |
|||
|
|||
/* PLL output is enable when x=1, with x=p,q or r */ |
|||
#define PQR(p, q, r) (((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2)) |
|||
|
|||
/* st,clksrc: mandatory clock source */ |
|||
|
|||
#define CLK_MPU_HSI 0x00000200 |
|||
#define CLK_MPU_HSE 0x00000201 |
|||
#define CLK_MPU_PLL1P 0x00000202 |
|||
#define CLK_MPU_PLL1P_DIV 0x00000203 |
|||
|
|||
#define CLK_AXI_HSI 0x00000240 |
|||
#define CLK_AXI_HSE 0x00000241 |
|||
#define CLK_AXI_PLL2P 0x00000242 |
|||
|
|||
#define CLK_MCU_HSI 0x00000480 |
|||
#define CLK_MCU_HSE 0x00000481 |
|||
#define CLK_MCU_CSI 0x00000482 |
|||
#define CLK_MCU_PLL3P 0x00000483 |
|||
|
|||
#define CLK_PLL12_HSI 0x00000280 |
|||
#define CLK_PLL12_HSE 0x00000281 |
|||
|
|||
#define CLK_PLL3_HSI 0x00008200 |
|||
#define CLK_PLL3_HSE 0x00008201 |
|||
#define CLK_PLL3_CSI 0x00008202 |
|||
|
|||
#define CLK_PLL4_HSI 0x00008240 |
|||
#define CLK_PLL4_HSE 0x00008241 |
|||
#define CLK_PLL4_CSI 0x00008242 |
|||
#define CLK_PLL4_I2SCKIN 0x00008243 |
|||
|
|||
#define CLK_RTC_DISABLED 0x00001400 |
|||
#define CLK_RTC_LSE 0x00001401 |
|||
#define CLK_RTC_LSI 0x00001402 |
|||
#define CLK_RTC_HSE 0x00001403 |
|||
|
|||
#define CLK_MCO1_HSI 0x00008000 |
|||
#define CLK_MCO1_HSE 0x00008001 |
|||
#define CLK_MCO1_CSI 0x00008002 |
|||
#define CLK_MCO1_LSI 0x00008003 |
|||
#define CLK_MCO1_LSE 0x00008004 |
|||
#define CLK_MCO1_DISABLED 0x0000800F |
|||
|
|||
#define CLK_MCO2_MPU 0x00008040 |
|||
#define CLK_MCO2_AXI 0x00008041 |
|||
#define CLK_MCO2_MCU 0x00008042 |
|||
#define CLK_MCO2_PLL4P 0x00008043 |
|||
#define CLK_MCO2_HSE 0x00008044 |
|||
#define CLK_MCO2_HSI 0x00008045 |
|||
#define CLK_MCO2_DISABLED 0x0000804F |
|||
|
|||
/* st,pkcs: peripheral kernel clock source */ |
|||
|
|||
#define CLK_I2C12_PCLK1 0x00008C00 |
|||
#define CLK_I2C12_PLL4R 0x00008C01 |
|||
#define CLK_I2C12_HSI 0x00008C02 |
|||
#define CLK_I2C12_CSI 0x00008C03 |
|||
#define CLK_I2C12_DISABLED 0x00008C07 |
|||
|
|||
#define CLK_I2C35_PCLK1 0x00008C40 |
|||
#define CLK_I2C35_PLL4R 0x00008C41 |
|||
#define CLK_I2C35_HSI 0x00008C42 |
|||
#define CLK_I2C35_CSI 0x00008C43 |
|||
#define CLK_I2C35_DISABLED 0x00008C47 |
|||
|
|||
#define CLK_I2C46_PCLK5 0x00000C00 |
|||
#define CLK_I2C46_PLL3Q 0x00000C01 |
|||
#define CLK_I2C46_HSI 0x00000C02 |
|||
#define CLK_I2C46_CSI 0x00000C03 |
|||
#define CLK_I2C46_DISABLED 0x00000C07 |
|||
|
|||
#define CLK_SAI1_PLL4Q 0x00008C80 |
|||
#define CLK_SAI1_PLL3Q 0x00008C81 |
|||
#define CLK_SAI1_I2SCKIN 0x00008C82 |
|||
#define CLK_SAI1_CKPER 0x00008C83 |
|||
#define CLK_SAI1_PLL3R 0x00008C84 |
|||
#define CLK_SAI1_DISABLED 0x00008C87 |
|||
|
|||
#define CLK_SAI2_PLL4Q 0x00008CC0 |
|||
#define CLK_SAI2_PLL3Q 0x00008CC1 |
|||
#define CLK_SAI2_I2SCKIN 0x00008CC2 |
|||
#define CLK_SAI2_CKPER 0x00008CC3 |
|||
#define CLK_SAI2_SPDIF 0x00008CC4 |
|||
#define CLK_SAI2_PLL3R 0x00008CC5 |
|||
#define CLK_SAI2_DISABLED 0x00008CC7 |
|||
|
|||
#define CLK_SAI3_PLL4Q 0x00008D00 |
|||
#define CLK_SAI3_PLL3Q 0x00008D01 |
|||
#define CLK_SAI3_I2SCKIN 0x00008D02 |
|||
#define CLK_SAI3_CKPER 0x00008D03 |
|||
#define CLK_SAI3_PLL3R 0x00008D04 |
|||
#define CLK_SAI3_DISABLED 0x00008D07 |
|||
|
|||
#define CLK_SAI4_PLL4Q 0x00008D40 |
|||
#define CLK_SAI4_PLL3Q 0x00008D41 |
|||
#define CLK_SAI4_I2SCKIN 0x00008D42 |
|||
#define CLK_SAI4_CKPER 0x00008D43 |
|||
#define CLK_SAI4_PLL3R 0x00008D44 |
|||
#define CLK_SAI4_DISABLED 0x00008D47 |
|||
|
|||
#define CLK_SPI2S1_PLL4P 0x00008D80 |
|||
#define CLK_SPI2S1_PLL3Q 0x00008D81 |
|||
#define CLK_SPI2S1_I2SCKIN 0x00008D82 |
|||
#define CLK_SPI2S1_CKPER 0x00008D83 |
|||
#define CLK_SPI2S1_PLL3R 0x00008D84 |
|||
#define CLK_SPI2S1_DISABLED 0x00008D87 |
|||
|
|||
#define CLK_SPI2S23_PLL4P 0x00008DC0 |
|||
#define CLK_SPI2S23_PLL3Q 0x00008DC1 |
|||
#define CLK_SPI2S23_I2SCKIN 0x00008DC2 |
|||
#define CLK_SPI2S23_CKPER 0x00008DC3 |
|||
#define CLK_SPI2S23_PLL3R 0x00008DC4 |
|||
#define CLK_SPI2S23_DISABLED 0x00008DC7 |
|||
|
|||
#define CLK_SPI45_PCLK2 0x00008E00 |
|||
#define CLK_SPI45_PLL4Q 0x00008E01 |
|||
#define CLK_SPI45_HSI 0x00008E02 |
|||
#define CLK_SPI45_CSI 0x00008E03 |
|||
#define CLK_SPI45_HSE 0x00008E04 |
|||
#define CLK_SPI45_DISABLED 0x00008E07 |
|||
|
|||
#define CLK_SPI6_PCLK5 0x00000C40 |
|||
#define CLK_SPI6_PLL4Q 0x00000C41 |
|||
#define CLK_SPI6_HSI 0x00000C42 |
|||
#define CLK_SPI6_CSI 0x00000C43 |
|||
#define CLK_SPI6_HSE 0x00000C44 |
|||
#define CLK_SPI6_PLL3Q 0x00000C45 |
|||
#define CLK_SPI6_DISABLED 0x00000C47 |
|||
|
|||
#define CLK_UART6_PCLK2 0x00008E40 |
|||
#define CLK_UART6_PLL4Q 0x00008E41 |
|||
#define CLK_UART6_HSI 0x00008E42 |
|||
#define CLK_UART6_CSI 0x00008E43 |
|||
#define CLK_UART6_HSE 0x00008E44 |
|||
#define CLK_UART6_DISABLED 0x00008E47 |
|||
|
|||
#define CLK_UART24_PCLK1 0x00008E80 |
|||
#define CLK_UART24_PLL4Q 0x00008E81 |
|||
#define CLK_UART24_HSI 0x00008E82 |
|||
#define CLK_UART24_CSI 0x00008E83 |
|||
#define CLK_UART24_HSE 0x00008E84 |
|||
#define CLK_UART24_DISABLED 0x00008E87 |
|||
|
|||
#define CLK_UART35_PCLK1 0x00008EC0 |
|||
#define CLK_UART35_PLL4Q 0x00008EC1 |
|||
#define CLK_UART35_HSI 0x00008EC2 |
|||
#define CLK_UART35_CSI 0x00008EC3 |
|||
#define CLK_UART35_HSE 0x00008EC4 |
|||
#define CLK_UART35_DISABLED 0x00008EC7 |
|||
|
|||
#define CLK_UART78_PCLK1 0x00008F00 |
|||
#define CLK_UART78_PLL4Q 0x00008F01 |
|||
#define CLK_UART78_HSI 0x00008F02 |
|||
#define CLK_UART78_CSI 0x00008F03 |
|||
#define CLK_UART78_HSE 0x00008F04 |
|||
#define CLK_UART78_DISABLED 0x00008F07 |
|||
|
|||
#define CLK_UART1_PCLK5 0x00000C80 |
|||
#define CLK_UART1_PLL3Q 0x00000C81 |
|||
#define CLK_UART1_HSI 0x00000C82 |
|||
#define CLK_UART1_CSI 0x00000C83 |
|||
#define CLK_UART1_PLL4Q 0x00000C84 |
|||
#define CLK_UART1_HSE 0x00000C85 |
|||
#define CLK_UART1_DISABLED 0x00000C87 |
|||
|
|||
#define CLK_SDMMC12_HCLK6 0x00008F40 |
|||
#define CLK_SDMMC12_PLL3R 0x00008F41 |
|||
#define CLK_SDMMC12_PLL4P 0x00008F42 |
|||
#define CLK_SDMMC12_HSI 0x00008F43 |
|||
#define CLK_SDMMC12_DISABLED 0x00008F47 |
|||
|
|||
#define CLK_SDMMC3_HCLK2 0x00008F80 |
|||
#define CLK_SDMMC3_PLL3R 0x00008F81 |
|||
#define CLK_SDMMC3_PLL4P 0x00008F82 |
|||
#define CLK_SDMMC3_HSI 0x00008F83 |
|||
#define CLK_SDMMC3_DISABLED 0x00008F87 |
|||
|
|||
#define CLK_ETH_PLL4P 0x00008FC0 |
|||
#define CLK_ETH_PLL3Q 0x00008FC1 |
|||
#define CLK_ETH_DISABLED 0x00008FC3 |
|||
|
|||
#define CLK_QSPI_ACLK 0x00009000 |
|||
#define CLK_QSPI_PLL3R 0x00009001 |
|||
#define CLK_QSPI_PLL4P 0x00009002 |
|||
#define CLK_QSPI_CKPER 0x00009003 |
|||
|
|||
#define CLK_FMC_ACLK 0x00009040 |
|||
#define CLK_FMC_PLL3R 0x00009041 |
|||
#define CLK_FMC_PLL4P 0x00009042 |
|||
#define CLK_FMC_CKPER 0x00009043 |
|||
|
|||
#define CLK_FDCAN_HSE 0x000090C0 |
|||
#define CLK_FDCAN_PLL3Q 0x000090C1 |
|||
#define CLK_FDCAN_PLL4Q 0x000090C2 |
|||
#define CLK_FDCAN_PLL4R 0x000090C3 |
|||
|
|||
#define CLK_SPDIF_PLL4P 0x00009140 |
|||
#define CLK_SPDIF_PLL3Q 0x00009141 |
|||
#define CLK_SPDIF_HSI 0x00009142 |
|||
#define CLK_SPDIF_DISABLED 0x00009143 |
|||
|
|||
#define CLK_CEC_LSE 0x00009180 |
|||
#define CLK_CEC_LSI 0x00009181 |
|||
#define CLK_CEC_CSI_DIV122 0x00009182 |
|||
#define CLK_CEC_DISABLED 0x00009183 |
|||
|
|||
#define CLK_USBPHY_HSE 0x000091C0 |
|||
#define CLK_USBPHY_PLL4R 0x000091C1 |
|||
#define CLK_USBPHY_HSE_DIV2 0x000091C2 |
|||
#define CLK_USBPHY_DISABLED 0x000091C3 |
|||
|
|||
#define CLK_USBO_PLL4R 0x800091C0 |
|||
#define CLK_USBO_USBPHY 0x800091C1 |
|||
|
|||
#define CLK_RNG1_CSI 0x00000CC0 |
|||
#define CLK_RNG1_PLL4R 0x00000CC1 |
|||
#define CLK_RNG1_LSE 0x00000CC2 |
|||
#define CLK_RNG1_LSI 0x00000CC3 |
|||
|
|||
#define CLK_RNG2_CSI 0x00009200 |
|||
#define CLK_RNG2_PLL4R 0x00009201 |
|||
#define CLK_RNG2_LSE 0x00009202 |
|||
#define CLK_RNG2_LSI 0x00009203 |
|||
|
|||
#define CLK_CKPER_HSI 0x00000D00 |
|||
#define CLK_CKPER_CSI 0x00000D01 |
|||
#define CLK_CKPER_HSE 0x00000D02 |
|||
#define CLK_CKPER_DISABLED 0x00000D03 |
|||
|
|||
#define CLK_STGEN_HSI 0x00000D40 |
|||
#define CLK_STGEN_HSE 0x00000D41 |
|||
#define CLK_STGEN_DISABLED 0x00000D43 |
|||
|
|||
#define CLK_DSI_DSIPLL 0x00009240 |
|||
#define CLK_DSI_PLL4P 0x00009241 |
|||
|
|||
#define CLK_ADC_PLL4R 0x00009280 |
|||
#define CLK_ADC_CKPER 0x00009281 |
|||
#define CLK_ADC_PLL3Q 0x00009282 |
|||
#define CLK_ADC_DISABLED 0x00009283 |
|||
|
|||
#define CLK_LPTIM45_PCLK3 0x000092C0 |
|||
#define CLK_LPTIM45_PLL4P 0x000092C1 |
|||
#define CLK_LPTIM45_PLL3Q 0x000092C2 |
|||
#define CLK_LPTIM45_LSE 0x000092C3 |
|||
#define CLK_LPTIM45_LSI 0x000092C4 |
|||
#define CLK_LPTIM45_CKPER 0x000092C5 |
|||
#define CLK_LPTIM45_DISABLED 0x000092C7 |
|||
|
|||
#define CLK_LPTIM23_PCLK3 0x00009300 |
|||
#define CLK_LPTIM23_PLL4Q 0x00009301 |
|||
#define CLK_LPTIM23_CKPER 0x00009302 |
|||
#define CLK_LPTIM23_LSE 0x00009303 |
|||
#define CLK_LPTIM23_LSI 0x00009304 |
|||
#define CLK_LPTIM23_DISABLED 0x00009307 |
|||
|
|||
#define CLK_LPTIM1_PCLK1 0x00009340 |
|||
#define CLK_LPTIM1_PLL4P 0x00009341 |
|||
#define CLK_LPTIM1_PLL3Q 0x00009342 |
|||
#define CLK_LPTIM1_LSE 0x00009343 |
|||
#define CLK_LPTIM1_LSI 0x00009344 |
|||
#define CLK_LPTIM1_CKPER 0x00009345 |
|||
#define CLK_LPTIM1_DISABLED 0x00009347 |
|||
|
|||
/* define for st,pll /csg */ |
|||
#define SSCG_MODE_CENTER_SPREAD 0 |
|||
#define SSCG_MODE_DOWN_SPREAD 1 |
|||
|
|||
/* define for st,drive */ |
|||
#define LSEDRV_LOWEST 0 |
|||
#define LSEDRV_MEDIUM_LOW 1 |
|||
#define LSEDRV_MEDIUM_HIGH 2 |
|||
#define LSEDRV_HIGHEST 3 |
|||
|
|||
#endif |
@ -0,0 +1,35 @@ |
|||
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ |
|||
/*
|
|||
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved |
|||
* Author: Torgue Alexandre <alexandre.torgue@st.com> for STMicroelectronics. |
|||
*/ |
|||
|
|||
#ifndef _DT_BINDINGS_STM32_PINFUNC_H |
|||
#define _DT_BINDINGS_STM32_PINFUNC_H |
|||
|
|||
/* define PIN modes */ |
|||
#define GPIO 0x0 |
|||
#define AF0 0x1 |
|||
#define AF1 0x2 |
|||
#define AF2 0x3 |
|||
#define AF3 0x4 |
|||
#define AF4 0x5 |
|||
#define AF5 0x6 |
|||
#define AF6 0x7 |
|||
#define AF7 0x8 |
|||
#define AF8 0x9 |
|||
#define AF9 0xa |
|||
#define AF10 0xb |
|||
#define AF11 0xc |
|||
#define AF12 0xd |
|||
#define AF13 0xe |
|||
#define AF14 0xf |
|||
#define AF15 0x10 |
|||
#define ANALOG 0x11 |
|||
|
|||
/* define Pins number*/ |
|||
#define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) |
|||
|
|||
#define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode)) |
|||
|
|||
#endif /* _DT_BINDINGS_STM32_PINFUNC_H */ |
@ -0,0 +1,108 @@ |
|||
/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ |
|||
/*
|
|||
* Copyright (C) STMicroelectronics 2018 - All Rights Reserved |
|||
* Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics. |
|||
*/ |
|||
|
|||
#ifndef _DT_BINDINGS_STM32MP1_RESET_H_ |
|||
#define _DT_BINDINGS_STM32MP1_RESET_H_ |
|||
|
|||
#define LTDC_R 3072 |
|||
#define DSI_R 3076 |
|||
#define DDRPERFM_R 3080 |
|||
#define USBPHY_R 3088 |
|||
#define SPI6_R 3136 |
|||
#define I2C4_R 3138 |
|||
#define I2C6_R 3139 |
|||
#define USART1_R 3140 |
|||
#define STGEN_R 3156 |
|||
#define GPIOZ_R 3200 |
|||
#define CRYP1_R 3204 |
|||
#define HASH1_R 3205 |
|||
#define RNG1_R 3206 |
|||
#define AXIM_R 3216 |
|||
#define GPU_R 3269 |
|||
#define ETHMAC_R 3274 |
|||
#define FMC_R 3276 |
|||
#define QSPI_R 3278 |
|||
#define SDMMC1_R 3280 |
|||
#define SDMMC2_R 3281 |
|||
#define CRC1_R 3284 |
|||
#define USBH_R 3288 |
|||
#define MDMA_R 3328 |
|||
#define MCU_R 8225 |
|||
#define TIM2_R 19456 |
|||
#define TIM3_R 19457 |
|||
#define TIM4_R 19458 |
|||
#define TIM5_R 19459 |
|||
#define TIM6_R 19460 |
|||
#define TIM7_R 19461 |
|||
#define TIM12_R 16462 |
|||
#define TIM13_R 16463 |
|||
#define TIM14_R 16464 |
|||
#define LPTIM1_R 19465 |
|||
#define SPI2_R 19467 |
|||
#define SPI3_R 19468 |
|||
#define USART2_R 19470 |
|||
#define USART3_R 19471 |
|||
#define UART4_R 19472 |
|||
#define UART5_R 19473 |
|||
#define UART7_R 19474 |
|||
#define UART8_R 19475 |
|||
#define I2C1_R 19477 |
|||
#define I2C2_R 19478 |
|||
#define I2C3_R 19479 |
|||
#define I2C5_R 19480 |
|||
#define SPDIF_R 19482 |
|||
#define CEC_R 19483 |
|||
#define DAC12_R 19485 |
|||
#define MDIO_R 19847 |
|||
#define TIM1_R 19520 |
|||
#define TIM8_R 19521 |
|||
#define TIM15_R 19522 |
|||
#define TIM16_R 19523 |
|||
#define TIM17_R 19524 |
|||
#define SPI1_R 19528 |
|||
#define SPI4_R 19529 |
|||
#define SPI5_R 19530 |
|||
#define USART6_R 19533 |
|||
#define SAI1_R 19536 |
|||
#define SAI2_R 19537 |
|||
#define SAI3_R 19538 |
|||
#define DFSDM_R 19540 |
|||
#define FDCAN_R 19544 |
|||
#define LPTIM2_R 19584 |
|||
#define LPTIM3_R 19585 |
|||
#define LPTIM4_R 19586 |
|||
#define LPTIM5_R 19587 |
|||
#define SAI4_R 19592 |
|||
#define SYSCFG_R 19595 |
|||
#define VREF_R 19597 |
|||
#define TMPSENS_R 19600 |
|||
#define PMBCTRL_R 19601 |
|||
#define DMA1_R 19648 |
|||
#define DMA2_R 19649 |
|||
#define DMAMUX_R 19650 |
|||
#define ADC12_R 19653 |
|||
#define USBO_R 19656 |
|||
#define SDMMC3_R 19664 |
|||
#define CAMITF_R 19712 |
|||
#define CRYP2_R 19716 |
|||
#define HASH2_R 19717 |
|||
#define RNG2_R 19718 |
|||
#define CRC2_R 19719 |
|||
#define HSEM_R 19723 |
|||
#define MBOX_R 19724 |
|||
#define GPIOA_R 19776 |
|||
#define GPIOB_R 19777 |
|||
#define GPIOC_R 19778 |
|||
#define GPIOD_R 19779 |
|||
#define GPIOE_R 19780 |
|||
#define GPIOF_R 19781 |
|||
#define GPIOG_R 19782 |
|||
#define GPIOH_R 19783 |
|||
#define GPIOI_R 19784 |
|||
#define GPIOJ_R 19785 |
|||
#define GPIOK_R 19786 |
|||
|
|||
#endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ |
@ -0,0 +1,193 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <assert.h> |
|||
#include <boot_api.h> |
|||
#include <debug.h> |
|||
#include <io_driver.h> |
|||
#include <io_dummy.h> |
|||
#include <io_storage.h> |
|||
#include <mmio.h> |
|||
#include <platform.h> |
|||
#include <platform_def.h> |
|||
#include <stm32mp1_private.h> |
|||
#include <stm32mp1_rcc.h> |
|||
#include <string.h> |
|||
#include <utils.h> |
|||
|
|||
/* IO devices */ |
|||
static const io_dev_connector_t *dummy_dev_con; |
|||
static uintptr_t dummy_dev_handle; |
|||
static uintptr_t dummy_dev_spec; |
|||
|
|||
static const io_block_spec_t bl32_block_spec = { |
|||
.offset = BL32_BASE, |
|||
.length = STM32MP1_BL32_SIZE |
|||
}; |
|||
|
|||
static const io_block_spec_t bl2_block_spec = { |
|||
.offset = BL2_BASE, |
|||
.length = STM32MP1_BL2_SIZE, |
|||
}; |
|||
|
|||
static int open_dummy(const uintptr_t spec); |
|||
|
|||
struct plat_io_policy { |
|||
uintptr_t *dev_handle; |
|||
uintptr_t image_spec; |
|||
int (*check)(const uintptr_t spec); |
|||
}; |
|||
|
|||
static const struct plat_io_policy policies[] = { |
|||
[BL2_IMAGE_ID] = { |
|||
.dev_handle = &dummy_dev_handle, |
|||
.image_spec = (uintptr_t)&bl2_block_spec, |
|||
.check = open_dummy |
|||
}, |
|||
[BL32_IMAGE_ID] = { |
|||
.dev_handle = &dummy_dev_handle, |
|||
.image_spec = (uintptr_t)&bl32_block_spec, |
|||
.check = open_dummy |
|||
}, |
|||
}; |
|||
|
|||
static int open_dummy(const uintptr_t spec) |
|||
{ |
|||
return io_dev_init(dummy_dev_handle, 0); |
|||
} |
|||
|
|||
static void print_boot_device(boot_api_context_t *boot_context) |
|||
{ |
|||
switch (boot_context->boot_interface_selected) { |
|||
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: |
|||
INFO("Using SDMMC\n"); |
|||
break; |
|||
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: |
|||
INFO("Using EMMC\n"); |
|||
break; |
|||
default: |
|||
ERROR("Boot interface not found\n"); |
|||
panic(); |
|||
break; |
|||
} |
|||
|
|||
if (boot_context->boot_interface_instance != 0U) { |
|||
INFO(" Instance %d\n", boot_context->boot_interface_instance); |
|||
} |
|||
} |
|||
|
|||
static void print_reset_reason(void) |
|||
{ |
|||
uint32_t rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR); |
|||
|
|||
if (rstsr == 0U) { |
|||
WARN("Reset reason unknown\n"); |
|||
return; |
|||
} |
|||
|
|||
INFO("Reset reason (0x%x):\n", rstsr); |
|||
|
|||
if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) { |
|||
if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) { |
|||
INFO("System exits from STANDBY\n"); |
|||
return; |
|||
} |
|||
|
|||
if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) { |
|||
INFO("MPU exits from CSTANDBY\n"); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) { |
|||
INFO(" Power-on Reset (rst_por)\n"); |
|||
return; |
|||
} |
|||
|
|||
if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) { |
|||
INFO(" Brownout Reset (rst_bor)\n"); |
|||
return; |
|||
} |
|||
|
|||
if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) { |
|||
INFO(" System reset generated by MPU (MPSYSRST)\n"); |
|||
return; |
|||
} |
|||
|
|||
if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) { |
|||
INFO(" Reset due to a clock failure on HSE\n"); |
|||
return; |
|||
} |
|||
|
|||
if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) { |
|||
INFO(" IWDG1 Reset (rst_iwdg1)\n"); |
|||
return; |
|||
} |
|||
|
|||
if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) { |
|||
INFO(" IWDG2 Reset (rst_iwdg2)\n"); |
|||
return; |
|||
} |
|||
|
|||
if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { |
|||
INFO(" Pad Reset from NRST\n"); |
|||
return; |
|||
} |
|||
|
|||
if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) { |
|||
INFO(" Reset due to a failure of VDD_CORE\n"); |
|||
return; |
|||
} |
|||
|
|||
ERROR(" Unidentified reset reason\n"); |
|||
} |
|||
|
|||
void stm32mp1_io_setup(void) |
|||
{ |
|||
int io_result __unused; |
|||
boot_api_context_t *boot_context = |
|||
(boot_api_context_t *)stm32mp1_get_boot_ctx_address(); |
|||
|
|||
print_reset_reason(); |
|||
|
|||
print_boot_device(boot_context); |
|||
|
|||
if ((boot_context->boot_partition_used_toboot == 1U) || |
|||
(boot_context->boot_partition_used_toboot == 2U)) { |
|||
INFO("Boot used partition fsbl%d\n", |
|||
boot_context->boot_partition_used_toboot); |
|||
} |
|||
|
|||
io_result = register_io_dev_dummy(&dummy_dev_con); |
|||
assert(io_result == 0); |
|||
|
|||
io_result = io_dev_open(dummy_dev_con, dummy_dev_spec, |
|||
&dummy_dev_handle); |
|||
assert(io_result == 0); |
|||
} |
|||
|
|||
/*
|
|||
* 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 rc; |
|||
const struct plat_io_policy *policy; |
|||
|
|||
assert(image_id < ARRAY_SIZE(policies)); |
|||
|
|||
policy = &policies[image_id]; |
|||
rc = policy->check(policy->image_spec); |
|||
if (rc == 0) { |
|||
*image_spec = policy->image_spec; |
|||
*dev_handle = *(policy->dev_handle); |
|||
} |
|||
|
|||
return rc; |
|||
} |
@ -0,0 +1,161 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, 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 <boot_api.h> |
|||
#include <console.h> |
|||
#include <debug.h> |
|||
#include <delay_timer.h> |
|||
#include <desc_image_load.h> |
|||
#include <generic_delay_timer.h> |
|||
#include <mmio.h> |
|||
#include <platform.h> |
|||
#include <platform_def.h> |
|||
#include <stm32mp1_clk.h> |
|||
#include <stm32mp1_dt.h> |
|||
#include <stm32mp1_pmic.h> |
|||
#include <stm32mp1_private.h> |
|||
#include <stm32mp1_context.h> |
|||
#include <stm32mp1_pwr.h> |
|||
#include <stm32mp1_ram.h> |
|||
#include <stm32mp1_rcc.h> |
|||
#include <stm32mp1_reset.h> |
|||
#include <string.h> |
|||
#include <xlat_tables_v2.h> |
|||
|
|||
void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1, |
|||
u_register_t arg2, u_register_t arg3) |
|||
{ |
|||
stm32mp1_save_boot_ctx_address(arg0); |
|||
} |
|||
|
|||
void bl2_platform_setup(void) |
|||
{ |
|||
int ret; |
|||
|
|||
if (dt_check_pmic()) { |
|||
initialize_pmic(); |
|||
} |
|||
|
|||
ret = stm32mp1_ddr_probe(); |
|||
if (ret < 0) { |
|||
ERROR("Invalid DDR init: error %d\n", ret); |
|||
panic(); |
|||
} |
|||
|
|||
INFO("BL2 runs SP_MIN setup\n"); |
|||
} |
|||
|
|||
void bl2_el3_plat_arch_setup(void) |
|||
{ |
|||
int32_t result; |
|||
struct dt_node_info dt_dev_info; |
|||
const char *board_model; |
|||
boot_api_context_t *boot_context = |
|||
(boot_api_context_t *)stm32mp1_get_boot_ctx_address(); |
|||
uint32_t clk_rate; |
|||
|
|||
/*
|
|||
* Disable the backup domain write protection. |
|||
* The protection is enable at each reset by hardware |
|||
* and must be disabled by software. |
|||
*/ |
|||
mmio_setbits_32(PWR_BASE + PWR_CR1, PWR_CR1_DBP); |
|||
|
|||
while ((mmio_read_32(PWR_BASE + PWR_CR1) & PWR_CR1_DBP) == 0U) { |
|||
; |
|||
} |
|||
|
|||
/* Reset backup domain on cold boot cases */ |
|||
if ((mmio_read_32(RCC_BASE + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) { |
|||
mmio_setbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST); |
|||
|
|||
while ((mmio_read_32(RCC_BASE + RCC_BDCR) & RCC_BDCR_VSWRST) == |
|||
0U) { |
|||
; |
|||
} |
|||
|
|||
mmio_clrbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST); |
|||
} |
|||
|
|||
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, |
|||
BL_CODE_END - BL_CODE_BASE, |
|||
MT_CODE | MT_SECURE); |
|||
|
|||
/* Prevent corruption of preloaded BL32 */ |
|||
mmap_add_region(BL32_BASE, BL32_BASE, |
|||
BL32_LIMIT - BL32_BASE, |
|||
MT_MEMORY | MT_RO | MT_SECURE); |
|||
|
|||
/* Prevent corruption of preloaded Device Tree */ |
|||
mmap_add_region(DTB_BASE, DTB_BASE, |
|||
DTB_LIMIT - DTB_BASE, |
|||
MT_MEMORY | MT_RO | MT_SECURE); |
|||
|
|||
configure_mmu(); |
|||
|
|||
generic_delay_timer_init(); |
|||
|
|||
if (dt_open_and_check() < 0) { |
|||
panic(); |
|||
} |
|||
|
|||
if (stm32mp1_clk_probe() < 0) { |
|||
panic(); |
|||
} |
|||
|
|||
if (stm32mp1_clk_init() < 0) { |
|||
panic(); |
|||
} |
|||
|
|||
result = dt_get_stdout_uart_info(&dt_dev_info); |
|||
|
|||
if ((result <= 0) || |
|||
(dt_dev_info.status == 0U) || |
|||
(dt_dev_info.clock < 0) || |
|||
(dt_dev_info.reset < 0)) { |
|||
goto skip_console_init; |
|||
} |
|||
|
|||
if (dt_set_stdout_pinctrl() != 0) { |
|||
goto skip_console_init; |
|||
} |
|||
|
|||
if (stm32mp1_clk_enable((unsigned long)dt_dev_info.clock) != 0) { |
|||
goto skip_console_init; |
|||
} |
|||
|
|||
stm32mp1_reset_assert((uint32_t)dt_dev_info.reset); |
|||
udelay(2); |
|||
stm32mp1_reset_deassert((uint32_t)dt_dev_info.reset); |
|||
mdelay(1); |
|||
|
|||
clk_rate = stm32mp1_clk_get_rate((unsigned long)dt_dev_info.clock); |
|||
|
|||
if (console_init(dt_dev_info.base, clk_rate, |
|||
STM32MP1_UART_BAUDRATE) == 0) { |
|||
panic(); |
|||
} |
|||
|
|||
board_model = dt_get_board_model(); |
|||
if (board_model != NULL) { |
|||
NOTICE("%s\n", board_model); |
|||
} |
|||
|
|||
skip_console_init: |
|||
|
|||
if (stm32_save_boot_interface(boot_context->boot_interface_selected, |
|||
boot_context->boot_interface_instance) != |
|||
0) { |
|||
ERROR("Cannot save boot interface\n"); |
|||
} |
|||
|
|||
stm32mp1_arch_security_setup(); |
|||
|
|||
stm32mp1_io_setup(); |
|||
} |
@ -0,0 +1,235 @@ |
|||
/*
|
|||
* Copyright (c) 2017, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __BOOT_API_H |
|||
#define __BOOT_API_H |
|||
|
|||
#include <stdint.h> |
|||
|
|||
/*
|
|||
* Possible value of boot context field 'boot_interface_sel' |
|||
*/ |
|||
|
|||
/* Value of field 'boot_interface_sel' when no boot occurred */ |
|||
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_NO 0x0U |
|||
|
|||
/* Boot occurred on SD */ |
|||
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD 0x1U |
|||
|
|||
/* Boot occurred on EMMC */ |
|||
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC 0x2U |
|||
|
|||
/**
|
|||
* @brief Possible value of boot context field 'EmmcXferStatus' |
|||
*/ |
|||
/*
|
|||
* Possible value of boot context field 'emmc_xfer_status' |
|||
*/ |
|||
#define BOOT_API_CTX_EMMC_XFER_STATUS_NOT_STARTED 0x0U |
|||
#define BOOT_API_CTX_EMMC_XFER_STATUS_DATAEND_DETECTED 0x1U |
|||
#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_OVERALL_TIMEOUT_DETECTED 0x2U |
|||
#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_DATA_TIMEOUT 0x3U |
|||
|
|||
/*
|
|||
* Possible value of boot context field 'emmc_error_status' |
|||
*/ |
|||
#define BOOT_API_CTX_EMMC_ERROR_STATUS_NONE 0x0U |
|||
#define BOOT_API_CTX_EMMC_ERROR_STATUS_CMD_TIMEOUT 0x1U |
|||
#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_TIMEOUT 0x2U |
|||
#define BOOT_API_CTX_EMMC_ERROR_STATUS_DATA_CRC_FAIL 0x3U |
|||
#define BOOT_API_CTX_EMMC_ERROR_STATUS_NOT_ENOUGH_BOOT_DATA_RX 0x4U |
|||
#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND 0x5U |
|||
#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO 0x6U |
|||
#define BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE 0x7U |
|||
|
|||
/* Image Header related definitions */ |
|||
|
|||
/* Definition of header version */ |
|||
#define BOOT_API_HEADER_VERSION 0x00010000U |
|||
|
|||
/*
|
|||
* Magic number used to detect header in memory |
|||
* Its value must be 'S' 'T' 'M' 0x32, i.e 0x324D5453 as field |
|||
* 'bootapi_image_header_t.magic' |
|||
* This identifies the start of a boot image. |
|||
*/ |
|||
#define BOOT_API_IMAGE_HEADER_MAGIC_NB 0x324D5453U |
|||
|
|||
/* Definitions related to Authentication used in image header structure */ |
|||
#define BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES 64 |
|||
#define BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES 64 |
|||
#define BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES 32 |
|||
|
|||
/* Possible values of the field 'boot_api_image_header_t.ecc_algo_type' */ |
|||
#define BOOT_API_ECDSA_ALGO_TYPE_P256NIST 1 |
|||
#define BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256 2 |
|||
|
|||
/*
|
|||
* Cores secure magic numbers |
|||
* Constant to be stored in bakcup register |
|||
* BOOT_API_MAGIC_NUMBER_TAMP_BCK_REG_IDX |
|||
*/ |
|||
#define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xCA7FACE0U |
|||
#define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1U |
|||
|
|||
/*
|
|||
* TAMP_BCK4R register index |
|||
* This register is used to write a Magic Number in order to restart |
|||
* Cortex A7 Core 1 and make it execute @ branch address from TAMP_BCK5R |
|||
*/ |
|||
#define BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX 4U |
|||
|
|||
/*
|
|||
* TAMP_BCK5R register index |
|||
* This register is used to contain the branch address of |
|||
* Cortex A7 Core 1 when restarted by a TAMP_BCK4R magic number writing |
|||
*/ |
|||
#define BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX 5U |
|||
|
|||
/*
|
|||
* Possible value of boot context field 'hse_clock_value_in_hz' |
|||
*/ |
|||
#define BOOT_API_CTX_HSE_CLOCK_VALUE_UNDEFINED 0U |
|||
#define BOOT_API_CTX_HSE_CLOCK_VALUE_24_MHZ 24000000U |
|||
#define BOOT_API_CTX_HSE_CLOCK_VALUE_25_MHZ 25000000U |
|||
#define BOOT_API_CTX_HSE_CLOCK_VALUE_26_MHZ 26000000U |
|||
|
|||
/*
|
|||
* Possible value of boot context field 'boot_partition_used_toboot' |
|||
*/ |
|||
#define BOOT_API_CTX_BOOT_PARTITION_UNDEFINED 0U |
|||
|
|||
/* Used FSBL1 to boot */ |
|||
#define BOOT_API_CTX_BOOT_PARTITION_FSBL1 1U |
|||
|
|||
/* Used FSBL2 to boot */ |
|||
#define BOOT_API_CTX_BOOT_PARTITION_FSBL2 2U |
|||
|
|||
/* OTP_CFG0 */ |
|||
#define BOOT_API_OTP_MODE_WORD_NB 0 |
|||
/* Closed = OTP_CFG0[6] */ |
|||
#define BOOT_API_OTP_MODE_CLOSED_BIT_POS 6 |
|||
|
|||
/*
|
|||
* Boot Context related definitions |
|||
*/ |
|||
|
|||
/*
|
|||
* Boot core boot configuration structure |
|||
* Specifies all items of the cold boot configuration |
|||
* Memory and peripheral part. |
|||
*/ |
|||
typedef struct { |
|||
/*
|
|||
* Boot interface used to boot : take values from defines |
|||
* BOOT_API_CTX_BOOT_INTERFACE_SEL_XXX above |
|||
*/ |
|||
uint16_t boot_interface_selected; |
|||
uint16_t boot_interface_instance; |
|||
uint32_t reserved1[13]; |
|||
uint32_t otp_afmux_values[3]; |
|||
uint32_t reserved[9]; |
|||
/*
|
|||
* Information specific to an SD boot |
|||
* Updated each time an SD boot is at least attempted, |
|||
* even if not successful |
|||
* Note : This is useful to understand why an SD boot failed |
|||
* in particular |
|||
*/ |
|||
uint32_t sd_err_internal_timeout_cnt; |
|||
uint32_t sd_err_dcrc_fail_cnt; |
|||
uint32_t sd_err_dtimeout_cnt; |
|||
uint32_t sd_err_ctimeout_cnt; |
|||
uint32_t sd_err_ccrc_fail_cnt; |
|||
uint32_t sd_overall_retry_cnt; |
|||
/*
|
|||
* Information specific to an eMMC boot |
|||
* Updated each time an eMMC boot is at least attempted, |
|||
* even if not successful |
|||
* Note : This is useful to understand why an eMMC boot failed |
|||
* in particular |
|||
*/ |
|||
uint32_t emmc_xfer_status; |
|||
uint32_t emmc_error_status; |
|||
uint32_t emmc_nbbytes_rxcopied_tosysram_download_area; |
|||
uint32_t hse_clock_value_in_hz; |
|||
/*
|
|||
* Boot partition : |
|||
* ie FSBL partition on which the boot was successful |
|||
*/ |
|||
uint32_t boot_partition_used_toboot; |
|||
|
|||
} __packed boot_api_context_t; |
|||
|
|||
/*
|
|||
* Image Header related definitions |
|||
*/ |
|||
|
|||
/*
|
|||
* Structure used to define the common Header format used for FSBL, xloader, |
|||
* ... and in particular used by bootROM for FSBL header readout. |
|||
* FSBL header size is 256 Bytes = 0x100 |
|||
*/ |
|||
typedef struct { |
|||
/* BOOT_API_IMAGE_HEADER_MAGIC_NB */ |
|||
uint32_t magic; |
|||
uint8_t image_signature[BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES]; |
|||
/*
|
|||
* Checksum of payload |
|||
* 32-bit sum all all payload bytes considered as 8 bit unigned numbers, |
|||
* discarding any overflow bits. |
|||
* Use to check UART/USB downloaded image integrity when signature |
|||
* is not used (i.e bit 0 : 'No_sig_check' = 1 in option flags) |
|||
*/ |
|||
uint32_t payload_checksum; |
|||
/* Image header version : should have value BOOT_API_HEADER_VERSION */ |
|||
uint32_t header_version; |
|||
/* Image length in bytes */ |
|||
uint32_t image_length; |
|||
/*
|
|||
* Image Entry point address : should be in the SYSRAM area |
|||
* and at least within the download area range |
|||
*/ |
|||
uint32_t image_entry_point; |
|||
/* Reserved */ |
|||
uint32_t reserved1; |
|||
/*
|
|||
* Image load address : not used by bootROM but to be consistent |
|||
* with header format for other packages (xloader, ...) |
|||
*/ |
|||
uint32_t load_address; |
|||
/* Reserved */ |
|||
uint32_t reserved2; |
|||
/* Image version to be compared by bootROM with monotonic
|
|||
* counter value in OTP_CFG4 prior executing the downloaded image |
|||
*/ |
|||
uint32_t image_version; |
|||
/*
|
|||
* Option flags: |
|||
* Bit 0 : No signature check request : 'No_sig_check' |
|||
* value 1 : for No signature check request |
|||
* value 0 : No request to bypass the signature check |
|||
* Note : No signature check is never allowed on a Secured chip |
|||
*/ |
|||
uint32_t option_flags; |
|||
/*
|
|||
* Type of ECC algorithm to use : |
|||
* value 1 : for P-256 NIST algorithm |
|||
* value 2 : for Brainpool 256 algorithm |
|||
* See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above. |
|||
*/ |
|||
uint32_t ecc_algo_type; |
|||
/*
|
|||
* OEM ECC Public Key (aka Root pubk) provided in header on 512 bits. |
|||
* The SHA-256 hash of the OEM ECC pubk must match the one stored |
|||
* in OTP cells. |
|||
*/ |
|||
uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES]; |
|||
/* Pad up to 256 byte total size */ |
|||
uint8_t pad[84]; |
|||
} __packed boot_api_image_header_t; |
|||
|
|||
#endif /* __BOOT_API_H */ |
@ -0,0 +1,187 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef PLATFORM_DEF_H |
|||
#define PLATFORM_DEF_H |
|||
|
|||
#include <arch.h> |
|||
#include <common_def.h> |
|||
#include <gic_common.h> |
|||
#include <utils_def.h> |
|||
#include "../stm32mp1_def.h" |
|||
|
|||
/*******************************************************************************
|
|||
* Generic platform constants |
|||
******************************************************************************/ |
|||
|
|||
/* Size of cacheable stacks */ |
|||
#if defined(IMAGE_BL32) |
|||
#define PLATFORM_STACK_SIZE 0x600 |
|||
#else |
|||
#define PLATFORM_STACK_SIZE 0xC00 |
|||
#endif |
|||
|
|||
/* SSBL = second stage boot loader */ |
|||
#define BL33_IMAGE_NAME "ssbl" |
|||
|
|||
#define STM32MP1_PRIMARY_CPU U(0x0) |
|||
|
|||
#define PLATFORM_CACHE_LINE_SIZE 64 |
|||
#define PLATFORM_CLUSTER_COUNT ULL(1) |
|||
#define PLATFORM_CLUSTER0_CORE_COUNT U(2) |
|||
#define PLATFORM_CLUSTER1_CORE_COUNT U(0) |
|||
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ |
|||
PLATFORM_CLUSTER0_CORE_COUNT) |
|||
#define PLATFORM_MAX_CPUS_PER_CLUSTER 2 |
|||
|
|||
#define MAX_IO_DEVICES 4 |
|||
#define MAX_IO_HANDLES 4 |
|||
|
|||
/*******************************************************************************
|
|||
* BL2 specific defines. |
|||
******************************************************************************/ |
|||
/*
|
|||
* Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug |
|||
* size plus a little space for growth. |
|||
*/ |
|||
#define BL2_BASE STM32MP1_BL2_BASE |
|||
#define BL2_LIMIT (STM32MP1_BL2_BASE + \ |
|||
STM32MP1_BL2_SIZE) |
|||
|
|||
/*******************************************************************************
|
|||
* BL32 specific defines. |
|||
******************************************************************************/ |
|||
#define BL32_BASE STM32MP1_BL32_BASE |
|||
#define BL32_LIMIT (STM32MP1_BL32_BASE + \ |
|||
STM32MP1_BL32_SIZE) |
|||
|
|||
/*******************************************************************************
|
|||
* BL33 specific defines. |
|||
******************************************************************************/ |
|||
#define BL33_BASE STM32MP1_BL33_BASE |
|||
|
|||
/*
|
|||
* Load address of BL33 for this platform port |
|||
*/ |
|||
#define PLAT_STM32MP1_NS_IMAGE_OFFSET BL33_BASE |
|||
|
|||
/*******************************************************************************
|
|||
* DTB specific defines. |
|||
******************************************************************************/ |
|||
#define DTB_BASE STM32MP1_DTB_BASE |
|||
#define DTB_LIMIT (STM32MP1_DTB_BASE + \ |
|||
STM32MP1_DTB_SIZE) |
|||
|
|||
/*******************************************************************************
|
|||
* Platform specific page table and MMU setup constants |
|||
******************************************************************************/ |
|||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) |
|||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) |
|||
|
|||
/*******************************************************************************
|
|||
* Declarations and constants to access the mailboxes safely. Each mailbox is |
|||
* aligned on the biggest cache line size in the platform. This is known only |
|||
* to the platform as it might have a combination of integrated and external |
|||
* caches. Such alignment ensures that two maiboxes do not sit on the same cache |
|||
* line at any cache level. They could belong to different cpus/clusters & |
|||
* get written while being protected by different locks causing corruption of |
|||
* a valid mailbox address. |
|||
******************************************************************************/ |
|||
#define CACHE_WRITEBACK_SHIFT 6 |
|||
#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) |
|||
|
|||
/*
|
|||
* Secure Interrupt: based on the standard ARM mapping |
|||
*/ |
|||
#define ARM_IRQ_SEC_PHY_TIMER U(29) |
|||
|
|||
#define ARM_IRQ_SEC_SGI_0 U(8) |
|||
#define ARM_IRQ_SEC_SGI_1 U(9) |
|||
#define ARM_IRQ_SEC_SGI_2 U(10) |
|||
#define ARM_IRQ_SEC_SGI_3 U(11) |
|||
#define ARM_IRQ_SEC_SGI_4 U(12) |
|||
#define ARM_IRQ_SEC_SGI_5 U(13) |
|||
#define ARM_IRQ_SEC_SGI_6 U(14) |
|||
#define ARM_IRQ_SEC_SGI_7 U(15) |
|||
|
|||
#define STM32MP1_IRQ_TZC400 U(36) |
|||
#define STM32MP1_IRQ_TAMPSERRS U(229) |
|||
#define STM32MP1_IRQ_AXIERRIRQ U(244) |
|||
|
|||
/*
|
|||
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 |
|||
* terminology. On a GICv2 system or mode, the lists will be merged and treated |
|||
* as Group 0 interrupts. |
|||
*/ |
|||
#define PLATFORM_G1S_PROPS(grp) \ |
|||
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_LEVEL), \ |
|||
INTR_PROP_DESC(STM32MP1_IRQ_TAMPSERRS, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_LEVEL), \ |
|||
INTR_PROP_DESC(STM32MP1_IRQ_AXIERRIRQ, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_LEVEL), \ |
|||
INTR_PROP_DESC(STM32MP1_IRQ_TZC400, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_LEVEL), \ |
|||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_EDGE), \ |
|||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_EDGE), \ |
|||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_EDGE), \ |
|||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_EDGE), \ |
|||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_EDGE), \ |
|||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_EDGE) |
|||
|
|||
#define PLATFORM_G0_PROPS(grp) \ |
|||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_EDGE), \ |
|||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, \ |
|||
GIC_HIGHEST_SEC_PRIORITY, \ |
|||
grp, GIC_INTR_CFG_EDGE) |
|||
|
|||
/*
|
|||
* Power |
|||
*/ |
|||
#define PLAT_MAX_PWR_LVL U(1) |
|||
|
|||
/* Local power state for power domains in Run state. */ |
|||
#define ARM_LOCAL_STATE_RUN U(0) |
|||
/* Local power state for retention. Valid only for CPU power domains */ |
|||
#define ARM_LOCAL_STATE_RET U(1) |
|||
/* Local power state for power-down. Valid for CPU and cluster power domains */ |
|||
#define ARM_LOCAL_STATE_OFF U(2) |
|||
/*
|
|||
* This macro defines the deepest retention state possible. |
|||
* A higher state id will represent an invalid or a power down state. |
|||
*/ |
|||
#define PLAT_MAX_RET_STATE ARM_LOCAL_STATE_RET |
|||
/*
|
|||
* This macro defines the deepest power down states possible. Any state ID |
|||
* higher than this is invalid. |
|||
*/ |
|||
#define PLAT_MAX_OFF_STATE ARM_LOCAL_STATE_OFF |
|||
|
|||
/*******************************************************************************
|
|||
* Size of the per-cpu data in bytes that should be reserved in the generic |
|||
* per-cpu data structure for the FVP port. |
|||
******************************************************************************/ |
|||
#define PLAT_PCPU_DATA_SIZE 2 |
|||
|
|||
#endif /* PLATFORM_DEF_H */ |
@ -0,0 +1,14 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_CONTEXT_H__ |
|||
#define __STM32MP1_CONTEXT_H__ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
int stm32_save_boot_interface(uint32_t interface, uint32_t instance); |
|||
|
|||
#endif /* __STM32MP1_CONTEXT_H__ */ |
@ -0,0 +1,41 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_DT_H__ |
|||
#define __STM32MP1_DT_H__ |
|||
|
|||
#include <stdbool.h> |
|||
|
|||
struct dt_node_info { |
|||
uint32_t base; |
|||
int32_t clock; |
|||
int32_t reset; |
|||
bool status; |
|||
bool sec_status; |
|||
}; |
|||
|
|||
/*******************************************************************************
|
|||
* Function and variable prototypes |
|||
******************************************************************************/ |
|||
int dt_open_and_check(void); |
|||
int fdt_get_address(void **fdt_addr); |
|||
bool fdt_check_node(int node); |
|||
bool fdt_check_status(int node); |
|||
bool fdt_check_secure_status(int node); |
|||
uint32_t fdt_read_uint32_default(int node, const char *prop_name, |
|||
uint32_t dflt_value); |
|||
int fdt_read_uint32_array(int node, const char *prop_name, |
|||
uint32_t *array, uint32_t count); |
|||
int dt_set_pinctrl_config(int node); |
|||
int dt_set_stdout_pinctrl(void); |
|||
void dt_fill_device_info(struct dt_node_info *info, int node); |
|||
int dt_get_node(struct dt_node_info *info, int offset, const char *compat); |
|||
int dt_get_stdout_uart_info(struct dt_node_info *info); |
|||
int dt_get_stdout_node_offset(void); |
|||
uint32_t dt_get_ddr_size(void); |
|||
const char *dt_get_board_model(void); |
|||
|
|||
#endif /* __STM32MP1_DT_H__ */ |
@ -0,0 +1,22 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_PRIVATE_H__ |
|||
#define __STM32MP1_PRIVATE_H__ |
|||
|
|||
void stm32mp1_io_setup(void); |
|||
void configure_mmu(void); |
|||
|
|||
void stm32mp1_arch_security_setup(void); |
|||
void stm32mp1_security_setup(void); |
|||
|
|||
void stm32mp1_save_boot_ctx_address(uintptr_t address); |
|||
uintptr_t stm32mp1_get_boot_ctx_address(void); |
|||
|
|||
void stm32mp1_gic_pcpu_init(void); |
|||
void stm32mp1_gic_init(void); |
|||
|
|||
#endif /* __STM32MP1_PRIVATE_H__ */ |
@ -0,0 +1,68 @@ |
|||
/*
|
|||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <bl_common.h> |
|||
#include <desc_image_load.h> |
|||
#include <platform.h> |
|||
#include <platform_def.h> |
|||
|
|||
/*******************************************************************************
|
|||
* Following descriptor provides BL image/ep information that gets used |
|||
* by BL2 to load the images and also subset of this information is |
|||
* passed to next BL image. The image loading sequence is managed by |
|||
* populating the images in required loading order. The image execution |
|||
* sequence is managed by populating the `next_handoff_image_id` with |
|||
* the next executable image id. |
|||
******************************************************************************/ |
|||
static bl_mem_params_node_t bl2_mem_params_descs[] = { |
|||
/* Fill BL32 related information */ |
|||
{ |
|||
.image_id = BL32_IMAGE_ID, |
|||
|
|||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, |
|||
VERSION_2, entry_point_info_t, |
|||
SECURE | EXECUTABLE | EP_FIRST_EXE), |
|||
|
|||
.ep_info.pc = BL32_BASE, |
|||
.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, |
|||
SPSR_E_LITTLE, |
|||
DISABLE_ALL_EXCEPTIONS), |
|||
|
|||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, |
|||
VERSION_2, image_info_t, |
|||
IMAGE_ATTRIB_PLAT_SETUP), |
|||
|
|||
.image_info.image_base = BL32_BASE, |
|||
.image_info.image_max_size = BL32_LIMIT - BL32_BASE, |
|||
|
|||
.next_handoff_image_id = BL33_IMAGE_ID, |
|||
}, |
|||
|
|||
/* Fill BL33 related information */ |
|||
{ |
|||
.image_id = BL33_IMAGE_ID, |
|||
|
|||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, |
|||
VERSION_2, entry_point_info_t, |
|||
NON_SECURE | EXECUTABLE), |
|||
|
|||
.ep_info.pc = PLAT_STM32MP1_NS_IMAGE_OFFSET, |
|||
.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, |
|||
SPSR_E_LITTLE, |
|||
DISABLE_ALL_EXCEPTIONS), |
|||
|
|||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, |
|||
VERSION_2, image_info_t, 0), |
|||
|
|||
.image_info.image_base = PLAT_STM32MP1_NS_IMAGE_OFFSET, |
|||
.image_info.image_max_size = STM32MP1_DDR_MAX_SIZE - |
|||
(PLAT_STM32MP1_NS_IMAGE_OFFSET - STM32MP1_DDR_BASE), |
|||
|
|||
.next_handoff_image_id = INVALID_IMAGE_ID, |
|||
} |
|||
}; |
|||
|
|||
REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) |
@ -0,0 +1,32 @@ |
|||
/*
|
|||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <desc_image_load.h> |
|||
|
|||
/*******************************************************************************
|
|||
* This function flushes the data structures so that they are visible |
|||
* in memory for the next BL image. |
|||
******************************************************************************/ |
|||
void plat_flush_next_bl_params(void) |
|||
{ |
|||
flush_bl_params_desc(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function returns the list of loadable images. |
|||
******************************************************************************/ |
|||
bl_load_info_t *plat_get_bl_image_load_info(void) |
|||
{ |
|||
return get_bl_load_info_from_mem_params_desc(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function returns the list of executable images. |
|||
******************************************************************************/ |
|||
bl_params_t *plat_get_next_bl_params(void) |
|||
{ |
|||
return get_next_bl_params_from_mem_params_desc(); |
|||
} |
@ -0,0 +1,148 @@ |
|||
#
|
|||
# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
|||
#
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
|||
#
|
|||
|
|||
ARM_CORTEX_A7 := yes |
|||
ARM_WITH_NEON := yes |
|||
LOAD_IMAGE_V2 := 1 |
|||
BL2_AT_EL3 := 1 |
|||
ENABLE_PLAT_COMPAT := 0 |
|||
USE_COHERENT_MEM := 0 |
|||
|
|||
STM32_TF_VERSION ?= 0 |
|||
|
|||
# Not needed for Cortex-A7
|
|||
WORKAROUND_CVE_2017_5715:= 0 |
|||
|
|||
PLAT_INCLUDES := -Iplat/st/stm32mp1/include/ |
|||
PLAT_INCLUDES += -Iinclude/common/tbbr |
|||
PLAT_INCLUDES += -Iinclude/drivers/st |
|||
|
|||
# Device tree
|
|||
STM32_DTB_FILE_NAME ?= stm32mp157c-ev1.dtb |
|||
FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32_DTB_FILE_NAME))) |
|||
DTC_FLAGS += -Wno-unit_address_vs_reg |
|||
|
|||
include lib/libfdt/libfdt.mk |
|||
|
|||
PLAT_BL_COMMON_SOURCES := plat/st/stm32mp1/stm32mp1_common.c |
|||
|
|||
PLAT_BL_COMMON_SOURCES += drivers/console/aarch32/console.S \
|
|||
drivers/st/uart/aarch32/stm32_console.S |
|||
|
|||
ifneq (${ENABLE_STACK_PROTECTOR},0) |
|||
PLAT_BL_COMMON_SOURCES += plat/st/stm32mp1/stm32mp1_stack_protector.c |
|||
endif |
|||
|
|||
include lib/xlat_tables_v2/xlat_tables.mk |
|||
PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} |
|||
|
|||
PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S |
|||
|
|||
PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \
|
|||
drivers/arm/tzc/tzc400.c \
|
|||
drivers/delay_timer/delay_timer.c \
|
|||
drivers/delay_timer/generic_delay_timer.c \
|
|||
drivers/st/clk/stm32mp1_clk.c \
|
|||
drivers/st/clk/stm32mp1_clkfunc.c \
|
|||
drivers/st/ddr/stm32mp1_ddr_helpers.c \
|
|||
drivers/st/gpio/stm32_gpio.c \
|
|||
drivers/st/pmic/stm32_i2c.c \
|
|||
drivers/st/pmic/stm32mp1_pmic.c \
|
|||
drivers/st/pmic/stpmu1.c \
|
|||
drivers/st/reset/stm32mp1_reset.c \
|
|||
plat/st/stm32mp1/stm32mp1_context.c \
|
|||
plat/st/stm32mp1/stm32mp1_dt.c \
|
|||
plat/st/stm32mp1/stm32mp1_helper.S \
|
|||
plat/st/stm32mp1/stm32mp1_security.c |
|||
|
|||
BL2_SOURCES += drivers/io/io_dummy.c \
|
|||
drivers/io/io_storage.c \
|
|||
plat/st/stm32mp1/bl2_io_storage.c \
|
|||
plat/st/stm32mp1/bl2_plat_setup.c |
|||
|
|||
BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \
|
|||
drivers/st/ddr/stm32mp1_ram.c |
|||
|
|||
BL2_SOURCES += common/desc_image_load.c \
|
|||
plat/st/stm32mp1/plat_bl2_mem_params_desc.c \
|
|||
plat/st/stm32mp1/plat_image_load.c |
|||
|
|||
# For memory footprint optimization, build with thumb and interwork support
|
|||
ASFLAGS += -mthumb -mthumb-interwork |
|||
TF_CFLAGS += -mthumb -mthumb-interwork |
|||
|
|||
# Macros and rules to build TF binary
|
|||
STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed |
|||
STM32_DT_BASENAME := $(STM32_DTB_FILE_NAME:.dtb=) |
|||
STM32_TF_STM32 := ${BUILD_PLAT}/tf-a-${STM32_DT_BASENAME}.stm32 |
|||
STM32_TF_BINARY := $(STM32_TF_STM32:.stm32=.bin) |
|||
STM32_TF_MAPFILE := $(STM32_TF_STM32:.stm32=.map) |
|||
STM32_TF_LINKERFILE := $(STM32_TF_STM32:.stm32=.ld) |
|||
STM32_TF_ELF := $(STM32_TF_STM32:.stm32=.elf) |
|||
STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${STM32_DTB_FILE_NAME} |
|||
STM32_TF_OBJS := ${BUILD_PLAT}/stm32mp1.o |
|||
|
|||
# Variables for use with stm32image
|
|||
STM32IMAGEPATH ?= tools/stm32image |
|||
STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT} |
|||
|
|||
.PHONY: ${STM32_TF_STM32} |
|||
.SUFFIXES: |
|||
|
|||
all: check_dtc_version ${STM32_TF_STM32} stm32image |
|||
|
|||
ifeq ($(AARCH32_SP),sp_min) |
|||
# BL32 is built only if using SP_MIN
|
|||
BL32_DEP := bl32 |
|||
BL32_PATH := -DBL32_BIN_PATH=\"${BUILD_PLAT}/bl32.bin\" |
|||
endif |
|||
|
|||
distclean realclean clean: clean_stm32image |
|||
|
|||
stm32image: |
|||
${Q}${MAKE} CPPFLAGS="" --no-print-directory -C ${STM32IMAGEPATH} |
|||
|
|||
clean_stm32image: |
|||
${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean |
|||
|
|||
check_dtc_version: |
|||
$(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}')) |
|||
$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g"))) |
|||
@if [ ${DTC_VERSION} -lt 10404 ]; then \
|
|||
echo "dtc version too old (${DTC_V}), you need at least version 1.4.4"; \
|
|||
false; \
|
|||
fi |
|||
|
|||
|
|||
${STM32_TF_OBJS}: plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} ${STM32_TF_DTBFILE} |
|||
@echo " AS $<" |
|||
${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
|
|||
${BL32_PATH} \
|
|||
-DBL2_BIN_PATH=\"${BUILD_PLAT}/bl2.bin\" \
|
|||
-DDTB_BIN_PATH=\"${STM32_TF_DTBFILE}\" \
|
|||
-c plat/st/stm32mp1/stm32mp1.S -o $@ |
|||
|
|||
${STM32_TF_LINKERFILE}: plat/st/stm32mp1/stm32mp1.ld.S |
|||
@echo " LDS $<" |
|||
${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} -P -E $< -o $@ |
|||
|
|||
${STM32_TF_ELF}: ${STM32_TF_OBJS} ${STM32_TF_LINKERFILE} |
|||
@echo " LDS $<" |
|||
${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=${STM32_TF_MAPFILE} --script ${STM32_TF_LINKERFILE} ${STM32_TF_OBJS} |
|||
|
|||
${STM32_TF_BINARY}: ${STM32_TF_ELF} |
|||
${Q}${OC} -O binary ${STM32_TF_ELF} $@ |
|||
@echo |
|||
@echo "Built $@ successfully" |
|||
@echo |
|||
|
|||
${STM32_TF_STM32}: stm32image ${STM32_TF_BINARY} |
|||
@echo |
|||
@echo "Generated $@" |
|||
$(eval LOADADDR = $(shell cat ${STM32_TF_MAPFILE} | grep RAM | awk '{print $$2}')) |
|||
$(eval ENTRY = $(shell cat ${STM32_TF_MAPFILE} | grep "__BL2_IMAGE_START" | awk '{print $$1}')) |
|||
${STM32IMAGE} -s ${STM32_TF_BINARY} -d $@ -l $(LOADADDR) -e ${ENTRY} -v ${STM32_TF_VERSION} |
|||
@echo |
@ -0,0 +1,21 @@ |
|||
#
|
|||
# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
|||
#
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
|||
#
|
|||
|
|||
SP_MIN_WITH_SECURE_FIQ := 1 |
|||
|
|||
BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \
|
|||
plat/st/stm32mp1/sp_min/sp_min_setup.c \
|
|||
plat/st/stm32mp1/stm32mp1_pm.c \
|
|||
plat/st/stm32mp1/stm32mp1_topology.c |
|||
# Generic GIC v2
|
|||
BL32_SOURCES += drivers/arm/gic/common/gic_common.c \
|
|||
drivers/arm/gic/v2/gicv2_helpers.c \
|
|||
drivers/arm/gic/v2/gicv2_main.c \
|
|||
plat/common/plat_gicv2.c \
|
|||
plat/st/stm32mp1/stm32mp1_gic.c |
|||
|
|||
# Generic PSCI
|
|||
BL32_SOURCES += plat/common/plat_psci_common.c |
@ -0,0 +1,144 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, 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 <context.h> |
|||
#include <context_mgmt.h> |
|||
#include <debug.h> |
|||
#include <dt-bindings/clock/stm32mp1-clks.h> |
|||
#include <generic_delay_timer.h> |
|||
#include <mmio.h> |
|||
#include <platform.h> |
|||
#include <platform_def.h> |
|||
#include <platform_sp_min.h> |
|||
#include <stm32mp1_clk.h> |
|||
#include <stm32mp1_dt.h> |
|||
#include <stm32mp1_private.h> |
|||
#include <string.h> |
|||
#include <tzc400.h> |
|||
#include <xlat_tables_v2.h> |
|||
|
|||
/******************************************************************************
|
|||
* Placeholder variables for copying the arguments that have been passed to |
|||
* BL32 from BL2. |
|||
******************************************************************************/ |
|||
static entry_point_info_t bl33_image_ep_info; |
|||
|
|||
/*******************************************************************************
|
|||
* Interrupt handler for FIQ (secure IRQ) |
|||
******************************************************************************/ |
|||
void sp_min_plat_fiq_handler(uint32_t id) |
|||
{ |
|||
switch (id) { |
|||
case STM32MP1_IRQ_TZC400: |
|||
ERROR("STM32MP1_IRQ_TZC400 generated\n"); |
|||
panic(); |
|||
break; |
|||
case STM32MP1_IRQ_AXIERRIRQ: |
|||
ERROR("STM32MP1_IRQ_AXIERRIRQ generated\n"); |
|||
panic(); |
|||
break; |
|||
default: |
|||
ERROR("SECURE IT handler not define for it : %i", id); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Return a pointer to the 'entry_point_info' structure of the next image for |
|||
* the security state specified. BL33 corresponds to the non-secure image type |
|||
* while BL32 corresponds to the secure image type. A NULL pointer is returned |
|||
* if the image does not exist. |
|||
******************************************************************************/ |
|||
entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) |
|||
{ |
|||
entry_point_info_t *next_image_info; |
|||
|
|||
next_image_info = &bl33_image_ep_info; |
|||
|
|||
if (next_image_info->pc == 0U) { |
|||
return NULL; |
|||
} |
|||
|
|||
return next_image_info; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Perform any BL32 specific platform actions. |
|||
******************************************************************************/ |
|||
void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, |
|||
u_register_t arg2, u_register_t arg3) |
|||
{ |
|||
struct dt_node_info dt_dev_info; |
|||
int result; |
|||
bl_params_t *params_from_bl2 = (bl_params_t *)arg0; |
|||
|
|||
/* Imprecise aborts can be masked in NonSecure */ |
|||
write_scr(read_scr() | SCR_AW_BIT); |
|||
|
|||
assert(params_from_bl2 != NULL); |
|||
assert(params_from_bl2->h.type == PARAM_BL_PARAMS); |
|||
assert(params_from_bl2->h.version >= VERSION_2); |
|||
|
|||
bl_params_node_t *bl_params = params_from_bl2->head; |
|||
|
|||
/*
|
|||
* Copy BL33 entry point information. |
|||
* They are stored in Secure RAM, in BL2's address space. |
|||
*/ |
|||
while (bl_params != NULL) { |
|||
if (bl_params->image_id == BL33_IMAGE_ID) { |
|||
bl33_image_ep_info = *bl_params->ep_info; |
|||
break; |
|||
} |
|||
|
|||
bl_params = bl_params->next_params_info; |
|||
} |
|||
|
|||
if (dt_open_and_check() < 0) { |
|||
panic(); |
|||
} |
|||
|
|||
if (stm32mp1_clk_probe() < 0) { |
|||
panic(); |
|||
} |
|||
|
|||
result = dt_get_stdout_uart_info(&dt_dev_info); |
|||
|
|||
if ((result > 0) && dt_dev_info.status) { |
|||
if (console_init(dt_dev_info.base, 0, STM32MP1_UART_BAUDRATE) |
|||
== 0) { |
|||
panic(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Initialize the MMU, security and the GIC. |
|||
******************************************************************************/ |
|||
void sp_min_platform_setup(void) |
|||
{ |
|||
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, |
|||
BL_CODE_END - BL_CODE_BASE, |
|||
MT_CODE | MT_SECURE); |
|||
|
|||
configure_mmu(); |
|||
|
|||
/* Initialize tzc400 after DDR initialization */ |
|||
stm32mp1_security_setup(); |
|||
|
|||
generic_delay_timer_init(); |
|||
|
|||
stm32mp1_gic_init(); |
|||
} |
|||
|
|||
void sp_min_plat_arch_setup(void) |
|||
{ |
|||
} |
@ -0,0 +1,16 @@ |
|||
/* |
|||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifdef BL32_BIN_PATH |
|||
.section .bl32_image |
|||
.incbin BL32_BIN_PATH |
|||
#endif |
|||
|
|||
.section .bl2_image |
|||
.incbin BL2_BIN_PATH |
|||
|
|||
.section .dtb_image |
|||
.incbin DTB_BIN_PATH |
@ -0,0 +1,76 @@ |
|||
/* |
|||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __STM32MP1_LD_S__ |
|||
#define __STM32MP1_LD_S__ |
|||
#include <platform_def.h> |
|||
#include <xlat_tables_defs.h> |
|||
|
|||
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) |
|||
OUTPUT_ARCH(PLATFORM_LINKER_ARCH) |
|||
|
|||
ENTRY(__BL2_IMAGE_START__) |
|||
|
|||
MEMORY { |
|||
HEADER (rw) : ORIGIN = 0x00000000, LENGTH = 0x3000 |
|||
RAM (rwx) : ORIGIN = STM32MP1_BINARY_BASE, LENGTH = STM32MP1_BINARY_SIZE |
|||
} |
|||
|
|||
SECTIONS |
|||
{ |
|||
/* |
|||
* TF mapping must conform to ROM code specification. |
|||
*/ |
|||
.header : { |
|||
__HEADER_START__ = .; |
|||
KEEP(*(.header)) |
|||
. = ALIGN(4); |
|||
__HEADER_END__ = .; |
|||
} >HEADER |
|||
|
|||
. = STM32MP1_BINARY_BASE; |
|||
.data . : { |
|||
. = ALIGN(PAGE_SIZE); |
|||
__DATA_START__ = .; |
|||
*(.data*) |
|||
|
|||
/* |
|||
* dtb. |
|||
* The strongest and only alignment contraint is MMU 4K page. |
|||
* Indeed as images below will be removed, 4K pages will be re-used. |
|||
*/ |
|||
. = ( STM32MP1_DTB_BASE - STM32MP1_BINARY_BASE ); |
|||
__DTB_IMAGE_START__ = .; |
|||
*(.dtb_image*) |
|||
__DTB_IMAGE_END__ = .; |
|||
|
|||
/* |
|||
* bl2. |
|||
* The strongest and only alignment contraint is MMU 4K page. |
|||
* Indeed as images below will be removed, 4K pages will be re-used. |
|||
*/ |
|||
. = ( STM32MP1_BL2_BASE - STM32MP1_BINARY_BASE ); |
|||
__BL2_IMAGE_START__ = .; |
|||
*(.bl2_image*) |
|||
__BL2_IMAGE_END__ = .; |
|||
|
|||
/* |
|||
* bl32 will be settled by bl2. |
|||
* The strongest and only alignment constraint is 8 words to simplify |
|||
* memraise8 assembly code. |
|||
*/ |
|||
. = ( STM32MP1_BL32_BASE - STM32MP1_BINARY_BASE ); |
|||
__BL32_IMAGE_START__ = .; |
|||
*(.bl32_image*) |
|||
__BL32_IMAGE_END__ = .; |
|||
|
|||
__DATA_END__ = .; |
|||
} >RAM |
|||
|
|||
__TF_END__ = .; |
|||
|
|||
} |
|||
#endif /*__STM32MP1_LD_S__*/ |
@ -0,0 +1,101 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, 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 <gicv2.h> |
|||
#include <mmio.h> |
|||
#include <platform_def.h> |
|||
#include <platform.h> |
|||
#include <stm32mp1_private.h> |
|||
#include <xlat_tables_v2.h> |
|||
|
|||
#define MAP_SRAM MAP_REGION_FLAT(STM32MP1_SRAM_BASE, \ |
|||
STM32MP1_SRAM_SIZE, \ |
|||
MT_MEMORY | \ |
|||
MT_RW | \ |
|||
MT_SECURE | \ |
|||
MT_EXECUTE_NEVER) |
|||
|
|||
#define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \ |
|||
STM32MP1_DEVICE1_SIZE, \ |
|||
MT_DEVICE | \ |
|||
MT_RW | \ |
|||
MT_SECURE | \ |
|||
MT_EXECUTE_NEVER) |
|||
|
|||
#define MAP_DEVICE2 MAP_REGION_FLAT(STM32MP1_DEVICE2_BASE, \ |
|||
STM32MP1_DEVICE2_SIZE, \ |
|||
MT_DEVICE | \ |
|||
MT_RW | \ |
|||
MT_SECURE | \ |
|||
MT_EXECUTE_NEVER) |
|||
|
|||
#define MAP_DDR MAP_REGION_FLAT(STM32MP1_DDR_BASE, \ |
|||
STM32MP1_DDR_MAX_SIZE, \ |
|||
MT_MEMORY | \ |
|||
MT_RW | \ |
|||
MT_SECURE | \ |
|||
MT_EXECUTE_NEVER) |
|||
|
|||
#define MAP_DDR_NS MAP_REGION_FLAT(STM32MP1_DDR_BASE, \ |
|||
STM32MP1_DDR_MAX_SIZE, \ |
|||
MT_MEMORY | \ |
|||
MT_RW | \ |
|||
MT_NS | \ |
|||
MT_EXECUTE_NEVER) |
|||
|
|||
#if defined(IMAGE_BL2) |
|||
static const mmap_region_t stm32mp1_mmap[] = { |
|||
MAP_SRAM, |
|||
MAP_DEVICE1, |
|||
MAP_DEVICE2, |
|||
MAP_DDR, |
|||
{0} |
|||
}; |
|||
#endif |
|||
#if defined(IMAGE_BL32) |
|||
static const mmap_region_t stm32mp1_mmap[] = { |
|||
MAP_SRAM, |
|||
MAP_DEVICE1, |
|||
MAP_DEVICE2, |
|||
MAP_DDR_NS, |
|||
{0} |
|||
}; |
|||
#endif |
|||
|
|||
void configure_mmu(void) |
|||
{ |
|||
mmap_add(stm32mp1_mmap); |
|||
init_xlat_tables(); |
|||
|
|||
enable_mmu_secure(0); |
|||
} |
|||
|
|||
uintptr_t plat_get_ns_image_entrypoint(void) |
|||
{ |
|||
return BL33_BASE; |
|||
} |
|||
|
|||
unsigned int plat_get_syscnt_freq2(void) |
|||
{ |
|||
return read_cntfrq_el0(); |
|||
} |
|||
|
|||
/* Functions to save and get boot context address given by ROM code */ |
|||
static uintptr_t boot_ctx_address; |
|||
|
|||
void stm32mp1_save_boot_ctx_address(uintptr_t address) |
|||
{ |
|||
boot_ctx_address = address; |
|||
} |
|||
|
|||
uintptr_t stm32mp1_get_boot_ctx_address(void) |
|||
{ |
|||
return boot_ctx_address; |
|||
} |
@ -0,0 +1,42 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <dt-bindings/clock/stm32mp1-clks.h> |
|||
#include <errno.h> |
|||
#include <mmio.h> |
|||
#include <platform_def.h> |
|||
#include <stm32mp1_clk.h> |
|||
#include <stm32mp1_context.h> |
|||
|
|||
#define TAMP_BOOT_ITF_BACKUP_REG_ID U(20) |
|||
#define TAMP_BOOT_ITF_MASK U(0x0000FF00) |
|||
#define TAMP_BOOT_ITF_SHIFT 8 |
|||
|
|||
int stm32_save_boot_interface(uint32_t interface, uint32_t instance) |
|||
{ |
|||
uint32_t tamp_clk_off = 0; |
|||
uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID); |
|||
|
|||
if (!stm32mp1_clk_is_enabled(RTCAPB)) { |
|||
tamp_clk_off = 1; |
|||
if (stm32mp1_clk_enable(RTCAPB) != 0) { |
|||
return -EINVAL; |
|||
} |
|||
} |
|||
|
|||
mmio_clrsetbits_32(bkpr_itf_idx, |
|||
TAMP_BOOT_ITF_MASK, |
|||
((interface << 4) | (instance & 0xFU)) << |
|||
TAMP_BOOT_ITF_SHIFT); |
|||
|
|||
if (tamp_clk_off != 0U) { |
|||
if (stm32mp1_clk_disable(RTCAPB) != 0) { |
|||
return -EINVAL; |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,193 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef STM32MP1_DEF_H |
|||
#define STM32MP1_DEF_H |
|||
|
|||
#include <tbbr_img_def.h> |
|||
#include <utils_def.h> |
|||
#include <xlat_tables_defs.h> |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 memory map related constants |
|||
******************************************************************************/ |
|||
|
|||
#define STM32MP1_SRAM_BASE U(0x2FFC0000) |
|||
#define STM32MP1_SRAM_SIZE U(0x00040000) |
|||
|
|||
/* DDR configuration */ |
|||
#define STM32MP1_DDR_BASE U(0xC0000000) |
|||
#define STM32MP1_DDR_SIZE_DFLT U(0x20000000) /* 512 MB */ |
|||
#define STM32MP1_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */ |
|||
#define STM32MP1_DDR_SPEED_DFLT 528 |
|||
|
|||
/* DDR power initializations */ |
|||
#ifndef __ASSEMBLY__ |
|||
enum ddr_type { |
|||
STM32MP_DDR3, |
|||
STM32MP_LPDDR2, |
|||
}; |
|||
#endif |
|||
|
|||
/* Section used inside TF binaries */ |
|||
#define STM32MP1_PARAM_LOAD_SIZE U(0x00002400) /* 9 Ko for param */ |
|||
/* 256 Octets reserved for header */ |
|||
#define STM32MP1_HEADER_SIZE U(0x00000100) |
|||
|
|||
#define STM32MP1_BINARY_BASE (STM32MP1_SRAM_BASE + \ |
|||
STM32MP1_PARAM_LOAD_SIZE + \ |
|||
STM32MP1_HEADER_SIZE) |
|||
|
|||
#define STM32MP1_BINARY_SIZE (STM32MP1_SRAM_SIZE - \ |
|||
(STM32MP1_PARAM_LOAD_SIZE + \ |
|||
STM32MP1_HEADER_SIZE)) |
|||
|
|||
#if STACK_PROTECTOR_ENABLED |
|||
#define STM32MP1_BL32_SIZE U(0x00012000) /* 72 Ko for BL32 */ |
|||
#else |
|||
#define STM32MP1_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */ |
|||
#endif |
|||
|
|||
#define STM32MP1_BL32_BASE (STM32MP1_SRAM_BASE + \ |
|||
STM32MP1_SRAM_SIZE - \ |
|||
STM32MP1_BL32_SIZE) |
|||
|
|||
#if STACK_PROTECTOR_ENABLED |
|||
#define STM32MP1_BL2_SIZE U(0x00015000) /* 84 Ko for BL2 */ |
|||
#else |
|||
#define STM32MP1_BL2_SIZE U(0x00013000) /* 76 Ko for BL2 */ |
|||
#endif |
|||
|
|||
#define STM32MP1_BL2_BASE (STM32MP1_BL32_BASE - \ |
|||
STM32MP1_BL2_SIZE) |
|||
|
|||
/* BL2 and BL32/sp_min require 5 tables */ |
|||
#define MAX_XLAT_TABLES 5 |
|||
|
|||
/*
|
|||
* MAX_MMAP_REGIONS is usually: |
|||
* BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup |
|||
*/ |
|||
#if defined(IMAGE_BL2) |
|||
#define MAX_MMAP_REGIONS 11 |
|||
#endif |
|||
#if defined(IMAGE_BL32) |
|||
#define MAX_MMAP_REGIONS 6 |
|||
#endif |
|||
|
|||
/* DTB initialization value */ |
|||
#define STM32MP1_DTB_SIZE U(0x00004000) /* 16Ko for DTB */ |
|||
|
|||
#define STM32MP1_DTB_BASE (STM32MP1_BL2_BASE - \ |
|||
STM32MP1_DTB_SIZE) |
|||
|
|||
#define STM32MP1_BL33_BASE (STM32MP1_DDR_BASE + U(0x100000)) |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 device/io map related constants (used for MMU) |
|||
******************************************************************************/ |
|||
#define STM32MP1_DEVICE1_BASE U(0x40000000) |
|||
#define STM32MP1_DEVICE1_SIZE U(0x40000000) |
|||
|
|||
#define STM32MP1_DEVICE2_BASE U(0x80000000) |
|||
#define STM32MP1_DEVICE2_SIZE U(0x40000000) |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 RCC |
|||
******************************************************************************/ |
|||
#define RCC_BASE U(0x50000000) |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 PWR |
|||
******************************************************************************/ |
|||
#define PWR_BASE U(0x50001000) |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 UART |
|||
******************************************************************************/ |
|||
#define USART1_BASE U(0x5C000000) |
|||
#define USART2_BASE U(0x4000E000) |
|||
#define USART3_BASE U(0x4000F000) |
|||
#define UART4_BASE U(0x40010000) |
|||
#define UART5_BASE U(0x40011000) |
|||
#define USART6_BASE U(0x44003000) |
|||
#define UART7_BASE U(0x40018000) |
|||
#define UART8_BASE U(0x40019000) |
|||
#define STM32MP1_DEBUG_USART_BASE UART4_BASE |
|||
#define STM32MP1_UART_BAUDRATE 115200 |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 GIC-400 |
|||
******************************************************************************/ |
|||
#define STM32MP1_GICD_BASE U(0xA0021000) |
|||
#define STM32MP1_GICC_BASE U(0xA0022000) |
|||
#define STM32MP1_GICH_BASE U(0xA0024000) |
|||
#define STM32MP1_GICV_BASE U(0xA0026000) |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 TZC (TZ400) |
|||
******************************************************************************/ |
|||
#define STM32MP1_TZC_BASE U(0x5C006000) |
|||
|
|||
#define STM32MP1_TZC_A7_ID U(0) |
|||
#define STM32MP1_TZC_LCD_ID U(3) |
|||
#define STM32MP1_TZC_GPU_ID U(4) |
|||
#define STM32MP1_TZC_MDMA_ID U(5) |
|||
#define STM32MP1_TZC_DMA_ID U(6) |
|||
#define STM32MP1_TZC_USB_HOST_ID U(7) |
|||
#define STM32MP1_TZC_USB_OTG_ID U(8) |
|||
#define STM32MP1_TZC_SDMMC_ID U(9) |
|||
#define STM32MP1_TZC_ETH_ID U(10) |
|||
#define STM32MP1_TZC_DAP_ID U(15) |
|||
|
|||
#define STM32MP1_MEMORY_NS 0 |
|||
#define STM32MP1_MEMORY_SECURE 1 |
|||
|
|||
#define STM32MP1_FILTER_BIT_ALL 3 |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 SDMMC |
|||
******************************************************************************/ |
|||
#define STM32MP1_SDMMC1_BASE U(0x58005000) |
|||
#define STM32MP1_SDMMC2_BASE U(0x58007000) |
|||
#define STM32MP1_SDMMC3_BASE U(0x48004000) |
|||
|
|||
#define STM32MP1_SD_INIT_FREQ 400000 /*400 KHz*/ |
|||
#define STM32MP1_SD_NORMAL_SPEED_MAX_FREQ 25000000 /*25 MHz*/ |
|||
#define STM32MP1_SD_HIGH_SPEED_MAX_FREQ 50000000 /*50 MHz*/ |
|||
#define STM32MP1_EMMC_INIT_FREQ STM32MP1_SD_INIT_FREQ |
|||
#define STM32MP1_EMMC_NORMAL_SPEED_MAX_FREQ 26000000 /*26 MHz*/ |
|||
#define STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ 52000000 /*52 MHz*/ |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 TAMP |
|||
******************************************************************************/ |
|||
#define TAMP_BASE U(0x5C00A000) |
|||
#define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100)) |
|||
|
|||
#if !(defined(__LINKER__) || defined(__ASSEMBLY__)) |
|||
static inline uint32_t tamp_bkpr(uint32_t idx) |
|||
{ |
|||
return TAMP_BKP_REGISTER_BASE + (idx << 2); |
|||
} |
|||
#endif |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 DDRCTRL |
|||
******************************************************************************/ |
|||
#define DDRCTRL_BASE U(0x5A003000) |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 DDRPHYC |
|||
******************************************************************************/ |
|||
#define DDRPHYC_BASE U(0x5A004000) |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 I2C4 |
|||
******************************************************************************/ |
|||
#define I2C4_BASE U(0x5C002000) |
|||
|
|||
#endif /* STM32MP1_DEF_H */ |
@ -0,0 +1,476 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <assert.h> |
|||
#include <debug.h> |
|||
#include <libfdt.h> |
|||
#include <platform_def.h> |
|||
#include <stm32_gpio.h> |
|||
#include <stm32mp1_clk.h> |
|||
#include <stm32mp1_clkfunc.h> |
|||
#include <stm32mp1_ddr.h> |
|||
#include <stm32mp1_dt.h> |
|||
#include <stm32mp1_ram.h> |
|||
|
|||
#define DT_GPIO_BANK_SHIFT 12 |
|||
#define DT_GPIO_BANK_MASK 0x1F000U |
|||
#define DT_GPIO_PIN_SHIFT 8 |
|||
#define DT_GPIO_PIN_MASK 0xF00U |
|||
#define DT_GPIO_MODE_MASK 0xFFU |
|||
|
|||
static int fdt_checked; |
|||
|
|||
static void *fdt = (void *)(uintptr_t)STM32MP1_DTB_BASE; |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets the pin settings from DT information. |
|||
* When analyze and parsing is done, set the GPIO registers. |
|||
* Return 0 on success, else return a negative FDT_ERR_xxx error code. |
|||
******************************************************************************/ |
|||
static int dt_set_gpio_config(int node) |
|||
{ |
|||
const fdt32_t *cuint, *slewrate; |
|||
int len, pinctrl_node, pinctrl_subnode; |
|||
uint32_t i; |
|||
uint32_t speed = GPIO_SPEED_LOW; |
|||
uint32_t pull = GPIO_NO_PULL; |
|||
|
|||
cuint = fdt_getprop(fdt, node, "pinmux", &len); |
|||
if (cuint == NULL) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); |
|||
if (pinctrl_node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); |
|||
if (slewrate != NULL) { |
|||
speed = fdt32_to_cpu(*slewrate); |
|||
} |
|||
|
|||
if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { |
|||
pull = GPIO_PULL_UP; |
|||
} else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { |
|||
pull = GPIO_PULL_DOWN; |
|||
} else { |
|||
VERBOSE("No bias configured in node %d\n", node); |
|||
} |
|||
|
|||
for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { |
|||
uint32_t pincfg; |
|||
uint32_t bank; |
|||
uint32_t pin; |
|||
uint32_t mode; |
|||
uint32_t alternate = GPIO_ALTERNATE_0; |
|||
|
|||
pincfg = fdt32_to_cpu(*cuint); |
|||
cuint++; |
|||
|
|||
bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; |
|||
|
|||
pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; |
|||
|
|||
mode = pincfg & DT_GPIO_MODE_MASK; |
|||
|
|||
switch (mode) { |
|||
case 0: |
|||
mode = GPIO_MODE_INPUT; |
|||
break; |
|||
case 1 ... 16: |
|||
alternate = mode - 1U; |
|||
mode = GPIO_MODE_ALTERNATE; |
|||
break; |
|||
case 17: |
|||
mode = GPIO_MODE_ANALOG; |
|||
break; |
|||
default: |
|||
mode = GPIO_MODE_OUTPUT; |
|||
break; |
|||
} |
|||
|
|||
if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { |
|||
mode |= GPIO_OPEN_DRAIN; |
|||
} |
|||
|
|||
fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { |
|||
uint32_t bank_offset; |
|||
const fdt32_t *cuint2; |
|||
|
|||
if (fdt_getprop(fdt, pinctrl_subnode, |
|||
"gpio-controller", NULL) == NULL) { |
|||
continue; |
|||
} |
|||
|
|||
cuint2 = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); |
|||
if (cuint2 == NULL) { |
|||
continue; |
|||
} |
|||
|
|||
if (bank == GPIO_BANK_Z) { |
|||
bank_offset = 0; |
|||
} else { |
|||
bank_offset = bank * STM32_GPIO_BANK_OFFSET; |
|||
} |
|||
|
|||
if (fdt32_to_cpu(*cuint2) == bank_offset) { |
|||
int clk_id = fdt_get_clock_id(pinctrl_subnode); |
|||
|
|||
if (clk_id < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
if (stm32mp1_clk_enable((unsigned long)clk_id) < |
|||
0) { |
|||
return -FDT_ERR_BADVALUE; |
|||
} |
|||
|
|||
break; |
|||
} |
|||
} |
|||
|
|||
set_gpio(bank, pin, mode, speed, pull, alternate); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function checks device tree file with its header. |
|||
* Returns 0 if success, and a negative value else. |
|||
******************************************************************************/ |
|||
int dt_open_and_check(void) |
|||
{ |
|||
int ret = fdt_check_header(fdt); |
|||
|
|||
if (ret == 0) { |
|||
fdt_checked = 1; |
|||
} |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets the address of the DT. |
|||
* If DT is OK, fdt_addr is filled with DT address. |
|||
* Returns 1 if success, 0 otherwise. |
|||
******************************************************************************/ |
|||
int fdt_get_address(void **fdt_addr) |
|||
{ |
|||
if (fdt_checked == 1) { |
|||
*fdt_addr = fdt; |
|||
} |
|||
|
|||
return fdt_checked; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function check the presence of a node (generic use of fdt library). |
|||
* Returns true if present, false else. |
|||
******************************************************************************/ |
|||
bool fdt_check_node(int node) |
|||
{ |
|||
int len; |
|||
const char *cchar; |
|||
|
|||
cchar = fdt_get_name(fdt, node, &len); |
|||
|
|||
return (cchar != NULL) && (len >= 0); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function check the status of a node (generic use of fdt library). |
|||
* Returns true if "okay" or missing, false else. |
|||
******************************************************************************/ |
|||
bool fdt_check_status(int node) |
|||
{ |
|||
int len; |
|||
const char *cchar; |
|||
|
|||
cchar = fdt_getprop(fdt, node, "status", &len); |
|||
if (cchar == NULL) { |
|||
return true; |
|||
} |
|||
|
|||
return strncmp(cchar, "okay", (size_t)len) == 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function check the secure-status of a node (generic use of fdt library). |
|||
* Returns true if "okay" or missing, false else. |
|||
******************************************************************************/ |
|||
bool fdt_check_secure_status(int node) |
|||
{ |
|||
int len; |
|||
const char *cchar; |
|||
|
|||
cchar = fdt_getprop(fdt, node, "secure-status", &len); |
|||
if (cchar == NULL) { |
|||
return true; |
|||
} |
|||
|
|||
return strncmp(cchar, "okay", (size_t)len) == 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function reads a value of a node property (generic use of fdt |
|||
* library). |
|||
* Returns value if success, and a default value if property not found. |
|||
* Default value is passed as parameter. |
|||
******************************************************************************/ |
|||
uint32_t fdt_read_uint32_default(int node, const char *prop_name, |
|||
uint32_t dflt_value) |
|||
{ |
|||
const fdt32_t *cuint; |
|||
int lenp; |
|||
|
|||
cuint = fdt_getprop(fdt, node, prop_name, &lenp); |
|||
if (cuint == NULL) { |
|||
return dflt_value; |
|||
} |
|||
|
|||
return fdt32_to_cpu(*cuint); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function reads a series of parameters in a node property |
|||
* (generic use of fdt library). |
|||
* It reads the values inside the device tree, from property name and node. |
|||
* The number of parameters is also indicated as entry parameter. |
|||
* Returns 0 if success, and a negative value else. |
|||
* If success, values are stored at the third parameter address. |
|||
******************************************************************************/ |
|||
int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, |
|||
uint32_t count) |
|||
{ |
|||
const fdt32_t *cuint; |
|||
int len; |
|||
uint32_t i; |
|||
|
|||
cuint = fdt_getprop(fdt, node, prop_name, &len); |
|||
if (cuint == NULL) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
if ((uint32_t)len != (count * sizeof(uint32_t))) { |
|||
return -FDT_ERR_BADLAYOUT; |
|||
} |
|||
|
|||
for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { |
|||
*array = fdt32_to_cpu(*cuint); |
|||
array++; |
|||
cuint++; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets the pin settings from DT information. |
|||
* When analyze and parsing is done, set the GPIO registers. |
|||
* Returns 0 if success, and a negative value else. |
|||
******************************************************************************/ |
|||
int dt_set_pinctrl_config(int node) |
|||
{ |
|||
const fdt32_t *cuint; |
|||
int lenp = 0; |
|||
uint32_t i; |
|||
|
|||
if (!fdt_check_status(node)) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp); |
|||
if (cuint == NULL) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
for (i = 0; i < ((uint32_t)lenp / 4U); i++) { |
|||
int phandle_node, phandle_subnode; |
|||
|
|||
phandle_node = |
|||
fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); |
|||
if (phandle_node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
fdt_for_each_subnode(phandle_subnode, fdt, phandle_node) { |
|||
int ret = dt_set_gpio_config(phandle_subnode); |
|||
|
|||
if (ret < 0) { |
|||
return ret; |
|||
} |
|||
} |
|||
|
|||
cuint++; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets the stdout pin configuration information from the DT. |
|||
* And then calls the sub-function to treat it and set GPIO registers. |
|||
* Returns 0 if success, and a negative value else. |
|||
******************************************************************************/ |
|||
int dt_set_stdout_pinctrl(void) |
|||
{ |
|||
int node; |
|||
|
|||
node = dt_get_stdout_node_offset(); |
|||
if (node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
return dt_set_pinctrl_config(node); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function fills the generic information from a given node. |
|||
******************************************************************************/ |
|||
void dt_fill_device_info(struct dt_node_info *info, int node) |
|||
{ |
|||
const fdt32_t *cuint; |
|||
|
|||
cuint = fdt_getprop(fdt, node, "reg", NULL); |
|||
if (cuint != NULL) { |
|||
info->base = fdt32_to_cpu(*cuint); |
|||
} else { |
|||
info->base = 0; |
|||
} |
|||
|
|||
cuint = fdt_getprop(fdt, node, "clocks", NULL); |
|||
if (cuint != NULL) { |
|||
cuint++; |
|||
info->clock = (int)fdt32_to_cpu(*cuint); |
|||
} else { |
|||
info->clock = -1; |
|||
} |
|||
|
|||
cuint = fdt_getprop(fdt, node, "resets", NULL); |
|||
if (cuint != NULL) { |
|||
cuint++; |
|||
info->reset = (int)fdt32_to_cpu(*cuint); |
|||
} else { |
|||
info->reset = -1; |
|||
} |
|||
|
|||
info->status = fdt_check_status(node); |
|||
info->sec_status = fdt_check_secure_status(node); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function retrieve the generic information from DT. |
|||
* Returns node if success, and a negative value else. |
|||
******************************************************************************/ |
|||
int dt_get_node(struct dt_node_info *info, int offset, const char *compat) |
|||
{ |
|||
int node; |
|||
|
|||
node = fdt_node_offset_by_compatible(fdt, offset, compat); |
|||
if (node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
dt_fill_device_info(info, node); |
|||
|
|||
return node; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets the UART instance info of stdout from the DT. |
|||
* Returns node if success, and a negative value else. |
|||
******************************************************************************/ |
|||
int dt_get_stdout_uart_info(struct dt_node_info *info) |
|||
{ |
|||
int node; |
|||
|
|||
node = dt_get_stdout_node_offset(); |
|||
if (node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
dt_fill_device_info(info, node); |
|||
|
|||
return node; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets the stdout path node. |
|||
* It reads the value indicated inside the device tree. |
|||
* Returns node if success, and a negative value else. |
|||
******************************************************************************/ |
|||
int dt_get_stdout_node_offset(void) |
|||
{ |
|||
int node; |
|||
const char *cchar; |
|||
|
|||
node = fdt_path_offset(fdt, "/chosen"); |
|||
if (node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
cchar = fdt_getprop(fdt, node, "stdout-path", NULL); |
|||
if (cchar == NULL) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
node = -FDT_ERR_NOTFOUND; |
|||
if (strchr(cchar, (int)':') != NULL) { |
|||
const char *name; |
|||
char *str = (char *)cchar; |
|||
int len = 0; |
|||
|
|||
while (strncmp(":", str, 1)) { |
|||
len++; |
|||
str++; |
|||
} |
|||
|
|||
name = fdt_get_alias_namelen(fdt, cchar, len); |
|||
|
|||
if (name != NULL) { |
|||
node = fdt_path_offset(fdt, name); |
|||
} |
|||
} else { |
|||
node = fdt_path_offset(fdt, cchar); |
|||
} |
|||
|
|||
return node; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function gets DDR size information from the DT. |
|||
* Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else. |
|||
******************************************************************************/ |
|||
uint32_t dt_get_ddr_size(void) |
|||
{ |
|||
int node; |
|||
|
|||
node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); |
|||
if (node < 0) { |
|||
INFO("%s: Cannot read DDR node in DT\n", __func__); |
|||
return STM32MP1_DDR_SIZE_DFLT; |
|||
} |
|||
|
|||
return fdt_read_uint32_default(node, "st,mem-size", |
|||
STM32MP1_DDR_SIZE_DFLT); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* This function retrieves board model from DT |
|||
* Returns string taken from model node, NULL otherwise |
|||
******************************************************************************/ |
|||
const char *dt_get_board_model(void) |
|||
{ |
|||
int node = fdt_path_offset(fdt, "/"); |
|||
|
|||
if (node < 0) { |
|||
return NULL; |
|||
} |
|||
|
|||
return (const char *)fdt_getprop(fdt, node, "model", NULL); |
|||
} |
@ -0,0 +1,48 @@ |
|||
/*
|
|||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <bl_common.h> |
|||
#include <gicv2.h> |
|||
#include <platform.h> |
|||
#include <platform_def.h> |
|||
#include <utils.h> |
|||
|
|||
#include <stm32mp1_private.h> |
|||
|
|||
/******************************************************************************
|
|||
* On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 |
|||
* interrupts. |
|||
*****************************************************************************/ |
|||
static const interrupt_prop_t stm32mp1_interrupt_props[] = { |
|||
PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0), |
|||
PLATFORM_G0_PROPS(GICV2_INTR_GROUP0) |
|||
}; |
|||
|
|||
static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; |
|||
|
|||
static const gicv2_driver_data_t platform_gic_data = { |
|||
.gicd_base = STM32MP1_GICD_BASE, |
|||
.gicc_base = STM32MP1_GICC_BASE, |
|||
.interrupt_props = stm32mp1_interrupt_props, |
|||
.interrupt_props_num = ARRAY_SIZE(stm32mp1_interrupt_props), |
|||
.target_masks = target_mask_array, |
|||
.target_masks_num = ARRAY_SIZE(target_mask_array), |
|||
}; |
|||
|
|||
void stm32mp1_gic_init(void) |
|||
{ |
|||
gicv2_driver_init(&platform_gic_data); |
|||
gicv2_distif_init(); |
|||
|
|||
stm32mp1_gic_pcpu_init(); |
|||
} |
|||
|
|||
void stm32mp1_gic_pcpu_init(void) |
|||
{ |
|||
gicv2_pcpu_distif_init(); |
|||
gicv2_set_pe_target_mask(plat_my_core_pos()); |
|||
gicv2_cpuif_enable(); |
|||
} |
@ -0,0 +1,180 @@ |
|||
/* |
|||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <arch.h> |
|||
#include <asm_macros.S> |
|||
#include <bl_common.h> |
|||
#include <platform_def.h> |
|||
#include <stm32_gpio.h> |
|||
#include <stm32mp1_rcc.h> |
|||
|
|||
#define GPIO_BANK_G_ADDRESS 0x50008000 |
|||
#define GPIO_TX_PORT 11 |
|||
#define GPIO_TX_SHIFT (GPIO_TX_PORT << 1) |
|||
#define GPIO_TX_ALT_SHIFT ((GPIO_TX_PORT - GPIO_ALT_LOWER_LIMIT) << 2) |
|||
#define STM32MP1_HSI_CLK 64000000 |
|||
|
|||
.globl platform_mem_init |
|||
.globl plat_report_exception |
|||
.globl plat_get_my_entrypoint |
|||
.globl plat_secondary_cold_boot_setup |
|||
.globl plat_reset_handler |
|||
.globl plat_is_my_cpu_primary |
|||
.globl plat_my_core_pos |
|||
.globl plat_crash_console_init |
|||
.globl plat_crash_console_flush |
|||
.globl plat_crash_console_putc |
|||
.globl plat_panic_handler |
|||
|
|||
func platform_mem_init |
|||
/* Nothing to do, don't need to init SYSRAM */ |
|||
bx lr |
|||
endfunc platform_mem_init |
|||
|
|||
func plat_report_exception |
|||
bx lr |
|||
endfunc plat_report_exception |
|||
|
|||
func plat_reset_handler |
|||
bx lr |
|||
endfunc plat_reset_handler |
|||
|
|||
/* ------------------------------------------------------------------ |
|||
* unsigned long plat_get_my_entrypoint (void); |
|||
* |
|||
* Main job of this routine is to distinguish between a cold and warm |
|||
* boot. |
|||
* |
|||
* Currently supports only cold boot |
|||
* ------------------------------------------------------------------ |
|||
*/ |
|||
func plat_get_my_entrypoint |
|||
mov r0, #0 |
|||
bx lr |
|||
endfunc plat_get_my_entrypoint |
|||
|
|||
/* --------------------------------------------- |
|||
* void plat_secondary_cold_boot_setup (void); |
|||
* |
|||
* Cold-booting secondary CPUs is not supported. |
|||
* --------------------------------------------- |
|||
*/ |
|||
func plat_secondary_cold_boot_setup |
|||
b . |
|||
endfunc plat_secondary_cold_boot_setup |
|||
|
|||
/* ----------------------------------------------------- |
|||
* unsigned int plat_is_my_cpu_primary (void); |
|||
* |
|||
* Find out whether the current cpu is the primary cpu. |
|||
* ----------------------------------------------------- |
|||
*/ |
|||
func plat_is_my_cpu_primary |
|||
ldcopr r0, MPIDR |
|||
ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) |
|||
and r0, r1 |
|||
cmp r0, #STM32MP1_PRIMARY_CPU |
|||
moveq r0, #1 |
|||
movne r0, #0 |
|||
bx lr |
|||
endfunc plat_is_my_cpu_primary |
|||
|
|||
/* ------------------------------------------- |
|||
* int plat_stm32mp1_get_core_pos(int mpidr); |
|||
* |
|||
* Return CorePos = (ClusterId * 4) + CoreId |
|||
* ------------------------------------------- |
|||
*/ |
|||
func plat_stm32mp1_get_core_pos |
|||
and r1, r0, #MPIDR_CPU_MASK |
|||
and r0, r0, #MPIDR_CLUSTER_MASK |
|||
add r0, r1, r0, LSR #6 |
|||
bx lr |
|||
endfunc plat_stm32mp1_get_core_pos |
|||
|
|||
/* ------------------------------------ |
|||
* unsigned int plat_my_core_pos(void) |
|||
* ------------------------------------ |
|||
*/ |
|||
func plat_my_core_pos |
|||
ldcopr r0, MPIDR |
|||
b plat_stm32mp1_get_core_pos |
|||
endfunc plat_my_core_pos |
|||
|
|||
/* --------------------------------------------- |
|||
* int plat_crash_console_init(void) |
|||
* |
|||
* Initialize the crash console without a C Runtime stack. |
|||
* --------------------------------------------- |
|||
*/ |
|||
func plat_crash_console_init |
|||
/* Enable GPIOs for UART4 TX */ |
|||
ldr r1, =(RCC_BASE + RCC_MP_AHB4ENSETR) |
|||
ldr r2, [r1] |
|||
/* Configure GPIO G11 */ |
|||
orr r2, r2, #RCC_MP_AHB4ENSETR_GPIOGEN |
|||
str r2, [r1] |
|||
ldr r1, =GPIO_BANK_G_ADDRESS |
|||
/* Set GPIO mode alternate */ |
|||
ldr r2, [r1, #GPIO_MODE_OFFSET] |
|||
bic r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT) |
|||
orr r2, r2, #(GPIO_MODE_ALTERNATE << GPIO_TX_SHIFT) |
|||
str r2, [r1, #GPIO_MODE_OFFSET] |
|||
/* Set GPIO speed low */ |
|||
ldr r2, [r1, #GPIO_SPEED_OFFSET] |
|||
bic r2, r2, #(GPIO_SPEED_MASK << GPIO_TX_SHIFT) |
|||
str r2, [r1, #GPIO_SPEED_OFFSET] |
|||
/* Set no-pull */ |
|||
ldr r2, [r1, #GPIO_PUPD_OFFSET] |
|||
bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT) |
|||
str r2, [r1, #GPIO_PUPD_OFFSET] |
|||
/* Set alternate AF6 */ |
|||
ldr r2, [r1, #GPIO_AFRH_OFFSET] |
|||
bic r2, r2, #(GPIO_ALTERNATE_MASK << GPIO_TX_ALT_SHIFT) |
|||
orr r2, r2, #(GPIO_ALTERNATE_6 << GPIO_TX_ALT_SHIFT) |
|||
str r2, [r1, #GPIO_AFRH_OFFSET] |
|||
|
|||
/* Enable UART clock, with HSI source */ |
|||
ldr r1, =(RCC_BASE + RCC_UART24CKSELR) |
|||
mov r2, #RCC_UART24CKSELR_HSI |
|||
str r2, [r1] |
|||
ldr r1, =(RCC_BASE + RCC_MP_APB1ENSETR) |
|||
ldr r2, [r1] |
|||
orr r2, r2, #RCC_MP_APB1ENSETR_UART4EN |
|||
str r2, [r1] |
|||
|
|||
ldr r0, =STM32MP1_DEBUG_USART_BASE |
|||
ldr r1, =STM32MP1_HSI_CLK |
|||
ldr r2, =STM32MP1_UART_BAUDRATE |
|||
b console_core_init |
|||
endfunc plat_crash_console_init |
|||
|
|||
/* --------------------------------------------- |
|||
* int plat_crash_console_flush(void) |
|||
* |
|||
* Flush the crash console without a C Runtime stack. |
|||
* --------------------------------------------- |
|||
*/ |
|||
func plat_crash_console_flush |
|||
ldr r1, =STM32MP1_DEBUG_USART_BASE |
|||
b console_core_flush |
|||
endfunc plat_crash_console_flush |
|||
|
|||
/* --------------------------------------------- |
|||
* int plat_crash_console_putc(int c) |
|||
* |
|||
* Print a character on the crash console without a C Runtime stack. |
|||
* Clobber list : r1 - r3 |
|||
* |
|||
* In case of bootloading through uart, we keep console crash as this. |
|||
* Characters could be sent to the programmer, but will be ignored. |
|||
* No specific code in that case. |
|||
* --------------------------------------------- |
|||
*/ |
|||
func plat_crash_console_putc |
|||
ldr r1, =STM32MP1_DEBUG_USART_BASE |
|||
b console_core_putc |
|||
endfunc plat_crash_console_putc |
@ -0,0 +1,255 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <assert.h> |
|||
#include <boot_api.h> |
|||
#include <debug.h> |
|||
#include <dt-bindings/clock/stm32mp1-clks.h> |
|||
#include <errno.h> |
|||
#include <gic_common.h> |
|||
#include <gicv2.h> |
|||
#include <mmio.h> |
|||
#include <platform_def.h> |
|||
#include <platform.h> |
|||
#include <psci.h> |
|||
#include <stm32mp1_clk.h> |
|||
#include <stm32mp1_private.h> |
|||
#include <stm32mp1_rcc.h> |
|||
|
|||
static uint32_t stm32_sec_entrypoint; |
|||
static uint32_t cntfrq_core0; |
|||
|
|||
#define SEND_SECURE_IT_TO_CORE_1 0x20000U |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 handler called when a CPU is about to enter standby. |
|||
* call by core 1 to enter in wfi |
|||
******************************************************************************/ |
|||
static void stm32_cpu_standby(plat_local_state_t cpu_state) |
|||
{ |
|||
uint32_t interrupt = GIC_SPURIOUS_INTERRUPT; |
|||
|
|||
assert(cpu_state == ARM_LOCAL_STATE_RET); |
|||
|
|||
/*
|
|||
* Enter standby state |
|||
* dsb is good practice before using wfi to enter low power states |
|||
*/ |
|||
dsb(); |
|||
while (interrupt == GIC_SPURIOUS_INTERRUPT) { |
|||
wfi(); |
|||
|
|||
/* Acknoledge IT */ |
|||
interrupt = gicv2_acknowledge_interrupt(); |
|||
/* If Interrupt == 1022 it will be acknowledged by non secure */ |
|||
if ((interrupt != PENDING_G1_INTID) && |
|||
(interrupt != GIC_SPURIOUS_INTERRUPT)) { |
|||
gicv2_end_of_interrupt(interrupt); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 handler called when a power domain is about to be turned on. The |
|||
* mpidr determines the CPU to be turned on. |
|||
* call by core 0 to activate core 1 |
|||
******************************************************************************/ |
|||
static int stm32_pwr_domain_on(u_register_t mpidr) |
|||
{ |
|||
unsigned long current_cpu_mpidr = read_mpidr_el1(); |
|||
uint32_t tamp_clk_off = 0; |
|||
uint32_t bkpr_core1_addr = |
|||
tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); |
|||
uint32_t bkpr_core1_magic = |
|||
tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); |
|||
|
|||
if (mpidr == current_cpu_mpidr) { |
|||
return PSCI_E_INVALID_PARAMS; |
|||
} |
|||
|
|||
if ((stm32_sec_entrypoint < STM32MP1_SRAM_BASE) || |
|||
(stm32_sec_entrypoint > (STM32MP1_SRAM_BASE + |
|||
(STM32MP1_SRAM_SIZE - 1)))) { |
|||
return PSCI_E_INVALID_ADDRESS; |
|||
} |
|||
|
|||
if (!stm32mp1_clk_is_enabled(RTCAPB)) { |
|||
tamp_clk_off = 1; |
|||
if (stm32mp1_clk_enable(RTCAPB) != 0) { |
|||
panic(); |
|||
} |
|||
} |
|||
|
|||
cntfrq_core0 = read_cntfrq_el0(); |
|||
|
|||
/* Write entrypoint in backup RAM register */ |
|||
mmio_write_32(bkpr_core1_addr, stm32_sec_entrypoint); |
|||
|
|||
/* Write magic number in backup register */ |
|||
mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER); |
|||
|
|||
if (tamp_clk_off != 0U) { |
|||
if (stm32mp1_clk_disable(RTCAPB) != 0) { |
|||
panic(); |
|||
} |
|||
} |
|||
|
|||
/* Generate an IT to core 1 */ |
|||
mmio_write_32(STM32MP1_GICD_BASE + GICD_SGIR, |
|||
SEND_SECURE_IT_TO_CORE_1 | ARM_IRQ_SEC_SGI_0); |
|||
|
|||
return PSCI_E_SUCCESS; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 handler called when a power domain is about to be turned off. The |
|||
* target_state encodes the power state that each level should transition to. |
|||
******************************************************************************/ |
|||
static void stm32_pwr_domain_off(const psci_power_state_t *target_state) |
|||
{ |
|||
/* Nothing to do */ |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 handler called when a power domain is about to be suspended. The |
|||
* target_state encodes the power state that each level should transition to. |
|||
******************************************************************************/ |
|||
static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state) |
|||
{ |
|||
/* Nothing to do, power domain is not disabled */ |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 handler called when a power domain has just been powered on after |
|||
* being turned off earlier. The target_state encodes the low power state that |
|||
* each level has woken up from. |
|||
* call by core 1 just after wake up |
|||
******************************************************************************/ |
|||
static void stm32_pwr_domain_on_finish(const psci_power_state_t *target_state) |
|||
{ |
|||
stm32mp1_gic_pcpu_init(); |
|||
|
|||
write_cntfrq_el0(cntfrq_core0); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* STM32MP1 handler called when a power domain has just been powered on after |
|||
* having been suspended earlier. The target_state encodes the low power state |
|||
* that each level has woken up from. |
|||
******************************************************************************/ |
|||
static void stm32_pwr_domain_suspend_finish(const psci_power_state_t |
|||
*target_state) |
|||
{ |
|||
/* Nothing to do, power domain is not disabled */ |
|||
} |
|||
|
|||
static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t |
|||
*target_state) |
|||
{ |
|||
ERROR("stm32mpu1 Power Down WFI: operation not handled.\n"); |
|||
panic(); |
|||
} |
|||
|
|||
static void __dead2 stm32_system_off(void) |
|||
{ |
|||
ERROR("stm32mpu1 System Off: operation not handled.\n"); |
|||
panic(); |
|||
} |
|||
|
|||
static void __dead2 stm32_system_reset(void) |
|||
{ |
|||
mmio_setbits_32(RCC_BASE + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPSYSRST); |
|||
|
|||
/* Loop in case system reset is not immediately caught */ |
|||
for ( ; ; ) { |
|||
; |
|||
} |
|||
} |
|||
|
|||
static int stm32_validate_power_state(unsigned int power_state, |
|||
psci_power_state_t *req_state) |
|||
{ |
|||
int pstate = psci_get_pstate_type(power_state); |
|||
|
|||
if (pstate != 0) { |
|||
return PSCI_E_INVALID_PARAMS; |
|||
} |
|||
|
|||
if (psci_get_pstate_pwrlvl(power_state)) { |
|||
return PSCI_E_INVALID_PARAMS; |
|||
} |
|||
|
|||
if (psci_get_pstate_id(power_state)) { |
|||
return PSCI_E_INVALID_PARAMS; |
|||
} |
|||
|
|||
req_state->pwr_domain_state[0] = ARM_LOCAL_STATE_RET; |
|||
req_state->pwr_domain_state[1] = ARM_LOCAL_STATE_RUN; |
|||
|
|||
return PSCI_E_SUCCESS; |
|||
} |
|||
|
|||
static int stm32_validate_ns_entrypoint(uintptr_t entrypoint) |
|||
{ |
|||
/* The non-secure entry point must be in DDR */ |
|||
if (entrypoint < STM32MP1_DDR_BASE) { |
|||
return PSCI_E_INVALID_ADDRESS; |
|||
} |
|||
|
|||
return PSCI_E_SUCCESS; |
|||
} |
|||
|
|||
static int stm32_node_hw_state(u_register_t target_cpu, |
|||
unsigned int power_level) |
|||
{ |
|||
/*
|
|||
* The format of 'power_level' is implementation-defined, but 0 must |
|||
* mean a CPU. Only allow level 0. |
|||
*/ |
|||
if (power_level != MPIDR_AFFLVL0) { |
|||
return PSCI_E_INVALID_PARAMS; |
|||
} |
|||
|
|||
/*
|
|||
* From psci view the CPU 0 is always ON, |
|||
* CPU 1 can be SUSPEND or RUNNING. |
|||
* Therefore do not manage POWER OFF state and always return HW_ON. |
|||
*/ |
|||
|
|||
return (int)HW_ON; |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Export the platform handlers. The ARM Standard platform layer will take care |
|||
* of registering the handlers with PSCI. |
|||
******************************************************************************/ |
|||
static const plat_psci_ops_t stm32_psci_ops = { |
|||
.cpu_standby = stm32_cpu_standby, |
|||
.pwr_domain_on = stm32_pwr_domain_on, |
|||
.pwr_domain_off = stm32_pwr_domain_off, |
|||
.pwr_domain_suspend = stm32_pwr_domain_suspend, |
|||
.pwr_domain_on_finish = stm32_pwr_domain_on_finish, |
|||
.pwr_domain_suspend_finish = stm32_pwr_domain_suspend_finish, |
|||
.pwr_domain_pwr_down_wfi = stm32_pwr_domain_pwr_down_wfi, |
|||
.system_off = stm32_system_off, |
|||
.system_reset = stm32_system_reset, |
|||
.validate_power_state = stm32_validate_power_state, |
|||
.validate_ns_entrypoint = stm32_validate_ns_entrypoint, |
|||
.get_node_hw_state = stm32_node_hw_state |
|||
}; |
|||
|
|||
/*******************************************************************************
|
|||
* Export the platform specific power ops. |
|||
******************************************************************************/ |
|||
int plat_setup_psci_ops(uintptr_t sec_entrypoint, |
|||
const plat_psci_ops_t **psci_ops) |
|||
{ |
|||
stm32_sec_entrypoint = sec_entrypoint; |
|||
*psci_ops = &stm32_psci_ops; |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,127 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <debug.h> |
|||
#include <dt-bindings/clock/stm32mp1-clks.h> |
|||
#include <mmio.h> |
|||
#include <stdint.h> |
|||
#include <stm32mp1_clk.h> |
|||
#include <stm32mp1_dt.h> |
|||
#include <stm32mp1_private.h> |
|||
#include <stm32mp1_rcc.h> |
|||
#include <tzc400.h> |
|||
#include "platform_def.h" |
|||
|
|||
/*******************************************************************************
|
|||
* Initialize the TrustZone Controller. Configure Region 0 with Secure RW access |
|||
* and allow Non-Secure masters full access. |
|||
******************************************************************************/ |
|||
static void init_tzc400(void) |
|||
{ |
|||
unsigned long long region_base, region_top; |
|||
unsigned long long ddr_base = STM32MP1_DDR_BASE; |
|||
unsigned long long ddr_size = (unsigned long long)dt_get_ddr_size(); |
|||
|
|||
tzc400_init(STM32MP1_TZC_BASE); |
|||
|
|||
tzc400_disable_filters(); |
|||
|
|||
/* Region 1 set to cover all DRAM at 0xC000_0000. Apply the
|
|||
* same configuration to all filters in the TZC. |
|||
*/ |
|||
region_base = ddr_base; |
|||
region_top = ddr_base + (ddr_size - 1U); |
|||
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, |
|||
region_base, |
|||
region_top, |
|||
TZC_REGION_S_RDWR, |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)); |
|||
|
|||
/* Raise an exception if a NS device tries to access secure memory */ |
|||
tzc400_set_action(TZC_ACTION_ERR); |
|||
|
|||
tzc400_enable_filters(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Initialize the TrustZone Controller. |
|||
* Early initialization create only one region with full access to secure. |
|||
* This setting is used before and during DDR initialization. |
|||
******************************************************************************/ |
|||
static void early_init_tzc400(void) |
|||
{ |
|||
uint32_t rstsr, rst_standby; |
|||
|
|||
rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR); |
|||
|
|||
/* No warning if return from (C)STANDBY */ |
|||
rst_standby = rstsr & |
|||
(RCC_MP_RSTSCLRR_STDBYRSTF | RCC_MP_RSTSCLRR_CSTDBYRSTF); |
|||
|
|||
if (stm32mp1_clk_is_enabled(TZC1) && (rst_standby == 0U)) { |
|||
WARN("TZC400 port 1 clock already enable\n"); |
|||
} |
|||
|
|||
if (stm32mp1_clk_is_enabled(TZC2) && (rst_standby == 0U)) { |
|||
WARN("TZC400 port 2 clock already enable\n"); |
|||
} |
|||
|
|||
if (stm32mp1_clk_enable(TZC1) != 0) { |
|||
ERROR("Cannot enable TZC1 clock\n"); |
|||
panic(); |
|||
} |
|||
if (stm32mp1_clk_enable(TZC2) != 0) { |
|||
ERROR("Cannot enable TZC2 clock\n"); |
|||
panic(); |
|||
} |
|||
|
|||
tzc400_init(STM32MP1_TZC_BASE); |
|||
|
|||
tzc400_disable_filters(); |
|||
|
|||
/*
|
|||
* Region 1 set to cover Non-Secure DRAM at 0x8000_0000. Apply the |
|||
* same configuration to all filters in the TZC. |
|||
*/ |
|||
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, |
|||
STM32MP1_DDR_BASE, |
|||
STM32MP1_DDR_BASE + |
|||
(STM32MP1_DDR_MAX_SIZE - 1U), |
|||
TZC_REGION_S_RDWR, |
|||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID)); |
|||
|
|||
/* Raise an exception if a NS device tries to access secure memory */ |
|||
tzc400_set_action(TZC_ACTION_ERR); |
|||
|
|||
tzc400_enable_filters(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Initialize the secure environment. At this moment only the TrustZone |
|||
* Controller is initialized. |
|||
******************************************************************************/ |
|||
void stm32mp1_arch_security_setup(void) |
|||
{ |
|||
early_init_tzc400(); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* Initialize the secure environment. At this moment only the TrustZone |
|||
* Controller is initialized. |
|||
******************************************************************************/ |
|||
void stm32mp1_security_setup(void) |
|||
{ |
|||
init_tzc400(); |
|||
} |
@ -0,0 +1,21 @@ |
|||
/*
|
|||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <arch_helpers.h> |
|||
#include <platform.h> |
|||
#include <stdint.h> |
|||
|
|||
#define RANDOM_CANARY_VALUE 2144346116U |
|||
|
|||
u_register_t plat_get_stack_protector_canary(void) |
|||
{ |
|||
/*
|
|||
* Ideally, a random number should be returned instead of the |
|||
* combination of a timer's value and a compile-time constant. |
|||
*/ |
|||
return RANDOM_CANARY_VALUE ^ (u_register_t)read_cntpct_el0(); |
|||
} |
|||
|
@ -0,0 +1,56 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <platform_def.h> |
|||
#include <platform.h> |
|||
#include <psci.h> |
|||
|
|||
/* 1 cluster, all cores into */ |
|||
static const unsigned char stm32mp1_power_domain_tree_desc[] = { |
|||
PLATFORM_CLUSTER_COUNT, |
|||
PLATFORM_CORE_COUNT, |
|||
}; |
|||
|
|||
/* This function returns the platform topology */ |
|||
const unsigned char *plat_get_power_domain_tree_desc(void) |
|||
{ |
|||
return stm32mp1_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; |
|||
u_register_t mpidr_copy = mpidr; |
|||
|
|||
mpidr_copy &= MPIDR_AFFINITY_MASK; |
|||
|
|||
if ((mpidr_copy & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) { |
|||
return -1; |
|||
} |
|||
|
|||
cluster_id = (mpidr_copy >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; |
|||
cpu_id = (mpidr_copy >> 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) { |
|||
return -1; |
|||
} |
|||
|
|||
return (int)cpu_id; |
|||
} |
@ -0,0 +1,49 @@ |
|||
#
|
|||
# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
|||
#
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
|||
#
|
|||
|
|||
MAKE_HELPERS_DIRECTORY := ../../make_helpers/ |
|||
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk |
|||
include ${MAKE_HELPERS_DIRECTORY}build_env.mk |
|||
|
|||
PROJECT := stm32image${BIN_EXT} |
|||
OBJECTS := stm32image.o |
|||
V := 0 |
|||
|
|||
override CPPFLAGS += -D_GNU_SOURCE |
|||
CFLAGS := -Wall -Werror -pedantic -std=c99 |
|||
ifeq (${DEBUG},1) |
|||
CFLAGS += -g -O0 -DDEBUG |
|||
else |
|||
CFLAGS += -O2 |
|||
endif |
|||
|
|||
ifeq (${V},0) |
|||
Q := @ |
|||
else |
|||
Q := |
|||
endif |
|||
|
|||
CC := gcc |
|||
|
|||
.PHONY: all clean distclean |
|||
|
|||
all: ${PROJECT} |
|||
|
|||
${PROJECT}: ${OBJECTS} Makefile |
|||
@echo " LD $@" |
|||
${Q}${CC} ${OBJECTS} -o $@ |
|||
@${ECHO_BLANK_LINE} |
|||
@echo "Built $@ successfully" |
|||
@${ECHO_BLANK_LINE} |
|||
|
|||
%.o: %.c %.h Makefile |
|||
@echo " CC $<" |
|||
${Q}${CC} -c ${CFLAGS} $< -o $@ |
|||
|
|||
clean: |
|||
$(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS}) |
|||
|
|||
distclean: clean |
@ -0,0 +1,247 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <asm/byteorder.h> |
|||
#include <errno.h> |
|||
#include <fcntl.h> |
|||
#include <stdint.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <sys/mman.h> |
|||
#include <sys/stat.h> |
|||
#include <sys/types.h> |
|||
#include <unistd.h> |
|||
|
|||
/* Magic = 'S' 'T' 'M' 0x32 */ |
|||
#define HEADER_MAGIC __be32_to_cpu(0x53544D32) |
|||
#define VER_MAJOR 2 |
|||
#define VER_MINOR 1 |
|||
#define VER_VARIANT 0 |
|||
#define HEADER_VERSION_V1 0x1 |
|||
#define TF_BINARY_TYPE 0x0 |
|||
|
|||
/* Default option : bit0 => no signature */ |
|||
#define HEADER_DEFAULT_OPTION (__cpu_to_le32(0x00000001)) |
|||
|
|||
struct stm32_header { |
|||
uint32_t magic_number; |
|||
uint8_t image_signature[64]; |
|||
uint32_t image_checksum; |
|||
uint8_t header_version[4]; |
|||
uint32_t image_length; |
|||
uint32_t image_entry_point; |
|||
uint32_t reserved1; |
|||
uint32_t load_address; |
|||
uint32_t reserved2; |
|||
uint32_t version_number; |
|||
uint32_t option_flags; |
|||
uint32_t ecdsa_algorithm; |
|||
uint8_t ecdsa_public_key[64]; |
|||
uint8_t padding[83]; |
|||
uint8_t binary_type; |
|||
}; |
|||
|
|||
static struct stm32_header stm32image_header; |
|||
|
|||
static void stm32image_default_header(struct stm32_header *ptr) |
|||
{ |
|||
if (!ptr) { |
|||
return; |
|||
} |
|||
|
|||
ptr->magic_number = HEADER_MAGIC; |
|||
ptr->header_version[VER_MAJOR] = HEADER_VERSION_V1; |
|||
ptr->option_flags = HEADER_DEFAULT_OPTION; |
|||
ptr->ecdsa_algorithm = 1; |
|||
ptr->version_number = 0; |
|||
ptr->binary_type = TF_BINARY_TYPE; |
|||
} |
|||
|
|||
static uint32_t stm32image_checksum(void *start, uint32_t len) |
|||
{ |
|||
uint32_t csum = 0; |
|||
uint32_t hdr_len = sizeof(struct stm32_header); |
|||
uint8_t *p; |
|||
|
|||
if (len < hdr_len) { |
|||
return 0; |
|||
} |
|||
|
|||
p = (unsigned char *)start + hdr_len; |
|||
len -= hdr_len; |
|||
|
|||
while (len > 0) { |
|||
csum += *p; |
|||
p++; |
|||
len--; |
|||
} |
|||
|
|||
return csum; |
|||
} |
|||
|
|||
static void stm32image_print_header(const void *ptr) |
|||
{ |
|||
struct stm32_header *stm32hdr = (struct stm32_header *)ptr; |
|||
|
|||
printf("Image Type : ST Microelectronics STM32 V%d.%d\n", |
|||
stm32hdr->header_version[VER_MAJOR], |
|||
stm32hdr->header_version[VER_MINOR]); |
|||
printf("Image Size : %lu bytes\n", |
|||
(unsigned long)__le32_to_cpu(stm32hdr->image_length)); |
|||
printf("Image Load : 0x%08x\n", |
|||
__le32_to_cpu(stm32hdr->load_address)); |
|||
printf("Entry Point : 0x%08x\n", |
|||
__le32_to_cpu(stm32hdr->image_entry_point)); |
|||
printf("Checksum : 0x%08x\n", |
|||
__le32_to_cpu(stm32hdr->image_checksum)); |
|||
printf("Option : 0x%08x\n", |
|||
__le32_to_cpu(stm32hdr->option_flags)); |
|||
printf("Version : 0x%08x\n", |
|||
__le32_to_cpu(stm32hdr->version_number)); |
|||
} |
|||
|
|||
static void stm32image_set_header(void *ptr, struct stat *sbuf, int ifd, |
|||
uint32_t loadaddr, uint32_t ep, uint32_t ver) |
|||
{ |
|||
struct stm32_header *stm32hdr = (struct stm32_header *)ptr; |
|||
|
|||
stm32image_default_header(stm32hdr); |
|||
|
|||
stm32hdr->load_address = __cpu_to_le32(loadaddr); |
|||
stm32hdr->image_entry_point = __cpu_to_le32(ep); |
|||
stm32hdr->image_length = __cpu_to_le32((uint32_t)sbuf->st_size - |
|||
sizeof(struct stm32_header)); |
|||
stm32hdr->image_checksum = stm32image_checksum(ptr, sbuf->st_size); |
|||
stm32hdr->version_number = __cpu_to_le32(ver); |
|||
} |
|||
|
|||
static int stm32image_create_header_file(char *srcname, char *destname, |
|||
uint32_t loadaddr, uint32_t entry, |
|||
uint32_t version) |
|||
{ |
|||
int src_fd, dest_fd; |
|||
struct stat sbuf; |
|||
unsigned char *ptr; |
|||
|
|||
dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666); |
|||
if (dest_fd == -1) { |
|||
fprintf(stderr, "Can't open %s: %s\n", destname, |
|||
strerror(errno)); |
|||
return -1; |
|||
} |
|||
|
|||
src_fd = open(srcname, O_RDONLY); |
|||
if (src_fd == -1) { |
|||
fprintf(stderr, "Can't open %s: %s\n", srcname, |
|||
strerror(errno)); |
|||
return -1; |
|||
} |
|||
|
|||
if (fstat(src_fd, &sbuf) < 0) { |
|||
return -1; |
|||
} |
|||
|
|||
ptr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, src_fd, 0); |
|||
if (ptr == MAP_FAILED) { |
|||
fprintf(stderr, "Can't read %s\n", srcname); |
|||
return -1; |
|||
} |
|||
|
|||
memset(&stm32image_header, 0, sizeof(struct stm32_header)); |
|||
|
|||
if (write(dest_fd, &stm32image_header, sizeof(struct stm32_header)) != |
|||
sizeof(struct stm32_header)) { |
|||
fprintf(stderr, "Write error %s: %s\n", destname, |
|||
strerror(errno)); |
|||
return -1; |
|||
} |
|||
|
|||
if (write(dest_fd, ptr, sbuf.st_size) != sbuf.st_size) { |
|||
fprintf(stderr, "Write error on %s: %s\n", destname, |
|||
strerror(errno)); |
|||
return -1; |
|||
} |
|||
|
|||
munmap((void *)ptr, sbuf.st_size); |
|||
close(src_fd); |
|||
|
|||
if (fstat(dest_fd, &sbuf) < 0) { |
|||
return -1; |
|||
} |
|||
|
|||
ptr = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, |
|||
dest_fd, 0); |
|||
|
|||
if (ptr == MAP_FAILED) { |
|||
fprintf(stderr, "Can't read %s\n", srcname); |
|||
return -1; |
|||
} |
|||
|
|||
stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr, entry, version); |
|||
|
|||
stm32image_print_header(ptr); |
|||
|
|||
munmap((void *)ptr, sbuf.st_size); |
|||
close(dest_fd); |
|||
return 0; |
|||
} |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
int opt, loadaddr = -1, entry = -1, err = 0, version = 0; |
|||
char *dest = NULL, *src = NULL; |
|||
|
|||
while ((opt = getopt(argc, argv, ":s:d:l:e:v:")) != -1) { |
|||
switch (opt) { |
|||
case 's': |
|||
src = optarg; |
|||
break; |
|||
case 'd': |
|||
dest = optarg; |
|||
break; |
|||
case 'l': |
|||
loadaddr = strtol(optarg, NULL, 16); |
|||
break; |
|||
case 'e': |
|||
entry = strtol(optarg, NULL, 16); |
|||
break; |
|||
case 'v': |
|||
version = strtol(optarg, NULL, 10); |
|||
break; |
|||
default: |
|||
fprintf(stderr, |
|||
"Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point]\n", |
|||
argv[0]); |
|||
return -1; |
|||
} |
|||
} |
|||
|
|||
if (!src) { |
|||
fprintf(stderr, "Missing -s option\n"); |
|||
return -1; |
|||
} |
|||
|
|||
if (!dest) { |
|||
fprintf(stderr, "Missing -d option\n"); |
|||
return -1; |
|||
} |
|||
|
|||
if (loadaddr == -1) { |
|||
fprintf(stderr, "Missing -l option\n"); |
|||
return -1; |
|||
} |
|||
|
|||
if (entry == -1) { |
|||
fprintf(stderr, "Missing -e option\n"); |
|||
return -1; |
|||
} |
|||
|
|||
err = stm32image_create_header_file(src, dest, loadaddr, |
|||
entry, version); |
|||
|
|||
return err; |
|||
} |
Loading…
Reference in new issue