Browse Source

Merge pull request #1466 from Yann-lms/stm32mp1

Add STMicroelectronics STM32MP1 platform support
pull/1490/merge
danh-arm 6 years ago
committed by GitHub
parent
commit
d87d524ee4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .gitignore
  2. 2
      acknowledgements.rst
  3. 82
      docs/plat/stm32mp1.rst
  4. 1611
      drivers/st/clk/stm32mp1_clk.c
  5. 365
      drivers/st/clk/stm32mp1_clkfunc.c
  6. 895
      drivers/st/ddr/stm32mp1_ddr.c
  7. 20
      drivers/st/ddr/stm32mp1_ddr_helpers.c
  8. 308
      drivers/st/ddr/stm32mp1_ram.c
  9. 86
      drivers/st/gpio/stm32_gpio.c
  10. 851
      drivers/st/pmic/stm32_i2c.c
  11. 346
      drivers/st/pmic/stm32mp1_pmic.c
  12. 600
      drivers/st/pmic/stpmu1.c
  13. 39
      drivers/st/reset/stm32mp1_reset.c
  14. 184
      drivers/st/uart/aarch32/stm32_console.S
  15. 153
      fdts/stm32mp15-ddr.dtsi
  16. 121
      fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
  17. 250
      fdts/stm32mp157-pinctrl.dtsi
  18. 246
      fdts/stm32mp157c-ed1.dts
  19. 25
      fdts/stm32mp157c-ev1.dts
  20. 240
      fdts/stm32mp157c.dtsi
  21. 90
      fdts/stm32mp157caa-pinctrl.dtsi
  22. 101
      include/drivers/st/stm32_gpio.h
  23. 300
      include/drivers/st/stm32_i2c.h
  24. 30
      include/drivers/st/stm32mp1_clk.h
  25. 42
      include/drivers/st/stm32mp1_clkfunc.h
  26. 173
      include/drivers/st/stm32mp1_ddr.h
  27. 12
      include/drivers/st/stm32mp1_ddr_helpers.h
  28. 413
      include/drivers/st/stm32mp1_ddr_regs.h
  29. 18
      include/drivers/st/stm32mp1_pmic.h
  30. 32
      include/drivers/st/stm32mp1_pwr.h
  31. 12
      include/drivers/st/stm32mp1_ram.h
  32. 368
      include/drivers/st/stm32mp1_rcc.h
  33. 15
      include/drivers/st/stm32mp1_reset.h
  34. 141
      include/drivers/st/stpmu1.h
  35. 251
      include/dt-bindings/clock/stm32mp1-clks.h
  36. 283
      include/dt-bindings/clock/stm32mp1-clksrc.h
  37. 35
      include/dt-bindings/pinctrl/stm32-pinfunc.h
  38. 108
      include/dt-bindings/reset/stm32mp1-resets.h
  39. 11
      maintainers.rst
  40. 193
      plat/st/stm32mp1/bl2_io_storage.c
  41. 161
      plat/st/stm32mp1/bl2_plat_setup.c
  42. 235
      plat/st/stm32mp1/include/boot_api.h
  43. 187
      plat/st/stm32mp1/include/platform_def.h
  44. 14
      plat/st/stm32mp1/include/stm32mp1_context.h
  45. 41
      plat/st/stm32mp1/include/stm32mp1_dt.h
  46. 22
      plat/st/stm32mp1/include/stm32mp1_private.h
  47. 68
      plat/st/stm32mp1/plat_bl2_mem_params_desc.c
  48. 32
      plat/st/stm32mp1/plat_image_load.c
  49. 148
      plat/st/stm32mp1/platform.mk
  50. 21
      plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
  51. 144
      plat/st/stm32mp1/sp_min/sp_min_setup.c
  52. 16
      plat/st/stm32mp1/stm32mp1.S
  53. 76
      plat/st/stm32mp1/stm32mp1.ld.S
  54. 101
      plat/st/stm32mp1/stm32mp1_common.c
  55. 42
      plat/st/stm32mp1/stm32mp1_context.c
  56. 193
      plat/st/stm32mp1/stm32mp1_def.h
  57. 476
      plat/st/stm32mp1/stm32mp1_dt.c
  58. 48
      plat/st/stm32mp1/stm32mp1_gic.c
  59. 180
      plat/st/stm32mp1/stm32mp1_helper.S
  60. 255
      plat/st/stm32mp1/stm32mp1_pm.c
  61. 127
      plat/st/stm32mp1/stm32mp1_security.c
  62. 21
      plat/st/stm32mp1/stm32mp1_stack_protector.c
  63. 56
      plat/st/stm32mp1/stm32mp1_topology.c
  64. 49
      tools/stm32image/Makefile
  65. 247
      tools/stm32image/stm32image.c

3
.gitignore

@ -19,6 +19,9 @@ tools/cert_create/src/**/*.o
tools/cert_create/cert_create
tools/cert_create/cert_create.exe
tools/doimage/doimage
tools/stm32image/*.o
tools/stm32image/stm32image
tools/stm32image/stm32image.exe
# GNU GLOBAL files
GPATH

2
acknowledgements.rst

@ -16,5 +16,7 @@ NXP Semiconductors
Marvell International Ltd.
STMicroelectronics
Individuals
-----------

82
docs/plat/stm32mp1.rst

@ -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.

1611
drivers/st/clk/stm32mp1_clk.c

File diff suppressed because it is too large

365
drivers/st/clk/stm32mp1_clkfunc.c

@ -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);
}

895
drivers/st/ddr/stm32mp1_ddr.c

@ -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));
}

20
drivers/st/ddr/stm32mp1_ddr_helpers.c

@ -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);
}

308
drivers/st/ddr/stm32mp1_ram.c

@ -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();
}

86
drivers/st/gpio/stm32_gpio.c

@ -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));
}

851
drivers/st/pmic/stm32_i2c.c

@ -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;
}

346
drivers/st/pmic/stm32mp1_pmic.c

@ -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;
}

600
drivers/st/pmic/stpmu1.c

@ -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 &regulators_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;
}

39
drivers/st/reset/stm32mp1_reset.c

@ -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) {
;
}
}

184
drivers/st/uart/aarch32/stm32_console.S

@ -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

153
fdts/stm32mp15-ddr.dtsi

@ -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";
};
};
};

121
fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi

@ -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"

250
fdts/stm32mp157-pinctrl.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>;
};
};
};
};
};

246
fdts/stm32mp157c-ed1.dts

@ -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;

25
fdts/stm32mp157c-ev1.dts

@ -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";
};

240
fdts/stm32mp157c.dtsi

@ -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";
};
};
};

90
fdts/stm32mp157caa-pinctrl.dtsi

@ -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>;
};
};
};
};

101
include/drivers/st/stm32_gpio.h

@ -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__*/

300
include/drivers/st/stm32_i2c.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 */

30
include/drivers/st/stm32mp1_clk.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__ */

42
include/drivers/st/stm32mp1_clkfunc.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__ */

173
include/drivers/st/stm32mp1_ddr.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 */

12
include/drivers/st/stm32mp1_ddr_helpers.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__ */

413
include/drivers/st/stm32mp1_ddr_regs.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 */

18
include/drivers/st/stm32mp1_pmic.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__ */

32
include/drivers/st/stm32mp1_pwr.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__ */

12
include/drivers/st/stm32mp1_ram.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 */

368
include/drivers/st/stm32mp1_rcc.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__ */

15
include/drivers/st/stm32mp1_reset.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__ */

141
include/drivers/st/stpmu1.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__ */

251
include/dt-bindings/clock/stm32mp1-clks.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_ */

283
include/dt-bindings/clock/stm32mp1-clksrc.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

35
include/dt-bindings/pinctrl/stm32-pinfunc.h

@ -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 */

108
include/dt-bindings/reset/stm32mp1-resets.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_ */

11
maintainers.rst

@ -125,6 +125,16 @@ RockChip platform port
:G: `rockchip-linux`_
:F: plat/rockchip/
STM32MP1 platform port
----------------------
:M: Yann Gautier <yann.gautier@st.com>
:G: `Yann-lms`_
:F: docs/plat/stm32mp1.rst
:F: fdts/stm32\*
:F: include/dt-bindings/\*/stm32\*
:F: plat/st/
:F: tools/stm32image/
Synquacer platform port
-----------------------
:M: Sumit Garg <sumit.garg@linaro.org>
@ -184,3 +194,4 @@ Xilinx platform port
.. _soby-mathew: https://github.com/soby-mathew
.. _TonyXie06: https://github.com/TonyXie06
.. _vwadekar: https://github.com/vwadekar
.. _Yann-lms: https://github.com/Yann-lms

193
plat/st/stm32mp1/bl2_io_storage.c

@ -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;
}

161
plat/st/stm32mp1/bl2_plat_setup.c

@ -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();
}

235
plat/st/stm32mp1/include/boot_api.h

@ -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 */

187
plat/st/stm32mp1/include/platform_def.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 */

14
plat/st/stm32mp1/include/stm32mp1_context.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__ */

41
plat/st/stm32mp1/include/stm32mp1_dt.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__ */

22
plat/st/stm32mp1/include/stm32mp1_private.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__ */

68
plat/st/stm32mp1/plat_bl2_mem_params_desc.c

@ -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)

32
plat/st/stm32mp1/plat_image_load.c

@ -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();
}

148
plat/st/stm32mp1/platform.mk

@ -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

21
plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk

@ -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

144
plat/st/stm32mp1/sp_min/sp_min_setup.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)
{
}

16
plat/st/stm32mp1/stm32mp1.S

@ -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

76
plat/st/stm32mp1/stm32mp1.ld.S

@ -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__*/

101
plat/st/stm32mp1/stm32mp1_common.c

@ -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;
}

42
plat/st/stm32mp1/stm32mp1_context.c

@ -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;
}

193
plat/st/stm32mp1/stm32mp1_def.h

@ -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 */

476
plat/st/stm32mp1/stm32mp1_dt.c

@ -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);
}

48
plat/st/stm32mp1/stm32mp1_gic.c

@ -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();
}

180
plat/st/stm32mp1/stm32mp1_helper.S

@ -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

255
plat/st/stm32mp1/stm32mp1_pm.c

@ -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;
}

127
plat/st/stm32mp1/stm32mp1_security.c

@ -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();
}

21
plat/st/stm32mp1/stm32mp1_stack_protector.c

@ -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();
}

56
plat/st/stm32mp1/stm32mp1_topology.c

@ -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;
}

49
tools/stm32image/Makefile

@ -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

247
tools/stm32image/stm32image.c

@ -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…
Cancel
Save