From c9d75b3cf98c7f2a78d3f916bcf9e2b3a2c55967 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 14 Feb 2019 11:13:25 +0100 Subject: [PATCH 01/11] stm32mp1: split code between common and private parts Some parts of code could be shared with platform derivatives, or new platforms. A new folder plat/st/common is created to put common parts. stm32mp_common.h is a common API aggregate. Remove some casts where applicable. Fix some types where applicable. Remove also some platform includes that are already in stm32mp1_def.h. Change-Id: I46d763c8d9e15732d1ee7383207fd58206d7f583 Signed-off-by: Yann Gautier Signed-off-by: Etienne Carriere --- drivers/st/gpio/stm32_gpio.c | 8 +- plat/st/{stm32mp1 => common}/bl2_io_storage.c | 3 - plat/st/common/include/stm32mp_common.h | 34 +++++ .../include/stm32mp_dt.h} | 8 +- plat/st/common/stm32mp_common.c | 69 ++++++++++ .../stm32mp1_dt.c => common/stm32mp_dt.c} | 7 +- plat/st/stm32mp1/bl2_plat_setup.c | 3 - plat/st/stm32mp1/include/stm32mp1_private.h | 8 -- plat/st/stm32mp1/platform.mk | 10 +- plat/st/stm32mp1/sp_min/sp_min_setup.c | 2 - plat/st/stm32mp1/stm32mp1_common.c | 123 ------------------ plat/st/stm32mp1/stm32mp1_def.h | 3 +- plat/st/stm32mp1/stm32mp1_gic.c | 3 - plat/st/stm32mp1/stm32mp1_pm.c | 3 - plat/st/stm32mp1/stm32mp1_private.c | 55 ++++++++ plat/st/stm32mp1/stm32mp1_security.c | 3 - 16 files changed, 178 insertions(+), 164 deletions(-) rename plat/st/{stm32mp1 => common}/bl2_io_storage.c (99%) create mode 100644 plat/st/common/include/stm32mp_common.h rename plat/st/{stm32mp1/include/stm32mp1_dt.h => common/include/stm32mp_dt.h} (91%) create mode 100644 plat/st/common/stm32mp_common.c rename plat/st/{stm32mp1/stm32mp1_dt.c => common/stm32mp_dt.c} (98%) delete mode 100644 plat/st/stm32mp1/stm32mp1_common.c create mode 100644 plat/st/stm32mp1/stm32mp1_private.c diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c index d217c4501..5fee82cdf 100644 --- a/drivers/st/gpio/stm32_gpio.c +++ b/drivers/st/gpio/stm32_gpio.c @@ -254,17 +254,17 @@ void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, mmio_read_32(base + GPIO_AFRH_OFFSET)); - stm32mp1_clk_disable((unsigned long)clock); + stm32mp1_clk_disable(clock); } void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) { uintptr_t base = stm32_get_gpio_bank_base(bank); - int clock = stm32_get_gpio_bank_clock(bank); + unsigned long clock = stm32_get_gpio_bank_clock(bank); assert(pin <= GPIO_PIN_MAX); - stm32mp1_clk_enable((unsigned long)clock); + stm32mp1_clk_enable(clock); if (secure) { mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); @@ -272,5 +272,5 @@ void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); } - stm32mp1_clk_disable((unsigned long)clock); + stm32mp1_clk_disable(clock); } diff --git a/plat/st/stm32mp1/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c similarity index 99% rename from plat/st/stm32mp1/bl2_io_storage.c rename to plat/st/common/bl2_io_storage.c index 8ccbc246c..18342aa0a 100644 --- a/plat/st/stm32mp1/bl2_io_storage.c +++ b/plat/st/common/bl2_io_storage.c @@ -25,9 +25,6 @@ #include #include -#include -#include - /* IO devices */ static const io_dev_connector_t *dummy_dev_con; static uintptr_t dummy_dev_handle; diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h new file mode 100644 index 000000000..11dd845bc --- /dev/null +++ b/plat/st/common/include/stm32mp_common.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_COMMON_H +#define STM32MP_COMMON_H + +/* Functions to save and get boot context address given by ROM code */ +void stm32mp1_save_boot_ctx_address(uintptr_t address); +uintptr_t stm32mp1_get_boot_ctx_address(void); + +/* + * Platform util functions for the GPIO driver + * @bank: Target GPIO bank ID as per DT bindings + * + * Platform shall implement these functions to provide to stm32_gpio + * driver the resource reference for a target GPIO bank. That are + * memory mapped interface base address, interface offset (see below) + * and clock identifier. + * + * stm32_get_gpio_bank_offset() returns a bank offset that is used to + * check DT configuration matches platform implementation of the banks + * description. + */ +uintptr_t stm32_get_gpio_bank_base(unsigned int bank); +unsigned long stm32_get_gpio_bank_clock(unsigned int bank); +uint32_t stm32_get_gpio_bank_offset(unsigned int bank); + +/* Initialise the IO layer and register platform IO devices */ +void stm32mp1_io_setup(void); + +#endif /* STM32MP_COMMON_H */ diff --git a/plat/st/stm32mp1/include/stm32mp1_dt.h b/plat/st/common/include/stm32mp_dt.h similarity index 91% rename from plat/st/stm32mp1/include/stm32mp1_dt.h rename to plat/st/common/include/stm32mp_dt.h index d5640c1fd..56357dbff 100644 --- a/plat/st/stm32mp1/include/stm32mp1_dt.h +++ b/plat/st/common/include/stm32mp_dt.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef STM32MP1_DT_H -#define STM32MP1_DT_H +#ifndef STM32MP_DT_H +#define STM32MP_DT_H #include @@ -27,7 +27,7 @@ struct dt_node_info { int dt_open_and_check(void); int fdt_get_address(void **fdt_addr); bool fdt_check_node(int node); -uint32_t fdt_get_status(int node); +uint8_t fdt_get_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, @@ -40,4 +40,4 @@ 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 */ +#endif /* STM32MP_DT_H */ diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c new file mode 100644 index 000000000..7744aa023 --- /dev/null +++ b/plat/st/common/stm32mp_common.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include + +uintptr_t plat_get_ns_image_entrypoint(void) +{ + return BL33_BASE; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return read_cntfrq_el0(); +} + +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; +} + +uintptr_t stm32_get_gpio_bank_base(unsigned int bank) +{ + if (bank == GPIO_BANK_Z) { + return GPIOZ_BASE; + } + + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); + + return GPIOA_BASE + (bank * GPIO_BANK_OFFSET); +} + +unsigned long stm32_get_gpio_bank_clock(unsigned int bank) +{ + if (bank == GPIO_BANK_Z) { + return GPIOZ; + } + + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); + + return GPIOA + (bank - GPIO_BANK_A); +} + +uint32_t stm32_get_gpio_bank_offset(unsigned int bank) +{ + if (bank == GPIO_BANK_Z) { + return 0; + } + + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); + + return bank * GPIO_BANK_OFFSET; +} diff --git a/plat/st/stm32mp1/stm32mp1_dt.c b/plat/st/common/stm32mp_dt.c similarity index 98% rename from plat/st/stm32mp1/stm32mp1_dt.c rename to plat/st/common/stm32mp_dt.c index 8493b8786..2eaa9d93d 100644 --- a/plat/st/stm32mp1/stm32mp1_dt.c +++ b/plat/st/common/stm32mp_dt.c @@ -14,10 +14,11 @@ #include #include #include -#include #include #include +#include + static int fdt_checked; static void *fdt = (void *)(uintptr_t)STM32MP1_DTB_BASE; @@ -68,9 +69,9 @@ bool fdt_check_node(int node) /******************************************************************************* * This function return global node status (generic use of fdt library). ******************************************************************************/ -uint32_t fdt_get_status(int node) +uint8_t fdt_get_status(int node) { - uint32_t status = DT_DISABLED; + uint8_t status = DT_DISABLED; int len; const char *cchar; diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index a1ffd5a9d..5525efd23 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -26,10 +26,7 @@ #include #include -#include #include -#include -#include static struct console_stm32 console; diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h index 04c9a9ad5..49a2bdf41 100644 --- a/plat/st/stm32mp1/include/stm32mp1_private.h +++ b/plat/st/stm32mp1/include/stm32mp1_private.h @@ -9,20 +9,12 @@ #include -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); -uintptr_t stm32_get_gpio_bank_base(unsigned int bank); -unsigned long stm32_get_gpio_bank_clock(unsigned int bank); -uint32_t stm32_get_gpio_bank_offset(unsigned int bank); - #endif /* STM32MP1_PRIVATE_H */ diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk index 4288f23d9..1c5f6273e 100644 --- a/plat/st/stm32mp1/platform.mk +++ b/plat/st/stm32mp1/platform.mk @@ -21,7 +21,8 @@ $(eval $(call add_define,STM32_TF_A_COPIES)) PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 1))) $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) -PLAT_INCLUDES := -Iplat/st/stm32mp1/include/ +PLAT_INCLUDES := -Iplat/st/common/include/ +PLAT_INCLUDES += -Iplat/st/stm32mp1/include/ # Device tree DTB_FILE_NAME ?= stm32mp157c-ev1.dtb @@ -30,7 +31,8 @@ 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 := plat/st/common/stm32mp_common.c \ + plat/st/stm32mp1/stm32mp1_private.c PLAT_BL_COMMON_SOURCES += drivers/st/uart/aarch32/stm32_console.S @@ -56,8 +58,8 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \ drivers/st/pmic/stm32mp_pmic.c \ drivers/st/pmic/stpmic1.c \ drivers/st/reset/stm32mp1_reset.c \ + plat/st/common/stm32mp_dt.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 @@ -65,7 +67,7 @@ BL2_SOURCES += drivers/io/io_block.c \ drivers/io/io_dummy.c \ drivers/io/io_storage.c \ drivers/st/io/io_stm32image.c \ - plat/st/stm32mp1/bl2_io_storage.c \ + plat/st/common/bl2_io_storage.c \ plat/st/stm32mp1/bl2_plat_setup.c BL2_SOURCES += drivers/mmc/mmc.c \ diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c index 0d76fb7e3..f747ee711 100644 --- a/plat/st/stm32mp1/sp_min/sp_min_setup.c +++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c @@ -27,8 +27,6 @@ #include #include -#include -#include /****************************************************************************** * Placeholder variables for copying the arguments that have been passed to diff --git a/plat/st/stm32mp1/stm32mp1_common.c b/plat/st/stm32mp1/stm32mp1_common.c deleted file mode 100644 index cd93d2eef..000000000 --- a/plat/st/stm32mp1/stm32mp1_common.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#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) - -#if defined(IMAGE_BL2) -static const mmap_region_t stm32mp1_mmap[] = { - MAP_SRAM, - MAP_DEVICE1, - MAP_DEVICE2, - {0} -}; -#endif -#if defined(IMAGE_BL32) -static const mmap_region_t stm32mp1_mmap[] = { - MAP_SRAM, - MAP_DEVICE1, - MAP_DEVICE2, - {0} -}; -#endif - -void configure_mmu(void) -{ - mmap_add(stm32mp1_mmap); - init_xlat_tables(); - - enable_mmu_svc_mon(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; -} - -uintptr_t stm32_get_gpio_bank_base(unsigned int bank) -{ - switch (bank) { - case GPIO_BANK_A ... GPIO_BANK_K: - return GPIOA_BASE + (bank * GPIO_BANK_OFFSET); - case GPIO_BANK_Z: - return GPIOZ_BASE; - default: - panic(); - } -} - -/* Return clock ID on success, negative value on error */ -unsigned long stm32_get_gpio_bank_clock(unsigned int bank) -{ - switch (bank) { - case GPIO_BANK_A ... GPIO_BANK_K: - return GPIOA + (bank - GPIO_BANK_A); - case GPIO_BANK_Z: - return GPIOZ; - default: - panic(); - } -} - -uint32_t stm32_get_gpio_bank_offset(unsigned int bank) -{ - if (bank == GPIO_BANK_Z) { - return 0; - } else { - return bank * GPIO_BANK_OFFSET; - } -} diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index 8cd5aeb26..d12a93ffb 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -13,7 +13,8 @@ #ifndef __ASSEMBLY__ #include -#include +#include +#include #include #endif diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c index becb925c2..851a9cf0c 100644 --- a/plat/st/stm32mp1/stm32mp1_gic.c +++ b/plat/st/stm32mp1/stm32mp1_gic.c @@ -15,9 +15,6 @@ #include #include -#include -#include - struct stm32_gic_instance { uint32_t cells; uint32_t phandle_node; diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c index c0e9c4eb8..20f66e98b 100644 --- a/plat/st/stm32mp1/stm32mp1_pm.c +++ b/plat/st/stm32mp1/stm32mp1_pm.c @@ -20,9 +20,6 @@ #include #include -#include -#include - static uintptr_t stm32_sec_entrypoint; static uint32_t cntfrq_core0; diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c new file mode 100644 index 000000000..f3beb591f --- /dev/null +++ b/plat/st/stm32mp1/stm32mp1_private.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#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) + +#if defined(IMAGE_BL2) +static const mmap_region_t stm32mp1_mmap[] = { + MAP_SRAM, + MAP_DEVICE1, + MAP_DEVICE2, + {0} +}; +#endif +#if defined(IMAGE_BL32) +static const mmap_region_t stm32mp1_mmap[] = { + MAP_SRAM, + MAP_DEVICE1, + MAP_DEVICE2, + {0} +}; +#endif + +void configure_mmu(void) +{ + mmap_add(stm32mp1_mmap); + init_xlat_tables(); + + enable_mmu_svc_mon(0); +} diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c index cfdbf3185..99719e42f 100644 --- a/plat/st/stm32mp1/stm32mp1_security.c +++ b/plat/st/stm32mp1/stm32mp1_security.c @@ -15,9 +15,6 @@ #include #include -#include -#include - /******************************************************************************* * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access * and allow Non-Secure masters full access. From 3f9c97842e5780e0e21f8eb36844c8154635c8c4 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 14 Feb 2019 11:13:39 +0100 Subject: [PATCH 02/11] stm32mp1: make functions and macros more common Mainly remove suffix 1 from prefix stm32mp1 in several macros and functions that can be used in drivers shared by different platforms. Change-Id: I2295c44f5b1edac7e80a93c0e8dfd671b36e88e7 Signed-off-by: Yann Gautier Signed-off-by: Etienne Carriere --- drivers/st/clk/stm32mp1_clk.c | 10 +-- drivers/st/ddr/stm32mp1_ddr.c | 2 +- drivers/st/ddr/stm32mp1_ram.c | 46 ++++++------- drivers/st/gpio/stm32_gpio.c | 8 +-- drivers/st/mmc/stm32_sdmmc2.c | 20 +++--- drivers/st/pmic/stm32mp_pmic.c | 2 +- drivers/st/reset/stm32mp1_reset.c | 8 +-- include/drivers/st/stm32mp1_clk.h | 8 +-- include/drivers/st/stm32mp1_reset.h | 15 ----- include/drivers/st/stm32mp_reset.h | 15 +++++ plat/st/common/bl2_io_storage.c | 18 ++--- plat/st/common/include/stm32mp_common.h | 17 ++++- plat/st/common/stm32mp_common.c | 4 +- plat/st/common/stm32mp_dt.c | 2 +- plat/st/stm32mp1/bl2_plat_setup.c | 24 +++---- plat/st/stm32mp1/include/platform_def.h | 26 +++---- plat/st/stm32mp1/plat_bl2_mem_params_desc.c | 10 +-- plat/st/stm32mp1/sp_min/sp_min_setup.c | 2 +- plat/st/stm32mp1/stm32mp1.ld.S | 12 ++-- plat/st/stm32mp1/stm32mp1_context.c | 8 +-- plat/st/stm32mp1/stm32mp1_def.h | 75 ++++++++++----------- plat/st/stm32mp1/stm32mp1_helper.S | 12 ++-- plat/st/stm32mp1/stm32mp1_pm.c | 16 ++--- plat/st/stm32mp1/stm32mp1_private.c | 4 +- plat/st/stm32mp1/stm32mp1_security.c | 12 ++-- 25 files changed, 190 insertions(+), 186 deletions(-) delete mode 100644 include/drivers/st/stm32mp1_reset.h create mode 100644 include/drivers/st/stm32mp_reset.h diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index e4cc9b9e8..02866a214 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ @@ -777,7 +777,7 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) return clock; } -bool stm32mp1_clk_is_enabled(unsigned long id) +bool stm32mp_clk_is_enabled(unsigned long id) { struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; const struct stm32mp1_clk_gate *gate = priv->data->gate; @@ -791,7 +791,7 @@ bool stm32mp1_clk_is_enabled(unsigned long id) BIT(gate[i].bit)) != 0U); } -int stm32mp1_clk_enable(unsigned long id) +int stm32mp_clk_enable(unsigned long id) { struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; const struct stm32mp1_clk_gate *gate = priv->data->gate; @@ -810,7 +810,7 @@ int stm32mp1_clk_enable(unsigned long id) return 0; } -int stm32mp1_clk_disable(unsigned long id) +int stm32mp_clk_disable(unsigned long id) { struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; const struct stm32mp1_clk_gate *gate = priv->data->gate; @@ -831,7 +831,7 @@ int stm32mp1_clk_disable(unsigned long id) return 0; } -unsigned long stm32mp1_clk_get_rate(unsigned long id) +unsigned long stm32mp_clk_get_rate(unsigned long id) { struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; int p = stm32mp1_clk_get_parent(priv, id); diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c index 79aff6e73..b9347540d 100644 --- a/drivers/st/ddr/stm32mp1_ddr.c +++ b/drivers/st/ddr/stm32mp1_ddr.c @@ -639,7 +639,7 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) */ /* Change Bypass Mode Frequency Range */ - if (stm32mp1_clk_get_rate(DDRPHYC) < 100000000U) { + if (stm32mp_clk_get_rate(DDRPHYC) < 100000000U) { mmio_clrbits_32((uintptr_t)&priv->phy->dllgcr, DDRPHYC_DLLGCR_BPS200); } else { diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c index e65fbeaa2..532062e01 100644 --- a/drivers/st/ddr/stm32mp1_ram.c +++ b/drivers/st/ddr/stm32mp1_ram.c @@ -31,7 +31,7 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) ddr_enable_clock(); - ddrphy_clk = stm32mp1_clk_get_rate(DDRPHYC); + ddrphy_clk = stm32mp_clk_get_rate(DDRPHYC); VERBOSE("DDR: mem_speed (%d kHz), RCC %ld kHz\n", mem_speed, ddrphy_clk / 1000U); @@ -65,10 +65,10 @@ 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); + mmio_write_32(STM32MP_DDR_BASE, pattern); - if (mmio_read_32(STM32MP1_DDR_BASE) != pattern) { - return (uint32_t)STM32MP1_DDR_BASE; + if (mmio_read_32(STM32MP_DDR_BASE) != pattern) { + return (uint32_t)STM32MP_DDR_BASE; } } @@ -92,44 +92,44 @@ static uint32_t ddr_test_addr_bus(void) /* 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, + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)offset, DDR_PATTERN); } /* Check for address bits stuck high. */ - mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, + mmio_write_32(STM32MP_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) != + if (mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) != DDR_PATTERN) { - return (uint32_t)(STM32MP1_DDR_BASE + offset); + return (uint32_t)(STM32MP_DDR_BASE + offset); } } - mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN); + mmio_write_32(STM32MP_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, + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_ANTIPATTERN); - if (mmio_read_32(STM32MP1_DDR_BASE) != DDR_PATTERN) { - return STM32MP1_DDR_BASE; + if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { + return STM32MP_DDR_BASE; } for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; offset <<= 1) { - if ((mmio_read_32(STM32MP1_DDR_BASE + + if ((mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) != DDR_PATTERN) && (offset != testoffset)) { - return (uint32_t)(STM32MP1_DDR_BASE + offset); + return (uint32_t)(STM32MP_DDR_BASE + offset); } } - mmio_write_32(STM32MP1_DDR_BASE + (uint32_t)testoffset, + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN); } @@ -147,13 +147,13 @@ static uint32_t ddr_check_size(void) { uint32_t offset = sizeof(uint32_t); - mmio_write_32(STM32MP1_DDR_BASE, DDR_PATTERN); + mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); - while (offset < STM32MP1_DDR_MAX_SIZE) { - mmio_write_32(STM32MP1_DDR_BASE + offset, DDR_ANTIPATTERN); + while (offset < STM32MP_DDR_MAX_SIZE) { + mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN); dsb(); - if (mmio_read_32(STM32MP1_DDR_BASE) != DDR_PATTERN) { + if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { break; } @@ -240,15 +240,15 @@ static int stm32mp1_ddr_setup(void) } } - if (!stm32mp1_clk_is_enabled(RTCAPB)) { + if (!stm32mp_clk_is_enabled(RTCAPB)) { tamp_clk_off = 1; - if (stm32mp1_clk_enable(RTCAPB) != 0) { + if (stm32mp_clk_enable(RTCAPB) != 0) { return -EINVAL; } } if (tamp_clk_off != 0U) { - if (stm32mp1_clk_disable(RTCAPB) != 0) { + if (stm32mp_clk_disable(RTCAPB) != 0) { return -EINVAL; } } @@ -306,7 +306,7 @@ int stm32mp1_ddr_probe(void) priv->pwr = PWR_BASE; priv->rcc = RCC_BASE; - priv->info.base = STM32MP1_DDR_BASE; + priv->info.base = STM32MP_DDR_BASE; priv->info.size = 0; return stm32mp1_ddr_setup(); diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c index 5fee82cdf..1d8111a1b 100644 --- a/drivers/st/gpio/stm32_gpio.c +++ b/drivers/st/gpio/stm32_gpio.c @@ -208,7 +208,7 @@ void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, assert(pin <= GPIO_PIN_MAX); - stm32mp1_clk_enable(clock); + stm32mp_clk_enable(clock); mmio_clrbits_32(base + GPIO_MODE_OFFSET, ((uint32_t)GPIO_MODE_MASK << (pin << 1))); @@ -254,7 +254,7 @@ void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, mmio_read_32(base + GPIO_AFRH_OFFSET)); - stm32mp1_clk_disable(clock); + stm32mp_clk_disable(clock); } void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) @@ -264,7 +264,7 @@ void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) assert(pin <= GPIO_PIN_MAX); - stm32mp1_clk_enable(clock); + stm32mp_clk_enable(clock); if (secure) { mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); @@ -272,5 +272,5 @@ void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); } - stm32mp1_clk_disable(clock); + stm32mp_clk_disable(clock); } diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c index 57812d899..10fd5f5d0 100644 --- a/drivers/st/mmc/stm32_sdmmc2.c +++ b/drivers/st/mmc/stm32_sdmmc2.c @@ -19,9 +19,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -159,7 +159,7 @@ static void stm32_sdmmc2_init(void) uintptr_t base = sdmmc2_params.reg_base; clock_div = div_round_up(sdmmc2_params.clk_rate, - STM32MP1_MMC_INIT_FREQ * 2); + STM32MP_MMC_INIT_FREQ * 2); mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div | sdmmc2_params.negedge | @@ -429,15 +429,15 @@ static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width) if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { if (max_bus_freq >= 52000000U) { - max_freq = STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ; + max_freq = STM32MP_EMMC_HIGH_SPEED_MAX_FREQ; } else { - max_freq = STM32MP1_EMMC_NORMAL_SPEED_MAX_FREQ; + max_freq = STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ; } } else { if (max_bus_freq >= 50000000U) { - max_freq = STM32MP1_SD_HIGH_SPEED_MAX_FREQ; + max_freq = STM32MP_SD_HIGH_SPEED_MAX_FREQ; } else { - max_freq = STM32MP1_SD_NORMAL_SPEED_MAX_FREQ; + max_freq = STM32MP_SD_NORMAL_SPEED_MAX_FREQ; } } @@ -720,19 +720,19 @@ int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) return -ENOMEM; } - ret = stm32mp1_clk_enable(sdmmc2_params.clock_id); + ret = stm32mp_clk_enable(sdmmc2_params.clock_id); if (ret != 0) { ERROR("%s: clock %d failed\n", __func__, sdmmc2_params.clock_id); return ret; } - stm32mp1_reset_assert(sdmmc2_params.reset_id); + stm32mp_reset_assert(sdmmc2_params.reset_id); udelay(2); - stm32mp1_reset_deassert(sdmmc2_params.reset_id); + stm32mp_reset_deassert(sdmmc2_params.reset_id); mdelay(1); - sdmmc2_params.clk_rate = stm32mp1_clk_get_rate(sdmmc2_params.clock_id); + sdmmc2_params.clk_rate = stm32mp_clk_get_rate(sdmmc2_params.clock_id); return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate, sdmmc2_params.bus_width, sdmmc2_params.flags, diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c index 6beabc153..eb5c6e66d 100644 --- a/drivers/st/pmic/stm32mp_pmic.c +++ b/drivers/st/pmic/stm32mp_pmic.c @@ -167,7 +167,7 @@ void initialize_pmic_i2c(void) panic(); } - if (stm32mp1_clk_enable((uint32_t)i2c_info.clock) < 0) { + if (stm32mp_clk_enable((uint32_t)i2c_info.clock) < 0) { ERROR("I2C clock enable failed\n"); panic(); } diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c index f58e10b27..aac74e15d 100644 --- a/drivers/st/reset/stm32mp1_reset.c +++ b/drivers/st/reset/stm32mp1_reset.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -10,14 +10,14 @@ #include #include +#include #include -#include #include #include #define RST_CLR_OFFSET 4U -void stm32mp1_reset_assert(uint32_t id) +void stm32mp_reset_assert(uint32_t id) { uint32_t offset = (id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t); uint32_t bit = id % (uint32_t)__LONG_BIT; @@ -28,7 +28,7 @@ void stm32mp1_reset_assert(uint32_t id) } } -void stm32mp1_reset_deassert(uint32_t id) +void stm32mp_reset_deassert(uint32_t id) { uint32_t offset = ((id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t)) + RST_CLR_OFFSET; diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h index 5594e2327..11ff7bf24 100644 --- a/include/drivers/st/stm32mp1_clk.h +++ b/include/drivers/st/stm32mp1_clk.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,16 +7,10 @@ #ifndef STM32MP1_CLK_H #define STM32MP1_CLK_H -#include - #include 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) diff --git a/include/drivers/st/stm32mp1_reset.h b/include/drivers/st/stm32mp1_reset.h deleted file mode 100644 index cd488cc33..000000000 --- a/include/drivers/st/stm32mp1_reset.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2018, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef STM32MP1_RESET_H -#define STM32MP1_RESET_H - -#include - -void stm32mp1_reset_assert(uint32_t reset_id); -void stm32mp1_reset_deassert(uint32_t reset_id); - -#endif /* STM32MP1_RESET_H */ diff --git a/include/drivers/st/stm32mp_reset.h b/include/drivers/st/stm32mp_reset.h new file mode 100644 index 000000000..2da5adf44 --- /dev/null +++ b/include/drivers/st/stm32mp_reset.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_RESET_H +#define STM32MP_RESET_H + +#include + +void stm32mp_reset_assert(uint32_t reset_id); +void stm32mp_reset_deassert(uint32_t reset_id); + +#endif /* STM32MP_RESET_H */ diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c index 18342aa0a..5b649a342 100644 --- a/plat/st/common/bl2_io_storage.c +++ b/plat/st/common/bl2_io_storage.c @@ -57,12 +57,12 @@ static const io_dev_connector_t *mmc_dev_con; static const io_block_spec_t bl32_block_spec = { .offset = BL32_BASE, - .length = STM32MP1_BL32_SIZE + .length = STM32MP_BL32_SIZE }; static const io_block_spec_t bl2_block_spec = { .offset = BL2_BASE, - .length = STM32MP1_BL2_SIZE, + .length = STM32MP_BL2_SIZE, }; static const struct stm32image_part_info bl33_partition_spec = { @@ -163,7 +163,7 @@ static void print_boot_device(boot_api_context_t *boot_context) } } -void stm32mp1_io_setup(void) +void stm32mp_io_setup(void) { int io_result __unused; uint8_t idx; @@ -173,7 +173,7 @@ void stm32mp1_io_setup(void) uintptr_t mmc_default_instance; const partition_entry_t *entry; boot_api_context_t *boot_context = - (boot_api_context_t *)stm32mp1_get_boot_ctx_address(); + (boot_api_context_t *)stm32mp_get_boot_ctx_address(); print_boot_device(boot_context); @@ -200,21 +200,21 @@ void stm32mp1_io_setup(void) if (boot_context->boot_interface_selected == BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC) { device_info.mmc_dev_type = MMC_IS_EMMC; - mmc_default_instance = STM32MP1_SDMMC2_BASE; + mmc_default_instance = STM32MP_SDMMC2_BASE; } else { device_info.mmc_dev_type = MMC_IS_SD; - mmc_default_instance = STM32MP1_SDMMC1_BASE; + mmc_default_instance = STM32MP_SDMMC1_BASE; } switch (boot_context->boot_interface_instance) { case 1: - params.reg_base = STM32MP1_SDMMC1_BASE; + params.reg_base = STM32MP_SDMMC1_BASE; break; case 2: - params.reg_base = STM32MP1_SDMMC2_BASE; + params.reg_base = STM32MP_SDMMC2_BASE; break; case 3: - params.reg_base = STM32MP1_SDMMC3_BASE; + params.reg_base = STM32MP_SDMMC3_BASE; break; default: WARN("SDMMC instance not found, using default\n"); diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h index 11dd845bc..269d8acbb 100644 --- a/plat/st/common/include/stm32mp_common.h +++ b/plat/st/common/include/stm32mp_common.h @@ -7,9 +7,11 @@ #ifndef STM32MP_COMMON_H #define STM32MP_COMMON_H +#include + /* Functions to save and get boot context address given by ROM code */ -void stm32mp1_save_boot_ctx_address(uintptr_t address); -uintptr_t stm32mp1_get_boot_ctx_address(void); +void stm32mp_save_boot_ctx_address(uintptr_t address); +uintptr_t stm32mp_get_boot_ctx_address(void); /* * Platform util functions for the GPIO driver @@ -28,7 +30,16 @@ uintptr_t stm32_get_gpio_bank_base(unsigned int bank); unsigned long stm32_get_gpio_bank_clock(unsigned int bank); uint32_t stm32_get_gpio_bank_offset(unsigned int bank); +/* + * Util for clock gating and to get clock rate for stm32 and platform drivers + * @id: Target clock ID, ID used in clock DT bindings + */ +bool stm32mp_clk_is_enabled(unsigned long id); +int stm32mp_clk_enable(unsigned long id); +int stm32mp_clk_disable(unsigned long id); +unsigned long stm32mp_clk_get_rate(unsigned long id); + /* Initialise the IO layer and register platform IO devices */ -void stm32mp1_io_setup(void); +void stm32mp_io_setup(void); #endif /* STM32MP_COMMON_H */ diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c index 7744aa023..20aa57da1 100644 --- a/plat/st/common/stm32mp_common.c +++ b/plat/st/common/stm32mp_common.c @@ -25,12 +25,12 @@ unsigned int plat_get_syscnt_freq2(void) static uintptr_t boot_ctx_address; -void stm32mp1_save_boot_ctx_address(uintptr_t address) +void stm32mp_save_boot_ctx_address(uintptr_t address) { boot_ctx_address = address; } -uintptr_t stm32mp1_get_boot_ctx_address(void) +uintptr_t stm32mp_get_boot_ctx_address(void) { return boot_ctx_address; } diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c index 2eaa9d93d..0b6a0d32f 100644 --- a/plat/st/common/stm32mp_dt.c +++ b/plat/st/common/stm32mp_dt.c @@ -21,7 +21,7 @@ static int fdt_checked; -static void *fdt = (void *)(uintptr_t)STM32MP1_DTB_BASE; +static void *fdt = (void *)(uintptr_t)STM32MP_DTB_BASE; /******************************************************************************* * This function checks device tree file with its header. diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index 5525efd23..beea69a9d 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -17,11 +17,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -120,7 +120,7 @@ void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg2 __unused, u_register_t arg3 __unused) { - stm32mp1_save_boot_ctx_address(arg0); + stm32mp_save_boot_ctx_address(arg0); } void bl2_platform_setup(void) @@ -146,7 +146,7 @@ void bl2_el3_plat_arch_setup(void) struct dt_node_info dt_uart_info; const char *board_model; boot_api_context_t *boot_context = - (boot_api_context_t *)stm32mp1_get_boot_ctx_address(); + (boot_api_context_t *)stm32mp_get_boot_ctx_address(); uint32_t clk_rate; mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, @@ -159,9 +159,9 @@ void bl2_el3_plat_arch_setup(void) MT_MEMORY | MT_RO | MT_SECURE); /* Map non secure DDR for BL33 load and DDR training area restore */ - mmap_add_region(STM32MP1_DDR_BASE, - STM32MP1_DDR_BASE, - STM32MP1_DDR_MAX_SIZE, + mmap_add_region(STM32MP_DDR_BASE, + STM32MP_DDR_BASE, + STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_NS); /* Prevent corruption of preloaded Device Tree */ @@ -221,19 +221,19 @@ void bl2_el3_plat_arch_setup(void) goto skip_console_init; } - if (stm32mp1_clk_enable((unsigned long)dt_uart_info.clock) != 0) { + if (stm32mp_clk_enable((unsigned long)dt_uart_info.clock) != 0) { goto skip_console_init; } - stm32mp1_reset_assert((uint32_t)dt_uart_info.reset); + stm32mp_reset_assert((uint32_t)dt_uart_info.reset); udelay(2); - stm32mp1_reset_deassert((uint32_t)dt_uart_info.reset); + stm32mp_reset_deassert((uint32_t)dt_uart_info.reset); mdelay(1); - clk_rate = stm32mp1_clk_get_rate((unsigned long)dt_uart_info.clock); + clk_rate = stm32mp_clk_get_rate((unsigned long)dt_uart_info.clock); if (console_stm32_register(dt_uart_info.base, clk_rate, - STM32MP1_UART_BAUDRATE, &console) == 0) { + STM32MP_UART_BAUDRATE, &console) == 0) { panic(); } @@ -254,5 +254,5 @@ skip_console_init: print_reset_reason(); - stm32mp1_io_setup(); + stm32mp_io_setup(); } diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h index 6d3d36dba..5019b1a3b 100644 --- a/plat/st/stm32mp1/include/platform_def.h +++ b/plat/st/stm32mp1/include/platform_def.h @@ -29,8 +29,8 @@ #define BL33_IMAGE_NAME "ssbl" #define BL33_BINARY_TYPE U(0x0) -#define STM32MP1_PRIMARY_CPU U(0x0) -#define STM32MP1_SECONDARY_CPU U(0x1) +#define STM32MP_PRIMARY_CPU U(0x0) +#define STM32MP_SECONDARY_CPU U(0x1) #define PLATFORM_CLUSTER_COUNT ULL(1) #define PLATFORM_CLUSTER0_CORE_COUNT U(2) @@ -50,33 +50,33 @@ * 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) +#define BL2_BASE STM32MP_BL2_BASE +#define BL2_LIMIT (STM32MP_BL2_BASE + \ + STM32MP_BL2_SIZE) /******************************************************************************* * BL32 specific defines. ******************************************************************************/ -#define BL32_BASE STM32MP1_BL32_BASE -#define BL32_LIMIT (STM32MP1_BL32_BASE + \ - STM32MP1_BL32_SIZE) +#define BL32_BASE STM32MP_BL32_BASE +#define BL32_LIMIT (STM32MP_BL32_BASE + \ + STM32MP_BL32_SIZE) /******************************************************************************* * BL33 specific defines. ******************************************************************************/ -#define BL33_BASE STM32MP1_BL33_BASE +#define BL33_BASE STM32MP_BL33_BASE /* * Load address of BL33 for this platform port */ -#define PLAT_STM32MP1_NS_IMAGE_OFFSET BL33_BASE +#define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE /******************************************************************************* * DTB specific defines. ******************************************************************************/ -#define DTB_BASE STM32MP1_DTB_BASE -#define DTB_LIMIT (STM32MP1_DTB_BASE + \ - STM32MP1_DTB_SIZE) +#define DTB_BASE STM32MP_DTB_BASE +#define DTB_LIMIT (STM32MP_DTB_BASE + \ + STM32MP_DTB_SIZE) /******************************************************************************* * Platform specific page table and MMU setup constants diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c index 621419439..0da93e4fa 100644 --- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c +++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -50,7 +50,7 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), - .ep_info.pc = PLAT_STM32MP1_NS_IMAGE_OFFSET, + .ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET, .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS), @@ -58,9 +58,9 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { 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), + .image_info.image_base = PLAT_STM32MP_NS_IMAGE_OFFSET, + .image_info.image_max_size = STM32MP_DDR_MAX_SIZE - + (PLAT_STM32MP_NS_IMAGE_OFFSET - STM32MP_DDR_BASE), .next_handoff_image_id = INVALID_IMAGE_ID, } diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c index f747ee711..329ff688a 100644 --- a/plat/st/stm32mp1/sp_min/sp_min_setup.c +++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c @@ -123,7 +123,7 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, if ((result > 0) && (dt_uart_info.status != 0U)) { if (console_stm32_register(dt_uart_info.base, 0, - STM32MP1_UART_BAUDRATE, &console) == + STM32MP_UART_BAUDRATE, &console) == 0) { panic(); } diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S index a8e822063..c041fb67d 100644 --- a/plat/st/stm32mp1/stm32mp1.ld.S +++ b/plat/st/stm32mp1/stm32mp1.ld.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,7 +17,7 @@ ENTRY(__BL2_IMAGE_START__) MEMORY { HEADER (rw) : ORIGIN = 0x00000000, LENGTH = 0x3000 - RAM (rwx) : ORIGIN = STM32MP1_BINARY_BASE, LENGTH = STM32MP1_BINARY_SIZE + RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE } SECTIONS @@ -32,7 +32,7 @@ SECTIONS __HEADER_END__ = .; } >HEADER - . = STM32MP1_BINARY_BASE; + . = STM32MP_BINARY_BASE; .data . : { . = ALIGN(PAGE_SIZE); __DATA_START__ = .; @@ -43,7 +43,7 @@ SECTIONS * 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 ); + . = ( STM32MP_DTB_BASE - STM32MP_BINARY_BASE ); __DTB_IMAGE_START__ = .; *(.dtb_image*) __DTB_IMAGE_END__ = .; @@ -53,7 +53,7 @@ SECTIONS * 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 ); + . = ( STM32MP_BL2_BASE - STM32MP_BINARY_BASE ); __BL2_IMAGE_START__ = .; *(.bl2_image*) __BL2_IMAGE_END__ = .; @@ -63,7 +63,7 @@ SECTIONS * The strongest and only alignment constraint is 8 words to simplify * memraise8 assembly code. */ - . = ( STM32MP1_BL32_BASE - STM32MP1_BINARY_BASE ); + . = ( STM32MP_BL32_BASE - STM32MP_BINARY_BASE ); __BL32_IMAGE_START__ = .; *(.bl32_image*) __BL32_IMAGE_END__ = .; diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c index a8f9bf46d..c402c2039 100644 --- a/plat/st/stm32mp1/stm32mp1_context.c +++ b/plat/st/stm32mp1/stm32mp1_context.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -23,9 +23,9 @@ 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)) { + if (!stm32mp_clk_is_enabled(RTCAPB)) { tamp_clk_off = 1; - if (stm32mp1_clk_enable(RTCAPB) != 0) { + if (stm32mp_clk_enable(RTCAPB) != 0) { return -EINVAL; } } @@ -36,7 +36,7 @@ int stm32_save_boot_interface(uint32_t interface, uint32_t instance) TAMP_BOOT_ITF_SHIFT); if (tamp_clk_off != 0U) { - if (stm32mp1_clk_disable(RTCAPB) != 0) { + if (stm32mp_clk_disable(RTCAPB) != 0) { return -EINVAL; } } diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index d12a93ffb..a456f263b 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -22,14 +22,13 @@ * STM32MP1 memory map related constants ******************************************************************************/ -#define STM32MP1_SRAM_BASE U(0x2FFC0000) -#define STM32MP1_SRAM_SIZE U(0x00040000) +#define STM32MP_SYSRAM_BASE U(0x2FFC0000) +#define STM32MP_SYSRAM_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 +#define STM32MP_DDR_BASE U(0xC0000000) +#define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */ +#define STM32MP_DDR_SPEED_DFLT 528 /* DDR power initializations */ #ifndef __ASSEMBLY__ @@ -40,36 +39,36 @@ enum ddr_type { #endif /* Section used inside TF binaries */ -#define STM32MP1_PARAM_LOAD_SIZE U(0x00002400) /* 9 Ko for param */ +#define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 Ko for param */ /* 256 Octets reserved for header */ -#define STM32MP1_HEADER_SIZE U(0x00000100) +#define STM32MP_HEADER_SIZE U(0x00000100) -#define STM32MP1_BINARY_BASE (STM32MP1_SRAM_BASE + \ - STM32MP1_PARAM_LOAD_SIZE + \ - STM32MP1_HEADER_SIZE) +#define STM32MP_BINARY_BASE (STM32MP_SYSRAM_BASE + \ + STM32MP_PARAM_LOAD_SIZE + \ + STM32MP_HEADER_SIZE) -#define STM32MP1_BINARY_SIZE (STM32MP1_SRAM_SIZE - \ - (STM32MP1_PARAM_LOAD_SIZE + \ - STM32MP1_HEADER_SIZE)) +#define STM32MP_BINARY_SIZE (STM32MP_SYSRAM_SIZE - \ + (STM32MP_PARAM_LOAD_SIZE + \ + STM32MP_HEADER_SIZE)) #if STACK_PROTECTOR_ENABLED -#define STM32MP1_BL32_SIZE U(0x00012000) /* 72 Ko for BL32 */ +#define STM32MP_BL32_SIZE U(0x00012000) /* 72 Ko for BL32 */ #else -#define STM32MP1_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */ +#define STM32MP_BL32_SIZE U(0x00011000) /* 68 Ko for BL32 */ #endif -#define STM32MP1_BL32_BASE (STM32MP1_SRAM_BASE + \ - STM32MP1_SRAM_SIZE - \ - STM32MP1_BL32_SIZE) +#define STM32MP_BL32_BASE (STM32MP_SYSRAM_BASE + \ + STM32MP_SYSRAM_SIZE - \ + STM32MP_BL32_SIZE) #if STACK_PROTECTOR_ENABLED -#define STM32MP1_BL2_SIZE U(0x00015000) /* 84 Ko for BL2 */ +#define STM32MP_BL2_SIZE U(0x00015000) /* 84 Ko for BL2 */ #else -#define STM32MP1_BL2_SIZE U(0x00013000) /* 76 Ko for BL2 */ +#define STM32MP_BL2_SIZE U(0x00013000) /* 76 Ko for BL2 */ #endif -#define STM32MP1_BL2_BASE (STM32MP1_BL32_BASE - \ - STM32MP1_BL2_SIZE) +#define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \ + STM32MP_BL2_SIZE) /* BL2 and BL32/sp_min require 5 tables */ #define MAX_XLAT_TABLES 5 @@ -86,12 +85,12 @@ enum ddr_type { #endif /* DTB initialization value */ -#define STM32MP1_DTB_SIZE U(0x00004000) /* 16Ko for DTB */ +#define STM32MP_DTB_SIZE U(0x00004000) /* 16Ko for DTB */ -#define STM32MP1_DTB_BASE (STM32MP1_BL2_BASE - \ - STM32MP1_DTB_SIZE) +#define STM32MP_DTB_BASE (STM32MP_BL2_BASE - \ + STM32MP_DTB_SIZE) -#define STM32MP1_BL33_BASE (STM32MP1_DDR_BASE + U(0x100000)) +#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000)) /******************************************************************************* * STM32MP1 device/io map related constants (used for MMU) @@ -156,12 +155,12 @@ enum ddr_type { #define USART6_BASE U(0x44003000) #define UART7_BASE U(0x40018000) #define UART8_BASE U(0x40019000) -#define STM32MP1_UART_BAUDRATE U(115200) +#define STM32MP_UART_BAUDRATE U(115200) /* For UART crash console */ -#define STM32MP1_DEBUG_USART_BASE UART4_BASE +#define STM32MP_DEBUG_USART_BASE UART4_BASE /* UART4 on HSI@64MHz, TX on GPIOG11 Alternate 6 */ -#define STM32MP1_DEBUG_USART_CLK_FRQ 64000000 +#define STM32MP_DEBUG_USART_CLK_FRQ 64000000 #define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOG_BASE #define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_AHB4ENSETR #define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_AHB4ENSETR_GPIOGEN @@ -193,15 +192,15 @@ enum ddr_type { /******************************************************************************* * STM32MP1 SDMMC ******************************************************************************/ -#define STM32MP1_SDMMC1_BASE U(0x58005000) -#define STM32MP1_SDMMC2_BASE U(0x58007000) -#define STM32MP1_SDMMC3_BASE U(0x48004000) +#define STM32MP_SDMMC1_BASE U(0x58005000) +#define STM32MP_SDMMC2_BASE U(0x58007000) +#define STM32MP_SDMMC3_BASE U(0x48004000) -#define STM32MP1_MMC_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_NORMAL_SPEED_MAX_FREQ 26000000 /*26 MHz*/ -#define STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ 52000000 /*52 MHz*/ +#define STM32MP_MMC_INIT_FREQ 400000 /*400 KHz*/ +#define STM32MP_SD_NORMAL_SPEED_MAX_FREQ 25000000 /*25 MHz*/ +#define STM32MP_SD_HIGH_SPEED_MAX_FREQ 50000000 /*50 MHz*/ +#define STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ 26000000 /*26 MHz*/ +#define STM32MP_EMMC_HIGH_SPEED_MAX_FREQ 52000000 /*52 MHz*/ /******************************************************************************* * STM32MP1 BSEC / OTP diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S index 8c2e1b6ea..c6759655a 100644 --- a/plat/st/stm32mp1/stm32mp1_helper.S +++ b/plat/st/stm32mp1/stm32mp1_helper.S @@ -74,7 +74,7 @@ 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 + cmp r0, #STM32MP_PRIMARY_CPU moveq r0, #1 movne r0, #0 bx lr @@ -143,9 +143,9 @@ func plat_crash_console_init orr r2, r2, #DEBUG_UART_TX_EN str r2, [r1] - ldr r0, =STM32MP1_DEBUG_USART_BASE - ldr r1, =STM32MP1_DEBUG_USART_CLK_FRQ - ldr r2, =STM32MP1_UART_BAUDRATE + ldr r0, =STM32MP_DEBUG_USART_BASE + ldr r1, =STM32MP_DEBUG_USART_CLK_FRQ + ldr r2, =STM32MP_UART_BAUDRATE b console_stm32_core_init endfunc plat_crash_console_init @@ -156,7 +156,7 @@ endfunc plat_crash_console_init * --------------------------------------------- */ func plat_crash_console_flush - ldr r1, =STM32MP1_DEBUG_USART_BASE + ldr r1, =STM32MP_DEBUG_USART_BASE b console_stm32_core_flush endfunc plat_crash_console_flush @@ -172,6 +172,6 @@ endfunc plat_crash_console_flush * --------------------------------------------- */ func plat_crash_console_putc - ldr r1, =STM32MP1_DEBUG_USART_BASE + ldr r1, =STM32MP_DEBUG_USART_BASE b console_stm32_core_putc endfunc plat_crash_console_putc diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c index 20f66e98b..18921ef00 100644 --- a/plat/st/stm32mp1/stm32mp1_pm.c +++ b/plat/st/stm32mp1/stm32mp1_pm.c @@ -70,15 +70,15 @@ static int stm32_pwr_domain_on(u_register_t mpidr) return PSCI_E_INVALID_PARAMS; } - if ((stm32_sec_entrypoint < STM32MP1_SRAM_BASE) || - (stm32_sec_entrypoint > (STM32MP1_SRAM_BASE + - (STM32MP1_SRAM_SIZE - 1)))) { + if ((stm32_sec_entrypoint < STM32MP_SYSRAM_BASE) || + (stm32_sec_entrypoint > (STM32MP_SYSRAM_BASE + + (STM32MP_SYSRAM_SIZE - 1)))) { return PSCI_E_INVALID_ADDRESS; } - if (!stm32mp1_clk_is_enabled(RTCAPB)) { + if (!stm32mp_clk_is_enabled(RTCAPB)) { tamp_clk_off = 1; - if (stm32mp1_clk_enable(RTCAPB) != 0) { + if (stm32mp_clk_enable(RTCAPB) != 0) { panic(); } } @@ -92,13 +92,13 @@ static int stm32_pwr_domain_on(u_register_t mpidr) mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER); if (tamp_clk_off != 0U) { - if (stm32mp1_clk_disable(RTCAPB) != 0) { + if (stm32mp_clk_disable(RTCAPB) != 0) { panic(); } } /* Generate an IT to core 1 */ - gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP1_SECONDARY_CPU); + gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP_SECONDARY_CPU); return PSCI_E_SUCCESS; } @@ -194,7 +194,7 @@ static int stm32_validate_power_state(unsigned int power_state, static int stm32_validate_ns_entrypoint(uintptr_t entrypoint) { /* The non-secure entry point must be in DDR */ - if (entrypoint < STM32MP1_DDR_BASE) { + if (entrypoint < STM32MP_DDR_BASE) { return PSCI_E_INVALID_ADDRESS; } diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c index f3beb591f..20eb88e72 100644 --- a/plat/st/stm32mp1/stm32mp1_private.c +++ b/plat/st/stm32mp1/stm32mp1_private.c @@ -8,8 +8,8 @@ #include -#define MAP_SRAM MAP_REGION_FLAT(STM32MP1_SRAM_BASE, \ - STM32MP1_SRAM_SIZE, \ +#define MAP_SRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \ + STM32MP_SYSRAM_SIZE, \ MT_MEMORY | \ MT_RW | \ MT_SECURE | \ diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c index 99719e42f..bb66b4b5a 100644 --- a/plat/st/stm32mp1/stm32mp1_security.c +++ b/plat/st/stm32mp1/stm32mp1_security.c @@ -22,7 +22,7 @@ static void init_tzc400(void) { unsigned long long region_base, region_top; - unsigned long long ddr_base = STM32MP1_DDR_BASE; + unsigned long long ddr_base = STM32MP_DDR_BASE; unsigned long long ddr_size = (unsigned long long)dt_get_ddr_size(); tzc400_init(STM32MP1_TZC_BASE); @@ -62,11 +62,11 @@ static void init_tzc400(void) ******************************************************************************/ static void early_init_tzc400(void) { - if (stm32mp1_clk_enable(TZC1) != 0) { + if (stm32mp_clk_enable(TZC1) != 0) { ERROR("Cannot enable TZC1 clock\n"); panic(); } - if (stm32mp1_clk_enable(TZC2) != 0) { + if (stm32mp_clk_enable(TZC2) != 0) { ERROR("Cannot enable TZC2 clock\n"); panic(); } @@ -80,9 +80,9 @@ static void early_init_tzc400(void) * 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), + STM32MP_DDR_BASE, + STM32MP_DDR_BASE + + (STM32MP_DDR_MAX_SIZE - 1U), TZC_REGION_S_RDWR, TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID)); From e0a8ce5d0d1395da3b442c7c019ba62d1361e92b Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 14 Feb 2019 11:13:50 +0100 Subject: [PATCH 03/11] stm32mp1: remove some dependencies on clocks and reset in drivers Include all RCC, clocks and reset headers from stm32mp1_def.h which if exported to the firmware through platform_def.h. The same dependency removal is done in common code as well. Some useless includes are also removed in stm32_sdmmc2 driver. Change-Id: I731ea5775c3fdb7f7b0c388b93923ed5e84b8d3f Signed-off-by: Yann Gautier --- drivers/st/ddr/stm32mp1_ddr.c | 3 --- drivers/st/ddr/stm32mp1_ddr_helpers.c | 3 +-- drivers/st/ddr/stm32mp1_ram.c | 3 --- drivers/st/gpio/stm32_gpio.c | 1 - drivers/st/mmc/stm32_sdmmc2.c | 4 ---- drivers/st/pmic/stm32mp_pmic.c | 1 - drivers/st/reset/stm32mp1_reset.c | 1 - plat/st/common/bl2_io_storage.c | 1 - plat/st/common/stm32mp_common.c | 1 - plat/st/common/stm32mp_dt.c | 1 - plat/st/stm32mp1/bl2_plat_setup.c | 1 - plat/st/stm32mp1/stm32mp1_def.h | 5 +++++ plat/st/stm32mp1/stm32mp1_helper.S | 1 - plat/st/stm32mp1/stm32mp1_pm.c | 1 - plat/st/stm32mp1/stm32mp1_security.c | 1 - 15 files changed, 6 insertions(+), 22 deletions(-) diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c index b9347540d..26a5a4d91 100644 --- a/drivers/st/ddr/stm32mp1_ddr.c +++ b/drivers/st/ddr/stm32mp1_ddr.c @@ -14,13 +14,10 @@ #include #include #include -#include #include #include #include #include -#include -#include #include #include diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c index a8c1b7769..e50b27be8 100644 --- a/drivers/st/ddr/stm32mp1_ddr_helpers.c +++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,7 +7,6 @@ #include #include -#include #include void ddr_enable_clock(void) diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c index 532062e01..7b13385fc 100644 --- a/drivers/st/ddr/stm32mp1_ram.c +++ b/drivers/st/ddr/stm32mp1_ram.c @@ -12,12 +12,9 @@ #include #include -#include #include #include #include -#include -#include #include #define DDR_PATTERN 0xAAAAAAAAU diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c index 1d8111a1b..5733046d0 100644 --- a/drivers/st/gpio/stm32_gpio.c +++ b/drivers/st/gpio/stm32_gpio.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c index 10fd5f5d0..dce8345b0 100644 --- a/drivers/st/mmc/stm32_sdmmc2.c +++ b/drivers/st/mmc/stm32_sdmmc2.c @@ -20,10 +20,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c index eb5c6e66d..52f712f10 100644 --- a/drivers/st/pmic/stm32mp_pmic.c +++ b/drivers/st/pmic/stm32mp_pmic.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c index aac74e15d..b9a7ac7c9 100644 --- a/drivers/st/reset/stm32mp1_reset.c +++ b/drivers/st/reset/stm32mp1_reset.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c index 5b649a342..c8bb559f4 100644 --- a/plat/st/common/bl2_io_storage.c +++ b/plat/st/common/bl2_io_storage.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c index 20aa57da1..aecef4718 100644 --- a/plat/st/common/stm32mp_common.c +++ b/plat/st/common/stm32mp_common.c @@ -10,7 +10,6 @@ #include #include -#include #include uintptr_t plat_get_ns_image_entrypoint(void) diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c index 0b6a0d32f..c0b0518d9 100644 --- a/plat/st/common/stm32mp_dt.c +++ b/plat/st/common/stm32mp_dt.c @@ -13,7 +13,6 @@ #include #include -#include #include #include diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index beea69a9d..bcf1aa9ed 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index a456f263b..95d341252 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -8,10 +8,15 @@ #define STM32MP1_DEF_H #include +#include +#include +#include #include #include #ifndef __ASSEMBLY__ +#include + #include #include #include diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S index c6759655a..bfcd991a3 100644 --- a/plat/st/stm32mp1/stm32mp1_helper.S +++ b/plat/st/stm32mp1/stm32mp1_helper.S @@ -10,7 +10,6 @@ #include #include #include -#include #define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) #define GPIO_TX_ALT_SHIFT ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2) diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c index 18921ef00..c4d023271 100644 --- a/plat/st/stm32mp1/stm32mp1_pm.c +++ b/plat/st/stm32mp1/stm32mp1_pm.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c index bb66b4b5a..baa3916d0 100644 --- a/plat/st/stm32mp1/stm32mp1_security.c +++ b/plat/st/stm32mp1/stm32mp1_security.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include From 6f4572bd7857122e65bd6d9bce9e39fc572d7c56 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 14 Feb 2019 11:14:18 +0100 Subject: [PATCH 04/11] Introduce timeout_init_us/timeout_elapsed() delay tracking with CNTPCT. timeout_init_us(some_timeout_us); returns a reference to detect timeout for the provided microsecond delay value from current time. timeout_elapsed(reference) return true/false whether the reference timeout is elapsed. This change is inspired by the OP-TEE OS timeout resources [1]. [1] https://github.com/OP-TEE/optee_os/blob/3.4.0/core/arch/arm/include/kernel/delay.h#L45 Change-Id: Id81ff48aa49693f555dc621064878417101d5587 Signed-off-by: Yann Gautier Signed-off-by: Etienne Carriere --- plat/st/common/include/stm32mp_common.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h index 269d8acbb..5f54b103d 100644 --- a/plat/st/common/include/stm32mp_common.h +++ b/plat/st/common/include/stm32mp_common.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved + * Copyright (c) 2018-2019, Linaro Limited * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,6 +10,8 @@ #include +#include + /* Functions to save and get boot context address given by ROM code */ void stm32mp_save_boot_ctx_address(uintptr_t address); uintptr_t stm32mp_get_boot_ctx_address(void); @@ -42,4 +45,19 @@ unsigned long stm32mp_clk_get_rate(unsigned long id); /* Initialise the IO layer and register platform IO devices */ void stm32mp_io_setup(void); +static inline uint64_t arm_cnt_us2cnt(uint32_t us) +{ + return ((uint64_t)us * (uint64_t)read_cntfrq()) / 1000000ULL; +} + +static inline uint64_t timeout_init_us(uint32_t us) +{ + return read_cntpct_el0() + arm_cnt_us2cnt(us); +} + +static inline bool timeout_elapsed(uint64_t expire) +{ + return read_cntpct_el0() > expire; +} + #endif /* STM32MP_COMMON_H */ From dfdb057a179556a48e313d2c884af3f877530b7e Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 14 Feb 2019 11:14:39 +0100 Subject: [PATCH 05/11] stm32mp1: use new functions to manage timeouts Remove the previously use function: get_timer, and use new functions timeout_init_us and timeout_elapsed. Change-Id: I4e95b123648bff7ca91e40462a2a3ae24cfe1697 Signed-off-by: Yann Gautier Signed-off-by: Etienne Carriere Signed-off-by: Nicolas LE BAYON --- drivers/st/clk/stm32mp1_clk.c | 51 +++++++++++++++---------------- drivers/st/ddr/stm32mp1_ddr.c | 51 +++++++++++++------------------ drivers/st/mmc/stm32_sdmmc2.c | 23 +++++++------- include/drivers/st/stm32mp1_clk.h | 9 ------ 4 files changed, 58 insertions(+), 76 deletions(-) diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index 02866a214..2e89ecf36 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -27,16 +27,16 @@ #include #include -#define MAX_HSI_HZ 64000000 +#define MAX_HSI_HZ 64000000 -#define TIMEOUT_200MS (plat_get_syscnt_freq2() / 5U) -#define TIMEOUT_1S plat_get_syscnt_freq2() +#define TIMEOUT_US_200MS U(200000) +#define TIMEOUT_US_1S U(1000000) -#define PLLRDY_TIMEOUT TIMEOUT_200MS -#define CLKSRC_TIMEOUT TIMEOUT_200MS -#define CLKDIV_TIMEOUT TIMEOUT_200MS -#define HSIDIV_TIMEOUT TIMEOUT_200MS -#define OSCRDY_TIMEOUT TIMEOUT_1S +#define PLLRDY_TIMEOUT TIMEOUT_US_200MS +#define CLKSRC_TIMEOUT TIMEOUT_US_200MS +#define CLKDIV_TIMEOUT TIMEOUT_US_200MS +#define HSIDIV_TIMEOUT TIMEOUT_US_200MS +#define OSCRDY_TIMEOUT TIMEOUT_US_1S enum stm32mp1_parent_id { /* Oscillators are defined in enum stm32mp_osc_id */ @@ -870,7 +870,7 @@ static void stm32mp1_hs_ocs_set(int enable, uint32_t rcc, uint32_t mask_on) static int stm32mp1_osc_wait(int enable, uint32_t rcc, uint32_t offset, uint32_t mask_rdy) { - unsigned long start; + uint64_t timeout; uint32_t mask_test; uint32_t address = rcc + offset; @@ -880,9 +880,9 @@ static int stm32mp1_osc_wait(int enable, uint32_t rcc, uint32_t offset, mask_test = 0; } - start = get_timer(0); + timeout = timeout_init_us(OSCRDY_TIMEOUT); while ((mmio_read_32(address) & mask_rdy) != mask_test) { - if (get_timer(start) > OSCRDY_TIMEOUT) { + if (timeout_elapsed(timeout)) { ERROR("OSC %x @ %x timeout for enable=%d : 0x%x\n", mask_rdy, address, enable, mmio_read_32(address)); return -ETIMEDOUT; @@ -975,16 +975,16 @@ static void stm32mp1_hsi_set(uint32_t rcc, int enable) static int stm32mp1_set_hsidiv(uint32_t rcc, uint8_t hsidiv) { - unsigned long start; uint32_t address = rcc + RCC_OCRDYR; + uint64_t timeout; mmio_clrsetbits_32(rcc + RCC_HSICFGR, RCC_HSICFGR_HSIDIV_MASK, RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); - start = get_timer(0); + timeout = timeout_init_us(HSIDIV_TIMEOUT); while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { - if (get_timer(start) > HSIDIV_TIMEOUT) { + if (timeout_elapsed(timeout)) { ERROR("HSIDIV failed @ 0x%x: 0x%x\n", address, mmio_read_32(address)); return -ETIMEDOUT; @@ -1032,12 +1032,11 @@ static int stm32mp1_pll_output(struct stm32mp1_clk_priv *priv, { const struct stm32mp1_clk_pll *pll = priv->data->pll; uint32_t pllxcr = priv->base + pll[pll_id].pllxcr; - unsigned long start; + uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); - start = get_timer(0); /* Wait PLL lock */ while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { - if (get_timer(start) > PLLRDY_TIMEOUT) { + if (timeout_elapsed(timeout)) { ERROR("PLL%d start failed @ 0x%x: 0x%x\n", pll_id, pllxcr, mmio_read_32(pllxcr)); return -ETIMEDOUT; @@ -1055,7 +1054,7 @@ static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv, { const struct stm32mp1_clk_pll *pll = priv->data->pll; uint32_t pllxcr = priv->base + pll[pll_id].pllxcr; - unsigned long start; + uint64_t timeout; /* Stop all output */ mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | @@ -1064,10 +1063,10 @@ static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv, /* Stop PLL */ mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON); - start = get_timer(0); + timeout = timeout_init_us(PLLRDY_TIMEOUT); /* Wait PLL stopped */ while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { - if (get_timer(start) > PLLRDY_TIMEOUT) { + if (timeout_elapsed(timeout)) { ERROR("PLL%d stop failed @ 0x%x: 0x%x\n", pll_id, pllxcr, mmio_read_32(pllxcr)); return -ETIMEDOUT; @@ -1166,14 +1165,14 @@ static int stm32mp1_set_clksrc(struct stm32mp1_clk_priv *priv, unsigned int clksrc) { uint32_t address = priv->base + (clksrc >> 4); - unsigned long start; + uint64_t timeout; mmio_clrsetbits_32(address, RCC_SELR_SRC_MASK, clksrc & RCC_SELR_SRC_MASK); - start = get_timer(0); + timeout = timeout_init_us(CLKSRC_TIMEOUT); while ((mmio_read_32(address) & RCC_SELR_SRCRDY) == 0U) { - if (get_timer(start) > CLKSRC_TIMEOUT) { + if (timeout_elapsed(timeout)) { ERROR("CLKSRC %x start failed @ 0x%x: 0x%x\n", clksrc, address, mmio_read_32(address)); return -ETIMEDOUT; @@ -1185,14 +1184,14 @@ static int stm32mp1_set_clksrc(struct stm32mp1_clk_priv *priv, static int stm32mp1_set_clkdiv(unsigned int clkdiv, uint32_t address) { - unsigned long start; + uint64_t timeout; mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK, clkdiv & RCC_DIVR_DIV_MASK); - start = get_timer(0); + timeout = timeout_init_us(CLKDIV_TIMEOUT); while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) { - if (get_timer(start) > CLKDIV_TIMEOUT) { + if (timeout_elapsed(timeout)) { ERROR("CLKDIV %x start failed @ 0x%x: 0x%x\n", clkdiv, address, mmio_read_32(address)); return -ETIMEDOUT; diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c index 26a5a4d91..9db0c5dcf 100644 --- a/drivers/st/ddr/stm32mp1_ddr.c +++ b/drivers/st/ddr/stm32mp1_ddr.c @@ -29,7 +29,7 @@ struct reg_desc { #define INVALID_OFFSET 0xFFU -#define TIMESLOT_1US (plat_get_syscnt_freq2() / 1000000U) +#define TIMEOUT_US_1S 1000000U #define DDRCTL_REG(x, y) \ { \ @@ -324,49 +324,43 @@ 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; + uint64_t timeout = timeout_init_us(TIMEOUT_US_1S); do { pgsr = mmio_read_32((uintptr_t)&phy->pgsr); - time = get_timer(start); - if (time != time0) { - VERBOSE(" > [0x%lx] pgsr = 0x%x &\n", - (uintptr_t)&phy->pgsr, pgsr); - VERBOSE(" [0x%lx] pir = 0x%x (time=%lx)\n", - (uintptr_t)&phy->pir, - mmio_read_32((uintptr_t)&phy->pir), - time); - } - time0 = time; - if (time > plat_get_syscnt_freq2()) { + VERBOSE(" > [0x%lx] pgsr = 0x%x &\n", + (uintptr_t)&phy->pgsr, pgsr); + + if (timeout_elapsed(timeout)) { 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); + } while (((pgsr & DDRPHYC_PGSR_IDONE) == 0U) && (error == 0)); VERBOSE("\n[0x%lx] pgsr = 0x%x\n", (uintptr_t)&phy->pgsr, pgsr); } @@ -398,21 +392,19 @@ static void stm32mp1_start_sw_done(struct stm32mp1_ddrctl *ctl) /* Wait quasi dynamic register update */ static void stm32mp1_wait_sw_done_ack(struct stm32mp1_ddrctl *ctl) { - unsigned long start; + uint64_t timeout; uint32_t swstat; mmio_setbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); VERBOSE("[0x%lx] swctl = 0x%x\n", (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl)); - start = get_timer(0); + timeout = timeout_init_us(TIMEOUT_US_1S); do { swstat = mmio_read_32((uintptr_t)&ctl->swstat); VERBOSE("[0x%lx] swstat = 0x%x ", (uintptr_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()) { + if (timeout_elapsed(timeout)) { panic(); } } while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U); @@ -424,22 +416,21 @@ static void stm32mp1_wait_sw_done_ack(struct stm32mp1_ddrctl *ctl) /* Wait quasi dynamic register update */ static void stm32mp1_wait_operating_mode(struct ddr_info *priv, uint32_t mode) { - unsigned long start; + uint64_t timeout; uint32_t stat; - uint32_t operating_mode; - uint32_t selref_type; int break_loop = 0; - start = get_timer(0); + timeout = timeout_init_us(TIMEOUT_US_1S); for ( ; ; ) { + uint32_t operating_mode; + uint32_t selref_type; + stat = mmio_read_32((uintptr_t)&priv->ctl->stat); operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK; selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK; VERBOSE("[0x%lx] stat = 0x%x\n", (uintptr_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()) { + if (timeout_elapsed(timeout)) { panic(); } diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c index dce8345b0..017dd88ff 100644 --- a/drivers/st/mmc/stm32_sdmmc2.c +++ b/drivers/st/mmc/stm32_sdmmc2.c @@ -119,8 +119,8 @@ SDMMC_STAR_IDMATE | \ SDMMC_STAR_IDMABTC) -#define TIMEOUT_10_MS (plat_get_syscnt_freq2() / 100U) -#define TIMEOUT_1_S plat_get_syscnt_freq2() +#define TIMEOUT_US_10_MS 10000U +#define TIMEOUT_US_1_S 1000000U #define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" @@ -181,11 +181,12 @@ static int stm32_sdmmc2_stop_transfer(void) static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) { + uint64_t timeout; uint32_t flags_cmd, status; uint32_t flags_data = 0; int err = 0; uintptr_t base = sdmmc2_params.reg_base; - unsigned int cmd_reg, arg_reg, start; + unsigned int cmd_reg, arg_reg; if (cmd == NULL) { return -EINVAL; @@ -268,10 +269,10 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) status = mmio_read_32(base + SDMMC_STAR); - start = get_timer(0); + timeout = timeout_init_us(TIMEOUT_US_10_MS); while ((status & flags_cmd) == 0U) { - if (get_timer(start) > TIMEOUT_10_MS) { + if (timeout_elapsed(timeout)) { err = -ETIMEDOUT; ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n", __func__, cmd->cmd_idx, status); @@ -335,10 +336,10 @@ static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) status = mmio_read_32(base + SDMMC_STAR); - start = get_timer(0); + timeout = timeout_init_us(TIMEOUT_US_10_MS); while ((status & flags_data) == 0U) { - if (get_timer(start) > TIMEOUT_10_MS) { + if (timeout_elapsed(timeout)) { ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n", __func__, cmd->cmd_idx, status); err = -ETIMEDOUT; @@ -360,7 +361,7 @@ err_exit: mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS); - if (err != 0) { + if ((err != 0) && ((status & SDMMC_STAR_DPSMACT) != 0U)) { int ret_stop = stm32_sdmmc2_stop_transfer(); if (ret_stop != 0) { @@ -519,7 +520,7 @@ static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size) uint32_t *buffer; uintptr_t base = sdmmc2_params.reg_base; uintptr_t fifo_reg = base + SDMMC_FIFOR; - unsigned int start; + uint64_t timeout; int ret; /* Assert buf is 4 bytes aligned */ @@ -537,7 +538,7 @@ static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size) flags |= SDMMC_STAR_DBCKEND; } - start = get_timer(0); + timeout = timeout_init_us(TIMEOUT_US_1_S); do { status = mmio_read_32(base + SDMMC_STAR); @@ -559,7 +560,7 @@ static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size) return -EIO; } - if (get_timer(start) > TIMEOUT_1_S) { + if (timeout_elapsed(timeout)) { ERROR("%s: timeout 1s (status = %x)\n", __func__, status); mmio_write_32(base + SDMMC_ICR, diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h index 11ff7bf24..3ba890942 100644 --- a/include/drivers/st/stm32mp1_clk.h +++ b/include/drivers/st/stm32mp1_clk.h @@ -13,13 +13,4 @@ int stm32mp1_clk_probe(void); int stm32mp1_clk_init(void); 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 */ From d82d4ff0666711067328d2d34e2bdc009e84969f Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 14 Feb 2019 11:15:03 +0100 Subject: [PATCH 06/11] stm32mp1: update I2C and PMIC drivers Regulator configuration at boot takes more information from DT. I2C configuration from DT is done in I2C driver. I2C driver manages more transfer modes. The min voltage of buck1 should also be increased to 1.2V, else the platform does not boot. Heavily modifies stm32_i2c.c since many functions move inside the source file to remove redundant declarations. Change-Id: I0bee5d776cf3ff15e687427cd6abc06ab237d025 Signed-off-by: Yann Gautier Signed-off-by: Etienne Carriere Signed-off-by: Lionel Debieve Signed-off-by: Nicolas LE BAYON --- drivers/st/ddr/stm32mp1_ddr.c | 2 +- drivers/st/i2c/stm32_i2c.c | 1367 ++++++++++++++++------------- drivers/st/pmic/stm32mp_pmic.c | 154 ++-- drivers/st/pmic/stpmic1.c | 11 +- fdts/stm32mp157c-ed1.dts | 2 +- include/drivers/st/stm32_i2c.h | 240 ++--- include/drivers/st/stm32mp_pmic.h | 37 +- plat/st/stm32mp1/bl2_plat_setup.c | 2 +- 8 files changed, 1008 insertions(+), 807 deletions(-) diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c index 9db0c5dcf..caf8eefa8 100644 --- a/drivers/st/ddr/stm32mp1_ddr.c +++ b/drivers/st/ddr/stm32mp1_ddr.c @@ -700,7 +700,7 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, static int board_ddr_power_init(enum ddr_type ddr_type) { - if (dt_check_pmic()) { + if (dt_pmic_status() > 0) { return pmic_ddr_power_init(ddr_type); } diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c index 2be7afe2d..ed880522b 100644 --- a/drivers/st/i2c/stm32_i2c.c +++ b/drivers/st/i2c/stm32_i2c.c @@ -8,10 +8,16 @@ #include #include -#include +#include + +#include + +#include #include +#include #include #include +#include /* STM32 I2C registers offsets */ #define I2C_CR1 0x00U @@ -26,50 +32,122 @@ #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 TIMINGR_CLEAR_MASK 0xF0FFFFFFU #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); +#define I2C_NSEC_PER_SEC 1000000000L -/* 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); +/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */ +#define I2C_TIMING 0x10D07DB5 -/* Private function to flush TXDR register */ -static void i2c_flush_txdr(struct i2c_handle_s *hi2c); +static void notif_i2c_timeout(struct i2c_handle_s *hi2c) +{ + hi2c->i2c_err |= I2C_ERROR_TIMEOUT; + hi2c->i2c_mode = I2C_MODE_NONE; + hi2c->i2c_state = I2C_STATE_READY; +} -/* 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 Configure I2C Analog noise filter. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C peripheral. + * @param analog_filter: New state of the Analog filter + * @retval 0 if OK, negative value else + */ +static int 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; +} + +/* + * @brief Get I2C setup information from the device tree and set pinctrl + * configuration. + * @param fdt: Pointer to the device tree + * @param node: I2C node offset + * @param init: Ref to the initialization configuration structure + * @retval 0 if OK, negative value else + */ +int stm32_i2c_get_setup_from_fdt(void *fdt, int node, + struct stm32_i2c_init_s *init) +{ + const fdt32_t *cuint; + + cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); + if (cuint == NULL) { + init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; + } else { + init->rise_time = fdt32_to_cpu(*cuint); + } + + cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); + if (cuint == NULL) { + init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; + } else { + init->fall_time = fdt32_to_cpu(*cuint); + } + + cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); + if (cuint == NULL) { + init->speed_mode = STM32_I2C_SPEED_DEFAULT; + } else { + switch (fdt32_to_cpu(*cuint)) { + case STANDARD_RATE: + init->speed_mode = I2C_SPEED_STANDARD; + break; + case FAST_RATE: + init->speed_mode = I2C_SPEED_FAST; + break; + case FAST_PLUS_RATE: + init->speed_mode = I2C_SPEED_FAST_PLUS; + break; + default: + init->speed_mode = STM32_I2C_SPEED_DEFAULT; + break; + } + } + + return dt_set_pinctrl_config(node); +} /* * @brief Initialize the I2C device. * @param hi2c: Pointer to a struct i2c_handle_s structure that contains * the configuration information for the specified I2C. + * @param init_data: Initialization configuration structure * @retval 0 if OK, negative value else */ -int stm32_i2c_init(struct i2c_handle_s *hi2c) +int stm32_i2c_init(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init_data) { + int rc = 0; + uint32_t timing = I2C_TIMING; + if (hi2c == NULL) { return -ENOENT; } @@ -80,34 +158,38 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c) hi2c->i2c_state = I2C_STATE_BUSY; + stm32mp_clk_enable(hi2c->clock); + /* 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); + timing & TIMINGR_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) { + if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) { mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, - I2C_OAR1_OA1EN | hi2c->i2c_init.own_address1); + I2C_OAR1_OA1EN | init_data->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); + init_data->own_address1); } + mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0); + /* 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); + if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) { + mmio_setbits_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) + * (should be disabled only during Slave process). */ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_AUTOEND | I2C_CR2_NACK); @@ -117,14 +199,14 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c) /* 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)); + init_data->dual_address_mode | + init_data->own_address2 | + (init_data->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); + init_data->general_call_mode | + init_data->no_stretch_mode); /* Enable the selected I2C peripheral */ mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); @@ -133,471 +215,23 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c) 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; + rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ? + I2C_ANALOGFILTER_ENABLE : + I2C_ANALOGFILTER_DISABLE); + if (rc != 0) { + ERROR("Cannot initialize I2C analog filter (%d)\n", rc); + stm32mp_clk_disable(hi2c->clock); + return rc; } - if ((p_data == NULL) || (size == 0U)) { - return -EINVAL; - } + stm32mp_clk_disable(hi2c->clock); - 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; + return rc; } /* * @brief I2C Tx data register flush process. - * @param hi2c: I2C handle. + * @param hi2c: I2C handle * @retval None */ static void i2c_flush_txdr(struct i2c_handle_s *hi2c) @@ -623,104 +257,28 @@ static void i2c_flush_txdr(struct i2c_handle_s *hi2c) * @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 + * @param flag: Specifies the I2C flag to check + * @param awaited_value: The awaited bit value for the flag (0 or 1) + * @param timeout_ref: Reference to target timeout * @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 awaited_value, uint64_t timeout_ref) { - uint8_t flag_check; + for ( ; ; ) { + uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR); - 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 (!!(isr & flag) != !!awaited_value) { + return 0; } - 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; - + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); hi2c->lock = 0; return -EIO; } } - - return 0; } /* @@ -728,12 +286,10 @@ static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint32_t timeout, * 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 + * @param timeout_ref: Reference to target timeout * @retval 0 if OK, negative value else */ -static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout, - uint32_t tick_start) +static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref) { if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) { return 0; @@ -745,17 +301,11 @@ static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout, */ 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; + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + hi2c->lock = 0; - hi2c->lock = 0; - - return -EIO; - } + return -EIO; } } @@ -776,16 +326,70 @@ static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint32_t timeout, return -EIO; } +/* + * @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_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_TXIS) == 0U) { + if (i2c_ack_failed(hi2c, timeout_ref) != 0) { + return -EIO; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + 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_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_STOPF) == 0U) { + if (i2c_ack_failed(hi2c, timeout_ref) != 0) { + return -EIO; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + hi2c->lock = 0; + + return -EIO; + } + } + + return 0; +} + /* * @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 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_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. @@ -815,38 +419,563 @@ static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, } /* - * @brief Configure I2C Analog noise filter. + * @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 I2Cx peripheral - * @param analog_filter: New state of the Analog filter. + * 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_ref: Reference to target timeout * @retval 0 if OK, negative value else */ -int stm32_i2c_config_analog_filter(struct i2c_handle_s *hi2c, - uint32_t analog_filter) +static int i2c_request_memory_write(struct i2c_handle_s *hi2c, + uint16_t dev_addr, uint16_t mem_addr, + uint16_t mem_add_size, uint64_t timeout_ref) { + i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE, + I2C_GENERATE_START_WRITE); + + if (i2c_wait_txis(hi2c, timeout_ref) != 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)); + + if (i2c_wait_txis(hi2c, timeout_ref) != 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_ref) != 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_ref: Reference to target timeout + * @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, + uint64_t timeout_ref) +{ + i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE, + I2C_GENERATE_START_WRITE); + + if (i2c_wait_txis(hi2c, timeout_ref) != 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)); + + if (i2c_wait_txis(hi2c, timeout_ref) != 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_ref) != 0) { + return -EIO; + } + + return 0; +} +/* + * @brief Generic function to write an amount of data in blocking mode + * (for Memory Mode and Master Mode) + * @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 (if Memory Mode) + * @param mem_add_size: Size of internal memory address (if Memory Mode) + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @param mode: Communication mode + * @retval 0 if OK, negative value else + */ +static int i2c_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_ms, + enum i2c_mode_e mode) +{ + uint64_t timeout_ref; + int rc = -EIO; + uint8_t *p_buff = p_data; + uint32_t xfer_size; + uint32_t xfer_count = size; + + if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { + return -1; + } + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { return -EBUSY; } + if ((p_data == NULL) || (size == 0U)) { + return -EINVAL; + } + + stm32mp_clk_enable(hi2c->clock); + hi2c->lock = 1; - hi2c->i2c_state = I2C_STATE_BUSY; + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); + if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { + goto bail; + } - /* Disable the selected I2C peripheral */ - mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); + hi2c->i2c_state = I2C_STATE_BUSY_TX; + hi2c->i2c_mode = mode; + hi2c->i2c_err = I2C_ERROR_NONE; - /* Reset I2Cx ANOFF bit */ - mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF); + timeout_ref = timeout_init_us(timeout_ms * 1000); - /* Set analog filter bit*/ - mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter); + if (mode == I2C_MODE_MEM) { + /* In Memory Mode, Send Slave Address and Memory Address */ + if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, + mem_add_size, timeout_ref) != 0) { + goto bail; + } - /* Enable the selected I2C peripheral */ - mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } else { + /* In Master Mode, Send Slave Address */ + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_RELOAD_MODE, + I2C_GENERATE_START_WRITE); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_AUTOEND_MODE, + I2C_GENERATE_START_WRITE); + } + } + + do { + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + goto bail; + } + + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff); + p_buff++; + xfer_count--; + xfer_size--; + + if ((xfer_count != 0U) && (xfer_size == 0U)) { + /* Wait until TCR flag is set */ + if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, + timeout_ref) != 0) { + goto bail; + } + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_RELOAD_MODE, + I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_AUTOEND_MODE, + I2C_NO_STARTSTOP); + } + } + + } while (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_ref) != 0) { + goto bail; + } + + 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; + rc = 0; + +bail: hi2c->lock = 0; + stm32mp_clk_disable(hi2c->clock); - return 0; + return rc; } + +/* + * @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_ms: Timeout duration in milliseconds + * @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_ms) +{ + return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size, + p_data, size, timeout_ms, I2C_MODE_MEM); +} + +/* + * @brief Transmits in master mode an amount of data in blocking mode. + * @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 p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @retval 0 if OK, negative value else + */ +int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms) +{ + return i2c_write(hi2c, dev_addr, 0, 0, + p_data, size, timeout_ms, I2C_MODE_MASTER); +} + +/* + * @brief Generic function to read an amount of data in blocking mode + * (for Memory Mode and Master Mode) + * @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 (if Memory Mode) + * @param mem_add_size: Size of internal memory address (if Memory Mode) + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @param mode: Communication mode + * @retval 0 if OK, negative value else + */ +static int i2c_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_ms, + enum i2c_mode_e mode) +{ + uint64_t timeout_ref; + int rc = -EIO; + uint8_t *p_buff = p_data; + uint32_t xfer_count = size; + uint32_t xfer_size; + + if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { + return -1; + } + + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { + return -EBUSY; + } + + if ((p_data == NULL) || (size == 0U)) { + return -EINVAL; + } + + stm32mp_clk_enable(hi2c->clock); + + hi2c->lock = 1; + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); + if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { + goto bail; + } + + hi2c->i2c_state = I2C_STATE_BUSY_RX; + hi2c->i2c_mode = mode; + hi2c->i2c_err = I2C_ERROR_NONE; + + if (mode == I2C_MODE_MEM) { + /* Send Memory Address */ + if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, + mem_add_size, timeout_ref) != 0) { + goto bail; + } + } + + /* + * Send Slave Address. + * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE + * and generate RESTART. + */ + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_RELOAD_MODE, I2C_GENERATE_START_READ); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); + } + + do { + if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout_ref) != 0) { + goto bail; + } + + *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR); + p_buff++; + xfer_size--; + xfer_count--; + + if ((xfer_count != 0U) && (xfer_size == 0U)) { + if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, + timeout_ref) != 0) { + goto bail; + } + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_RELOAD_MODE, + I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_AUTOEND_MODE, + I2C_NO_STARTSTOP); + } + } + } while (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_ref) != 0) { + goto bail; + } + + 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; + + rc = 0; + +bail: + hi2c->lock = 0; + stm32mp_clk_disable(hi2c->clock); + + return rc; +} + +/* + * @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_ms: Timeout duration in milliseconds + * @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_ms) +{ + return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size, + p_data, size, timeout_ms, I2C_MODE_MEM); +} + +/* + * @brief Receives in master mode an amount of data in blocking mode. + * @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 p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @retval 0 if OK, negative value else + */ +int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms) +{ + return i2c_read(hi2c, dev_addr, 0, 0, + p_data, size, timeout_ms, I2C_MODE_MASTER); +} + +/* + * @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_ms: Timeout duration in milliseconds + * @retval True if device is ready, false else + */ +bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, + uint16_t dev_addr, uint32_t trials, + uint32_t timeout_ms) +{ + uint32_t i2c_trials = 0U; + bool rc = false; + + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { + return rc; + } + + stm32mp_clk_enable(hi2c->clock); + + hi2c->lock = 1; + hi2c->i2c_mode = I2C_MODE_NONE; + + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) != + 0U) { + goto bail; + } + + hi2c->i2c_state = I2C_STATE_BUSY; + hi2c->i2c_err = I2C_ERROR_NONE; + + do { + uint64_t timeout_ref; + + /* Generate Start */ + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) & + I2C_OAR1_OA1MODE) == 0) { + 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. + */ + timeout_ref = timeout_init_us(timeout_ms * 1000); + do { + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) { + break; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + goto bail; + } + } while (true); + + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_AF) == 0U) { + if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, + timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, + I2C_FLAG_STOPF); + + hi2c->i2c_state = I2C_STATE_READY; + + rc = true; + goto bail; + } + + if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout_ref) != 0) { + goto bail; + } + + 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_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, + I2C_FLAG_STOPF); + } + + i2c_trials++; + } while (i2c_trials < trials); + + notif_i2c_timeout(hi2c); + +bail: + hi2c->lock = 0; + stm32mp_clk_disable(hi2c->clock); + + return rc; +} + diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c index 52f712f10..6fe51f443 100644 --- a/drivers/st/pmic/stm32mp_pmic.c +++ b/drivers/st/pmic/stm32mp_pmic.c @@ -5,7 +5,6 @@ */ #include -#include #include @@ -13,19 +12,12 @@ #include #include +#include #include -#include #include #include #include -/* 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 STPMIC1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2)) #define STPMIC1_LDO12356_OUTPUT_SHIFT 2 #define STPMIC1_LDO3_MODE (uint8_t)(BIT(7)) @@ -45,25 +37,29 @@ static int dt_get_pmic_node(void *fdt) return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); } -bool dt_check_pmic(void) +int dt_pmic_status(void) { int node; void *fdt; if (fdt_get_address(&fdt) == 0) { - return false; + return -ENOENT; } node = dt_get_pmic_node(fdt); - if (node < 0) { - VERBOSE("%s: No PMIC node found in DT\n", __func__); - return false; + if (node <= 0) { + return -FDT_ERR_NOTFOUND; } return fdt_get_status(node); } -static int dt_pmic_i2c_config(struct dt_node_info *i2c_info) +/* + * Get PMIC and its I2C bus configuration from the device tree. + * Return 0 on success, negative on error, 1 if no PMIC node is found. + */ +static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, + struct stm32_i2c_init_s *init) { int pmic_node, i2c_node; void *fdt; @@ -75,7 +71,7 @@ static int dt_pmic_i2c_config(struct dt_node_info *i2c_info) pmic_node = dt_get_pmic_node(fdt); if (pmic_node < 0) { - return -FDT_ERR_NOTFOUND; + return 1; } cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); @@ -98,10 +94,10 @@ static int dt_pmic_i2c_config(struct dt_node_info *i2c_info) return -FDT_ERR_NOTFOUND; } - return dt_set_pinctrl_config(i2c_node); + return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init); } -int dt_pmic_enable_boot_on_regulators(void) +int dt_pmic_configure_boot_on_regulators(void) { int pmic_node, regulators_node, regulator_node; void *fdt; @@ -119,14 +115,40 @@ int dt_pmic_enable_boot_on_regulators(void) fdt_for_each_subnode(regulator_node, fdt, regulators_node) { const fdt32_t *cuint; - const char *node_name; + const char *node_name = fdt_get_name(fdt, regulator_node, NULL); uint16_t voltage; + int status; +#if defined(IMAGE_BL2) + if ((fdt_getprop(fdt, regulator_node, "regulator-boot-on", + NULL) == NULL) && + (fdt_getprop(fdt, regulator_node, "regulator-always-on", + NULL) == NULL)) { +#else if (fdt_getprop(fdt, regulator_node, "regulator-boot-on", NULL) == NULL) { +#endif continue; } + if (fdt_getprop(fdt, regulator_node, "regulator-pull-down", + NULL) != NULL) { + + status = stpmic1_regulator_pull_down_set(node_name); + if (status != 0) { + return status; + } + } + + if (fdt_getprop(fdt, regulator_node, "st,mask-reset", + NULL) != NULL) { + + status = stpmic1_regulator_mask_reset_set(node_name); + if (status != 0) { + return status; + } + } + cuint = fdt_getprop(fdt, regulator_node, "regulator-min-microvolt", NULL); if (cuint == NULL) { @@ -135,17 +157,13 @@ int dt_pmic_enable_boot_on_regulators(void) /* DT uses microvolts, whereas driver awaits millivolts */ voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); - node_name = fdt_get_name(fdt, regulator_node, NULL); + + status = stpmic1_regulator_voltage_set(node_name, voltage); + if (status != 0) { + return status; + } if (stpmic1_is_regulator_enabled(node_name) == 0U) { - int status; - - status = stpmic1_regulator_voltage_set(node_name, - voltage); - if (status != 0) { - return status; - } - status = stpmic1_regulator_enable(node_name); if (status != 0) { return status; @@ -156,77 +174,77 @@ int dt_pmic_enable_boot_on_regulators(void) return 0; } -void initialize_pmic_i2c(void) +bool initialize_pmic_i2c(void) { int ret; struct dt_node_info i2c_info; + struct i2c_handle_s *i2c = &i2c_handle; + struct stm32_i2c_init_s i2c_init; - if (dt_pmic_i2c_config(&i2c_info) != 0) { - ERROR("I2C configuration failed\n"); + ret = dt_pmic_i2c_config(&i2c_info, &i2c_init); + if (ret < 0) { + ERROR("I2C configuration failed %d\n", ret); panic(); } - if (stm32mp_clk_enable((uint32_t)i2c_info.clock) < 0) { - ERROR("I2C clock enable failed\n"); - panic(); + if (ret != 0) { + return false; } /* 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; + i2c->i2c_base_addr = i2c_info.base; + i2c->dt_status = i2c_info.status; + i2c->clock = i2c_info.clock; + i2c_init.own_address1 = pmic_i2c_addr; + i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; + i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; + i2c_init.own_address2 = 0; + i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK; + i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE; + i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE; + i2c_init.analog_filter = 1; + i2c_init.digital_filter_coef = 0; - ret = stm32_i2c_init(&i2c_handle); + ret = stm32_i2c_init(i2c, &i2c_init); if (ret != 0) { ERROR("Cannot initialize I2C %x (%d)\n", - i2c_handle.i2c_base_addr, ret); + i2c->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); + if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1, + I2C_TIMEOUT_BUSY_MS)) { + ERROR("I2C device not ready\n"); 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(); - } + stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr); - stpmic1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr); + return true; } void initialize_pmic(void) { - int status; - uint8_t read_val; + unsigned long pmic_version; - initialize_pmic_i2c(); + if (!initialize_pmic_i2c()) { + VERBOSE("No PMIC\n"); + return; + } - status = stpmic1_register_read(VERSION_STATUS_REG, &read_val); - if (status != 0) { + if (stpmic1_get_version(&pmic_version) != 0) { + ERROR("Failed to access PMIC\n"); panic(); } - INFO("PMIC version = 0x%x\n", read_val); + INFO("PMIC version = 0x%02lx\n", pmic_version); + stpmic1_dump_regulators(); - /* Keep VDD on during the reset cycle */ - status = stpmic1_register_update(MASK_RESET_BUCK_REG, - MASK_RESET_BUCK3, - MASK_RESET_BUCK3); - if (status != 0) { +#if defined(IMAGE_BL2) + if (dt_pmic_configure_boot_on_regulators() != 0) { panic(); - } + }; +#endif } int pmic_ddr_power_init(enum ddr_type ddr_type) diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c index 465996da9..999963054 100644 --- a/drivers/st/pmic/stpmic1.c +++ b/drivers/st/pmic/stpmic1.c @@ -8,7 +8,8 @@ #include #include -#include + +#define I2C_TIMEOUT_MS 25 struct regul_struct { const char *dt_node_name; @@ -677,8 +678,9 @@ int stpmic1_regulator_voltage_get(const char *name) int stpmic1_register_read(uint8_t register_id, uint8_t *value) { return stm32_i2c_mem_read(pmic_i2c_handle, pmic_i2c_addr, - (uint16_t)register_id, I2C_MEMADD_SIZE_8BIT, - value, 1, 100000); + (uint16_t)register_id, + I2C_MEMADD_SIZE_8BIT, value, + 1, I2C_TIMEOUT_MS); } int stpmic1_register_write(uint8_t register_id, uint8_t value) @@ -687,7 +689,8 @@ int stpmic1_register_write(uint8_t register_id, uint8_t value) status = stm32_i2c_mem_write(pmic_i2c_handle, pmic_i2c_addr, (uint16_t)register_id, - I2C_MEMADD_SIZE_8BIT, &value, 1, 100000); + I2C_MEMADD_SIZE_8BIT, &value, + 1, I2C_TIMEOUT_MS); #if ENABLE_ASSERTIONS if (status != 0) { diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts index a97e8053b..5d8817f69 100644 --- a/fdts/stm32mp157c-ed1.dts +++ b/fdts/stm32mp157c-ed1.dts @@ -55,7 +55,7 @@ vddcore: buck1 { regulator-name = "vddcore"; - regulator-min-microvolt = <800000>; + regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <0>; diff --git a/include/drivers/st/stm32_i2c.h b/include/drivers/st/stm32_i2c.h index de2ca59c8..170d4cf81 100644 --- a/include/drivers/st/stm32_i2c.h +++ b/include/drivers/st/stm32_i2c.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -111,94 +111,113 @@ #define I2C_ICR_TIMOUTCF BIT(12) #define I2C_ICR_ALERTCF BIT(13) +enum i2c_speed_e { + I2C_SPEED_STANDARD, /* 100 kHz */ + I2C_SPEED_FAST, /* 400 kHz */ + I2C_SPEED_FAST_PLUS, /* 1 MHz */ +}; + +#define STANDARD_RATE 100000 +#define FAST_RATE 400000 +#define FAST_PLUS_RATE 1000000 + 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 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 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 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; /* 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 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 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. + */ - uint32_t no_stretch_mode; /* Specifies if nostretch mode is - * selected. - * This parameter can be a value of @ref - * I2C_NOSTRETCH_MODE. - */ + uint32_t rise_time; /* + * Specifies the SCL clock pin rising + * time in nanoseconds. + */ + uint32_t fall_time; /* + * Specifies the SCL clock pin falling + * time in nanoseconds. + */ + + enum i2c_speed_e speed_mode; /* + * Specifies the I2C clock source + * frequency mode. + * This parameter can be a value of @ref + * i2c_speed_mode_e. + */ + + int analog_filter; /* + * Specifies if the I2C analog noise + * filter is selected. + * This parameter can be 0 (filter + * off), all other values mean filter + * on. + */ + + uint8_t digital_filter_coef; /* + * Specifies the I2C digital noise + * filter coefficient. + * This parameter can be a value + * between 0 and + * STM32_I2C_DIGITAL_FILTER_MAX. + */ }; 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. */ - + I2C_STATE_RESET = 0x00U, /* Not yet initialized */ + I2C_STATE_READY = 0x20U, /* Ready for use */ + I2C_STATE_BUSY = 0x24U, /* Internal process ongoing */ + I2C_STATE_BUSY_TX = 0x21U, /* Data Transmission ongoing */ + I2C_STATE_BUSY_RX = 0x22U, /* Data Reception ongoing */ }; 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. */ + I2C_MODE_NONE = 0x00U, /* No active communication */ + I2C_MODE_MASTER = 0x10U, /* Communication in Master Mode */ + I2C_MODE_SLAVE = 0x20U, /* Communication in Slave Mode */ + I2C_MODE_MEM = 0x40U /* Communication in Memory Mode */ }; @@ -213,26 +232,12 @@ enum i2c_mode_e { 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 */ + unsigned int dt_status; /* DT nsec/sec status */ + unsigned int clock; /* Clock reference */ + 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 @@ -250,15 +255,15 @@ struct i2c_handle_s { #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_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 | \ +#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_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START) #define I2C_FLAG_TXE I2C_ISR_TXE #define I2C_FLAG_TXIS I2C_ISR_TXIS @@ -281,21 +286,36 @@ struct i2c_handle_s { I2C_CR2_NBYTES | I2C_CR2_RELOAD | \ I2C_CR2_RD_WRN) -#define I2C_ANALOGFILTER_ENABLE ((uint32_t)0x00000000U) +#define I2C_TIMEOUT_BUSY_MS 25U + +#define I2C_ANALOGFILTER_ENABLE 0x00000000U #define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF -int stm32_i2c_init(struct i2c_handle_s *hi2c); +/* STM32 specific defines */ +#define STM32_I2C_RISE_TIME_DEFAULT 25 /* ns */ +#define STM32_I2C_FALL_TIME_DEFAULT 10 /* ns */ +#define STM32_I2C_SPEED_DEFAULT I2C_SPEED_STANDARD +#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ +#define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ +#define STM32_I2C_DIGITAL_FILTER_MAX 16 +int stm32_i2c_get_setup_from_fdt(void *fdt, int node, + struct stm32_i2c_init_s *init); +int stm32_i2c_init(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init_data); 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); + uint8_t *p_data, uint16_t size, uint32_t timeout_ms); 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); + uint8_t *p_data, uint16_t size, uint32_t timeout_ms); +int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms); +int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms); +bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint32_t trials, uint32_t timeout_ms); #endif /* STM32_I2C_H */ diff --git a/include/drivers/st/stm32mp_pmic.h b/include/drivers/st/stm32mp_pmic.h index 700039b26..984cd6014 100644 --- a/include/drivers/st/stm32mp_pmic.h +++ b/include/drivers/st/stm32mp_pmic.h @@ -11,10 +11,41 @@ #include -bool dt_check_pmic(void); -int dt_pmic_enable_boot_on_regulators(void); -void initialize_pmic_i2c(void); +/* + * dt_pmic_status - Check PMIC status from device tree + * + * Returns the status of the PMIC (secure, non-secure), or a negative value on + * error + */ +int dt_pmic_status(void); + +/* + * dt_pmic_configure_boot_on_regulators - Configure boot-on and always-on + * regulators from device tree configuration + * + * Returns 0 on success, and negative values on errors + */ +int dt_pmic_configure_boot_on_regulators(void); + +/* + * initialize_pmic_i2c - Initialize I2C for the PMIC control + * + * Returns true if PMIC is available, false if not found, panics on errors + */ +bool initialize_pmic_i2c(void); + +/* + * initialize_pmic - Main PMIC initialization function, called at platform init + * + * Panics on errors + */ void initialize_pmic(void); + +/* + * pmic_ddr_power_init - Initialize regulators required for DDR + * + * Returns 0 on success, and negative values on errors + */ int pmic_ddr_power_init(enum ddr_type ddr_type); #endif /* STM32MP_PMIC_H */ diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index bcf1aa9ed..69dc3fb10 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -126,7 +126,7 @@ void bl2_platform_setup(void) { int ret; - if (dt_check_pmic()) { + if (dt_pmic_status() > 0) { initialize_pmic(); } From 447b2b137d7286a1ef451336c6e73fb7fd8999a1 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 14 Feb 2019 11:15:20 +0100 Subject: [PATCH 07/11] stm32mp1: split clkfunc code Create a new file stm32mp_clkfunc.c to put functions that could be common between several platforms. Change-Id: Ica915c796b162b2345056b33328acc05035a242c Signed-off-by: Yann Gautier --- drivers/st/clk/stm32mp1_clk.c | 2 +- drivers/st/clk/stm32mp1_clkfunc.c | 250 +++----------------------- drivers/st/clk/stm32mp_clkfunc.c | 206 +++++++++++++++++++++ drivers/st/gpio/stm32_gpio.c | 2 +- include/drivers/st/stm32mp1_clkfunc.h | 12 +- include/drivers/st/stm32mp_clkfunc.h | 25 +++ plat/st/stm32mp1/platform.mk | 1 + plat/st/stm32mp1/stm32mp1_def.h | 5 + 8 files changed, 261 insertions(+), 242 deletions(-) create mode 100644 drivers/st/clk/stm32mp_clkfunc.c create mode 100644 include/drivers/st/stm32mp_clkfunc.h diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index 2e89ecf36..4275f3bd1 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -18,10 +18,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c index 19dfe1b25..06c417b10 100644 --- a/drivers/st/clk/stm32mp1_clkfunc.c +++ b/drivers/st/clk/stm32mp1_clkfunc.c @@ -10,17 +10,12 @@ #include +#include +#include #include #include #include -#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", @@ -31,20 +26,12 @@ const char *stm32mp_osc_node_label[NB_OSC] = { [_USB_PHY_48] = "ck_usbo_48m" }; -/******************************************************************************* - * This function returns the RCC node in the device tree. - ******************************************************************************/ -static int fdt_get_rcc_node(void *fdt) -{ - return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); -} - -/******************************************************************************* - * This function reads the frequency of an oscillator from its name. - * It reads the value indicated inside the device tree. - * Returns 0 on success, and a negative FDT/ERRNO error code on failure. - * On success, value is stored in the second parameter. - ******************************************************************************/ +/* + * Get the frequency of an oscillator from its name in device tree. + * @param name: oscillator name + * @param freq: stores the frequency of the oscillator + * @return: 0 on success, and a negative FDT/ERRNO error code on failure. + */ int fdt_osc_read_freq(const char *name, uint32_t *freq) { int node, subnode; @@ -88,11 +75,12 @@ int fdt_osc_read_freq(const char *name, uint32_t *freq) 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. - ******************************************************************************/ +/* + * Check the presence of an oscillator property from its id. + * @param osc_id: oscillator ID + * @param prop_name: property name + * @return: true/false regarding search result. + */ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) { int node, subnode; @@ -133,11 +121,13 @@ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) return false; } -/******************************************************************************* - * This function reads a value of a oscillator property from its id. - * Returns value on success, and a default value if property not found. - * Default value is passed as parameter. - ******************************************************************************/ +/* + * Get the value of a oscillator property from its ID. + * @param osc_id: oscillator ID + * @param prop_name: property name + * @param dflt_value: default value + * @return oscillator value on success, default value if property not found. + */ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, const char *prop_name, uint32_t dflt_value) { @@ -176,201 +166,3 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, 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 on success, and a negative FDT/ERRNO error code on failure. - ******************************************************************************/ -int fdt_rcc_subnode_offset(const char *name) -{ - int node, subnode; - void *fdt; - - if (fdt_get_address(&fdt) == 0) { - return -ENOENT; - } - - node = fdt_get_rcc_node(fdt); - 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 on success, and NULL value on failure. - ******************************************************************************/ -const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) -{ - const fdt32_t *cuint; - int node, len; - void *fdt; - - if (fdt_get_address(&fdt) == 0) { - return NULL; - } - - node = fdt_get_rcc_node(fdt); - 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 true if rcc is available from secure world, false if not. - ******************************************************************************/ -bool fdt_get_rcc_secure_status(void) -{ - int node; - void *fdt; - - if (fdt_get_address(&fdt) == 0) { - return false; - } - - node = fdt_get_rcc_node(fdt); - if (node < 0) { - return false; - } - - return (fdt_get_status(node) & DT_SECURE) != 0U; -} - -/******************************************************************************* - * This function reads the stgen base address. - * It reads the value indicated inside the device tree. - * Returns address on success, and NULL value on failure. - ******************************************************************************/ -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 on success, and a negative FDT/ERRNO error code on failure. - ******************************************************************************/ -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); -} diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c new file mode 100644 index 000000000..16acef07b --- /dev/null +++ b/drivers/st/clk/stm32mp_clkfunc.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#include +#include + +#define DT_STGEN_COMPAT "st,stm32-stgen" + +/* + * Get the RCC node offset from the device tree + * @param fdt: Device tree reference + * @return: Node offset or a negative value on error + */ +int fdt_get_rcc_node(void *fdt) +{ + return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); +} + +/* + * Get the RCC base address from the device tree + * @return: RCC address or 0 on error + */ +uint32_t fdt_rcc_read_addr(void) +{ + int node; + void *fdt; + const fdt32_t *cuint; + + if (fdt_get_address(&fdt) == 0) { + return 0; + } + + node = fdt_get_rcc_node(fdt); + if (node < 0) { + return 0; + } + + cuint = fdt_getprop(fdt, node, "reg", NULL); + if (cuint == NULL) { + return 0; + } + + return fdt32_to_cpu(*cuint); +} + +/* + * Read a series of parameters in rcc-clk section in device tree + * @param prop_name: Name of the RCC property to be read + * @param array: the array to store the property parameters + * @param count: number of parameters to be read + * @return: 0 on succes or a negative value on error + */ +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_get_rcc_node(fdt); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + return fdt_read_uint32_array(node, prop_name, array, count); +} + +/* + * Get the subnode offset in rcc-clk section from its name in device tree + * @param name: name of the RCC property + * @return: offset on success, and a negative FDT/ERRNO error code on failure. + */ +int fdt_rcc_subnode_offset(const char *name) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_get_rcc_node(fdt); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + subnode = fdt_subnode_offset(fdt, node, name); + if (subnode <= 0) { + return -FDT_ERR_NOTFOUND; + } + + return subnode; +} + +/* + * Get the pointer to a rcc-clk property from its name. + * @param name: name of the RCC property + * @param lenp: stores the length of the property. + * @return: pointer to the property on success, and NULL value on failure. + */ +const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) +{ + const fdt32_t *cuint; + int node, len; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return NULL; + } + + node = fdt_get_rcc_node(fdt); + if (node < 0) { + return NULL; + } + + cuint = fdt_getprop(fdt, node, prop_name, &len); + if (cuint == NULL) { + return NULL; + } + + *lenp = len; + return cuint; +} + +/* + * Get the secure status for rcc node in device tree. + * @return: true if rcc is available from secure world, false if not. + */ +bool fdt_get_rcc_secure_status(void) +{ + int node; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return false; + } + + node = fdt_get_rcc_node(fdt); + if (node < 0) { + return false; + } + + return !!(fdt_get_status(node) & DT_SECURE); +} + +/* + * Get the stgen base address. + * @return: address of stgen on success, and NULL value on failure. + */ +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); +} + +/* + * Get the clock ID of the given node in device tree. + * @param node: node offset + * @return: Clock ID on success, and a negative FDT/ERRNO error code on failure. + */ +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); +} diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c index 5733046d0..343ad6c1d 100644 --- a/drivers/st/gpio/stm32_gpio.c +++ b/drivers/st/gpio/stm32_gpio.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/drivers/st/stm32mp1_clkfunc.h b/include/drivers/st/stm32mp1_clkfunc.h index 106dcae01..41b68fdd0 100644 --- a/include/drivers/st/stm32mp1_clkfunc.h +++ b/include/drivers/st/stm32mp1_clkfunc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -31,14 +31,4 @@ 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 fdt32_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 */ diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h new file mode 100644 index 000000000..5beb06bb2 --- /dev/null +++ b/include/drivers/st/stm32mp_clkfunc.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_CLKFUNC_H +#define STM32MP_CLKFUNC_H + +#include + +#include + +int fdt_get_rcc_node(void *fdt); +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 fdt32_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 /* STM32MP_CLKFUNC_H */ diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk index 1c5f6273e..3e3460189 100644 --- a/plat/st/stm32mp1/platform.mk +++ b/plat/st/stm32mp1/platform.mk @@ -50,6 +50,7 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \ drivers/delay_timer/delay_timer.c \ drivers/delay_timer/generic_delay_timer.c \ drivers/st/bsec/bsec.c \ + drivers/st/clk/stm32mp_clkfunc.c \ drivers/st/clk/stm32mp1_clk.c \ drivers/st/clk/stm32mp1_clkfunc.c \ drivers/st/ddr/stm32mp1_ddr_helpers.c \ diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index 95d341252..beb588c7f 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -250,4 +250,9 @@ static inline uint32_t tamp_bkpr(uint32_t idx) ******************************************************************************/ #define I2C4_BASE U(0x5C002000) +/******************************************************************************* + * Device Tree defines + ******************************************************************************/ +#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" + #endif /* STM32MP1_DEF_H */ From 7ae58c6ba79fee3cc032aae2105b073304409ebc Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 14 Feb 2019 11:01:20 +0100 Subject: [PATCH 08/11] stm32mp1: use functions to retrieve some peripheral addresses PWR, RCC, DDRPHYC & DDRCTRL addresses can be retrieved from device tree. Platform asserts the value read from the DT are the SoC addresses. Change-Id: I43f0890b51918a30c87ac067d3780ab27a0f59de Signed-off-by: Yann Gautier Signed-off-by: Etienne Carriere Signed-off-by: Nicolas LE BAYON --- drivers/st/ddr/stm32mp1_ddr_helpers.c | 2 +- drivers/st/ddr/stm32mp1_ram.c | 8 +-- drivers/st/reset/stm32mp1_reset.c | 10 ++-- plat/st/common/include/stm32mp_common.h | 12 +++++ plat/st/common/include/stm32mp_dt.h | 3 ++ plat/st/common/stm32mp_common.c | 53 +++++++++++++++++++ plat/st/common/stm32mp_dt.c | 67 +++++++++++++++++++++++++ plat/st/stm32mp1/bl2_plat_setup.c | 19 ++++--- plat/st/stm32mp1/stm32mp1_def.h | 1 + plat/st/stm32mp1/stm32mp1_pm.c | 3 +- 10 files changed, 161 insertions(+), 17 deletions(-) diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c index e50b27be8..c66c9e707 100644 --- a/drivers/st/ddr/stm32mp1_ddr_helpers.c +++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c @@ -11,7 +11,7 @@ void ddr_enable_clock(void) { - mmio_setbits_32(RCC_BASE + RCC_DDRITFCR, + mmio_setbits_32(stm32mp_rcc_base() + RCC_DDRITFCR, RCC_DDRITFCR_DDRC1EN | RCC_DDRITFCR_DDRC2EN | RCC_DDRITFCR_DDRPHYCEN | diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c index 7b13385fc..59b4351f0 100644 --- a/drivers/st/ddr/stm32mp1_ram.c +++ b/drivers/st/ddr/stm32mp1_ram.c @@ -298,10 +298,10 @@ int stm32mp1_ddr_probe(void) 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->ctl = (struct stm32mp1_ddrctl *)stm32mp_ddrctrl_base(); + priv->phy = (struct stm32mp1_ddrphy *)stm32mp_ddrphyc_base(); + priv->pwr = stm32mp_pwr_base(); + priv->rcc = stm32mp_rcc_base(); priv->info.base = STM32MP_DDR_BASE; priv->info.size = 0; diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c index b9a7ac7c9..b2de76085 100644 --- a/drivers/st/reset/stm32mp1_reset.c +++ b/drivers/st/reset/stm32mp1_reset.c @@ -20,9 +20,10 @@ void stm32mp_reset_assert(uint32_t id) { uint32_t offset = (id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t); uint32_t bit = id % (uint32_t)__LONG_BIT; + uintptr_t rcc_base = stm32mp_rcc_base(); - mmio_write_32(RCC_BASE + offset, BIT(bit)); - while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) == 0U) { + mmio_write_32(rcc_base + offset, BIT(bit)); + while ((mmio_read_32(rcc_base + offset) & BIT(bit)) == 0U) { ; } } @@ -32,9 +33,10 @@ void stm32mp_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; + uintptr_t rcc_base = stm32mp_rcc_base(); - mmio_write_32(RCC_BASE + offset, BIT(bit)); - while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) != 0U) { + mmio_write_32(rcc_base + offset, BIT(bit)); + while ((mmio_read_32(rcc_base + offset) & BIT(bit)) != 0U) { ; } } diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h index 5f54b103d..fa0b63031 100644 --- a/plat/st/common/include/stm32mp_common.h +++ b/plat/st/common/include/stm32mp_common.h @@ -16,6 +16,18 @@ void stm32mp_save_boot_ctx_address(uintptr_t address); uintptr_t stm32mp_get_boot_ctx_address(void); +/* Return the base address of the DDR controller */ +uintptr_t stm32mp_ddrctrl_base(void); + +/* Return the base address of the DDR PHY */ +uintptr_t stm32mp_ddrphyc_base(void); + +/* Return the base address of the PWR peripheral */ +uintptr_t stm32mp_pwr_base(void); + +/* Return the base address of the RCC peripheral */ +uintptr_t stm32mp_rcc_base(void); + /* * Platform util functions for the GPIO driver * @bank: Target GPIO bank ID as per DT bindings diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h index 56357dbff..3415b051d 100644 --- a/plat/st/common/include/stm32mp_dt.h +++ b/plat/st/common/include/stm32mp_dt.h @@ -38,6 +38,9 @@ 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); +uintptr_t dt_get_ddrctrl_base(void); +uintptr_t dt_get_ddrphyc_base(void); +uintptr_t dt_get_pwr_base(void); const char *dt_get_board_model(void); #endif /* STM32MP_DT_H */ diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c index aecef4718..2aba41e54 100644 --- a/plat/st/common/stm32mp_common.c +++ b/plat/st/common/stm32mp_common.c @@ -10,6 +10,7 @@ #include #include +#include #include uintptr_t plat_get_ns_image_entrypoint(void) @@ -34,6 +35,58 @@ uintptr_t stm32mp_get_boot_ctx_address(void) return boot_ctx_address; } +uintptr_t stm32mp_ddrctrl_base(void) +{ + static uintptr_t ddrctrl_base; + + if (ddrctrl_base == 0) { + ddrctrl_base = dt_get_ddrctrl_base(); + + assert(ddrctrl_base == DDRCTRL_BASE); + } + + return ddrctrl_base; +} + +uintptr_t stm32mp_ddrphyc_base(void) +{ + static uintptr_t ddrphyc_base; + + if (ddrphyc_base == 0) { + ddrphyc_base = dt_get_ddrphyc_base(); + + assert(ddrphyc_base == DDRPHYC_BASE); + } + + return ddrphyc_base; +} + +uintptr_t stm32mp_pwr_base(void) +{ + static uintptr_t pwr_base; + + if (pwr_base == 0) { + pwr_base = dt_get_pwr_base(); + + assert(pwr_base == PWR_BASE); + } + + return pwr_base; +} + +uintptr_t stm32mp_rcc_base(void) +{ + static uintptr_t rcc_base; + + if (rcc_base == 0) { + rcc_base = fdt_rcc_read_addr(); + + assert(rcc_base == RCC_BASE); + } + + return rcc_base; +} + uintptr_t stm32_get_gpio_bank_base(unsigned int bank) { if (bank == GPIO_BANK_Z) { diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c index c0b0518d9..e64433bc8 100644 --- a/plat/st/common/stm32mp_dt.c +++ b/plat/st/common/stm32mp_dt.c @@ -291,6 +291,73 @@ uint32_t dt_get_ddr_size(void) return fdt_read_uint32_default(node, "st,mem-size", 0); } +/******************************************************************************* + * This function gets DDRCTRL base address information from the DT. + * Returns value on success, and 0 on failure. + ******************************************************************************/ +uintptr_t dt_get_ddrctrl_base(void) +{ + int node; + uint32_t array[4]; + + 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 0; + } + + if (fdt_read_uint32_array(node, "reg", array, 4) < 0) { + return 0; + } + + return array[0]; +} + +/******************************************************************************* + * This function gets DDRPHYC base address information from the DT. + * Returns value on success, and 0 on failure. + ******************************************************************************/ +uintptr_t dt_get_ddrphyc_base(void) +{ + int node; + uint32_t array[4]; + + 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 0; + } + + if (fdt_read_uint32_array(node, "reg", array, 4) < 0) { + return 0; + } + + return array[2]; +} + +/******************************************************************************* + * This function gets PWR base address information from the DT. + * Returns value on success, and 0 on failure. + ******************************************************************************/ +uintptr_t dt_get_pwr_base(void) +{ + int node; + const fdt32_t *cuint; + + node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); + if (node < 0) { + INFO("%s: Cannot read PWR node in DT\n", __func__); + return 0; + } + + cuint = fdt_getprop(fdt, node, "reg", NULL); + if (cuint == NULL) { + return 0; + } + + return fdt32_to_cpu(*cuint); +} + /******************************************************************************* * This function retrieves board model from DT * Returns string taken from model node, NULL otherwise diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index 69dc3fb10..5ab20845c 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -31,7 +31,7 @@ static struct console_stm32 console; static void print_reset_reason(void) { - uint32_t rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR); + uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR); if (rstsr == 0U) { WARN("Reset reason unknown\n"); @@ -147,6 +147,8 @@ void bl2_el3_plat_arch_setup(void) boot_api_context_t *boot_context = (boot_api_context_t *)stm32mp_get_boot_ctx_address(); uint32_t clk_rate; + uintptr_t pwr_base; + uintptr_t rcc_base; mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, @@ -174,27 +176,30 @@ void bl2_el3_plat_arch_setup(void) panic(); } + pwr_base = stm32mp_pwr_base(); + rcc_base = stm32mp_rcc_base(); + /* * 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); + mmio_setbits_32(pwr_base + PWR_CR1, PWR_CR1_DBP); - while ((mmio_read_32(PWR_BASE + PWR_CR1) & PWR_CR1_DBP) == 0U) { + 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); + 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) == + while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) == 0U) { ; } - mmio_clrbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST); + mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); } generic_delay_timer_init(); diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index beb588c7f..8d7cea327 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -253,6 +253,7 @@ static inline uint32_t tamp_bkpr(uint32_t idx) /******************************************************************************* * Device Tree defines ******************************************************************************/ +#define DT_PWR_COMPAT "st,stm32mp1-pwr" #define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" #endif /* STM32MP1_DEF_H */ diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c index c4d023271..3262607a5 100644 --- a/plat/st/stm32mp1/stm32mp1_pm.c +++ b/plat/st/stm32mp1/stm32mp1_pm.c @@ -159,7 +159,8 @@ static void __dead2 stm32_system_off(void) static void __dead2 stm32_system_reset(void) { - mmio_setbits_32(RCC_BASE + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPSYSRST); + mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR, + RCC_MP_GRSTCSETR_MPSYSRST); /* Loop in case system reset is not immediately caught */ for ( ; ; ) { From 5202cb393da7f6f3a9cf48a49e2a12f3bdee2b16 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 14 Feb 2019 09:17:55 +0100 Subject: [PATCH 09/11] stm32mp1: add timeout detection in reset driver This change makes the platform to panic in case of peripheral reset resource malfunction. Change-Id: I17eb9cb045b78a4e5142a8c33b744e84992d732a Signed-off-by: Yann Gautier Signed-off-by: Etienne Carriere Signed-off-by: Nicolas LE BAYON --- drivers/st/reset/stm32mp1_reset.c | 44 ++++++++++++++++++++++--------- include/drivers/st/stm32mp1_rcc.h | 3 +++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c index b2de76085..fd3f93e01 100644 --- a/drivers/st/reset/stm32mp1_reset.c +++ b/drivers/st/reset/stm32mp1_reset.c @@ -10,33 +10,53 @@ #include #include +#include #include #include #include -#define RST_CLR_OFFSET 4U +#define RESET_TIMEOUT_US_1MS U(1000) + +static uint32_t id2reg_offset(unsigned int reset_id) +{ + return ((reset_id & GENMASK(31, 5)) >> 5) * sizeof(uint32_t); +} + +static uint8_t id2reg_bit_pos(unsigned int reset_id) +{ + return (uint8_t)(reset_id & GENMASK(4, 0)); +} void stm32mp_reset_assert(uint32_t id) { - uint32_t offset = (id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t); - uint32_t bit = id % (uint32_t)__LONG_BIT; + uint32_t offset = id2reg_offset(id); + uint32_t bitmsk = BIT(id2reg_bit_pos(id)); + uint64_t timeout_ref; uintptr_t rcc_base = stm32mp_rcc_base(); - mmio_write_32(rcc_base + offset, BIT(bit)); - while ((mmio_read_32(rcc_base + offset) & BIT(bit)) == 0U) { - ; + mmio_write_32(rcc_base + offset, bitmsk); + + timeout_ref = timeout_init_us(RESET_TIMEOUT_US_1MS); + while ((mmio_read_32(rcc_base + offset) & bitmsk) == 0U) { + if (timeout_elapsed(timeout_ref)) { + panic(); + } } } void stm32mp_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; + uint32_t offset = id2reg_offset(id) + RCC_RSTCLRR_OFFSET; + uint32_t bitmsk = BIT(id2reg_bit_pos(id)); + uint64_t timeout_ref; uintptr_t rcc_base = stm32mp_rcc_base(); - mmio_write_32(rcc_base + offset, BIT(bit)); - while ((mmio_read_32(rcc_base + offset) & BIT(bit)) != 0U) { - ; + mmio_write_32(rcc_base + offset, bitmsk); + + timeout_ref = timeout_init_us(RESET_TIMEOUT_US_1MS); + while ((mmio_read_32(rcc_base + offset) & bitmsk) != 0U) { + if (timeout_elapsed(timeout_ref)) { + panic(); + } } } diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h index 2f29e84d5..1922c4815 100644 --- a/include/drivers/st/stm32mp1_rcc.h +++ b/include/drivers/st/stm32mp1_rcc.h @@ -280,6 +280,9 @@ /* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ #define RCC_MP_ENCLRR_OFFSET U(4) +/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */ +#define RCC_RSTCLRR_OFFSET U(4) + /* Fields of RCC_BDCR register */ #define RCC_BDCR_LSEON BIT(0) #define RCC_BDCR_LSEBYP BIT(1) From 0d21680c35f328f1b793f0765760e994d883ff12 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 14 Feb 2019 10:53:33 +0100 Subject: [PATCH 10/11] stm32mp1: update clock driver Remove useless private structure in function prototypes. Add a reference counter on clocks. Prepare for future secured/shared/non-secured clocks. Change-Id: I3dbed81721da5ceff5e10b2c4155b1e340c036ee Signed-off-by: Yann Gautier Signed-off-by: Etienne Carriere Signed-off-by: Lionel Debieve Signed-off-by: Nicolas LE BAYON --- drivers/st/clk/stm32mp1_clk.c | 1249 ++++++++++------- drivers/st/clk/stm32mp1_clkfunc.c | 1 - drivers/st/ddr/stm32mp1_ddr_helpers.c | 4 + drivers/st/ddr/stm32mp1_ram.c | 15 +- drivers/st/mmc/stm32_sdmmc2.c | 9 +- include/drivers/st/stm32mp1_clk.h | 32 + include/drivers/st/stm32mp1_clkfunc.h | 1 - plat/st/common/include/stm32mp_common.h | 4 +- .../st/common/include/stm32mp_shres_helpers.h | 74 + plat/st/stm32mp1/bl2_plat_setup.c | 4 +- plat/st/stm32mp1/stm32mp1_context.c | 14 +- plat/st/stm32mp1/stm32mp1_def.h | 1 + plat/st/stm32mp1/stm32mp1_pm.c | 14 +- plat/st/stm32mp1/stm32mp1_security.c | 10 +- 14 files changed, 854 insertions(+), 578 deletions(-) create mode 100644 plat/st/common/include/stm32mp_shres_helpers.h diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index 4275f3bd1..c9bb9ff2b 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -24,10 +24,12 @@ #include #include #include +#include #include #include #define MAX_HSI_HZ 64000000 +#define USB_PHY_48_MHZ 48000000 #define TIMEOUT_US_200MS U(200000) #define TIMEOUT_US_1S U(1000000) @@ -68,12 +70,20 @@ enum stm32mp1_parent_id { _HCLK2, _CK_PER, _CK_MPU, + _USB_PHY_48, _PARENT_NB, _UNKNOWN_ID = 0xff, }; +/* Lists only the parent clock we are interested in */ enum stm32mp1_parent_sel { + _I2C12_SEL, + _I2C35_SEL, + _STGEN_SEL, _I2C46_SEL, + _SPI6_SEL, + _USART1_SEL, + _RNG1_SEL, _UART6_SEL, _UART24_SEL, _UART35_SEL, @@ -82,9 +92,9 @@ enum stm32mp1_parent_sel { _SDMMC3_SEL, _QSPI_SEL, _FMC_SEL, + _ASS_SEL, _USBPHY_SEL, _USBO_SEL, - _STGEN_SEL, _PARENT_SEL_NB, _UNKNOWN_SEL = 0xff, }; @@ -164,9 +174,8 @@ struct stm32mp1_clk_gate { uint8_t bit; uint8_t index; uint8_t set_clr; - enum stm32mp1_parent_sel sel; - enum stm32mp1_parent_id fixed; - bool secure; + uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ + uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ }; struct stm32mp1_clk_sel { @@ -189,21 +198,8 @@ struct stm32mp1_clk_pll { enum stm32mp_osc_id refclk[REFCLK_SIZE]; }; -struct stm32mp1_clk_data { - const struct stm32mp1_clk_gate *gate; - const struct stm32mp1_clk_sel *sel; - const struct stm32mp1_clk_pll *pll; - const int nb_gate; -}; - -struct stm32mp1_clk_priv { - uint32_t base; - const struct stm32mp1_clk_data *data; - unsigned long osc[NB_OSC]; - uint32_t pkcs_usb_value; -}; - -#define STM32MP1_CLK(off, b, idx, s) \ +/* Clocks with selectable source and non set/clr register access */ +#define _CLK_SELEC(off, b, idx, s) \ { \ .offset = (off), \ .bit = (b), \ @@ -211,10 +207,10 @@ struct stm32mp1_clk_priv { .set_clr = 0, \ .sel = (s), \ .fixed = _UNKNOWN_ID, \ - .secure = 0, \ } -#define STM32MP1_CLK_F(off, b, idx, f) \ +/* Clocks with fixed source and non set/clr register access */ +#define _CLK_FIXED(off, b, idx, f) \ { \ .offset = (off), \ .bit = (b), \ @@ -222,10 +218,10 @@ struct stm32mp1_clk_priv { .set_clr = 0, \ .sel = _UNKNOWN_SEL, \ .fixed = (f), \ - .secure = 0, \ } -#define STM32MP1_CLK_SET_CLR(off, b, idx, s) \ +/* Clocks with selectable source and set/clr register access */ +#define _CLK_SC_SELEC(off, b, idx, s) \ { \ .offset = (off), \ .bit = (b), \ @@ -233,10 +229,10 @@ struct stm32mp1_clk_priv { .set_clr = 1, \ .sel = (s), \ .fixed = _UNKNOWN_ID, \ - .secure = 0, \ } -#define STM32MP1_CLK_SET_CLR_F(off, b, idx, f) \ +/* Clocks with fixed source and set/clr register access */ +#define _CLK_SC_FIXED(off, b, idx, f) \ { \ .offset = (off), \ .bit = (b), \ @@ -244,32 +240,20 @@ struct stm32mp1_clk_priv { .set_clr = 1, \ .sel = _UNKNOWN_SEL, \ .fixed = (f), \ - .secure = 0, \ } -#define STM32MP1_CLK_SEC_SET_CLR(off, b, idx, s) \ - { \ - .offset = (off), \ - .bit = (b), \ - .index = (idx), \ - .set_clr = 1, \ - .sel = (s), \ - .fixed = _UNKNOWN_ID, \ - .secure = 1, \ - } - -#define STM32MP1_CLK_PARENT(idx, off, s, m, p) \ +#define _CLK_PARENT(idx, off, s, m, p) \ [(idx)] = { \ .offset = (off), \ .src = (s), \ .msk = (m), \ .parent = (p), \ - .nb_parent = ARRAY_SIZE((p)) \ + .nb_parent = ARRAY_SIZE(p) \ } -#define STM32MP1_CLK_PLL(idx, type, off1, off2, off3, \ - off4, off5, off6, \ - p1, p2, p3, p4) \ +#define _CLK_PLL(idx, type, off1, off2, off3, \ + off4, off5, off6, \ + p1, p2, p3, p4) \ [(idx)] = { \ .plltype = (type), \ .rckxselr = (off1), \ @@ -285,113 +269,176 @@ struct stm32mp1_clk_priv { } static const uint8_t stm32mp1_clks[][2] = { - {CK_PER, _CK_PER}, - {CK_MPU, _CK_MPU}, - {CK_AXI, _ACLK}, - {CK_HSE, _HSE}, - {CK_CSI, _CSI}, - {CK_LSI, _LSI}, - {CK_LSE, _LSE}, - {CK_HSI, _HSI}, - {CK_HSE_DIV2, _HSE_KER_DIV2}, + { CK_PER, _CK_PER }, + { CK_MPU, _CK_MPU }, + { CK_AXI, _ACLK }, + { CK_HSE, _HSE }, + { CK_CSI, _CSI }, + { CK_LSI, _LSI }, + { CK_LSE, _LSE }, + { CK_HSI, _HSI }, + { CK_HSE_DIV2, _HSE_KER_DIV2 }, }; +#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) + static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { - STM32MP1_CLK(RCC_DDRITFCR, 0, DDRC1, _UNKNOWN_SEL), - STM32MP1_CLK(RCC_DDRITFCR, 1, DDRC1LP, _UNKNOWN_SEL), - STM32MP1_CLK(RCC_DDRITFCR, 2, DDRC2, _UNKNOWN_SEL), - STM32MP1_CLK(RCC_DDRITFCR, 3, DDRC2LP, _UNKNOWN_SEL), - STM32MP1_CLK_F(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), - STM32MP1_CLK(RCC_DDRITFCR, 5, DDRPHYCLP, _UNKNOWN_SEL), - STM32MP1_CLK(RCC_DDRITFCR, 6, DDRCAPB, _UNKNOWN_SEL), - STM32MP1_CLK(RCC_DDRITFCR, 7, DDRCAPBLP, _UNKNOWN_SEL), - STM32MP1_CLK(RCC_DDRITFCR, 8, AXIDCG, _UNKNOWN_SEL), - STM32MP1_CLK(RCC_DDRITFCR, 9, DDRPHYCAPB, _UNKNOWN_SEL), - STM32MP1_CLK(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _UNKNOWN_SEL), + _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK), + _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK), + _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK), + _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK), + _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), + _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), + _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), + _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), + _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK), + _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), + _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), - STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), + _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), + _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), + _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), + _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), + _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), + _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), + _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), + _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), + _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), + _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), + _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), + _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), + _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), + _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), - STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), - STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), - STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 11, TZC1, _UNKNOWN_SEL), - STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 12, TZC2, _UNKNOWN_SEL), - STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), + _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), + _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), + _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), + _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _USART1_SEL), + _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), + _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), + _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), + _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), + _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), + _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), + _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), + _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), + _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), - STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 0, GPIOZ, _UNKNOWN_SEL), - STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 5, HASH1, _UNKNOWN_SEL), - STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 6, RNG1_K, _CSI_KER), - STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _UNKNOWN_SEL), + _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), + _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), + _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), + _CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), + _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), - STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), + _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), + _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), + _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), + _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), + _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), - STM32MP1_CLK(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), + _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), }; -static const uint8_t i2c46_parents[] = {_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER}; -static const uint8_t uart6_parents[] = {_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, - _HSE_KER}; -static const uint8_t uart24_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, - _HSE_KER}; -static const uint8_t uart35_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, - _HSE_KER}; -static const uint8_t uart78_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, - _HSE_KER}; -static const uint8_t sdmmc12_parents[] = {_HCLK6, _PLL3_R, _PLL4_P, _HSI_KER}; -static const uint8_t sdmmc3_parents[] = {_HCLK2, _PLL3_R, _PLL4_P, _HSI_KER}; -static const uint8_t qspi_parents[] = {_ACLK, _PLL3_R, _PLL4_P, _CK_PER}; -static const uint8_t fmc_parents[] = {_ACLK, _PLL3_R, _PLL4_P, _CK_PER}; -static const uint8_t usbphy_parents[] = {_HSE_KER, _PLL4_R, _HSE_KER_DIV2}; -static const uint8_t usbo_parents[] = {_PLL4_R, _USB_PHY_48}; -static const uint8_t stgen_parents[] = {_HSI_KER, _HSE_KER}; +static const uint8_t i2c12_parents[] = { + _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER +}; + +static const uint8_t i2c35_parents[] = { + _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER +}; + +static const uint8_t stgen_parents[] = { + _HSI_KER, _HSE_KER +}; + +static const uint8_t i2c46_parents[] = { + _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER +}; + +static const uint8_t spi6_parents[] = { + _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q +}; + +static const uint8_t usart1_parents[] = { + _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER +}; + +static const uint8_t rng1_parents[] = { + _CSI, _PLL4_R, _LSE, _LSI +}; + +static const uint8_t uart6_parents[] = { + _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER +}; + +static const uint8_t uart234578_parents[] = { + _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER +}; + +static const uint8_t sdmmc12_parents[] = { + _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER +}; + +static const uint8_t sdmmc3_parents[] = { + _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER +}; + +static const uint8_t qspi_parents[] = { + _ACLK, _PLL3_R, _PLL4_P, _CK_PER +}; + +static const uint8_t fmc_parents[] = { + _ACLK, _PLL3_R, _PLL4_P, _CK_PER +}; + +static const uint8_t ass_parents[] = { + _HSI, _HSE, _PLL2 +}; + +static const uint8_t usbphy_parents[] = { + _HSE_KER, _PLL4_R, _HSE_KER_DIV2 +}; + +static const uint8_t usbo_parents[] = { + _PLL4_R, _USB_PHY_48 +}; static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { - STM32MP1_CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents), - STM32MP1_CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents), - STM32MP1_CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, - uart24_parents), - STM32MP1_CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, - uart35_parents), - STM32MP1_CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, - uart78_parents), - STM32MP1_CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7, - sdmmc12_parents), - STM32MP1_CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7, - sdmmc3_parents), - STM32MP1_CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents), - STM32MP1_CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents), - STM32MP1_CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents), - STM32MP1_CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents), - STM32MP1_CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), + _CLK_PARENT(_I2C12_SEL, RCC_I2C12CKSELR, 0, 0x7, i2c12_parents), + _CLK_PARENT(_I2C35_SEL, RCC_I2C35CKSELR, 0, 0x7, i2c35_parents), + _CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), + _CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents), + _CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents), + _CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents), + _CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents), + _CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents), + _CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents), + _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents), + _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents), + _CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7, sdmmc12_parents), + _CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7, sdmmc3_parents), + _CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents), + _CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents), + _CLK_PARENT(_ASS_SEL, RCC_ASSCKSELR, 0, 0x3, ass_parents), + _CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents), + _CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents), }; /* Define characteristic of PLL according type */ @@ -413,26 +460,26 @@ static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { static const uint8_t pllncfgr2[_DIV_NB] = { [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, - [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT + [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, }; static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { - STM32MP1_CLK_PLL(_PLL1, PLL_1600, - RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, - RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, - _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), - STM32MP1_CLK_PLL(_PLL2, PLL_1600, - RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, - RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, - _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), - STM32MP1_CLK_PLL(_PLL3, PLL_800, - RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, - RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, - _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), - STM32MP1_CLK_PLL(_PLL4, PLL_800, - RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, - RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, - _HSI, _HSE, _CSI, _I2S_CKIN), + _CLK_PLL(_PLL1, PLL_1600, + RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, + RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, + _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL2, PLL_1600, + RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, + RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, + _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL3, PLL_800, + RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, + RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, + _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL4, PLL_800, + RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, + RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, + _HSI, _HSE, _CSI, _I2S_CKIN), }; /* Prescaler table lookups for clock computation */ @@ -449,33 +496,84 @@ static const uint8_t stm32mp1_axi_div[8] = { 1, 2, 3, 4, 4, 4, 4, 4 }; -static const struct stm32mp1_clk_data stm32mp1_data = { - .gate = stm32mp1_clk_gate, - .sel = stm32mp1_clk_sel, - .pll = stm32mp1_clk_pll, - .nb_gate = ARRAY_SIZE(stm32mp1_clk_gate), -}; +/* RCC clock device driver private */ +static unsigned long stm32mp1_osc[NB_OSC]; +static struct spinlock reg_lock; +static unsigned int gate_refcounts[NB_GATES]; +static struct spinlock refcount_lock; -static struct stm32mp1_clk_priv stm32mp1_clk_priv_data; +static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) +{ + return &stm32mp1_clk_gate[idx]; +} -static unsigned long stm32mp1_clk_get_fixed(struct stm32mp1_clk_priv *priv, - enum stm32mp_osc_id idx) +static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) +{ + return &stm32mp1_clk_sel[idx]; +} + +static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) +{ + return &stm32mp1_clk_pll[idx]; +} + +static int stm32mp1_lock_available(void) +{ + /* The spinlocks are used only when MMU is enabled */ + return (read_sctlr() & SCTLR_M_BIT) && (read_sctlr() & SCTLR_C_BIT); +} + +static void stm32mp1_clk_lock(struct spinlock *lock) +{ + if (stm32mp1_lock_available() == 0U) { + return; + } + + /* Assume interrupts are masked */ + spin_lock(lock); +} + +static void stm32mp1_clk_unlock(struct spinlock *lock) +{ + if (stm32mp1_lock_available() == 0U) { + return; + } + + spin_unlock(lock); +} + +bool stm32mp1_rcc_is_secure(void) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0; +} + +void stm32mp1_clk_rcc_regs_lock(void) +{ + stm32mp1_clk_lock(®_lock); +} + +void stm32mp1_clk_rcc_regs_unlock(void) +{ + stm32mp1_clk_unlock(®_lock); +} + +static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) { if (idx >= NB_OSC) { return 0; } - return priv->osc[idx]; + return stm32mp1_osc[idx]; } -static int stm32mp1_clk_get_id(struct stm32mp1_clk_priv *priv, unsigned long id) +static int stm32mp1_clk_get_gated_id(unsigned long id) { - const struct stm32mp1_clk_gate *gate = priv->data->gate; - int i; - int nb_clks = priv->data->nb_gate; + unsigned int i; - for (i = 0; i < nb_clks; i++) { - if (gate[i].index == id) { + for (i = 0U; i < NB_GATES; i++) { + if (gate_ref(i)->index == id) { return i; } } @@ -485,77 +583,64 @@ static int stm32mp1_clk_get_id(struct stm32mp1_clk_priv *priv, unsigned long id) return -EINVAL; } -static enum stm32mp1_parent_sel -stm32mp1_clk_get_sel(struct stm32mp1_clk_priv *priv, int i) +static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) { - const struct stm32mp1_clk_gate *gate = priv->data->gate; - - return gate[i].sel; + return (enum stm32mp1_parent_sel)(gate_ref(i)->sel); } -static enum stm32mp1_parent_id -stm32mp1_clk_get_fixed_parent(struct stm32mp1_clk_priv *priv, int i) +static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) { - const struct stm32mp1_clk_gate *gate = priv->data->gate; - - return gate[i].fixed; + return (enum stm32mp1_parent_id)(gate_ref(i)->fixed); } -static int stm32mp1_clk_get_parent(struct stm32mp1_clk_priv *priv, - unsigned long id) +static int stm32mp1_clk_get_parent(unsigned long id) { - const struct stm32mp1_clk_sel *sel = priv->data->sel; + const struct stm32mp1_clk_sel *sel; uint32_t j, p_sel; int i; enum stm32mp1_parent_id p; enum stm32mp1_parent_sel s; + uintptr_t rcc_base = stm32mp_rcc_base(); - for (j = 0; j < ARRAY_SIZE(stm32mp1_clks); j++) { + for (j = 0U; j < ARRAY_SIZE(stm32mp1_clks); j++) { if (stm32mp1_clks[j][0] == id) { return (int)stm32mp1_clks[j][1]; } } - i = stm32mp1_clk_get_id(priv, id); + i = stm32mp1_clk_get_gated_id(id); if (i < 0) { - return i; + panic(); } - p = stm32mp1_clk_get_fixed_parent(priv, i); + p = stm32mp1_clk_get_fixed_parent(i); if (p < _PARENT_NB) { return (int)p; } - s = stm32mp1_clk_get_sel(priv, i); - if (s >= _PARENT_SEL_NB) { + s = stm32mp1_clk_get_sel(i); + if (s == _UNKNOWN_SEL) { return -EINVAL; } - - p_sel = (mmio_read_32(priv->base + sel[s].offset) >> sel[s].src) & - sel[s].msk; - - if (p_sel < sel[s].nb_parent) { - return (int)sel[s].parent[p_sel]; + if (s >= _PARENT_SEL_NB) { + panic(); } - ERROR("%s: no parents defined for clk id %ld\n", __func__, id); + sel = clk_sel_ref(s); + p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & sel->msk; + if (p_sel < sel->nb_parent) { + return (int)sel->parent[p_sel]; + } return -EINVAL; } -static unsigned long stm32mp1_pll_get_fref_ck(struct stm32mp1_clk_priv *priv, - enum stm32mp1_pll_id pll_id) +static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) { - const struct stm32mp1_clk_pll *pll = priv->data->pll; - uint32_t selr, src; - unsigned long refclk; + uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr); + uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; - selr = mmio_read_32(priv->base + pll[pll_id].rckxselr); - src = selr & RCC_SELR_REFCLK_SRC_MASK; - - refclk = stm32mp1_clk_get_fixed(priv, pll[pll_id].refclk[src]); - - return refclk; + return stm32mp1_clk_get_fixed(pll->refclk[src]); } /* @@ -564,20 +649,19 @@ static unsigned long stm32mp1_pll_get_fref_ck(struct stm32mp1_clk_priv *priv, * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) */ -static unsigned long stm32mp1_pll_get_fvco(struct stm32mp1_clk_priv *priv, - enum stm32mp1_pll_id pll_id) +static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) { - const struct stm32mp1_clk_pll *pll = priv->data->pll; unsigned long refclk, fvco; uint32_t cfgr1, fracr, divm, divn; + uintptr_t rcc_base = stm32mp_rcc_base(); - cfgr1 = mmio_read_32(priv->base + pll[pll_id].pllxcfgr1); - fracr = mmio_read_32(priv->base + pll[pll_id].pllxfracr); + cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1); + fracr = mmio_read_32(rcc_base + pll->pllxfracr); divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; - refclk = stm32mp1_pll_get_fref_ck(priv, pll_id); + refclk = stm32mp1_pll_get_fref(pll); /* * With FRACV : @@ -586,13 +670,13 @@ static unsigned long stm32mp1_pll_get_fvco(struct stm32mp1_clk_priv *priv, * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) */ if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { - uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) - >> RCC_PLLNFRACR_FRACV_SHIFT; + uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> + RCC_PLLNFRACR_FRACV_SHIFT; unsigned long long numerator, denominator; - numerator = ((unsigned long long)divn + 1U) << 13; - numerator = (refclk * numerator) + fracv; - denominator = ((unsigned long long)divm + 1U) << 13; + numerator = (((unsigned long long)divn + 1U) << 13) + fracv; + numerator = refclk * numerator; + denominator = ((unsigned long long)divm + 1U) << 13; fvco = (unsigned long)(numerator / denominator); } else { fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); @@ -601,11 +685,10 @@ static unsigned long stm32mp1_pll_get_fvco(struct stm32mp1_clk_priv *priv, return fvco; } -static unsigned long stm32mp1_read_pll_freq(struct stm32mp1_clk_priv *priv, - enum stm32mp1_pll_id pll_id, +static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, enum stm32mp1_div_id div_id) { - const struct stm32mp1_clk_pll *pll = priv->data->pll; + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); unsigned long dfout; uint32_t cfgr2, divy; @@ -613,42 +696,42 @@ static unsigned long stm32mp1_read_pll_freq(struct stm32mp1_clk_priv *priv, return 0; } - cfgr2 = mmio_read_32(priv->base + pll[pll_id].pllxcfgr2); + cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2); divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; - dfout = stm32mp1_pll_get_fvco(priv, pll_id) / (divy + 1U); + dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); return dfout; } -static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) +static unsigned long get_clock_rate(int p) { uint32_t reg, clkdiv; unsigned long clock = 0; + uintptr_t rcc_base = stm32mp_rcc_base(); switch (p) { case _CK_MPU: /* MPU sub system */ - reg = mmio_read_32(priv->base + RCC_MPCKSELR); + reg = mmio_read_32(rcc_base + RCC_MPCKSELR); switch (reg & RCC_SELR_SRC_MASK) { case RCC_MPCKSELR_HSI: - clock = stm32mp1_clk_get_fixed(priv, _HSI); + clock = stm32mp1_clk_get_fixed(_HSI); break; case RCC_MPCKSELR_HSE: - clock = stm32mp1_clk_get_fixed(priv, _HSE); + clock = stm32mp1_clk_get_fixed(_HSE); break; case RCC_MPCKSELR_PLL: - clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P); + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); break; case RCC_MPCKSELR_PLL_MPUDIV: - clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P); + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); - reg = mmio_read_32(priv->base + RCC_MPCKDIVR); + reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); clkdiv = reg & RCC_MPUDIV_MASK; if (clkdiv != 0U) { clock /= stm32mp1_mpu_div[clkdiv]; } - break; default: break; @@ -660,32 +743,32 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) case _HCLK6: case _PCLK4: case _PCLK5: - reg = mmio_read_32(priv->base + RCC_ASSCKSELR); + reg = mmio_read_32(rcc_base + RCC_ASSCKSELR); switch (reg & RCC_SELR_SRC_MASK) { case RCC_ASSCKSELR_HSI: - clock = stm32mp1_clk_get_fixed(priv, _HSI); + clock = stm32mp1_clk_get_fixed(_HSI); break; case RCC_ASSCKSELR_HSE: - clock = stm32mp1_clk_get_fixed(priv, _HSE); + clock = stm32mp1_clk_get_fixed(_HSE); break; case RCC_ASSCKSELR_PLL: - clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_P); + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); break; default: break; } /* System clock divider */ - reg = mmio_read_32(priv->base + RCC_AXIDIVR); + reg = mmio_read_32(rcc_base + RCC_AXIDIVR); clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; switch (p) { case _PCLK4: - reg = mmio_read_32(priv->base + RCC_APB4DIVR); + reg = mmio_read_32(rcc_base + RCC_APB4DIVR); clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; break; case _PCLK5: - reg = mmio_read_32(priv->base + RCC_APB5DIVR); + reg = mmio_read_32(rcc_base + RCC_APB5DIVR); clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; break; default: @@ -693,16 +776,16 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) } break; case _CK_PER: - reg = mmio_read_32(priv->base + RCC_CPERCKSELR); + reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); switch (reg & RCC_SELR_SRC_MASK) { case RCC_CPERCKSELR_HSI: - clock = stm32mp1_clk_get_fixed(priv, _HSI); + clock = stm32mp1_clk_get_fixed(_HSI); break; case RCC_CPERCKSELR_HSE: - clock = stm32mp1_clk_get_fixed(priv, _HSE); + clock = stm32mp1_clk_get_fixed(_HSE); break; case RCC_CPERCKSELR_CSI: - clock = stm32mp1_clk_get_fixed(priv, _CSI); + clock = stm32mp1_clk_get_fixed(_CSI); break; default: break; @@ -710,65 +793,65 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) break; case _HSI: case _HSI_KER: - clock = stm32mp1_clk_get_fixed(priv, _HSI); + clock = stm32mp1_clk_get_fixed(_HSI); break; case _CSI: case _CSI_KER: - clock = stm32mp1_clk_get_fixed(priv, _CSI); + clock = stm32mp1_clk_get_fixed(_CSI); break; case _HSE: case _HSE_KER: - clock = stm32mp1_clk_get_fixed(priv, _HSE); + clock = stm32mp1_clk_get_fixed(_HSE); break; case _HSE_KER_DIV2: - clock = stm32mp1_clk_get_fixed(priv, _HSE) >> 1; + clock = stm32mp1_clk_get_fixed(_HSE) >> 1; break; case _LSI: - clock = stm32mp1_clk_get_fixed(priv, _LSI); + clock = stm32mp1_clk_get_fixed(_LSI); break; case _LSE: - clock = stm32mp1_clk_get_fixed(priv, _LSE); + clock = stm32mp1_clk_get_fixed(_LSE); break; /* PLL */ case _PLL1_P: - clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P); + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); break; case _PLL1_Q: - clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_Q); + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); break; case _PLL1_R: - clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_R); + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); break; case _PLL2_P: - clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_P); + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); break; case _PLL2_Q: - clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_Q); + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); break; case _PLL2_R: - clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_R); + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); break; case _PLL3_P: - clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_P); + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); break; case _PLL3_Q: - clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_Q); + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); break; case _PLL3_R: - clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_R); + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); break; case _PLL4_P: - clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_P); + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); break; case _PLL4_Q: - clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_Q); + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); break; case _PLL4_R: - clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_R); + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); break; /* Other */ case _USB_PHY_48: - clock = stm32mp1_clk_get_fixed(priv, _USB_PHY_48); + clock = USB_PHY_48_MHZ; break; default: break; @@ -777,104 +860,155 @@ static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) return clock; } +static void __clk_enable(struct stm32mp1_clk_gate const *gate) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + if (gate->set_clr != 0U) { + mmio_write_32(rcc_base + gate->offset, BIT(gate->bit)); + } else { + mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit)); + } + + VERBOSE("Clock %d has been enabled", gate->index); +} + +static void __clk_disable(struct stm32mp1_clk_gate const *gate) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + if (gate->set_clr != 0U) { + mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET, + BIT(gate->bit)); + } else { + mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit)); + } + + VERBOSE("Clock %d has been disabled", gate->index); +} + +static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); +} + +unsigned int stm32mp1_clk_get_refcount(unsigned long id) +{ + int i = stm32mp1_clk_get_gated_id(id); + + if (i < 0) { + panic(); + } + + return gate_refcounts[i]; +} + +void __stm32mp1_clk_enable(unsigned long id, bool secure) +{ + const struct stm32mp1_clk_gate *gate; + int i = stm32mp1_clk_get_gated_id(id); + unsigned int *refcnt; + + if (i < 0) { + ERROR("Clock %d can't be enabled\n", (uint32_t)id); + panic(); + } + + gate = gate_ref(i); + refcnt = &gate_refcounts[i]; + + stm32mp1_clk_lock(&refcount_lock); + + if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) { + __clk_enable(gate); + } + + stm32mp1_clk_unlock(&refcount_lock); +} + +void __stm32mp1_clk_disable(unsigned long id, bool secure) +{ + const struct stm32mp1_clk_gate *gate; + int i = stm32mp1_clk_get_gated_id(id); + unsigned int *refcnt; + + if (i < 0) { + ERROR("Clock %d can't be disabled\n", (uint32_t)id); + panic(); + } + + gate = gate_ref(i); + refcnt = &gate_refcounts[i]; + + stm32mp1_clk_lock(&refcount_lock); + + if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) { + __clk_disable(gate); + } + + stm32mp1_clk_unlock(&refcount_lock); +} + +void stm32mp_clk_enable(unsigned long id) +{ + __stm32mp1_clk_enable(id, true); +} + +void stm32mp_clk_disable(unsigned long id) +{ + __stm32mp1_clk_disable(id, true); +} + bool stm32mp_clk_is_enabled(unsigned long id) { - struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; - const struct stm32mp1_clk_gate *gate = priv->data->gate; - int i = stm32mp1_clk_get_id(priv, id); + int i = stm32mp1_clk_get_gated_id(id); if (i < 0) { - return false; + panic(); } - return ((mmio_read_32(priv->base + gate[i].offset) & - BIT(gate[i].bit)) != 0U); -} - -int stm32mp_clk_enable(unsigned long id) -{ - struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; - const struct stm32mp1_clk_gate *gate = priv->data->gate; - int i = stm32mp1_clk_get_id(priv, id); - - if (i < 0) { - return i; - } - - if (gate[i].set_clr != 0U) { - mmio_write_32(priv->base + gate[i].offset, BIT(gate[i].bit)); - } else { - mmio_setbits_32(priv->base + gate[i].offset, BIT(gate[i].bit)); - } - - return 0; -} - -int stm32mp_clk_disable(unsigned long id) -{ - struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; - const struct stm32mp1_clk_gate *gate = priv->data->gate; - int i = stm32mp1_clk_get_id(priv, id); - - if (i < 0) { - return i; - } - - if (gate[i].set_clr != 0U) { - mmio_write_32(priv->base + gate[i].offset - + RCC_MP_ENCLRR_OFFSET, - BIT(gate[i].bit)); - } else { - mmio_clrbits_32(priv->base + gate[i].offset, BIT(gate[i].bit)); - } - - return 0; + return __clk_is_enabled(gate_ref(i)); } unsigned long stm32mp_clk_get_rate(unsigned long id) { - struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; - int p = stm32mp1_clk_get_parent(priv, id); - unsigned long rate; + int p = stm32mp1_clk_get_parent(id); if (p < 0) { return 0; } - rate = stm32mp1_clk_get(priv, p); - - return rate; + return get_clock_rate(p); } -static void stm32mp1_ls_osc_set(int enable, uint32_t rcc, uint32_t offset, - uint32_t mask_on) +static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) { - uint32_t address = rcc + offset; + uintptr_t address = stm32mp_rcc_base() + offset; - if (enable != 0) { + if (enable) { mmio_setbits_32(address, mask_on); } else { mmio_clrbits_32(address, mask_on); } } -static void stm32mp1_hs_ocs_set(int enable, uint32_t rcc, uint32_t mask_on) +static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on) { - if (enable != 0) { - mmio_setbits_32(rcc + RCC_OCENSETR, mask_on); - } else { - mmio_setbits_32(rcc + RCC_OCENCLRR, mask_on); - } + uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR; + uintptr_t address = stm32mp_rcc_base() + offset; + + mmio_write_32(address, mask_on); } -static int stm32mp1_osc_wait(int enable, uint32_t rcc, uint32_t offset, - uint32_t mask_rdy) +static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy) { uint64_t timeout; uint32_t mask_test; - uint32_t address = rcc + offset; + uintptr_t address = stm32mp_rcc_base() + offset; - if (enable != 0) { + if (enable) { mask_test = mask_rdy; } else { mask_test = 0; @@ -883,7 +1017,7 @@ static int stm32mp1_osc_wait(int enable, uint32_t rcc, uint32_t offset, timeout = timeout_init_us(OSCRDY_TIMEOUT); while ((mmio_read_32(address) & mask_rdy) != mask_test) { if (timeout_elapsed(timeout)) { - ERROR("OSC %x @ %x timeout for enable=%d : 0x%x\n", + ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n", mask_rdy, address, enable, mmio_read_32(address)); return -ETIMEDOUT; } @@ -892,19 +1026,24 @@ static int stm32mp1_osc_wait(int enable, uint32_t rcc, uint32_t offset, return 0; } -static void stm32mp1_lse_enable(uint32_t rcc, bool bypass, uint32_t lsedrv) +static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv) { uint32_t value; + uintptr_t rcc_base = stm32mp_rcc_base(); - if (bypass) { - mmio_setbits_32(rcc + RCC_BDCR, RCC_BDCR_LSEBYP); + if (digbyp) { + mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP); + } + + if (bypass || digbyp) { + mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP); } /* * Warning: not recommended to switch directly from "high drive" * to "medium low drive", and vice-versa. */ - value = (mmio_read_32(rcc + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> + value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> RCC_BDCR_LSEDRV_SHIFT; while (value != lsedrv) { @@ -914,78 +1053,82 @@ static void stm32mp1_lse_enable(uint32_t rcc, bool bypass, uint32_t lsedrv) value++; } - mmio_clrsetbits_32(rcc + RCC_BDCR, + mmio_clrsetbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEDRV_MASK, value << RCC_BDCR_LSEDRV_SHIFT); } - stm32mp1_ls_osc_set(1, rcc, RCC_BDCR, RCC_BDCR_LSEON); + stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON); } -static void stm32mp1_lse_wait(uint32_t rcc) +static void stm32mp1_lse_wait(void) { - if (stm32mp1_osc_wait(1, rcc, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { + if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { VERBOSE("%s: failed\n", __func__); } } -static void stm32mp1_lsi_set(uint32_t rcc, int enable) +static void stm32mp1_lsi_set(bool enable) { - stm32mp1_ls_osc_set(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSION); - if (stm32mp1_osc_wait(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != - 0) { + stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION); + + if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) { VERBOSE("%s: failed\n", __func__); } } -static void stm32mp1_hse_enable(uint32_t rcc, bool bypass, bool css) +static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css) { - if (bypass) { - mmio_setbits_32(rcc + RCC_OCENSETR, RCC_OCENR_HSEBYP); + uintptr_t rcc_base = stm32mp_rcc_base(); + + if (digbyp) { + mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP); } - stm32mp1_hs_ocs_set(1, rcc, RCC_OCENR_HSEON); - if (stm32mp1_osc_wait(1, rcc, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != - 0) { + if (bypass || digbyp) { + mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP); + } + + stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON); + if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) { VERBOSE("%s: failed\n", __func__); } if (css) { - mmio_setbits_32(rcc + RCC_OCENSETR, RCC_OCENR_HSECSSON); + mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON); } } -static void stm32mp1_csi_set(uint32_t rcc, int enable) +static void stm32mp1_csi_set(bool enable) { - stm32mp1_ls_osc_set(enable, rcc, RCC_OCENSETR, RCC_OCENR_CSION); - if (stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != - 0) { + stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION); + if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) { VERBOSE("%s: failed\n", __func__); } } -static void stm32mp1_hsi_set(uint32_t rcc, int enable) +static void stm32mp1_hsi_set(bool enable) { - stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_HSION); - if (stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != - 0) { + stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION); + if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) { VERBOSE("%s: failed\n", __func__); } } -static int stm32mp1_set_hsidiv(uint32_t rcc, uint8_t hsidiv) +static int stm32mp1_set_hsidiv(uint8_t hsidiv) { - uint32_t address = rcc + RCC_OCRDYR; uint64_t timeout; + uintptr_t rcc_base = stm32mp_rcc_base(); + uintptr_t address = rcc_base + RCC_OCRDYR; - mmio_clrsetbits_32(rcc + RCC_HSICFGR, + mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, RCC_HSICFGR_HSIDIV_MASK, RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); timeout = timeout_init_us(HSIDIV_TIMEOUT); while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { if (timeout_elapsed(timeout)) { - ERROR("HSIDIV failed @ 0x%x: 0x%x\n", + ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", address, mmio_read_32(address)); return -ETIMEDOUT; } @@ -994,7 +1137,7 @@ static int stm32mp1_set_hsidiv(uint32_t rcc, uint8_t hsidiv) return 0; } -static int stm32mp1_hsidiv(uint32_t rcc, unsigned long hsifreq) +static int stm32mp1_hsidiv(unsigned long hsifreq) { uint8_t hsidiv; uint32_t hsidivfreq = MAX_HSI_HZ; @@ -1013,31 +1156,102 @@ static int stm32mp1_hsidiv(uint32_t rcc, unsigned long hsifreq) } if (hsidiv != 0U) { - return stm32mp1_set_hsidiv(rcc, hsidiv); + return stm32mp1_set_hsidiv(hsidiv); } return 0; } -static void stm32mp1_pll_start(struct stm32mp1_clk_priv *priv, - enum stm32mp1_pll_id pll_id) +static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id, + unsigned int clksrc, + uint32_t *pllcfg, int plloff) { - const struct stm32mp1_clk_pll *pll = priv->data->pll; + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t rcc_base = stm32mp_rcc_base(); + uintptr_t pllxcr = rcc_base + pll->pllxcr; + enum stm32mp1_plltype type = pll->plltype; + uintptr_t clksrc_address = rcc_base + (clksrc >> 4); + unsigned long refclk; + uint32_t ifrge = 0U; + uint32_t src, value, fracv; - mmio_write_32(priv->base + pll[pll_id].pllxcr, RCC_PLLNCR_PLLON); + /* Check PLL output */ + if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) { + return false; + } + + /* Check current clksrc */ + src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK; + if (src != (clksrc & RCC_SELR_SRC_MASK)) { + return false; + } + + /* Check Div */ + src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK; + + refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / + (pllcfg[PLLCFG_M] + 1U); + + if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || + (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { + return false; + } + + if ((type == PLL_800) && (refclk >= 8000000U)) { + ifrge = 1U; + } + + value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & + RCC_PLLNCFGR1_DIVN_MASK; + value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & + RCC_PLLNCFGR1_DIVM_MASK; + value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & + RCC_PLLNCFGR1_IFRGE_MASK; + if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { + return false; + } + + /* Fractional configuration */ + fracv = fdt_read_uint32_default(plloff, "frac", 0); + + value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; + value |= RCC_PLLNFRACR_FRACLE; + if (mmio_read_32(rcc_base + pll->pllxfracr) != value) { + return false; + } + + /* Output config */ + value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & + RCC_PLLNCFGR2_DIVP_MASK; + value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & + RCC_PLLNCFGR2_DIVQ_MASK; + value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & + RCC_PLLNCFGR2_DIVR_MASK; + if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) { + return false; + } + + return true; } -static int stm32mp1_pll_output(struct stm32mp1_clk_priv *priv, - enum stm32mp1_pll_id pll_id, uint32_t output) +static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id) { - const struct stm32mp1_clk_pll *pll = priv->data->pll; - uint32_t pllxcr = priv->base + pll[pll_id].pllxcr; + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; + + mmio_write_32(pllxcr, RCC_PLLNCR_PLLON); +} + +static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); /* Wait PLL lock */ while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { if (timeout_elapsed(timeout)) { - ERROR("PLL%d start failed @ 0x%x: 0x%x\n", + ERROR("PLL%d start failed @ 0x%lx: 0x%x\n", pll_id, pllxcr, mmio_read_32(pllxcr)); return -ETIMEDOUT; } @@ -1049,11 +1263,10 @@ static int stm32mp1_pll_output(struct stm32mp1_clk_priv *priv, return 0; } -static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv, - enum stm32mp1_pll_id pll_id) +static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) { - const struct stm32mp1_clk_pll *pll = priv->data->pll; - uint32_t pllxcr = priv->base + pll[pll_id].pllxcr; + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; uint64_t timeout; /* Stop all output */ @@ -1067,7 +1280,7 @@ static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv, /* Wait PLL stopped */ while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { if (timeout_elapsed(timeout)) { - ERROR("PLL%d stop failed @ 0x%x: 0x%x\n", + ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n", pll_id, pllxcr, mmio_read_32(pllxcr)); return -ETIMEDOUT; } @@ -1076,12 +1289,11 @@ static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv, return 0; } -static void stm32mp1_pll_config_output(struct stm32mp1_clk_priv *priv, - enum stm32mp1_pll_id pll_id, +static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, uint32_t *pllcfg) { - const struct stm32mp1_clk_pll *pll = priv->data->pll; - uint32_t rcc = priv->base; + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t rcc_base = stm32mp_rcc_base(); uint32_t value; value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & @@ -1090,24 +1302,23 @@ static void stm32mp1_pll_config_output(struct stm32mp1_clk_priv *priv, RCC_PLLNCFGR2_DIVQ_MASK; value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & RCC_PLLNCFGR2_DIVR_MASK; - mmio_write_32(rcc + pll[pll_id].pllxcfgr2, value); + mmio_write_32(rcc_base + pll->pllxcfgr2, value); } -static int stm32mp1_pll_config(struct stm32mp1_clk_priv *priv, - enum stm32mp1_pll_id pll_id, +static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, uint32_t *pllcfg, uint32_t fracv) { - const struct stm32mp1_clk_pll *pll = priv->data->pll; - uint32_t rcc = priv->base; - enum stm32mp1_plltype type = pll[pll_id].plltype; + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t rcc_base = stm32mp_rcc_base(); + enum stm32mp1_plltype type = pll->plltype; unsigned long refclk; uint32_t ifrge = 0; uint32_t src, value; - src = mmio_read_32(priv->base + pll[pll_id].rckxselr) & + src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK; - refclk = stm32mp1_clk_get_fixed(priv, pll[pll_id].refclk[src]) / + refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / (pllcfg[PLLCFG_M] + 1U); if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || @@ -1125,28 +1336,26 @@ static int stm32mp1_pll_config(struct stm32mp1_clk_priv *priv, RCC_PLLNCFGR1_DIVM_MASK; value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & RCC_PLLNCFGR1_IFRGE_MASK; - mmio_write_32(rcc + pll[pll_id].pllxcfgr1, value); + mmio_write_32(rcc_base + pll->pllxcfgr1, value); /* Fractional configuration */ value = 0; - mmio_write_32(rcc + pll[pll_id].pllxfracr, value); + mmio_write_32(rcc_base + pll->pllxfracr, value); value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; - mmio_write_32(rcc + pll[pll_id].pllxfracr, value); + mmio_write_32(rcc_base + pll->pllxfracr, value); value |= RCC_PLLNFRACR_FRACLE; - mmio_write_32(rcc + pll[pll_id].pllxfracr, value); + mmio_write_32(rcc_base + pll->pllxfracr, value); - stm32mp1_pll_config_output(priv, pll_id, pllcfg); + stm32mp1_pll_config_output(pll_id, pllcfg); return 0; } -static void stm32mp1_pll_csg(struct stm32mp1_clk_priv *priv, - enum stm32mp1_pll_id pll_id, - uint32_t *csg) +static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg) { - const struct stm32mp1_clk_pll *pll = priv->data->pll; + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); uint32_t pllxcsg = 0; pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) & @@ -1158,23 +1367,22 @@ static void stm32mp1_pll_csg(struct stm32mp1_clk_priv *priv, pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & RCC_PLLNCSGR_SSCG_MODE_MASK; - mmio_write_32(priv->base + pll[pll_id].pllxcsgr, pllxcsg); + mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); } -static int stm32mp1_set_clksrc(struct stm32mp1_clk_priv *priv, - unsigned int clksrc) +static int stm32mp1_set_clksrc(unsigned int clksrc) { - uint32_t address = priv->base + (clksrc >> 4); + uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); uint64_t timeout; - mmio_clrsetbits_32(address, RCC_SELR_SRC_MASK, + mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK, clksrc & RCC_SELR_SRC_MASK); timeout = timeout_init_us(CLKSRC_TIMEOUT); - while ((mmio_read_32(address) & RCC_SELR_SRCRDY) == 0U) { + while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) { if (timeout_elapsed(timeout)) { - ERROR("CLKSRC %x start failed @ 0x%x: 0x%x\n", - clksrc, address, mmio_read_32(address)); + ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc, + clksrc_address, mmio_read_32(clksrc_address)); return -ETIMEDOUT; } } @@ -1182,7 +1390,7 @@ static int stm32mp1_set_clksrc(struct stm32mp1_clk_priv *priv, return 0; } -static int stm32mp1_set_clkdiv(unsigned int clkdiv, uint32_t address) +static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address) { uint64_t timeout; @@ -1192,7 +1400,7 @@ static int stm32mp1_set_clkdiv(unsigned int clkdiv, uint32_t address) timeout = timeout_init_us(CLKDIV_TIMEOUT); while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) { if (timeout_elapsed(timeout)) { - ERROR("CLKDIV %x start failed @ 0x%x: 0x%x\n", + ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n", clkdiv, address, mmio_read_32(address)); return -ETIMEDOUT; } @@ -1201,10 +1409,9 @@ static int stm32mp1_set_clkdiv(unsigned int clkdiv, uint32_t address) return 0; } -static void stm32mp1_mco_csg(struct stm32mp1_clk_priv *priv, - uint32_t clksrc, uint32_t clkdiv) +static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv) { - uint32_t address = priv->base + (clksrc >> 4); + uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); /* * Binding clksrc : @@ -1213,22 +1420,21 @@ static void stm32mp1_mco_csg(struct stm32mp1_clk_priv *priv, * bit2-0: MCOSEL[2:0] */ if ((clksrc & 0x8U) != 0U) { - mmio_clrbits_32(address, RCC_MCOCFG_MCOON); + mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON); } else { - mmio_clrsetbits_32(address, + mmio_clrsetbits_32(clksrc_address, RCC_MCOCFG_MCOSRC_MASK, clksrc & RCC_MCOCFG_MCOSRC_MASK); - mmio_clrsetbits_32(address, + mmio_clrsetbits_32(clksrc_address, RCC_MCOCFG_MCODIV_MASK, clkdiv << RCC_MCOCFG_MCODIV_SHIFT); - mmio_setbits_32(address, RCC_MCOCFG_MCOON); + mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON); } } -static void stm32mp1_set_rtcsrc(struct stm32mp1_clk_priv *priv, - unsigned int clksrc, bool lse_css) +static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) { - uint32_t address = priv->base + RCC_BDCR; + uintptr_t address = stm32mp_rcc_base() + RCC_BDCR; if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) || (clksrc != (uint32_t)CLK_RTC_DISABLED)) { @@ -1247,38 +1453,35 @@ static void stm32mp1_set_rtcsrc(struct stm32mp1_clk_priv *priv, #define CNTCVL_OFF 0x008 #define CNTCVU_OFF 0x00C -static void stm32mp1_stgen_config(struct stm32mp1_clk_priv *priv) +static void stm32mp1_stgen_config(void) { uintptr_t stgen; - int p; uint32_t cntfid0; unsigned long rate; + unsigned long long counter; stgen = fdt_get_stgen_base(); - cntfid0 = mmio_read_32(stgen + CNTFID_OFF); - p = stm32mp1_clk_get_parent(priv, STGEN_K); - rate = stm32mp1_clk_get(priv, p); + rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K)); - if (cntfid0 != rate) { - unsigned long long counter; - - mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN); - counter = (unsigned long long) - mmio_read_32(stgen + CNTCVL_OFF); - counter |= ((unsigned long long) - (mmio_read_32(stgen + CNTCVU_OFF))) << 32; - counter = (counter * rate / cntfid0); - mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter); - mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32)); - mmio_write_32(stgen + CNTFID_OFF, rate); - mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN); - - write_cntfrq((u_register_t)rate); - - /* Need to update timer with new frequency */ - generic_delay_timer_init(); + if (cntfid0 == rate) { + return; } + + mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN); + counter = (unsigned long long)mmio_read_32(stgen + CNTCVL_OFF); + counter |= ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF)) << 32; + counter = (counter * rate / cntfid0); + + mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter); + mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32)); + mmio_write_32(stgen + CNTFID_OFF, rate); + mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN); + + write_cntfrq((u_register_t)rate); + + /* Need to update timer with new frequency */ + generic_delay_timer_init(); } void stm32mp1_stgen_increment(unsigned long long offset_in_ms) @@ -1299,9 +1502,9 @@ void stm32mp1_stgen_increment(unsigned long long offset_in_ms) mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN); } -static void stm32mp1_pkcs_config(struct stm32mp1_clk_priv *priv, uint32_t pkcs) +static void stm32mp1_pkcs_config(uint32_t pkcs) { - uint32_t address = priv->base + ((pkcs >> 4) & 0xFFFU); + uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU); uint32_t value = pkcs & 0xFU; uint32_t mask = 0xFU; @@ -1315,8 +1518,7 @@ static void stm32mp1_pkcs_config(struct stm32mp1_clk_priv *priv, uint32_t pkcs) int stm32mp1_clk_init(void) { - struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; - uint32_t rcc = priv->base; + uintptr_t rcc_base = stm32mp_rcc_base(); unsigned int clksrc[CLKSRC_NB]; unsigned int clkdiv[CLKDIV_NB]; unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; @@ -1324,11 +1526,14 @@ int stm32mp1_clk_init(void) int ret, len; enum stm32mp1_pll_id i; bool lse_css = false; + bool pll3_preserve = false; + bool pll4_preserve = false; + bool pll4_bootrom = false; const fdt32_t *pkcs_cell; /* Check status field to disable security */ if (!fdt_get_rcc_secure_status()) { - mmio_write_32(rcc + RCC_TZCR, 0); + mmio_write_32(rcc_base + RCC_TZCR, 0); } ret = fdt_rcc_read_uint32_array("st,clksrc", clksrc, @@ -1360,113 +1565,135 @@ int stm32mp1_clk_init(void) } } - stm32mp1_mco_csg(priv, clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); - stm32mp1_mco_csg(priv, clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); + stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); + stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); /* * Switch ON oscillator found in device-tree. * Note: HSI already ON after BootROM stage. */ - if (priv->osc[_LSI] != 0U) { - stm32mp1_lsi_set(rcc, 1); + if (stm32mp1_osc[_LSI] != 0U) { + stm32mp1_lsi_set(true); } - if (priv->osc[_LSE] != 0U) { - bool bypass; + if (stm32mp1_osc[_LSE] != 0U) { + bool bypass, digbyp; uint32_t lsedrv; bypass = fdt_osc_read_bool(_LSE, "st,bypass"); + digbyp = fdt_osc_read_bool(_LSE, "st,digbypass"); lse_css = fdt_osc_read_bool(_LSE, "st,css"); lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive", LSEDRV_MEDIUM_HIGH); - stm32mp1_lse_enable(rcc, bypass, lsedrv); + stm32mp1_lse_enable(bypass, digbyp, lsedrv); } - if (priv->osc[_HSE] != 0U) { - bool bypass, css; + if (stm32mp1_osc[_HSE] != 0U) { + bool bypass, digbyp, css; - bypass = fdt_osc_read_bool(_LSE, "st,bypass"); - css = fdt_osc_read_bool(_LSE, "st,css"); - stm32mp1_hse_enable(rcc, bypass, css); + bypass = fdt_osc_read_bool(_HSE, "st,bypass"); + digbyp = fdt_osc_read_bool(_HSE, "st,digbypass"); + css = fdt_osc_read_bool(_HSE, "st,css"); + stm32mp1_hse_enable(bypass, digbyp, css); } /* * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) * => switch on CSI even if node is not present in device tree */ - stm32mp1_csi_set(rcc, 1); + stm32mp1_csi_set(true); /* Come back to HSI */ - ret = stm32mp1_set_clksrc(priv, CLK_MPU_HSI); + ret = stm32mp1_set_clksrc(CLK_MPU_HSI); if (ret != 0) { return ret; } - ret = stm32mp1_set_clksrc(priv, CLK_AXI_HSI); + ret = stm32mp1_set_clksrc(CLK_AXI_HSI); if (ret != 0) { return ret; } + if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) & + RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) { + pll3_preserve = stm32mp1_check_pll_conf(_PLL3, + clksrc[CLKSRC_PLL3], + pllcfg[_PLL3], + plloff[_PLL3]); + pll4_preserve = stm32mp1_check_pll_conf(_PLL4, + clksrc[CLKSRC_PLL4], + pllcfg[_PLL4], + plloff[_PLL4]); + } + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { - if (i == _PLL4) + if (((i == _PLL3) && pll3_preserve) || + ((i == _PLL4) && pll4_preserve)) { continue; - ret = stm32mp1_pll_stop(priv, i); + } + + ret = stm32mp1_pll_stop(i); if (ret != 0) { return ret; } } /* Configure HSIDIV */ - if (priv->osc[_HSI] != 0U) { - ret = stm32mp1_hsidiv(rcc, priv->osc[_HSI]); + if (stm32mp1_osc[_HSI] != 0U) { + ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); if (ret != 0) { return ret; } - stm32mp1_stgen_config(priv); + stm32mp1_stgen_config(); } /* Select DIV */ /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ - mmio_write_32(rcc + RCC_MPCKDIVR, + mmio_write_32(rcc_base + RCC_MPCKDIVR, clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); - ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc + RCC_AXIDIVR); + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR); if (ret != 0) { return ret; } - ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc + RCC_APB4DIVR); + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR); if (ret != 0) { return ret; } - ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc + RCC_APB5DIVR); + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR); if (ret != 0) { return ret; } - ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc + RCC_APB1DIVR); + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR); if (ret != 0) { return ret; } - ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc + RCC_APB2DIVR); + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR); if (ret != 0) { return ret; } - ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc + RCC_APB3DIVR); + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR); if (ret != 0) { return ret; } /* No ready bit for RTC */ - mmio_write_32(rcc + RCC_RTCDIVR, + mmio_write_32(rcc_base + RCC_RTCDIVR, clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK); /* Configure PLLs source */ - ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL12]); - if (ret != 0) { - return ret; - } - ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL3]); + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]); if (ret != 0) { return ret; } - ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL4]); - if (ret != 0) { - return ret; + if (!pll3_preserve) { + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]); + if (ret != 0) { + return ret; + } + } + + if (!pll4_preserve) { + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]); + if (ret != 0) { + return ret; + } } /* Configure and start PLLs */ @@ -1474,25 +1701,36 @@ int stm32mp1_clk_init(void) uint32_t fracv; uint32_t csg[PLLCSG_NB]; + if (((i == _PLL3) && pll3_preserve) || + ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { + continue; + } + if (!fdt_check_node(plloff[i])) { continue; } + if ((i == _PLL4) && pll4_bootrom) { + /* Set output divider if not done by the Bootrom */ + stm32mp1_pll_config_output(i, pllcfg[i]); + continue; + } + fracv = fdt_read_uint32_default(plloff[i], "frac", 0); - ret = stm32mp1_pll_config(priv, i, pllcfg[i], fracv); + ret = stm32mp1_pll_config(i, pllcfg[i], fracv); if (ret != 0) { return ret; } ret = fdt_read_uint32_array(plloff[i], "csg", csg, (uint32_t)PLLCSG_NB); if (ret == 0) { - stm32mp1_pll_csg(priv, i, csg); + stm32mp1_pll_csg(i, csg); } else if (ret != -FDT_ERR_NOTFOUND) { return ret; } - stm32mp1_pll_start(priv, i); + stm32mp1_pll_start(i); } /* Wait and start PLLs ouptut when ready */ for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { @@ -1500,26 +1738,26 @@ int stm32mp1_clk_init(void) continue; } - ret = stm32mp1_pll_output(priv, i, pllcfg[i][PLLCFG_O]); + ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]); if (ret != 0) { return ret; } } /* Wait LSE ready before to use it */ - if (priv->osc[_LSE] != 0U) { - stm32mp1_lse_wait(rcc); + if (stm32mp1_osc[_LSE] != 0U) { + stm32mp1_lse_wait(); } /* Configure with expected clock source */ - ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_MPU]); + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]); if (ret != 0) { return ret; } - ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_AXI]); + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]); if (ret != 0) { return ret; } - stm32mp1_set_rtcsrc(priv, clksrc[CLKSRC_RTC], lse_css); + stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css); /* Configure PKCK */ pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len); @@ -1527,8 +1765,6 @@ int stm32mp1_clk_init(void) bool ckper_disabled = false; uint32_t j; - priv->pkcs_usb_value = 0; - for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) { uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]); @@ -1536,7 +1772,7 @@ int stm32mp1_clk_init(void) ckper_disabled = true; continue; } - stm32mp1_pkcs_config(priv, pkcs); + stm32mp1_pkcs_config(pkcs); } /* @@ -1546,18 +1782,18 @@ int stm32mp1_clk_init(void) * => deactivated CKPER only after switching clock */ if (ckper_disabled) { - stm32mp1_pkcs_config(priv, CLK_CKPER_DISABLED); + stm32mp1_pkcs_config(CLK_CKPER_DISABLED); } } /* Switch OFF HSI if not found in device-tree */ - if (priv->osc[_HSI] == 0U) { - stm32mp1_hsi_set(rcc, 0); + if (stm32mp1_osc[_HSI] == 0U) { + stm32mp1_hsi_set(false); } - stm32mp1_stgen_config(priv); + stm32mp1_stgen_config(); /* Software Self-Refresh mode (SSR) during DDR initilialization */ - mmio_clrsetbits_32(priv->base + RCC_DDRITFCR, + mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR, RCC_DDRITFCR_DDRCKMOD_MASK, RCC_DDRITFCR_DDRCKMOD_SSR << RCC_DDRITFCR_DDRCKMOD_SHIFT); @@ -1566,47 +1802,26 @@ int stm32mp1_clk_init(void) } static void stm32mp1_osc_clk_init(const char *name, - struct stm32mp1_clk_priv *priv, enum stm32mp_osc_id index) { uint32_t frequency; - priv->osc[index] = 0; - - if (fdt_osc_read_freq(name, &frequency) != 0) { - ERROR("%s frequency request failed\n", name); - panic(); - } else { - priv->osc[index] = frequency; + if (fdt_osc_read_freq(name, &frequency) == 0) { + stm32mp1_osc[index] = frequency; } } static void stm32mp1_osc_init(void) { - struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; enum stm32mp_osc_id i; for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) { - stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], priv, i); + stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i); } } int stm32mp1_clk_probe(void) { - struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data; - - priv->base = fdt_rcc_read_addr(); - if (priv->base == 0U) { - return -EINVAL; - } - - priv->data = &stm32mp1_data; - - if ((priv->data->gate == NULL) || (priv->data->sel == NULL) || - (priv->data->pll == NULL)) { - return -EINVAL; - } - stm32mp1_osc_init(); return 0; diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c index 06c417b10..1aa05bf55 100644 --- a/drivers/st/clk/stm32mp1_clkfunc.c +++ b/drivers/st/clk/stm32mp1_clkfunc.c @@ -23,7 +23,6 @@ const char *stm32mp_osc_node_label[NB_OSC] = { [_HSE] = "clk-hse", [_CSI] = "clk-csi", [_I2S_CKIN] = "i2s_ckin", - [_USB_PHY_48] = "ck_usbo_48m" }; /* diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c index c66c9e707..fcb4cfcfd 100644 --- a/drivers/st/ddr/stm32mp1_ddr_helpers.c +++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c @@ -11,10 +11,14 @@ void ddr_enable_clock(void) { + stm32mp1_clk_rcc_regs_lock(); + mmio_setbits_32(stm32mp_rcc_base() + RCC_DDRITFCR, RCC_DDRITFCR_DDRC1EN | RCC_DDRITFCR_DDRC2EN | RCC_DDRITFCR_DDRPHYCEN | RCC_DDRITFCR_DDRPHYCAPBEN | RCC_DDRITFCR_DDRCAPBEN); + + stm32mp1_clk_rcc_regs_unlock(); } diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c index 59b4351f0..4ae55fcc7 100644 --- a/drivers/st/ddr/stm32mp1_ram.c +++ b/drivers/st/ddr/stm32mp1_ram.c @@ -168,7 +168,7 @@ static int stm32mp1_ddr_setup(void) int ret; struct stm32mp1_ddr_config config; int node, len; - uint32_t tamp_clk_off = 0, uret, idx; + uint32_t uret, idx; void *fdt; #define PARAM(x, y) \ @@ -237,19 +237,6 @@ static int stm32mp1_ddr_setup(void) } } - if (!stm32mp_clk_is_enabled(RTCAPB)) { - tamp_clk_off = 1; - if (stm32mp_clk_enable(RTCAPB) != 0) { - return -EINVAL; - } - } - - if (tamp_clk_off != 0U) { - if (stm32mp_clk_disable(RTCAPB) != 0) { - return -EINVAL; - } - } - /* Disable axidcg clock gating during init */ mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c index 017dd88ff..06de112e9 100644 --- a/drivers/st/mmc/stm32_sdmmc2.c +++ b/drivers/st/mmc/stm32_sdmmc2.c @@ -702,8 +702,6 @@ unsigned long long stm32_sdmmc2_mmc_get_device_size(void) int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) { - int ret; - assert((params != NULL) && ((params->reg_base & MMC_BLOCK_MASK) == 0U) && ((params->bus_width == MMC_BUS_WIDTH_1) || @@ -717,12 +715,7 @@ int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) return -ENOMEM; } - ret = stm32mp_clk_enable(sdmmc2_params.clock_id); - if (ret != 0) { - ERROR("%s: clock %d failed\n", __func__, - sdmmc2_params.clock_id); - return ret; - } + stm32mp_clk_enable(sdmmc2_params.clock_id); stm32mp_reset_assert(sdmmc2_params.reset_id); udelay(2); diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h index 3ba890942..1e0d949ac 100644 --- a/include/drivers/st/stm32mp1_clk.h +++ b/include/drivers/st/stm32mp1_clk.h @@ -11,6 +11,38 @@ int stm32mp1_clk_probe(void); int stm32mp1_clk_init(void); + +bool stm32mp1_rcc_is_secure(void); + +void __stm32mp1_clk_enable(unsigned long id, bool caller_is_secure); +void __stm32mp1_clk_disable(unsigned long id, bool caller_is_secure); + +static inline void stm32mp1_clk_enable_non_secure(unsigned long id) +{ + __stm32mp1_clk_enable(id, false); +} + +static inline void stm32mp1_clk_enable_secure(unsigned long id) +{ + __stm32mp1_clk_enable(id, true); +} + +static inline void stm32mp1_clk_disable_non_secure(unsigned long id) +{ + __stm32mp1_clk_disable(id, false); +} + +static inline void stm32mp1_clk_disable_secure(unsigned long id) +{ + __stm32mp1_clk_disable(id, true); +} + +unsigned int stm32mp1_clk_get_refcount(unsigned long id); + +/* SMP protection on RCC registers access */ +void stm32mp1_clk_rcc_regs_lock(void); +void stm32mp1_clk_rcc_regs_unlock(void); + void stm32mp1_stgen_increment(unsigned long long offset_in_ms); #endif /* STM32MP1_CLK_H */ diff --git a/include/drivers/st/stm32mp1_clkfunc.h b/include/drivers/st/stm32mp1_clkfunc.h index 41b68fdd0..f30393734 100644 --- a/include/drivers/st/stm32mp1_clkfunc.h +++ b/include/drivers/st/stm32mp1_clkfunc.h @@ -18,7 +18,6 @@ enum stm32mp_osc_id { _LSI, _LSE, _I2S_CKIN, - _USB_PHY_48, NB_OSC, _UNKNOWN_OSC_ID = 0xFF }; diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h index fa0b63031..4bbc4dba5 100644 --- a/plat/st/common/include/stm32mp_common.h +++ b/plat/st/common/include/stm32mp_common.h @@ -50,8 +50,8 @@ uint32_t stm32_get_gpio_bank_offset(unsigned int bank); * @id: Target clock ID, ID used in clock DT bindings */ bool stm32mp_clk_is_enabled(unsigned long id); -int stm32mp_clk_enable(unsigned long id); -int stm32mp_clk_disable(unsigned long id); +void stm32mp_clk_enable(unsigned long id); +void stm32mp_clk_disable(unsigned long id); unsigned long stm32mp_clk_get_rate(unsigned long id); /* Initialise the IO layer and register platform IO devices */ diff --git a/plat/st/common/include/stm32mp_shres_helpers.h b/plat/st/common/include/stm32mp_shres_helpers.h new file mode 100644 index 000000000..8b786cc04 --- /dev/null +++ b/plat/st/common/include/stm32mp_shres_helpers.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_SHRES_HELPERS_H +#define STM32MP_SHRES_HELPERS_H + +#include + +#include + +/* + * Shared reference counter: increments by 2 on secure increment + * request, decrements by 2 on secure decrement request. Bit #0 + * is set to 1 on non-secure increment request and reset to 0 on + * non-secure decrement request. The counter initializes to + * either 0, 1 or 2 upon their expect default state. + * Counters saturates once above UINT_MAX / 2. + */ +#define SHREFCNT_NONSECURE_FLAG 0x1UL +#define SHREFCNT_SECURE_STEP 0x2UL +#define SHREFCNT_MAX (UINT32_MAX / 2) + +/* Return 1 if refcnt increments from 0, else return 0 */ +static inline int stm32mp_incr_shrefcnt(unsigned int *refcnt, bool secure) +{ + int rc = !*refcnt; + + if (secure) { + *refcnt += SHREFCNT_SECURE_STEP; + if (*refcnt >= SHREFCNT_MAX) { + panic(); + } + } else { + *refcnt |= SHREFCNT_NONSECURE_FLAG; + } + + return rc; +} + +/* Return 1 if refcnt decrements to 0, else return 0 */ +static inline int stm32mp_decr_shrefcnt(unsigned int *refcnt, bool secure) +{ + int rc = 0; + + if (secure) { + if (*refcnt < SHREFCNT_MAX) { + if (*refcnt < SHREFCNT_SECURE_STEP) { + panic(); + } + *refcnt -= SHREFCNT_SECURE_STEP; + rc = !*refcnt; + } + } else { + rc = (*refcnt == SHREFCNT_NONSECURE_FLAG) ? 1 : 0; + *refcnt &= ~SHREFCNT_NONSECURE_FLAG; + } + + return rc; +} + +static inline int stm32mp_incr_refcnt(unsigned int *refcnt) +{ + return stm32mp_incr_shrefcnt(refcnt, true); +} + +static inline int stm32mp_decr_refcnt(unsigned int *refcnt) +{ + return stm32mp_decr_shrefcnt(refcnt, true); +} + +#endif /* STM32MP_SHRES_HELPERS_H */ diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index 5ab20845c..c7bc39f4e 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -225,9 +225,7 @@ void bl2_el3_plat_arch_setup(void) goto skip_console_init; } - if (stm32mp_clk_enable((unsigned long)dt_uart_info.clock) != 0) { - goto skip_console_init; - } + stm32mp_clk_enable((unsigned long)dt_uart_info.clock); stm32mp_reset_assert((uint32_t)dt_uart_info.reset); udelay(2); diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c index c402c2039..cf8a91eb4 100644 --- a/plat/st/stm32mp1/stm32mp1_context.c +++ b/plat/st/stm32mp1/stm32mp1_context.c @@ -20,26 +20,16 @@ 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 (!stm32mp_clk_is_enabled(RTCAPB)) { - tamp_clk_off = 1; - if (stm32mp_clk_enable(RTCAPB) != 0) { - return -EINVAL; - } - } + stm32mp_clk_enable(RTCAPB); mmio_clrsetbits_32(bkpr_itf_idx, TAMP_BOOT_ITF_MASK, ((interface << 4) | (instance & 0xFU)) << TAMP_BOOT_ITF_SHIFT); - if (tamp_clk_off != 0U) { - if (stm32mp_clk_disable(RTCAPB) != 0) { - return -EINVAL; - } - } + stm32mp_clk_disable(RTCAPB); return 0; } diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index 8d7cea327..f0dc575e2 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #endif diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c index 3262607a5..cf9fa8e69 100644 --- a/plat/st/stm32mp1/stm32mp1_pm.c +++ b/plat/st/stm32mp1/stm32mp1_pm.c @@ -59,7 +59,6 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state) 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 = @@ -75,12 +74,7 @@ static int stm32_pwr_domain_on(u_register_t mpidr) return PSCI_E_INVALID_ADDRESS; } - if (!stm32mp_clk_is_enabled(RTCAPB)) { - tamp_clk_off = 1; - if (stm32mp_clk_enable(RTCAPB) != 0) { - panic(); - } - } + stm32mp_clk_enable(RTCAPB); cntfrq_core0 = read_cntfrq_el0(); @@ -90,11 +84,7 @@ static int stm32_pwr_domain_on(u_register_t mpidr) /* Write magic number in backup register */ mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER); - if (tamp_clk_off != 0U) { - if (stm32mp_clk_disable(RTCAPB) != 0) { - panic(); - } - } + stm32mp_clk_disable(RTCAPB); /* Generate an IT to core 1 */ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP_SECONDARY_CPU); diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c index baa3916d0..ebf1587a6 100644 --- a/plat/st/stm32mp1/stm32mp1_security.c +++ b/plat/st/stm32mp1/stm32mp1_security.c @@ -61,14 +61,8 @@ static void init_tzc400(void) ******************************************************************************/ static void early_init_tzc400(void) { - if (stm32mp_clk_enable(TZC1) != 0) { - ERROR("Cannot enable TZC1 clock\n"); - panic(); - } - if (stm32mp_clk_enable(TZC2) != 0) { - ERROR("Cannot enable TZC2 clock\n"); - panic(); - } + stm32mp_clk_enable(TZC1); + stm32mp_clk_enable(TZC2); tzc400_init(STM32MP1_TZC_BASE); From 6c1e71e1a13c486c524fdf46490b922cad3f088a Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Tue, 12 Feb 2019 19:00:29 +0100 Subject: [PATCH 11/11] stm32mp1: introduce STM32MP1 discovery boards Add the device tree files to support the 2 discovery boards: DK1 & DK2. Change-Id: I90b4797dc69bd0aab1b643a72c932ead48a03c1f Signed-off-by: Yann Gautier --- fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 121 ++++++++++ fdts/stm32mp157a-dk1.dts | 288 +++++++++++++++++++++++ fdts/stm32mp157c-dk2.dts | 16 ++ fdts/stm32mp157cac-pinctrl.dtsi | 78 ++++++ 4 files changed, 503 insertions(+) create mode 100644 fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi create mode 100644 fdts/stm32mp157a-dk1.dts create mode 100644 fdts/stm32mp157c-dk2.dts create mode 100644 fdts/stm32mp157cac-pinctrl.dtsi diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi new file mode 100644 index 000000000..16b8cf623 --- /dev/null +++ b/fdts/stm32mp15-ddr3-1x4Gb-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 DK1/DK2 BOARD configuration + * 1x DDR3L 4Gb, 16-bit, 533MHz. + * Reference used NT5CC256M16DP-DI from NANYA + * + * DDR type / Platform DDR3/3L + * freq 533MHz + * width 16 + * datasheet 0 = MT41J256M16-187 / DDR3-1066 bin G + * DDR density 4 + * timing mode optimized + * Scheduling/QoS options : type = 2 + * address mapping : RBC + * Tc > + 85C : N + */ + +#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.41" +#define DDR_MEM_SPEED 533000 +#define DDR_MEM_SIZE 0x20000000 + +#define DDR_MSTR 0x00041401 +#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 0x00070707 +#define DDR_ADDRMAP2 0x00000000 +#define DDR_ADDRMAP3 0x1F000000 +#define DDR_ADDRMAP4 0x00001F1F +#define DDR_ADDRMAP5 0x06060606 +#define DDR_ADDRMAP6 0x0F060606 +#define DDR_ADDRMAP9 0x00000000 +#define DDR_ADDRMAP10 0x00000000 +#define DDR_ADDRMAP11 0x00000000 +#define DDR_ODTCFG 0x06000600 +#define DDR_ODTMAP 0x00000001 +#define DDR_SCHED 0x00000C01 +#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 0x02100C03 +#define DDR_PCFGQOS1_0 0x00800100 +#define DDR_PCFGWQOS0_0 0x01100C03 +#define DDR_PCFGWQOS1_0 0x01000200 +#define DDR_PCFGR_1 0x00010000 +#define DDR_PCFGW_1 0x00000000 +#define DDR_PCFGQOS0_1 0x02100C03 +#define DDR_PCFGQOS1_1 0x00800040 +#define DDR_PCFGWQOS0_1 0x01100C03 +#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" diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts new file mode 100644 index 000000000..0314171f5 --- /dev/null +++ b/fdts/stm32mp157a-dk1.dts @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2018-2019 - All Rights Reserved + * Author: Alexandre Torgue . + */ + +/dts-v1/; + +#include "stm32mp157c.dtsi" +#include "stm32mp157cac-pinctrl.dtsi" + +/ { + model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; + compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; + + aliases { + serial0 = &uart4; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + +}; + +&clk_hse { + st,digbypass; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + st,main-control-register = <0x04>; + st,vin-control-register = <0xc0>; + st,usb-control-register = <0x20>; + + regulators { + compatible = "st,stpmic1-regulators"; + + ldo1-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo6-supply = <&v3v3>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + v1v8_audio: ldo1 { + regulator-name = "v1v8_audio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + v3v3_hdmi: ldo2 { + regulator-name = "v3v3_hdmi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v2_hdmi: ldo6 { + regulator-name = "v1v2_hdmi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; + }; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + broken-cd; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; + +/* ATF Specific */ +#include +#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" + +/ { + aliases { + gpio0 = &gpioa; + gpio1 = &gpiob; + gpio2 = &gpioc; + gpio3 = &gpiod; + gpio4 = &gpioe; + gpio5 = &gpiof; + gpio6 = &gpiog; + gpio7 = &gpioh; + gpio8 = &gpioi; + gpio25 = &gpioz; + i2c3 = &i2c4; + }; + + soc { + stgen: stgen@5C008000 { + compatible = "st,stm32-stgen"; + reg = <0x5C008000 0x1000>; + status = "okay"; + }; + }; +}; + +/* CLOCK init */ +&rcc { + secure-status = "disabled"; + 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_PLL4P + 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_PLL4P + 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_PLL4P + CLK_FDCAN_PLL4Q + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* 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 = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + cfg = < 1 33 1 16 36 PQR(1,1,1) >; + frac = < 0x1a04 >; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + cfg = < 3 98 5 7 7 PQR(1,1,1) >; + }; +}; diff --git a/fdts/stm32mp157c-dk2.dts b/fdts/stm32mp157c-dk2.dts new file mode 100644 index 000000000..fdcf4c802 --- /dev/null +++ b/fdts/stm32mp157c-dk2.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Alexandre Torgue . + */ + +/dts-v1/; + +#include "stm32mp157a-dk1.dts" + +/ { + model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; + compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; + +}; + diff --git a/fdts/stm32mp157cac-pinctrl.dtsi b/fdts/stm32mp157cac-pinctrl.dtsi new file mode 100644 index 000000000..777f9919d --- /dev/null +++ b/fdts/stm32mp157cac-pinctrl.dtsi @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Alexandre Torgue + */ + +#include "stm32mp157-pinctrl.dtsi" +/ { + soc { + pinctrl: pin-controller@50002000 { + st,package = ; + + 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 = <12>; + gpio-ranges = <&pinctrl 0 128 12>; + }; + }; + + pinctrl_z: pin-controller-z@54004000 { + st,package = ; + + gpioz: gpio@54004000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl_z 0 400 8>; + }; + }; + }; +};