From 1c09c131f67ca926d84733129dd3328eabd31039 Mon Sep 17 00:00:00 2001 From: Christophe Priouzeau Date: Mon, 30 May 2022 09:46:48 +0200 Subject: [PATCH 3/5] ARM-v2021.10-stm32mp-r1-MISC-DRIVERS --- CONTRIBUTING.md | 30 + MAINTAINERS | 1 + Makefile | 10 +- SECURITY.md | 8 + arch/arm/cpu/armv7/stv0991/timer.c | 6 +- arch/arm/include/asm/arch-stm32f4/gpio.h | 15 - arch/arm/include/asm/arch-stm32f7/gpio.h | 12 - arch/arm/include/asm/arch-stm32h7/gpio.h | 12 - .../include/asm/arch-stv0991/stv0991_gpt.h | 4 +- arch/sandbox/dts/test.dts | 42 +- arch/sandbox/include/asm/scmi_test.h | 13 +- board/congatec/cgtqmx8/spl.c | 2 +- board/dhelectronics/dh_stm32mp1/Kconfig | 2 +- board/dhelectronics/dh_stm32mp1/MAINTAINERS | 2 +- board/dhelectronics/dh_stm32mp1/Makefile | 1 - board/dhelectronics/dh_stm32mp1/board.c | 22 +- board/engicam/stm32mp1/Kconfig | 2 +- board/engicam/stm32mp1/stm32mp1.c | 3 - board/raspberrypi/rpi/rpi.c | 2 +- cmd/bind.c | 2 +- cmd/clk.c | 25 +- cmd/onenand.c | 9 +- common/Kconfig | 9 + common/Makefile | 2 +- common/{lcd_simplefb.c => fdt_simplefb.c} | 36 +- common/usb_hub.c | 6 +- configs/dh_imx6_defconfig | 2 + configs/kp_imx6q_tpc_defconfig | 2 + configs/mx53ppd_defconfig | 4 + configs/rpi_0_w_defconfig | 1 + configs/rpi_2_defconfig | 1 + configs/rpi_3_32b_defconfig | 1 + configs/rpi_3_b_plus_defconfig | 1 + configs/rpi_3_defconfig | 1 + configs/rpi_4_32b_defconfig | 1 + configs/rpi_4_defconfig | 1 + configs/rpi_arm64_defconfig | 1 + configs/rpi_defconfig | 1 + configs/sandbox_defconfig | 6 +- configs/stih410-b2260_defconfig | 4 + configs/stv0991_defconfig | 1 - doc/board/st/stm32mp1.rst | 223 ++- doc/device-tree-bindings/arm/arm,scmi.txt | 233 +-- .../memory-controllers/st,stm32mp1-ddr.txt | 69 +- drivers/adc/stm32-adc-core.c | 1 + drivers/adc/stm32-adc.c | 493 ++++- drivers/clk/Kconfig | 17 +- drivers/clk/Makefile | 2 + drivers/clk/clk-composite.c | 9 +- drivers/clk/clk-divider.c | 6 +- drivers/clk/clk-fixed-factor.c | 13 +- drivers/clk/clk-gate.c | 15 +- drivers/clk/clk-mux.c | 13 +- drivers/clk/clk-stm32-core.c | 372 ++++ drivers/clk/clk-stm32-core.h | 153 ++ drivers/clk/clk-stm32mp13.c | 844 ++++++++ drivers/clk/clk-uclass.c | 49 +- drivers/clk/clk.c | 20 +- drivers/clk/clk_fixed_factor.c | 3 + drivers/clk/clk_fixed_rate.c | 3 + drivers/clk/clk_scmi.c | 99 +- drivers/clk/clk_stm32mp1.c | 39 +- drivers/clk/stm32mp13_rcc.h | 1750 +++++++++++++++++ drivers/core/device.c | 2 +- drivers/core/lists.c | 4 +- drivers/core/root.c | 2 +- drivers/demo/demo-uclass.c | 9 +- drivers/dfu/dfu_mtd.c | 22 +- drivers/firmware/scmi/Kconfig | 28 +- drivers/firmware/scmi/Makefile | 5 +- drivers/firmware/scmi/mailbox_agent.c | 16 +- drivers/firmware/scmi/optee_agent.c | 312 +++ drivers/firmware/scmi/sandbox-scmi_agent.c | 255 +-- drivers/firmware/scmi/sandbox-scmi_devices.c | 4 +- drivers/firmware/scmi/scmi_agent-uclass.c | 17 +- drivers/firmware/scmi/smccc_agent.c | 16 +- drivers/gpio/stm32_gpio.c | 129 +- .../gpio.h => drivers/gpio/stm32_gpio_priv.h | 13 +- drivers/i2c/stm32f7_i2c.c | 96 +- drivers/misc/imx8/scu.c | 2 +- drivers/misc/stm32_rcc.c | 6 + drivers/mmc/mmc_write.c | 2 +- drivers/mmc/stm32_sdmmc2.c | 245 ++- drivers/mtd/Kconfig | 7 + drivers/mtd/altera_qspi.c | 3 - drivers/mtd/cfi_mtd.c | 1 - drivers/mtd/mtdconcat.c | 11 - drivers/mtd/mtdcore.c | 8 - drivers/mtd/mtdpart.c | 23 +- drivers/mtd/nand/raw/nand_base.c | 4 - drivers/mtd/nand/raw/stm32_fmc2_nand.c | 9 + drivers/mtd/onenand/onenand_base.c | 3 - drivers/mtd/spi/sf_mtd.c | 1 - drivers/mtd/spi/spi-nor-core.c | 46 +- drivers/mtd/ubi/io.c | 13 - drivers/net/dwc_eth_qos.c | 154 +- drivers/phy/phy-stm32-usbphyc.c | 355 +++- drivers/pinctrl/Kconfig | 8 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-mcp23017.c | 411 ++++ drivers/pinctrl/pinctrl-stmfx.c | 4 + drivers/pinctrl/pinctrl_stm32.c | 103 +- drivers/power/regulator/scmi_regulator.c | 125 +- drivers/power/regulator/stm32-vrefbuf.c | 25 +- drivers/ram/stm32mp1/Makefile | 1 - drivers/ram/stm32mp1/stm32mp1_ddr.c | 69 +- drivers/ram/stm32mp1/stm32mp1_ddr.h | 22 - drivers/ram/stm32mp1/stm32mp1_ddr_regs.h | 66 +- drivers/ram/stm32mp1/stm32mp1_interactive.c | 37 +- drivers/ram/stm32mp1/stm32mp1_ram.c | 238 ++- drivers/ram/stm32mp1/stm32mp1_tests.h | 3 - drivers/ram/stm32mp1/stm32mp1_tuning.c | 1540 --------------- drivers/reboot-mode/reboot-mode-uclass.c | 20 +- drivers/remoteproc/Kconfig | 8 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/rproc-optee.c | 235 +++ drivers/remoteproc/rproc-uclass.c | 16 +- drivers/remoteproc/stm32_copro.c | 118 +- drivers/reset/reset-scmi.c | 7 +- drivers/rng/Kconfig | 9 + drivers/rng/Makefile | 1 + drivers/rng/optee_rng.c | 184 ++ drivers/rng/stm32mp1_rng.c | 61 +- drivers/serial/serial-uclass.c | 2 +- drivers/spi/spi-uclass.c | 12 - drivers/spi/stm32_qspi.c | 27 +- drivers/spi/stm32_spi.c | 224 ++- drivers/tee/optee/core.c | 13 + drivers/tee/optee/optee_msg.h | 12 +- drivers/timer/timer-uclass.c | 2 +- drivers/usb/Kconfig | 2 + drivers/usb/gadget/dwc2_udc_otg.c | 21 +- drivers/usb/gadget/f_dfu.c | 2 + drivers/usb/gadget/gadget_chips.h | 8 + drivers/usb/host/usb-sandbox.c | 28 + drivers/usb/typec/Kconfig | 24 + drivers/usb/typec/Makefile | 5 + drivers/usb/typec/typec-stusb160x.c | 130 ++ drivers/usb/typec/typec-uclass.c | 127 ++ drivers/usb/typec/ucsi/Kconfig | 26 + drivers/usb/typec/ucsi/Makefile | 4 + drivers/usb/typec/ucsi/ucsi-stm32g0.c | 117 ++ drivers/usb/typec/ucsi/ucsi-uclass.c | 393 ++++ drivers/video/Kconfig | 9 + drivers/video/Makefile | 1 + drivers/video/dw_mipi_dsi.c | 1 - drivers/video/rocktech-hx8394.c | 250 +++ drivers/video/stm32/stm32_dsi.c | 1 - drivers/video/stm32/stm32_ltdc.c | 264 ++- drivers/video/video-uclass.c | 14 + env/mmc.c | 10 +- env/onenand.c | 4 +- fs/yaffs2/yaffs_mtdif.c | 1 - include/configs/dh_imx6.h | 2 - include/configs/dh_stm32mp1.h | 15 - include/configs/kp_imx6q_tpc.h | 2 - include/configs/mx53ppd.h | 4 - include/configs/pm9263.h | 1 - include/configs/rpi.h | 1 - include/configs/stih410-b2260.h | 5 - include/configs/stm32f429-discovery.h | 10 - include/configs/stm32f429-evaluation.h | 7 - include/configs/stm32f469-discovery.h | 7 - include/configs/stm32f746-disco.h | 7 - include/configs/stm32h743-disco.h | 5 - include/configs/stm32h743-eval.h | 5 - include/configs/stm32h750-art-pi.h | 5 - include/configs/stm32mp13_common.h | 151 ++ include/configs/stm32mp13_st_common.h | 55 + .../{stm32mp1.h => stm32mp15_common.h} | 66 +- include/configs/stm32mp15_dh_dhsom.h | 31 + include/configs/stm32mp15_st_common.h | 56 + include/dm/lists.h | 3 +- include/dm/pinctrl.h | 2 +- include/dm/uclass-id.h | 2 + include/dt-bindings/clock/stm32mp1-clks.h | 29 + include/dt-bindings/clock/stm32mp13-clks.h | 229 +++ include/dt-bindings/pinctrl/stm32-pinfunc.h | 1 + include/dt-bindings/reset/stm32mp1-resets.h | 14 + include/dt-bindings/reset/stm32mp13-resets.h | 100 + include/dt-bindings/rtc/rtc-stm32.h | 14 + include/dt-bindings/soc/stm32-hdp.h | 108 + include/dt-bindings/soc/stm32mp13-hdp.h | 133 ++ include/fdt_simplefb.h | 5 +- include/fdtdec.h | 5 +- include/linux/mtd/mtd.h | 11 - include/nand.h | 1 - include/netdev.h | 2 +- include/rproc_optee.h | 127 ++ include/scmi_agent.h | 6 +- include/scmi_protocols.h | 57 +- include/spi_flash.h | 9 + include/tee.h | 24 +- include/typec.h | 154 ++ include/ucsi.h | 112 ++ include/video.h | 7 + lib/uuid.c | 2 +- scripts/config_whitelist.txt | 6 - test/cmd/pinmux.c | 4 +- test/dm/nop.c | 2 +- test/dm/ofnode.c | 2 +- test/dm/pci.c | 4 +- test/dm/scmi.c | 132 +- test/dm/test-fdt.c | 2 +- test/py/tests/test_bind.py | 7 + test/py/tests/test_log.py | 8 +- test/py/tests/test_pinmux.py | 40 +- 207 files changed, 10069 insertions(+), 3332 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 SECURITY.md delete mode 100644 arch/arm/include/asm/arch-stm32f4/gpio.h delete mode 100644 arch/arm/include/asm/arch-stm32f7/gpio.h delete mode 100644 arch/arm/include/asm/arch-stm32h7/gpio.h rename common/{lcd_simplefb.c => fdt_simplefb.c} (66%) create mode 100644 drivers/clk/clk-stm32-core.c create mode 100644 drivers/clk/clk-stm32-core.h create mode 100644 drivers/clk/clk-stm32mp13.c create mode 100644 drivers/clk/stm32mp13_rcc.h create mode 100644 drivers/firmware/scmi/optee_agent.c rename arch/arm/include/asm/arch-stm32/gpio.h => drivers/gpio/stm32_gpio_priv.h (87%) create mode 100644 drivers/pinctrl/pinctrl-mcp23017.c delete mode 100644 drivers/ram/stm32mp1/stm32mp1_tuning.c create mode 100644 drivers/remoteproc/rproc-optee.c create mode 100644 drivers/rng/optee_rng.c create mode 100644 drivers/usb/typec/Kconfig create mode 100644 drivers/usb/typec/Makefile create mode 100644 drivers/usb/typec/typec-stusb160x.c create mode 100644 drivers/usb/typec/typec-uclass.c create mode 100644 drivers/usb/typec/ucsi/Kconfig create mode 100644 drivers/usb/typec/ucsi/Makefile create mode 100644 drivers/usb/typec/ucsi/ucsi-stm32g0.c create mode 100644 drivers/usb/typec/ucsi/ucsi-uclass.c create mode 100644 drivers/video/rocktech-hx8394.c delete mode 100644 include/configs/dh_stm32mp1.h create mode 100644 include/configs/stm32mp13_common.h create mode 100644 include/configs/stm32mp13_st_common.h rename include/configs/{stm32mp1.h => stm32mp15_common.h} (76%) create mode 100644 include/configs/stm32mp15_dh_dhsom.h create mode 100644 include/configs/stm32mp15_st_common.h create mode 100644 include/dt-bindings/clock/stm32mp13-clks.h create mode 100644 include/dt-bindings/reset/stm32mp13-resets.h create mode 100644 include/dt-bindings/rtc/rtc-stm32.h create mode 100644 include/dt-bindings/soc/stm32-hdp.h create mode 100644 include/dt-bindings/soc/stm32mp13-hdp.h create mode 100644 include/rproc_optee.h create mode 100644 include/typec.h create mode 100644 include/ucsi.h diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..3d1bacd78a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing guide + +This document serves as a checklist before contributing to this repository. It includes links to read up on if topics are unclear to you. + +This guide mainly focuses on the proper use of Git. + +## 1. Issues + +STM32MPU projects do not activate "Github issues" feature for the time being. If you need to report an issue or question about this project deliverables, you can report them using [ ST Support Center ](https://my.st.com/ols#/ols/newrequest) or [ ST Community MPU Forum ](https://community.st.com/s/topic/0TO0X0000003u2AWAQ/stm32-mpus). + +## 2. Pull Requests + +STMicrolectronics is happy to receive contributions from the community, based on an initial Contributor License Agreement (CLA) procedure. + +* If you are an individual writing original source code and you are sure **you own the intellectual property**, then you need to sign an Individual CLA (https://cla.st.com). +* If you work for a company that wants also to allow you to contribute with your work, your company needs to provide a Corporate CLA (https://cla.st.com) mentioning your GitHub account name. +* If you are not sure that a CLA (Individual or Corporate) has been signed for your GitHub account you can check here (https://cla.st.com). + +Please note that: +* The Corporate CLA will always take precedence over the Individual CLA. +* One CLA submission is sufficient, for any project proposed by STMicroelectronics. + +__How to proceed__ + +* We recommend to fork the project in your GitHub account to further develop your contribution. Please use the latest commit version. +* Please, submit one Pull Request for one new feature or proposal. This will ease the analysis and final merge if accepted. + +__Note__ + +Merge will not be done directly in GitHub but it will need first to follow internal integration process before public deliver in a standard release. The Pull request will stay open until it is merged and delivered. diff --git a/MAINTAINERS b/MAINTAINERS index 5370b55064..75969803d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -438,6 +438,7 @@ F: drivers/power/regulator/stpmic1.c F: drivers/ram/stm32mp1/ F: drivers/remoteproc/stm32_copro.c F: drivers/reset/stm32-reset.c +F: drivers/rng/optee_rng.c F: drivers/rng/stm32mp1_rng.c F: drivers/rtc/stm32_rtc.c F: drivers/serial/serial_stm32.* diff --git a/Makefile b/Makefile index 20c1aa3f58..6203f40cb1 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ VERSION = 2021 PATCHLEVEL = 10 SUBLEVEL = -EXTRAVERSION = +EXTRAVERSION = -stm32mp-r1 NAME = # *DOCUMENTATION* @@ -843,6 +843,7 @@ libs-y += drivers/usb/mtu3/ libs-y += drivers/usb/musb/ libs-y += drivers/usb/musb-new/ libs-y += drivers/usb/phy/ +libs-y += drivers/usb/typec/ libs-y += drivers/usb/ulpi/ ifdef CONFIG_POST libs-y += post/ @@ -1123,6 +1124,13 @@ ifneq ($(CONFIG_DM),y) @echo >&2 "Failure to update may result in board removal." @echo >&2 "See doc/driver-model/migration.rst for more info." @echo >&2 "====================================================" +endif +ifeq ($(CONFIG_STM32MP15x_STM32IMAGE),y) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board uses CONFIG_STM32MP15x_STM32IMAGE for STM32 image" + @echo >&2 "support in TF-A and these configuration is deprecated." + @echo >&2 "Please migrate to FIP support in TF-A instead." + @echo >&2 "====================================================" endif $(call deprecated,CONFIG_WDT,DM watchdog,v2019.10,\ $(CONFIG_WATCHDOG)$(CONFIG_HW_WATCHDOG)) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..4b3e4e6ba5 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,8 @@ +# Report potential product security vulnerabilities +ST places a high priority on security, and our Product Security Incident Response Team (PSIRT) is committed to rapidly addressing potential security vulnerabilities affecting our products. PSIRT's long history and vast experience in security allows ST to perform clear analyses and provide appropriate guidance on mitigations and solutions when applicable. +If you wish to report potential security vulnerabilities regarding our products, **please do not report them through public GitHub issues.** Instead, we encourage you to report them to our ST PSIRT following the process described at: **https://www.st.com/content/st_com/en/security/report-vulnerabilities.html** + +### IMPORTANT - READ CAREFULLY: +STMicroelectronics International N.V., on behalf of itself, its affiliates and subsidiaries, (collectively “ST”) takes all potential security vulnerability reports or other related communications (“Report(s)”) seriously. In order to review Your Report (the terms “You” and “Yours” include your employer, and all affiliates, subsidiaries and related persons or entities) and take actions as deemed appropriate, ST requires that we have the rights and Your permission to do so. +As such, by submitting Your Report to ST, You agree that You have the right to do so, and You grant to ST the rights to use the Report for purposes related to security vulnerability analysis, testing, correction, patching, reporting and any other related purpose or function. +By submitting Your Report, You agree that ST’s [Privacy Policy](https://www.st.com/content/st_com/en/common/privacy-portal.html) applies to all related communications. diff --git a/arch/arm/cpu/armv7/stv0991/timer.c b/arch/arm/cpu/armv7/stv0991/timer.c index 07033acb5c..67764ccf66 100644 --- a/arch/arm/cpu/armv7/stv0991/timer.c +++ b/arch/arm/cpu/armv7/stv0991/timer.c @@ -18,7 +18,7 @@ static struct stv0991_cgu_regs *const stv0991_cgu_regs = \ (struct stv0991_cgu_regs *) (CGU_BASE_ADDR); #define READ_TIMER() (readl(&gpt1_regs_ptr->cnt) & GPT_FREE_RUNNING) -#define GPT_RESOLUTION (CONFIG_STV0991_HZ_CLOCK / CONFIG_STV0991_HZ) +#define GPT_RESOLUTION (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ) DECLARE_GLOBAL_DATA_PTR; @@ -67,7 +67,7 @@ void __udelay(unsigned long usec) { ulong tmo; ulong start = get_timer_masked(); - ulong tenudelcnt = CONFIG_STV0991_HZ_CLOCK / (1000 * 100); + ulong tenudelcnt = CONFIG_SYS_HZ_CLOCK / (1000 * 100); ulong rndoff; rndoff = (usec % 10) ? 1 : 0; @@ -110,5 +110,5 @@ unsigned long long get_ticks(void) */ ulong get_tbclk(void) { - return CONFIG_STV0991_HZ; + return CONFIG_SYS_HZ; } diff --git a/arch/arm/include/asm/arch-stm32f4/gpio.h b/arch/arm/include/asm/arch-stm32f4/gpio.h deleted file mode 100644 index 490f686a85..0000000000 --- a/arch/arm/include/asm/arch-stm32f4/gpio.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2011 - * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com - * - * (C) Copyright 2015 - * Kamil Lulko, - */ - -#ifndef _STM32_GPIO_H_ -#define _STM32_GPIO_H_ - -#include - -#endif /* _STM32_GPIO_H_ */ diff --git a/arch/arm/include/asm/arch-stm32f7/gpio.h b/arch/arm/include/asm/arch-stm32f7/gpio.h deleted file mode 100644 index 21f4e0fd27..0000000000 --- a/arch/arm/include/asm/arch-stm32f7/gpio.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2016, STMicroelectronics - All Rights Reserved - * Author(s): Vikas Manocha, for STMicroelectronics. - */ - -#ifndef _STM32_GPIO_H_ -#define _STM32_GPIO_H_ - -#include - -#endif /* _STM32_GPIO_H_ */ diff --git a/arch/arm/include/asm/arch-stm32h7/gpio.h b/arch/arm/include/asm/arch-stm32h7/gpio.h deleted file mode 100644 index 4f57f175ff..0000000000 --- a/arch/arm/include/asm/arch-stm32h7/gpio.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2017, STMicroelectronics - All Rights Reserved - * Author(s): Patrice Chotard, for STMicroelectronics. - */ - -#ifndef _STM32_GPIO_H_ -#define _STM32_GPIO_H_ - -#include - -#endif /* _STM32_GPIO_H_ */ diff --git a/arch/arm/include/asm/arch-stv0991/stv0991_gpt.h b/arch/arm/include/asm/arch-stv0991/stv0991_gpt.h index cd27472ad7..f1d5667c32 100644 --- a/arch/arm/include/asm/arch-stv0991/stv0991_gpt.h +++ b/arch/arm/include/asm/arch-stv0991/stv0991_gpt.h @@ -36,7 +36,7 @@ struct gpt_regs *const gpt1_regs_ptr = #define GPT_FREE_RUNNING 0xFFFF /* Timer, HZ specific defines */ -#define CONFIG_STV0991_HZ 1000 -#define CONFIG_STV0991_HZ_CLOCK (27*1000*1000)/GPT_PRESCALER_128 +#define CONFIG_SYS_HZ 1000 +#define CONFIG_SYS_HZ_CLOCK ((27 * 1000 * 1000) / GPT_PRESCALER_128) #endif diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 962bdbe556..9cfd76658f 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -557,17 +557,21 @@ compatible = "sandbox,firmware"; }; - sandbox-scmi-agent@0 { + scmi { compatible = "sandbox,scmi-agent"; #address-cells = <1>; #size-cells = <0>; - clk_scmi0: protocol@14 { + protocol@10 { + reg = <0x10>; + }; + + clk_scmi: protocol@14 { reg = <0x14>; #clock-cells = <1>; }; - reset_scmi0: protocol@16 { + reset_scmi: protocol@16 { reg = <0x16>; #reset-cells = <1>; }; @@ -579,35 +583,21 @@ #address-cells = <1>; #size-cells = <0>; - regul0_scmi0: reg@0 { + regul0_scmi: reg@0 { reg = <0>; regulator-name = "sandbox-voltd0"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <3300000>; }; - regul1_scmi0: reg@1 { - reg = <0x1>; - regulator-name = "sandbox-voltd1"; + regul6_scmi: reg@6 { + regulator-name = "sandbox-voltd6"; + voltd-name = "regu6"; regulator-min-microvolt = <1800000>; + regulator-supply = <®ul0_scmi>; }; }; }; }; - - sandbox-scmi-agent@1 { - compatible = "sandbox,scmi-agent"; - #address-cells = <1>; - #size-cells = <0>; - - clk_scmi1: protocol@14 { - reg = <0x14>; - #clock-cells = <1>; - }; - - protocol@10 { - reg = <0x10>; - }; - }; }; pinctrl-gpio { @@ -1364,10 +1354,10 @@ sandbox_scmi { compatible = "sandbox,scmi-devices"; - clocks = <&clk_scmi0 7>, <&clk_scmi0 3>, <&clk_scmi1 1>; - resets = <&reset_scmi0 3>; - regul0-supply = <®ul0_scmi0>; - regul1-supply = <®ul1_scmi0>; + clocks = <&clk_scmi 2>, <&clk_scmi 0>; + resets = <&reset_scmi 3>; + regul0-supply = <®ul0_scmi>; + regul1-supply = <®ul6_scmi>; }; pinctrl { diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h index 2930e686d7..c72ec1e1cb 100644 --- a/arch/sandbox/include/asm/scmi_test.h +++ b/arch/sandbox/include/asm/scmi_test.h @@ -17,7 +17,6 @@ struct sandbox_scmi_service; * @rate: Clock rate in Hertz */ struct sandbox_scmi_clk { - uint id; bool enabled; ulong rate; }; @@ -46,7 +45,6 @@ struct sandbox_scmi_voltd { /** * struct sandbox_scmi_agent - Simulated SCMI service seen by SCMI agent - * @idx: Identifier for the SCMI agent, its index * @clk: Simulated clocks * @clk_count: Simulated clocks array size * @reset: Simulated reset domains @@ -55,7 +53,6 @@ struct sandbox_scmi_voltd { * @voltd_count: Simulated voltage domains array size */ struct sandbox_scmi_agent { - uint idx; struct sandbox_scmi_clk *clk; size_t clk_count; struct sandbox_scmi_reset *reset; @@ -66,12 +63,10 @@ struct sandbox_scmi_agent { /** * struct sandbox_scmi_service - Reference to simutaed SCMI agents/services - * @agent: Pointer to SCMI sandbox agent pointers array - * @agent_count: Number of emulated agents exposed in array @agent. + * @agent: Pointer to SCMI sandbox agent or NULL if not probed */ struct sandbox_scmi_service { - struct sandbox_scmi_agent **agent; - size_t agent_count; + struct sandbox_scmi_agent *agent; }; /** @@ -94,13 +89,13 @@ struct sandbox_scmi_devices { #ifdef CONFIG_SCMI_FIRMWARE /** - * sandbox_scmi_service_context - Get the simulated SCMI services context + * sandbox_scmi_service_ctx - Get the simulated SCMI services context * @return: Reference to backend simulated resources state */ struct sandbox_scmi_service *sandbox_scmi_service_ctx(void); /** - * sandbox_scmi_devices_get_ref - Get references to devices accessed through SCMI + * sandbox_scmi_devices_ctx - Get references to devices accessed through SCMI * @dev: Reference to the test device used get test resources * @return: Reference to the devices probed by the SCMI test */ diff --git a/board/congatec/cgtqmx8/spl.c b/board/congatec/cgtqmx8/spl.c index 2a5d4c1bcd..37b7221c52 100644 --- a/board/congatec/cgtqmx8/spl.c +++ b/board/congatec/cgtqmx8/spl.c @@ -32,7 +32,7 @@ void spl_board_init(void) offset = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "nxp,imx8-pd"); while (offset != -FDT_ERR_NOTFOUND) { lists_bind_fdt(gd->dm_root, offset_to_ofnode(offset), - NULL, true); + NULL, NULL, true); offset = fdt_node_offset_by_compatible(gd->fdt_blob, offset, "nxp,imx8-pd"); } diff --git a/board/dhelectronics/dh_stm32mp1/Kconfig b/board/dhelectronics/dh_stm32mp1/Kconfig index 1fc792c9d1..dc707c2753 100644 --- a/board/dhelectronics/dh_stm32mp1/Kconfig +++ b/board/dhelectronics/dh_stm32mp1/Kconfig @@ -7,7 +7,7 @@ config SYS_VENDOR default "dhelectronics" config SYS_CONFIG_NAME - default "dh_stm32mp1" + default "stm32mp15_dh_dhsom" config ENV_SECT_SIZE default 0x10000 if ENV_IS_IN_SPI_FLASH diff --git a/board/dhelectronics/dh_stm32mp1/MAINTAINERS b/board/dhelectronics/dh_stm32mp1/MAINTAINERS index 9ce21c3ab2..865588f5b8 100644 --- a/board/dhelectronics/dh_stm32mp1/MAINTAINERS +++ b/board/dhelectronics/dh_stm32mp1/MAINTAINERS @@ -6,4 +6,4 @@ F: arch/arm/dts/stm32mp15xx-dhcom* F: board/dhelectronics/dh_stm32mp1/ F: configs/stm32mp15_dhcom_basic_defconfig F: configs/stm32mp15_dhcor_basic_defconfig -F: include/configs/stm32mp1.h +F: include/configs/stm32mp15_dh_dhsom.h diff --git a/board/dhelectronics/dh_stm32mp1/Makefile b/board/dhelectronics/dh_stm32mp1/Makefile index b368b396a4..30db1dee80 100644 --- a/board/dhelectronics/dh_stm32mp1/Makefile +++ b/board/dhelectronics/dh_stm32mp1/Makefile @@ -5,5 +5,4 @@ obj-y += ../../st/common/stpmic1.o board.o -obj-$(CONFIG_SYS_MTDPARTS_RUNTIME) += ../../st/common/stm32mp_mtdparts.o obj-$(CONFIG_SET_DFU_ALT_INFO) += ../../st/common/stm32mp_dfu.o diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c index d7c1857c16..8695b1b6fc 100644 --- a/board/dhelectronics/dh_stm32mp1/board.c +++ b/board/dhelectronics/dh_stm32mp1/board.c @@ -211,34 +211,40 @@ static void board_get_coding_straps(void) ofnode node; int i, ret; + brdcode = 0; + ddr3code = 0; + somcode = 0; + node = ofnode_path("/config"); if (!ofnode_valid(node)) { printf("%s: no /config node?\n", __func__); return; } - brdcode = 0; - ddr3code = 0; - somcode = 0; - ret = gpio_request_list_by_name_nodev(node, "dh,som-coding-gpios", gpio, ARRAY_SIZE(gpio), GPIOD_IS_IN); for (i = 0; i < ret; i++) somcode |= !!dm_gpio_get_value(&(gpio[i])) << i; + gpio_free_list_nodev(gpio, ret); + ret = gpio_request_list_by_name_nodev(node, "dh,ddr3-coding-gpios", gpio, ARRAY_SIZE(gpio), GPIOD_IS_IN); for (i = 0; i < ret; i++) ddr3code |= !!dm_gpio_get_value(&(gpio[i])) << i; + gpio_free_list_nodev(gpio, ret); + ret = gpio_request_list_by_name_nodev(node, "dh,board-coding-gpios", gpio, ARRAY_SIZE(gpio), GPIOD_IS_IN); for (i = 0; i < ret; i++) brdcode |= !!dm_gpio_get_value(&(gpio[i])) << i; + gpio_free_list_nodev(gpio, ret); + printf("Code: SoM:rev=%d,ddr3=%d Board:rev=%d\n", somcode, ddr3code, brdcode); } @@ -590,12 +596,6 @@ static void board_init_fmc2(void) /* board dependent setup after realloc */ int board_init(void) { - /* address of boot parameters */ - gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100; - - if (CONFIG_IS_ENABLED(DM_GPIO_HOG)) - gpio_hog_probe_all(); - board_key_check(); #ifdef CONFIG_DM_REGULATOR @@ -652,7 +652,7 @@ void board_quiesce_devices(void) /* eth init function : weak called in eqos driver */ int board_interface_eth_init(struct udevice *dev, - phy_interface_t interface_type) + phy_interface_t interface_type, ulong rate) { u8 *syscfg; u32 value; diff --git a/board/engicam/stm32mp1/Kconfig b/board/engicam/stm32mp1/Kconfig index c800fd4e60..3802d44cef 100644 --- a/board/engicam/stm32mp1/Kconfig +++ b/board/engicam/stm32mp1/Kconfig @@ -7,6 +7,6 @@ config SYS_VENDOR default "engicam" config SYS_CONFIG_NAME - default "stm32mp1" + default "stm32mp15_common" endif diff --git a/board/engicam/stm32mp1/stm32mp1.c b/board/engicam/stm32mp1/stm32mp1.c index 8bf9c9c67d..20d8603c78 100644 --- a/board/engicam/stm32mp1/stm32mp1.c +++ b/board/engicam/stm32mp1/stm32mp1.c @@ -40,9 +40,6 @@ int checkboard(void) /* board dependent setup after realloc */ int board_init(void) { - /* address of boot parameters */ - gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100; - if (IS_ENABLED(CONFIG_DM_REGULATOR)) regulators_enable_boot_on(_DEBUG); diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 372b26b6f2..b2a17080c3 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -501,7 +501,7 @@ int ft_board_setup(void *blob, struct bd_info *bd) node = fdt_node_offset_by_compatible(blob, -1, "simple-framebuffer"); if (node < 0) - lcd_dt_simplefb_add_node(blob); + fdt_simplefb_add_node(blob); #ifdef CONFIG_EFI_LOADER /* Reserve the spin table */ diff --git a/cmd/bind.c b/cmd/bind.c index 07c629eff7..4d1b7885e6 100644 --- a/cmd/bind.c +++ b/cmd/bind.c @@ -152,7 +152,7 @@ static int bind_by_node_path(const char *path, const char *drv_name) } ofnode = ofnode_path(path); - ret = lists_bind_fdt(parent, ofnode, &dev, false); + ret = lists_bind_fdt(parent, ofnode, &dev, drv, false); if (!dev || ret) { printf("Unable to bind. err:%d\n", ret); diff --git a/cmd/clk.c b/cmd/clk.c index dbbdc31b35..a483fd8981 100644 --- a/cmd/clk.c +++ b/cmd/clk.c @@ -99,20 +99,6 @@ static int do_clk_dump(struct cmd_tbl *cmdtp, int flag, int argc, } #if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(CLK) -struct udevice *clk_lookup(const char *name) -{ - int i = 0; - struct udevice *dev; - - do { - uclass_get_device(UCLASS_CLK, i++, &dev); - if (!strcmp(name, dev->name)) - return dev; - } while (dev); - - return NULL; -} - static int do_clk_setfreq(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -120,16 +106,17 @@ static int do_clk_setfreq(struct cmd_tbl *cmdtp, int flag, int argc, s32 freq; struct udevice *dev; - freq = dectoul(argv[2], NULL); + if (argc != 3) + return CMD_RET_USAGE; - dev = clk_lookup(argv[1]); + freq = dectoul(argv[2], NULL); - if (dev) + if (!uclass_get_device_by_name(UCLASS_CLK, argv[1], &dev)) clk = dev_get_clk_ptr(dev); if (!clk) { printf("clock '%s' not found.\n", argv[1]); - return -EINVAL; + return CMD_RET_FAILURE; } freq = clk_set_rate(clk, freq); @@ -173,7 +160,7 @@ static int do_clk(struct cmd_tbl *cmdtp, int flag, int argc, #ifdef CONFIG_SYS_LONGHELP static char clk_help_text[] = "dump - Print clock frequencies\n" - "setfreq [clk] [freq] - Set clock frequency"; + "clk setfreq [clk] [freq] - Set clock frequency"; #endif U_BOOT_CMD(clk, 4, 1, do_clk, "CLK sub-system", clk_help_text); diff --git a/cmd/onenand.c b/cmd/onenand.c index 852ed5c7b2..592985a7ee 100644 --- a/cmd/onenand.c +++ b/cmd/onenand.c @@ -186,9 +186,7 @@ next: static int onenand_block_erase(u32 start, u32 size, int force) { struct onenand_chip *this = mtd->priv; - struct erase_info instr = { - .callback = NULL, - }; + struct erase_info instr = {}; loff_t ofs; int ret; int blocksize = 1 << this->erase_shift; @@ -219,10 +217,7 @@ static int onenand_block_erase(u32 start, u32 size, int force) static int onenand_block_test(u32 start, u32 size) { struct onenand_chip *this = mtd->priv; - struct erase_info instr = { - .callback = NULL, - .priv = 0, - }; + struct erase_info instr = {}; int blocks; loff_t ofs; diff --git a/common/Kconfig b/common/Kconfig index ee14d3ad5b..6c2d2eda99 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -767,3 +767,12 @@ config SPL_IMAGE_SIGN_INFO Enable image_sign_info helper functions in SPL. endif + +config FDT_SIMPLEFB + bool "FDT tools for simplefb support" + depends on OF_LIBFDT + help + Enable the fdt tools to manage the simple fb nodes in device tree. + These functions can be used by board to indicate to the OS + the presence of the simple frame buffer with associated reserved + memory diff --git a/common/Makefile b/common/Makefile index ae0430c35f..3fb378ffc4 100644 --- a/common/Makefile +++ b/common/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o obj-$(CONFIG_CMD_BEDBUG) += bedbug.o +obj-$(CONFIG_FDT_SIMPLEFB) += fdt_simplefb.o obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o obj-$(CONFIG_MII) += miiphyutil.o obj-$(CONFIG_CMD_MII) += miiphyutil.o @@ -49,7 +50,6 @@ ifndef CONFIG_DM_VIDEO obj-$(CONFIG_LCD) += lcd.o lcd_console.o endif obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o -obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o obj-$(CONFIG_LYNXKDI) += lynxkdi.o obj-$(CONFIG_MENU) += menu.o obj-$(CONFIG_UPDATE_COMMON) += update.o diff --git a/common/lcd_simplefb.c b/common/fdt_simplefb.c similarity index 66% rename from common/lcd_simplefb.c rename to common/fdt_simplefb.c index 1650615cdb..926696455b 100644 --- a/common/lcd_simplefb.c +++ b/common/fdt_simplefb.c @@ -16,7 +16,7 @@ DECLARE_GLOBAL_DATA_PTR; -static int lcd_dt_simplefb_configure_node(void *blob, int off) +static int fdt_simplefb_configure_node(void *blob, int off) { int xsize, ysize; int bpix; /* log2 of bits per pixel */ @@ -58,7 +58,7 @@ static int lcd_dt_simplefb_configure_node(void *blob, int off) xsize * (1 << bpix) / 8, name); } -int lcd_dt_simplefb_add_node(void *blob) +int fdt_simplefb_add_node(void *blob) { static const char compat[] = "simple-framebuffer"; static const char disabled[] = "disabled"; @@ -76,10 +76,10 @@ int lcd_dt_simplefb_add_node(void *blob) if (ret < 0) return -1; - return lcd_dt_simplefb_configure_node(blob, off); + return fdt_simplefb_configure_node(blob, off); } -int lcd_dt_simplefb_enable_existing_node(void *blob) +int fdt_simplefb_enable_existing_node(void *blob) { int off; @@ -87,5 +87,31 @@ int lcd_dt_simplefb_enable_existing_node(void *blob) if (off < 0) return -1; - return lcd_dt_simplefb_configure_node(blob, off); + return fdt_simplefb_configure_node(blob, off); } + +#if CONFIG_IS_ENABLED(DM_VIDEO) +int fdt_simplefb_enable_and_mem_rsv(void *blob) +{ + struct fdt_memory mem; + int ret; + + /* nothing to do when video is not active */ + if (!video_is_active()) + return 0; + + ret = fdt_simplefb_enable_existing_node(blob); + if (ret) + return ret; + + /* nothing to do when the frame buffer is not defined */ + if (gd->video_bottom == gd->video_top) + return 0; + + /* reserved with no-map tag the video buffer */ + mem.start = gd->video_bottom; + mem.end = gd->video_top - 1; + + return fdtdec_add_reserved_memory(blob, "framebuffer", &mem, NULL, true); +} +#endif diff --git a/common/usb_hub.c b/common/usb_hub.c index ba11a188ca..e681f1b307 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -47,6 +47,8 @@ #define HUB_SHORT_RESET_TIME 20 #define HUB_LONG_RESET_TIME 200 +#define HUB_DEBOUNCE_TIMEOUT 2000 + #define PORT_OVERCURRENT_MAX_SCAN_COUNT 3 struct usb_device_scan { @@ -208,10 +210,10 @@ static void usb_hub_power_on(struct usb_hub_device *hub) * will be done based on this value in the USB port loop in * usb_hub_configure() later. */ - hub->connect_timeout = hub->query_delay + 1000; + hub->connect_timeout = hub->query_delay + HUB_DEBOUNCE_TIMEOUT; debug("devnum=%d poweron: query_delay=%d connect_timeout=%d\n", dev->devnum, max(100, (int)pgood_delay), - max(100, (int)pgood_delay) + 1000); + max(100, (int)pgood_delay) + HUB_DEBOUNCE_TIMEOUT); } #if !CONFIG_IS_ENABLED(DM_USB) diff --git a/configs/dh_imx6_defconfig b/configs/dh_imx6_defconfig index ce966420f8..a1206d238e 100644 --- a/configs/dh_imx6_defconfig +++ b/configs/dh_imx6_defconfig @@ -98,6 +98,8 @@ CONFIG_MXC_SPI=y CONFIG_SYSRESET=y CONFIG_SYSRESET_WATCHDOG=y CONFIG_USB=y +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="dh" CONFIG_USB_GADGET_VENDOR_NUM=0x0525 diff --git a/configs/kp_imx6q_tpc_defconfig b/configs/kp_imx6q_tpc_defconfig index 96c1061683..63c7b38755 100644 --- a/configs/kp_imx6q_tpc_defconfig +++ b/configs/kp_imx6q_tpc_defconfig @@ -79,5 +79,7 @@ CONFIG_SYSRESET_WATCHDOG=y CONFIG_IMX_THERMAL=y CONFIG_USB=y # CONFIG_SPL_DM_USB is not set +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y CONFIG_WATCHDOG_TIMEOUT_MSECS=60000 CONFIG_IMX_WATCHDOG=y diff --git a/configs/mx53ppd_defconfig b/configs/mx53ppd_defconfig index 4a8fa34c27..f879133e94 100644 --- a/configs/mx53ppd_defconfig +++ b/configs/mx53ppd_defconfig @@ -69,6 +69,10 @@ CONFIG_SYSRESET=y CONFIG_SYSRESET_WATCHDOG=y CONFIG_USB=y CONFIG_USB_EHCI_MX5=y +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_MCS7830=y +CONFIG_USB_ETHER_SMSC95XX=y CONFIG_DM_VIDEO=y CONFIG_SYS_WHITE_ON_BLACK=y CONFIG_VIDEO_IPUV3=y diff --git a/configs/rpi_0_w_defconfig b/configs/rpi_0_w_defconfig index d17e102052..c217a95ff3 100644 --- a/configs/rpi_0_w_defconfig +++ b/configs/rpi_0_w_defconfig @@ -12,6 +12,7 @@ CONFIG_USE_PREBOOT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_MISC_INIT_R=y +CONFIG_FDT_SIMPLEFB=y CONFIG_SYS_PROMPT="U-Boot> " CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig index 8b8affb777..82968a486d 100644 --- a/configs/rpi_2_defconfig +++ b/configs/rpi_2_defconfig @@ -12,6 +12,7 @@ CONFIG_USE_PREBOOT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_MISC_INIT_R=y +CONFIG_FDT_SIMPLEFB=y CONFIG_SYS_PROMPT="U-Boot> " CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig index b867b7fa7b..9ccffef356 100644 --- a/configs/rpi_3_32b_defconfig +++ b/configs/rpi_3_32b_defconfig @@ -13,6 +13,7 @@ CONFIG_USE_PREBOOT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_MISC_INIT_R=y +CONFIG_FDT_SIMPLEFB=y CONFIG_SYS_PROMPT="U-Boot> " CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y diff --git a/configs/rpi_3_b_plus_defconfig b/configs/rpi_3_b_plus_defconfig index 043665c3d1..8d8e6cd03b 100644 --- a/configs/rpi_3_b_plus_defconfig +++ b/configs/rpi_3_b_plus_defconfig @@ -13,6 +13,7 @@ CONFIG_USE_PREBOOT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_MISC_INIT_R=y +CONFIG_FDT_SIMPLEFB=y CONFIG_SYS_PROMPT="U-Boot> " CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig index 3cebd657da..efd47bf924 100644 --- a/configs/rpi_3_defconfig +++ b/configs/rpi_3_defconfig @@ -13,6 +13,7 @@ CONFIG_USE_PREBOOT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_MISC_INIT_R=y +CONFIG_FDT_SIMPLEFB=y CONFIG_SYS_PROMPT="U-Boot> " CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig index b813d04639..f1c5cb8787 100644 --- a/configs/rpi_4_32b_defconfig +++ b/configs/rpi_4_32b_defconfig @@ -11,6 +11,7 @@ CONFIG_PREBOOT="pci enum; usb start;" # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_MISC_INIT_R=y +CONFIG_FDT_SIMPLEFB=y CONFIG_SYS_PROMPT="U-Boot> " CONFIG_CMD_DFU=y CONFIG_CMD_GPIO=y diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig index de2658ae88..1fe4bb23b4 100644 --- a/configs/rpi_4_defconfig +++ b/configs/rpi_4_defconfig @@ -11,6 +11,7 @@ CONFIG_PREBOOT="pci enum; usb start;" # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_MISC_INIT_R=y +CONFIG_FDT_SIMPLEFB=y CONFIG_SYS_PROMPT="U-Boot> " CONFIG_CMD_DFU=y CONFIG_CMD_GPIO=y diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig index f90107e548..fc0739978f 100644 --- a/configs/rpi_arm64_defconfig +++ b/configs/rpi_arm64_defconfig @@ -11,6 +11,7 @@ CONFIG_PREBOOT="pci enum; usb start;" # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_MISC_INIT_R=y +CONFIG_FDT_SIMPLEFB=y CONFIG_SYS_PROMPT="U-Boot> " CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig index af2189b8fe..59ae0ed4a8 100644 --- a/configs/rpi_defconfig +++ b/configs/rpi_defconfig @@ -12,6 +12,7 @@ CONFIG_USE_PREBOOT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_MISC_INIT_R=y +CONFIG_FDT_SIMPLEFB=y CONFIG_SYS_PROMPT="U-Boot> " CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index ea08a9e5bd..e16026d5f8 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -28,7 +28,6 @@ CONFIG_AUTOBOOT_STOP_STR_CRYPT="$5$rounds=640000$HrpE65IkB8CM5nCL$BKT3QdF98Bo8fJ CONFIG_CONSOLE_RECORD=y CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 CONFIG_PRE_CONSOLE_BUFFER=y -CONFIG_LOG=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_MISC_INIT_F=y CONFIG_STACKPROTECTOR=y @@ -105,6 +104,7 @@ CONFIG_CMD_CRAMFS=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_SQUASHFS=y CONFIG_CMD_MTDPARTS=y +CONFIG_CMD_LOG=y CONFIG_CMD_STACKPROTECTOR_TEST=y CONFIG_MAC_PARTITION=y CONFIG_AMIGA_PARTITION=y @@ -266,6 +266,10 @@ CONFIG_SANDBOX_TIMER=y CONFIG_USB=y CONFIG_USB_EMUL=y CONFIG_USB_KEYBOARD=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_USB_ETHER=y +CONFIG_USB_ETH_CDC=y CONFIG_DM_VIDEO=y CONFIG_VIDEO_COPY=y CONFIG_CONSOLE_ROTATION=y diff --git a/configs/stih410-b2260_defconfig b/configs/stih410-b2260_defconfig index 071dac96af..3ce7ca1eb7 100644 --- a/configs/stih410-b2260_defconfig +++ b/configs/stih410-b2260_defconfig @@ -50,6 +50,10 @@ CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_GENERIC=y CONFIG_USB_DWC3=y +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_MCS7830=y +CONFIG_USB_ETHER_SMSC95XX=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_VENDOR_NUM=0x483 diff --git a/configs/stv0991_defconfig b/configs/stv0991_defconfig index 7fe5f99f4d..f516272844 100644 --- a/configs/stv0991_defconfig +++ b/configs/stv0991_defconfig @@ -10,7 +10,6 @@ CONFIG_ENV_SIZE=0x10000 CONFIG_ENV_OFFSET=0x30000 CONFIG_ENV_SECT_SIZE=0x10000 CONFIG_DEFAULT_DEVICE_TREE="stv0991" -CONFIG_SYS_EXTRA_OPTIONS="STV0991" CONFIG_BOOTDELAY=3 CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n" diff --git a/doc/board/st/stm32mp1.rst b/doc/board/st/stm32mp1.rst index 42bb94148d..09187a2a88 100644 --- a/doc/board/st/stm32mp1.rst +++ b/doc/board/st/stm32mp1.rst @@ -1,41 +1,31 @@ .. SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause .. sectionauthor:: Patrick Delaunay -STM32MP15x boards +STM32MP1xx boards ================= -This is a quick instruction for setup STM32MP15x boards. +This is a quick instruction for setup STMicroelectronics STM32MP1xx boards. Futher information can be found in STMicrolectronics STM32 WIKI_. Supported devices ----------------- -U-Boot supports STMP32MP15x SoCs: +U-Boot supports all the STMicroelectronics MPU with the associated boards - - STM32MP157 - - STM32MP153 - - STM32MP151 + - STMP32MP15x SoCs: -The STM32MP15x is a Cortex-A MPU aimed at various applications. + - STM32MP157 + - STM32MP153 + - STM32MP151 -It features: - - - Dual core Cortex-A7 application core (Single on STM32MP151) - - 2D/3D image composition with GPU (only on STM32MP157) - - Standard memories interface support - - Standard connectivity, widely inherited from the STM32 MCU family - - Comprehensive security support + - STMP32MP13x SoCs: -Each line comes with a security option (cryptography & secure boot) and -a Cortex-A frequency option: - - - A : Cortex-A7 @ 650 MHz - - C : Secure Boot + HW Crypto + Cortex-A7 @ 650 MHz - - D : Cortex-A7 @ 800 MHz - - F : Secure Boot + HW Crypto + Cortex-A7 @ 800 MHz + - STM32MP135 + - STM32MP133 + - STM32MP131 -Everything is supported in Linux but U-Boot is limited to: +Everything is supported in Linux but U-Boot is limited to the boot device: 1. UART 2. SD card/MMC controller (SDMMC) @@ -49,16 +39,63 @@ And the necessary drivers 1. I2C 2. STPMIC1 (PMIC and regulator) 3. Clock, Reset, Sysreset - 4. Fuse + 4. Fuse (BSEC) + 5. OP-TEE + 6. ETH + 7. USB host + 8. WATCHDOG + 9. RNG + 10. RTC + +STM32MP15x +`````````` + +The STM32MP15x is a Cortex-A7 MPU aimed at various applications. + +It features: + + - Dual core Cortex-A7 application core (Single on STM32MP151) + - 2D/3D image composition with GPU (only on STM32MP157) + - Standard memories interface support + - Standard connectivity, widely inherited from the STM32 MCU family + - Comprehensive security support + - Cortex M4 coprocessor + +Each line comes with a security option (cryptography & secure boot) and +a Cortex-A frequency option: + + - A : Cortex-A7 @ 650 MHz + - C : Secure Boot + HW Crypto + Cortex-A7 @ 650 MHz + - D : Cortex-A7 @ 800 MHz + - F : Secure Boot + HW Crypto + Cortex-A7 @ 800 MHz Currently the following boards are supported: + stm32mp157a-dk1.dts + + stm32mp157a-ed1.dts + + stm32mp157a-ev1.dts + stm32mp157c-dk2.dts + stm32mp157c-ed1.dts + stm32mp157c-ev1.dts + + stm32mp157d-dk1.dts + + stm32mp157d-ed1.dts + + stm32mp157d-ev1.dts + + stm32mp157f-dk2.dts + + stm32mp157f-ed1.dts + + stm32mp157f-ev1.dts + stm32mp15xx-dhcor-avenger96.dts +STM32MP13x +`````````` + +The STM32MP13x is a single Cortex-A7 MPU aimed at various applications. + +Currently the following boards are supported: + + + stm32mp135d-dk.dts + + stm32mp135f-dk.dts + + Boot Sequences -------------- @@ -71,12 +108,22 @@ Boot Sequences + +------------------------+-------------------------+--------------+ | | embedded RAM | DDR | +----------+------------------------+-------------------------+--------------+ +| TrustZone| secure monitor | ++----------+------------------------+-------------------------+--------------+ + +The trusted boot chain is recommended with: + +- FSBL = **TF-A BL2** +- Secure monitor = **OP-TEE** +- SSBL = **U-Boot** + +It is the only supported boot chain for STM32MP13x family. The **Trusted** boot chain with TF-A_ ````````````````````````````````````` defconfig_file : - + **stm32mp15_defconfig** (for TF-A_ with FIP support) + + **stm32mp15_defconfig** and **stm32mp13_defconfig** (for TF-A_ with FIP support) + **stm32mp15_trusted_defconfig** (for TF-A_ without FIP support) +-------------+--------------------------+------------+-------+ @@ -98,8 +145,8 @@ TF-A_ (BL2) initialize the DDR and loads the next stage binaries from a FIP file the secure monitor to access to secure resources. + HW_CONFIG: The hardware configuration file = the U-Boot device tree -The **Basic** boot chain with SPL -````````````````````````````````` +The **Basic** boot chain with SPL (for STM32MP15x) +`````````````````````````````````````````````````` defconfig_file : + **stm32mp15_basic_defconfig** @@ -117,37 +164,58 @@ SPL has limited security initialization. U-Boot is running in secure mode and provide a secure monitor to the kernel with only PSCI support (Power State Coordination Interface defined by ARM). -All the STM32MP15x boards supported by U-Boot use the same generic board -stm32mp1 which support all the bootable devices. +.. warning:: This alternate **basic** boot chain with SPL is not supported/promoted by STMicroelectronics to make product. + +Device Tree +----------- -Each board is configured only with the associated device tree. +All the STM32MP15x and STM32MP13x boards supported by U-Boot use the same generic board +stm32mp1 which supports all the bootable devices. -Device Tree Selection ---------------------- +Each STMicroelectronics board is only configured with the associated device tree. -You need to select the appropriate device tree for your board, -the supported device trees for STM32MP15x are: +STM32MP15x device Tree Selection +```````````````````````````````` +The supported device trees for STM32MP15x (stm32mp15_trusted_defconfig and stm32mp15_basic_defconfig) are: + ev1: eval board with pmic stpmic1 (ev1 = mother board + daughter ed1) + + stm32mp157a-ev1 + stm32mp157c-ev1 + + stm32mp157d-ev1 + + stm32mp157f-ev1 + ed1: daughter board with pmic stpmic1 + + stm32mp157a-ed1 + stm32mp157c-ed1 + + stm32mp157d-ed1 + + stm32mp157f-ed1 + dk1: Discovery board + stm32mp157a-dk1 + + stm32mp157d-dk1 + dk2: Discovery board = dk1 with a BT/WiFI combo and a DSI panel + stm32mp157c-dk2 + + stm32mp157f-dk2 + avenger96: Avenger96 board from Arrow Electronics based on DH Elec. DHCOR SoM + stm32mp15xx-dhcor-avenger96 +STM32MP13x device Tree Selection +```````````````````````````````` +The supported device trees for STM32MP13x (stm32mp13_defconfig) are: + ++ dk: Discovery board + + + stm32mp135d-dk + + stm32mp135f-dk + + Build Procedure --------------- @@ -170,6 +238,7 @@ Build Procedure for example: use one output directory for each configuration:: + # export KBUILD_OUTPUT=stm32mp13 # export KBUILD_OUTPUT=stm32mp15 # export KBUILD_OUTPUT=stm32mp15_trusted # export KBUILD_OUTPUT=stm32mp15_basic @@ -184,9 +253,10 @@ Build Procedure with : - - For **trusted** boot mode : **stm32mp15_defconfig** or - stm32mp15_trusted_defconfig - - For basic boot mode: stm32mp15_basic_defconfig + - For **trusted** boot mode : + - For STM32MP13x: **stm32mp13_defconfig** + - For STM32MP15x: **stm32mp15_defconfig** or stm32mp15_trusted_defconfig + - For STM32MP15x basic boot mode: stm32mp15_basic_defconfig 5. Configure the device-tree and build the U-Boot image:: @@ -194,37 +264,42 @@ Build Procedure Examples: - a) trusted boot with FIP on ev1:: + a) trusted boot with FIP on STM32MP15x ev1:: # export KBUILD_OUTPUT=stm32mp15 # make stm32mp15_defconfig # make DEVICE_TREE=stm32mp157c-ev1 all - b) trusted boot without FIP on dk2:: + b) trusted boot on STM32MP13x discovery board:: - # export KBUILD_OUTPUT=stm32mp15_trusted - # make stm32mp15_trusted_defconfig - # make DEVICE_TREE=stm32mp157c-dk2 all + # export KBUILD_OUTPUT=stm32mp13 + # make stm32mp13_defconfig + # make DEVICE_TREE=stm32mp135d-dk all - c) basic boot on ev1:: + DEVICE_TEE selection is optional as stm32mp135f-dk is the default board of the defconfig:: + + # make stm32mp13_defconfig + # make all + + c) basic boot on STM32MP15x ev1:: # export KBUILD_OUTPUT=stm32mp15_basic # make stm32mp15_basic_defconfig # make DEVICE_TREE=stm32mp157c-ev1 all - d) basic boot on ed1:: + d) basic boot on STM32MP15x ed1:: # export KBUILD_OUTPUT=stm32mp15_basic # make stm32mp15_basic_defconfig # make DEVICE_TREE=stm32mp157c-ed1 all - e) basic boot on dk1:: + e) basic boot on STM32MP15x dk1:: # export KBUILD_OUTPUT=stm32mp15_basic # make stm32mp15_basic_defconfig # make DEVICE_TREE=stm32mp157a-dk1 all - f) basic boot on avenger96:: + f) basic boot on STM32MP15x avenger96:: # export KBUILD_OUTPUT=stm32mp15_basic # make stm32mp15_basic_defconfig @@ -235,6 +310,7 @@ Build Procedure So in the output directory (selected by KBUILD_OUTPUT), you can found the needed U-Boot files: + - stm32mp13_defconfig = **u-boot-nodtb.bin** and **u-boot.dtb** - stm32mp15_defconfig = **u-boot-nodtb.bin** and **u-boot.dtb** - stm32mp15_trusted_defconfig = u-boot.stm32 @@ -325,9 +401,9 @@ the boot pin values = BOOT0, BOOT1, BOOT2 | SPI-NAND | 1 | 1 | 1 | +-------------+---------+---------+---------+ -- on the **daugther board ed1 = MB1263** with the switch SW1 -- on **Avenger96** with switch S3 (NOR and SPI-NAND are not applicable) -- on board **DK1/DK2** with the switch SW1 = BOOT0, BOOT2 +- on the STM32MP15x **daugther board ed1 = MB1263** with the switch SW1 +- on STM32MP15x **Avenger96** with switch S3 (NOR and SPI-NAND are not applicable) +- on board STM32MP15x **DK1/DK2** with the switch SW1 = BOOT0, BOOT2 with only 2 pins available (BOOT1 is forced to 0 and NOR not supported), the possible value becomes: @@ -355,7 +431,7 @@ The communication between HOST and board is based on Prepare an SD card ------------------ -The minimal requirements for STMP32MP15x boot up to U-Boot are: +The minimal requirements for STMP32MP15x and STM32MP13x boot up to U-Boot are: - GPT partitioning (with gdisk or with sgdisk) - 2 fsbl partitions, named "fsbl1" and "fsbl2", size at least 256KiB @@ -511,14 +587,25 @@ MAC Address Please read doc/README.enetaddr for the implementation guidelines for mac id usage. Basically, environment has precedence over board specific storage. -For STMicroelectonics board, it is retrieved in STM32MP15x OTP : +For STMicroelectonics board, it is retrieved in: + + - STM32MP15x OTP: - - OTP_57[31:0] = MAC_ADDR[31:0] - - OTP_58[15:0] = MAC_ADDR[47:32] + - OTP_57[31:0] = MAC_ADDR[31:0] + - OTP_58[15:0] = MAC_ADDR[47:32] -To program a MAC address on virgin OTP words above, you can use the fuse command + - STM32MP13x OTP: + + - OTP_57[31:0] = MAC_ADDR0[31:0] + - OTP_58[15:0] = MAC_ADDR0[47:32] + - OTP_58[31:16] = MAC_ADDR1[15:0] + - OTP_59[31:0] = MAC_ADDR1[47:16] + +To program a MAC address on virgin STM32MP15x OTP words above, you can use the fuse command on bank 0 to access to internal OTP and lock them: +In the next example we are using the 2 OTPs used on STM32MP15x. + Prerequisite: check if a MAC address isn't yet programmed in OTP 1) check OTP: their value must be equal to 0:: @@ -532,7 +619,7 @@ Prerequisite: check if a MAC address isn't yet programmed in OTP STM32MP> env print ethaddr ## Error: "ethaddr" not defined -3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 1=locked):: +3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 0x40000000=locked):: STM32MP> fuse sense 0 0x10000039 2 Sensing bank 0: @@ -552,11 +639,11 @@ Example to set mac address "12:34:56:78:9a:bc" 3) Lock OTP:: - STM32MP> fuse prog 0 0x10000039 1 1 + STM32MP> fuse prog 0 0x10000039 0x40000000 0x40000000 STM32MP> fuse sense 0 0x10000039 2 Sensing bank 0: - Word 0x10000039: 00000001 00000001 + Word 0x10000039: 40000000 40000000 4) next REBOOT, in the trace:: @@ -571,8 +658,8 @@ Example to set mac address "12:34:56:78:9a:bc" OTP are protected. It is already done for the board provided by STMicroelectronics. -Coprocessor firmware --------------------- +Coprocessor firmware on STM32MP15x +---------------------------------- U-Boot can boot the coprocessor before the kernel (coprocessor early boot). @@ -645,16 +732,18 @@ On EV1 board, booting from SD card, without OP-TEE_:: dev: eMMC alt: 15 name: mmc1_rootfs layout: RAW_ADDR dev: eMMC alt: 16 name: mmc1_userfs layout: RAW_ADDR dev: MTD alt: 17 name: nor0 layout: RAW_ADDR - dev: MTD alt: 18 name: nand0 layout: RAW_ADDR - dev: VIRT alt: 19 name: OTP layout: RAW_ADDR - dev: VIRT alt: 20 name: PMIC layout: RAW_ADDR + dev: MTD alt: 18 name: nor1 layout: RAW_ADDR + dev: MTD alt: 19 name: nand0 layout: RAW_ADDR + dev: VIRT alt: 20 name: OTP layout: RAW_ADDR + dev: VIRT alt: 21 name: PMIC layout: RAW_ADDR All the supported device are exported for dfu-util tool:: $> dfu-util -l - Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=20, name="PMIC", serial="002700333338511934383330" - Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=19, name="OTP", serial="002700333338511934383330" - Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=18, name="nand0", serial="002700333338511934383330" + Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=21, name="PMIC", serial="002700333338511934383330" + Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=20, name="OTP", serial="002700333338511934383330" + Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=19, name="nand0", serial="002700333338511934383330" + Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=18, name="nor1", serial="002700333338511934383330" Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=17, name="nor0", serial="002700333338511934383330" Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=16, name="mmc1_userfs", serial="002700333338511934383330" Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=15, name="mmc1_rootfs", serial="002700333338511934383330" @@ -676,7 +765,7 @@ All the supported device are exported for dfu-util tool:: You can update the boot device: -- SD card (mmc0) :: +- SD card (mmc0):: $> dfu-util -d 0483:5720 -a 3 -D tf-a-stm32mp157c-ev1.stm32 $> dfu-util -d 0483:5720 -a 4 -D tf-a-stm32mp157c-ev1.stm32 @@ -705,12 +794,12 @@ You can update the boot device: When the board is booting for nor0 or nand0, only the MTD partition on the boot devices are available, for example: -- NOR (nor0 = alt 20) & NAND (nand0 = alt 26) :: +- NOR (nor0 = alt 20, nor1 = alt 26) & NAND (nand0 = alt 27) : $> dfu-util -d 0483:5720 -a 21 -D tf-a-stm32mp157c-ev1.stm32 $> dfu-util -d 0483:5720 -a 22 -D tf-a-stm32mp157c-ev1.stm32 $> dfu-util -d 0483:5720 -a 23 -D fip-stm32mp157c-ev1.bin - $> dfu-util -d 0483:5720 -a 27 -D st-image-weston-openstlinux-weston-stm32mp1_nand_4_256_multivolume.ubi + $> dfu-util -d 0483:5720 -a 28 -D st-image-weston-openstlinux-weston-stm32mp1_nand_4_256_multivolume.ubi - NAND (nand0 = alt 21):: diff --git a/doc/device-tree-bindings/arm/arm,scmi.txt b/doc/device-tree-bindings/arm/arm,scmi.txt index a76124f4a3..0a7886da24 100644 --- a/doc/device-tree-bindings/arm/arm,scmi.txt +++ b/doc/device-tree-bindings/arm/arm,scmi.txt @@ -1,231 +1,2 @@ -System Control and Management Interface (SCMI) Message Protocol ----------------------------------------------------------- - -The SCMI is intended to allow agents such as OSPM to manage various functions -that are provided by the hardware platform it is running on, including power -and performance functions. - -This binding is intended to define the interface the firmware implementing -the SCMI as described in ARM document number ARM DEN 0056A ("ARM System Control -and Management Interface Platform Design Document")[0] provide for OSPM in -the device tree. - -Required properties: - -The scmi node with the following properties shall be under the /firmware/ node. - -- compatible : shall be "arm,scmi" or "arm,scmi-smc" for smc/hvc transports -- mboxes: List of phandle and mailbox channel specifiers. It should contain - exactly one or two mailboxes, one for transmitting messages("tx") - and another optional for receiving the notifications("rx") if - supported. -- shmem : List of phandle pointing to the shared memory(SHM) area as per - generic mailbox client binding. -- #address-cells : should be '1' if the device has sub-nodes, maps to - protocol identifier for a given sub-node. -- #size-cells : should be '0' as 'reg' property doesn't have any size - associated with it. -- arm,smc-id : SMC id required when using smc or hvc transports - -Optional properties: - -- mbox-names: shall be "tx" or "rx" depending on mboxes entries. - -See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details -about the generic mailbox controller and client driver bindings. - -The mailbox is the only permitted method of calling the SCMI firmware. -Mailbox doorbell is used as a mechanism to alert the presence of a -messages and/or notification. - -Each protocol supported shall have a sub-node with corresponding compatible -as described in the following sections. If the platform supports dedicated -communication channel for a particular protocol, the 3 properties namely: -mboxes, mbox-names and shmem shall be present in the sub-node corresponding -to that protocol. - -Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol ------------------------------------------------------------- - -This binding uses the common clock binding[1]. - -Required properties: -- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands. - -Power domain bindings for the power domains based on SCMI Message Protocol ------------------------------------------------------------- - -This binding for the SCMI power domain providers uses the generic power -domain binding[2]. - -Required properties: - - #power-domain-cells : Should be 1. Contains the device or the power - domain ID value used by SCMI commands. - -Regulator bindings for the SCMI Regulator based on SCMI Message Protocol ------------------------------------------------------------- -An SCMI Regulator is permanently bound to a well defined SCMI Voltage Domain, -and should be always positioned as a root regulator. -It does not support any current operation. - -SCMI Regulators are grouped under a 'regulators' node which in turn is a child -of the SCMI Voltage protocol node inside the desired SCMI instance node. - -This binding uses the common regulator binding[6]. - -Required properties: - - reg : shall identify an existent SCMI Voltage Domain. - -Sensor bindings for the sensors based on SCMI Message Protocol --------------------------------------------------------------- -SCMI provides an API to access the various sensors on the SoC. - -Required properties: -- #thermal-sensor-cells: should be set to 1. This property follows the - thermal device tree bindings[3]. - - Valid cell values are raw identifiers (Sensor ID) - as used by the firmware. Refer to platform details - for your implementation for the IDs to use. - -Reset signal bindings for the reset domains based on SCMI Message Protocol ------------------------------------------------------------- - -This binding for the SCMI reset domain providers uses the generic reset -signal binding[5]. - -Required properties: - - #reset-cells : Should be 1. Contains the reset domain ID value used - by SCMI commands. - -SRAM and Shared Memory for SCMI -------------------------------- - -A small area of SRAM is reserved for SCMI communication between application -processors and SCP. - -The properties should follow the generic mmio-sram description found in [4] - -Each sub-node represents the reserved area for SCMI. - -Required sub-node properties: -- reg : The base offset and size of the reserved area with the SRAM -- compatible : should be "arm,scmi-shmem" for Non-secure SRAM based - shared memory - -[0] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt -[2] Documentation/devicetree/bindings/power/power-domain.yaml -[3] Documentation/devicetree/bindings/thermal/thermal.txt -[4] Documentation/devicetree/bindings/sram/sram.yaml -[5] Documentation/devicetree/bindings/reset/reset.txt -[6] Documentation/devicetree/bindings/regulator/regulator.yaml - -Example: - -sram@50000000 { - compatible = "mmio-sram"; - reg = <0x0 0x50000000 0x0 0x10000>; - - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0x0 0x50000000 0x10000>; - - cpu_scp_lpri: scp-shmem@0 { - compatible = "arm,scmi-shmem"; - reg = <0x0 0x200>; - }; - - cpu_scp_hpri: scp-shmem@200 { - compatible = "arm,scmi-shmem"; - reg = <0x200 0x200>; - }; -}; - -mailbox@40000000 { - .... - #mbox-cells = <1>; - reg = <0x0 0x40000000 0x0 0x10000>; -}; - -firmware { - - ... - - scmi { - compatible = "arm,scmi"; - mboxes = <&mailbox 0 &mailbox 1>; - mbox-names = "tx", "rx"; - shmem = <&cpu_scp_lpri &cpu_scp_hpri>; - #address-cells = <1>; - #size-cells = <0>; - - scmi_devpd: protocol@11 { - reg = <0x11>; - #power-domain-cells = <1>; - }; - - scmi_dvfs: protocol@13 { - reg = <0x13>; - #clock-cells = <1>; - }; - - scmi_clk: protocol@14 { - reg = <0x14>; - #clock-cells = <1>; - }; - - scmi_sensors0: protocol@15 { - reg = <0x15>; - #thermal-sensor-cells = <1>; - }; - - scmi_reset: protocol@16 { - reg = <0x16>; - #reset-cells = <1>; - }; - - scmi_voltage: protocol@17 { - reg = <0x17>; - - regulators { - regulator_devX: regulator@0 { - reg = <0x0>; - regulator-max-microvolt = <3300000>; - }; - - regulator_devY: regulator@9 { - reg = <0x9>; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <4200000>; - }; - - ... - }; - }; - }; -}; - -cpu@0 { - ... - reg = <0 0>; - clocks = <&scmi_dvfs 0>; -}; - -hdlcd@7ff60000 { - ... - reg = <0 0x7ff60000 0 0x1000>; - clocks = <&scmi_clk 4>; - power-domains = <&scmi_devpd 1>; - resets = <&scmi_reset 10>; -}; - -thermal-zones { - soc_thermal { - polling-delay-passive = <100>; - polling-delay = <1000>; - /* sensor ID */ - thermal-sensors = <&scmi_sensors0 3>; - ... - }; -}; +See Binding in Linux documentation: +Documentation/devicetree/bindings/firmware/arm,scmi.yaml diff --git a/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt b/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt index ac6a7df432..e6ea8d0ef5 100644 --- a/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt +++ b/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt @@ -3,7 +3,8 @@ ST,stm32mp1 DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL and DDRPHYC) -------------------- Required properties: -------------------- -- compatible : Should be "st,stm32mp1-ddr" +- compatible : Should be "st,stm32mp1-ddr" for STM32MP15x + Should be "st,stm32mp13-ddr" for STM32MP13x - reg : controleur (DDRCTRL) and phy (DDRPHYC) base address - clocks : controller clocks handle - clock-names : associated controller clock names @@ -13,6 +14,8 @@ Required properties: the next attributes are DDR parameters, they are generated by DDR tools included in STM32 Cube tool +They are required only in SPL, when TFABOOT is not activated. + info attributes: ---------------- - st,mem-name : name for DDR configuration, simple string for information @@ -24,7 +27,7 @@ controlleur attributes: ----------------------- - st,ctl-reg : controleur values depending of the DDR type (DDR3/LPDDR2/LPDDR3) - for STM32MP15x: 25 values are requested in this order + for STM32MP15x and STM32MP13x: 25 values are requested in this order MSTR MRCTRL0 MRCTRL1 @@ -53,7 +56,7 @@ controlleur attributes: - st,ctl-timing : controleur values depending of frequency and timing parameter of DDR - for STM32MP15x: 12 values are requested in this order + for STM32MP15x and STM32MP13x: 12 values are requested in this order RFSHTMG DRAMTMG0 DRAMTMG1 @@ -68,7 +71,7 @@ controlleur attributes: ODTCFG - st,ctl-map : controleur values depending of address mapping - for STM32MP15x: 9 values are requested in this order + for STM32MP15x and STM32MP13x: 9 values are requested in this order ADDRMAP1 ADDRMAP2 ADDRMAP3 @@ -99,6 +102,19 @@ controlleur attributes: PCFGWQOS0_1 PCFGWQOS1_1 + for STM32MP13x: 11 values are requested in this order + SCHED + SCHED1 + PERFHPR1 + PERFLPR1 + PERFWR1 + PCFGR_0 + PCFGW_0 + PCFGQOS0_0 + PCFGQOS1_0 + PCFGWQOS0_0 + PCFGWQOS1_0 + phyc attributes: ---------------- - st,phy-reg : phy values depending of the DDR type (DDR3/LPDDR2/LPDDR3) @@ -115,8 +131,19 @@ phyc attributes: DX2GCR DX3GCR + for STM32MP13x: 9 values are requested in this order + PGCR + ACIOCR + DXCCR + DSGCR + DCR + ODTCR + ZQ0CR1 + DX0GCR + DX1GCR + - st,phy-timing : phy values depending of frequency and timing parameter of DDR - for STM32MP15x: 10 values are requested in this order + for STM32MP15x and STM32MP13x: 10 values are requested in this order PTR0 PTR1 PTR2 @@ -128,33 +155,18 @@ phyc attributes: MR2 MR3 -- st,phy-cal : phy cal depending of calibration or tuning of DDR - This parameter is optional; when it is absent the built-in PHY - calibration is done. - for STM32MP15x: 12 values are requested in this order + for STM32MP13x: 6 values are requested in this order DX0DLLCR DX0DQTR DX0DQSTR DX1DLLCR DX1DQTR DX1DQSTR - DX2DLLCR - DX2DQTR - DX2DQSTR - DX3DLLCR - DX3DQTR - DX3DQSTR - Example: / { soc { - u-boot,dm-spl; - ddr: ddr@0x5A003000{ - u-boot,dm-spl; - u-boot,dm-pre-reloc; - compatible = "st,stm32mp1-ddr"; reg = <0x5A003000 0x550 @@ -280,21 +292,6 @@ Example: 0x00000000 /*MR3*/ >; - st,phy-cal = < - 0x40000000 /*DX0DLLCR*/ - 0xFFFFFFFF /*DX0DQTR*/ - 0x3DB02000 /*DX0DQSTR*/ - 0x40000000 /*DX1DLLCR*/ - 0xFFFFFFFF /*DX1DQTR*/ - 0x3DB02000 /*DX1DQSTR*/ - 0x40000000 /*DX2DLLCR*/ - 0xFFFFFFFF /*DX2DQTR*/ - 0x3DB02000 /*DX2DQSTR*/ - 0x40000000 /*DX3DLLCR*/ - 0xFFFFFFFF /*DX3DQTR*/ - 0x3DB02000 /*DX3DQSTR*/ - >; - status = "okay"; }; }; diff --git a/drivers/adc/stm32-adc-core.c b/drivers/adc/stm32-adc-core.c index 6c176961f1..bca030891c 100644 --- a/drivers/adc/stm32-adc-core.c +++ b/drivers/adc/stm32-adc-core.c @@ -201,6 +201,7 @@ err_aclk_disable: static const struct udevice_id stm32_adc_core_ids[] = { { .compatible = "st,stm32h7-adc-core" }, { .compatible = "st,stm32mp1-adc-core" }, + { .compatible = "st,stm32mp13-adc-core" }, {} }; diff --git a/drivers/adc/stm32-adc.c b/drivers/adc/stm32-adc.c index ad8d1a32cd..334a7358e8 100644 --- a/drivers/adc/stm32-adc.c +++ b/drivers/adc/stm32-adc.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,8 @@ #define STM32H7_ADC_SQR1 0x30 #define STM32H7_ADC_DR 0x40 #define STM32H7_ADC_DIFSEL 0xC0 +#define STM32H7_ADC_CALFACT 0xC4 +#define STM32H7_ADC_CALFACT2 0xC8 /* STM32H7_ADC_ISR - bit fields */ #define STM32MP1_VREGREADY BIT(12) @@ -33,13 +36,27 @@ #define STM32H7_ADRDY BIT(0) /* STM32H7_ADC_CR - bit fields */ +#define STM32H7_ADCAL BIT(31) +#define STM32H7_ADCALDIF BIT(30) #define STM32H7_DEEPPWD BIT(29) #define STM32H7_ADVREGEN BIT(28) +#define STM32H7_LINCALRDYW6 BIT(27) +#define STM32H7_LINCALRDYW5 BIT(26) +#define STM32H7_LINCALRDYW4 BIT(25) +#define STM32H7_LINCALRDYW3 BIT(24) +#define STM32H7_LINCALRDYW2 BIT(23) +#define STM32H7_LINCALRDYW1 BIT(22) +#define STM32H7_ADCALLIN BIT(16) #define STM32H7_BOOST BIT(8) +#define STM32H7_ADSTP BIT(4) #define STM32H7_ADSTART BIT(2) #define STM32H7_ADDIS BIT(1) #define STM32H7_ADEN BIT(0) +/* STM32H7_ADC_CALFACT2 - bit fields */ +#define STM32H7_LINCALFACT_SHIFT 0 +#define STM32H7_LINCALFACT_MASK GENMASK(29, 0) + /* STM32H7_ADC_CFGR bit fields */ #define STM32H7_EXTEN GENMASK(11, 10) #define STM32H7_DMNGT GENMASK(1, 0) @@ -47,80 +64,155 @@ /* STM32H7_ADC_SQR1 - bit fields */ #define STM32H7_SQ1_SHIFT 6 +/* STM32H7_ADC_DIFSEL - bit fields */ +#define STM32H7_DIFSEL_SHIFT 0 +#define STM32H7_DIFSEL_MASK GENMASK(19, 0) + /* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */ #define STM32H7_BOOST_CLKRATE 20000000UL +/* STM32MP13 - Registers for each ADC instance */ +#define STM32MP13_ADC_DIFSEL 0xB0 + +/* STM32MP13_ADC_CFGR specific bit fields */ +#define STM32MP13_DMAEN BIT(0) +#define STM32MP13_DMACFG BIT(1) + +/* STM32MP13_ADC_DIFSEL - bit fields */ +#define STM32MP13_DIFSEL_SHIFT 0 +#define STM32MP13_DIFSEL_MASK GENMASK(18, 0) + #define STM32_ADC_CH_MAX 20 /* max number of channels */ #define STM32_ADC_TIMEOUT_US 100000 +/* Number of linear calibration shadow registers / LINCALRDYW control bits */ +#define STM32H7_LINCALFACT_NUM 6 +#define STM32H7_LINCAL_NAME_LEN 32 struct stm32_adc_cfg { + const struct stm32_adc_regspec *regs; unsigned int max_channels; unsigned int num_bits; bool has_vregready; + bool has_boostmode; + bool has_linearcal; + bool has_presel; }; struct stm32_adc { void __iomem *regs; int active_channel; const struct stm32_adc_cfg *cfg; + u32 lincalfact[STM32H7_LINCALFACT_NUM]; }; -static int stm32_adc_stop(struct udevice *dev) +struct stm32_adc_regs { + int reg; + int mask; + int shift; +}; + +struct stm32_adc_regspec { + const struct stm32_adc_regs difsel; +}; + +static const struct stm32_adc_regspec stm32h7_adc_regspec = { + .difsel = { STM32H7_ADC_DIFSEL, STM32H7_DIFSEL_MASK }, +}; + +static const struct stm32_adc_regspec stm32mp13_adc_regspec = { + .difsel = { STM32MP13_ADC_DIFSEL, STM32MP13_DIFSEL_MASK }, +}; +static void stm32_adc_enter_pwr_down(struct udevice *dev) { struct stm32_adc *adc = dev_get_priv(dev); - setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS); clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST); /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD); - adc->active_channel = -1; - - return 0; } -static int stm32_adc_start_channel(struct udevice *dev, int channel) +static int stm32_adc_exit_pwr_down(struct udevice *dev) { - struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev)); struct stm32_adc *adc = dev_get_priv(dev); int ret; u32 val; + /* return immediately if ADC is not in deep power down mode */ + if (!(readl(adc->regs + STM32H7_ADC_CR) & STM32H7_DEEPPWD)) + return 0; + /* Exit deep power down, then enable ADC voltage regulator */ clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD); setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN); - if (common->rate > STM32H7_BOOST_CLKRATE) + if (adc->cfg->has_boostmode && common->rate > STM32H7_BOOST_CLKRATE) setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST); /* Wait for startup time */ if (!adc->cfg->has_vregready) { udelay(20); - } else { - ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val, - val & STM32MP1_VREGREADY, - STM32_ADC_TIMEOUT_US); - if (ret < 0) { - stm32_adc_stop(dev); - dev_err(dev, "Failed to enable vreg: %d\n", ret); - return ret; - } + return 0; } - /* Only use single ended channels */ - writel(0, adc->regs + STM32H7_ADC_DIFSEL); + ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val, + val & STM32MP1_VREGREADY, + STM32_ADC_TIMEOUT_US); + if (ret < 0) { + stm32_adc_enter_pwr_down(dev); + dev_err(dev, "Failed to enable vreg: %d\n", ret); + } + + return ret; +} + +static int stm32_adc_stop(struct udevice *dev) +{ + struct stm32_adc *adc = dev_get_priv(dev); + + setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS); + stm32_adc_enter_pwr_down(dev); + adc->active_channel = -1; + + return 0; +} + +static int stm32_adc_enable(struct udevice *dev) +{ + struct stm32_adc *adc = dev_get_priv(dev); + int ret; + u32 val; - /* Enable ADC, Poll for ADRDY to be set (after adc startup time) */ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADEN); ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val, val & STM32H7_ADRDY, STM32_ADC_TIMEOUT_US); if (ret < 0) { stm32_adc_stop(dev); dev_err(dev, "Failed to enable ADC: %d\n", ret); - return ret; } + return ret; +} + +static int stm32_adc_start_channel(struct udevice *dev, int channel) +{ + struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); + struct stm32_adc *adc = dev_get_priv(dev); + int ret; + + ret = stm32_adc_exit_pwr_down(dev); + if (ret < 0) + return ret; + + /* Only use single ended channels */ + clrbits_le32(adc->regs + adc->cfg->regs->difsel.reg, adc->cfg->regs->difsel.mask); + + ret = stm32_adc_enable(dev); + if (ret) + return ret; + /* Preselect channels */ - writel(uc_pdata->channel_mask, adc->regs + STM32H7_ADC_PCSEL); + if (adc->cfg->has_presel) + writel(uc_pdata->channel_mask, adc->regs + STM32H7_ADC_PCSEL); /* Set sampling time to max value by default */ writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR1); @@ -129,9 +221,11 @@ static int stm32_adc_start_channel(struct udevice *dev, int channel) /* Program regular sequence: chan in SQ1 & len = 0 for one channel */ writel(channel << STM32H7_SQ1_SHIFT, adc->regs + STM32H7_ADC_SQR1); - /* Trigger detection disabled (conversion can be launched in SW) */ - clrbits_le32(adc->regs + STM32H7_ADC_CFGR, STM32H7_EXTEN | - STM32H7_DMNGT); + /* + * Trigger detection disabled (conversion can be launched in SW) + * STM32H7_DMNGT is equivalent to STM32MP13_DMAEN & STM32MP13_DMACFG + */ + clrbits_le32(adc->regs + STM32H7_ADC_CFGR, STM32H7_EXTEN | STM32H7_DMNGT); adc->active_channel = channel; return 0; @@ -159,15 +253,247 @@ static int stm32_adc_channel_data(struct udevice *dev, int channel, *data = readl(adc->regs + STM32H7_ADC_DR); + ret = readl_poll_timeout(adc->regs + STM32H7_ADC_CR, val, + !(val & (STM32H7_ADSTART)), STM32_ADC_TIMEOUT_US); + if (ret) + dev_warn(dev, "conversion stop timed out\n"); + + if (adc->cfg->has_presel) + setbits_le32(adc->regs + STM32H7_ADC_PCSEL, 0); + + return ret; +} + +/** + * Fixed timeout value for ADC calibration. + * worst cases: + * - low clock frequency (0.12 MHz min) + * - maximum prescalers + * Calibration requires: + * - 16384 ADC clock cycle for the linear calibration + * - 20 ADC clock cycle for the offset calibration + * + * Set to 100ms for now + */ +#define STM32H7_ADC_CALIB_TIMEOUT_US 100000 + +static int stm32_adc_run_selfcalib(struct udevice *dev, int do_lincal) +{ + struct stm32_adc *adc = dev_get_priv(dev); + int ret; + u32 val, mask; + + /* + * Select calibration mode: + * - Offset calibration for single ended inputs + * - No linearity calibration. + */ + clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN); + + /* Start calibration, then wait for completion */ + setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCAL); + ret = readl_poll_sleep_timeout(adc->regs + STM32H7_ADC_CR, val, + !(val & STM32H7_ADCAL), 100, + STM32H7_ADC_CALIB_TIMEOUT_US); + if (ret) { + dev_err(dev, "calibration (offset single-ended) failed\n"); + goto out; + } + + /* + * Select calibration mode, then start calibration: + * - Offset calibration for differential input + * - Linearity calibration if not already done. + * will run simultaneously with offset calibration. + */ + mask = STM32H7_ADCALDIF; + if (adc->cfg->has_linearcal && do_lincal) + mask |= STM32H7_ADCALLIN; + setbits_le32(adc->regs + STM32H7_ADC_CR, mask); + + /* Start calibration, then wait for completion */ + setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCAL); + ret = readl_poll_sleep_timeout(adc->regs + STM32H7_ADC_CR, val, + !(val & STM32H7_ADCAL), 100, + STM32H7_ADC_CALIB_TIMEOUT_US); + if (ret) + dev_err(dev, "calibration (offset diff%s) failed\n", + (mask & STM32H7_ADCALLIN) ? "+linear" : ""); + +out: + clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN); + + return ret; +} + +/* Retrieve calibration data from env variables */ +static bool stm32_adc_getenv_selfcalib(struct udevice *dev) +{ + struct stm32_adc *adc = dev_get_priv(dev); + char env_name[STM32H7_LINCAL_NAME_LEN]; + char *env; + int i; + + memset(&adc->lincalfact, 0, STM32H7_LINCALFACT_NUM * sizeof(u32)); + for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) { + /* + * Save ADC linear calibration factors in U-boot environment variables + * Variables are instantiated according to the adc address through + * adcx_ prefix. + */ + snprintf(env_name, sizeof(env_name), "adc%x_lincalfact%d", (u32)adc->regs, i + 1); + env = env_get(env_name); + if (!env) + return false; + adc->lincalfact[i] = env_get_hex(env_name, 0); + } + return true; +} + +/* Save calibration data to env variables */ +static void stm32_adc_save_selfcalib(struct udevice *dev) +{ + struct stm32_adc *adc = dev_get_priv(dev); + char env_name[STM32H7_LINCAL_NAME_LEN]; + int i; + + for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) { + snprintf(env_name, sizeof(env_name), "adc%x_lincalfact%d", (u32)adc->regs, i + 1); + if (env_set_hex(env_name, adc->lincalfact[i])) + dev_warn(dev, "Failed to save %s\n", env_name); + } +} + +/* Read calibration data from ADC */ +static int stm32_adc_read_selfcalib(struct udevice *dev) +{ + struct stm32_adc *adc = dev_get_priv(dev); + u32 lincalrdyw_mask, val; + int i, ret; + + /* Read linearity calibration */ + lincalrdyw_mask = STM32H7_LINCALRDYW6; + for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) { + /* Clear STM32H7_LINCALRDYW[6..1]: transfer calib to CALFACT2 */ + clrbits_le32(adc->regs + STM32H7_ADC_CR, lincalrdyw_mask); + + /* Poll: wait calib data to be ready in CALFACT2 register */ + ret = readl_poll_sleep_timeout(adc->regs + STM32H7_ADC_CR, val, + !(val & lincalrdyw_mask), 100, + STM32_ADC_TIMEOUT_US); + if (ret) { + dev_err(dev, "Failed to read calfact\n"); + return ret; + } + + val = readl(adc->regs + STM32H7_ADC_CALFACT2); + adc->lincalfact[i] = (val & STM32H7_LINCALFACT_MASK); + adc->lincalfact[i] >>= STM32H7_LINCALFACT_SHIFT; + + lincalrdyw_mask >>= 1; + } + return 0; } -static int stm32_adc_chan_of_init(struct udevice *dev) +/* Write calibration data to ADC */ +static int stm32_adc_write_selfcalib(struct udevice *dev) { - struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); struct stm32_adc *adc = dev_get_priv(dev); - u32 chans[STM32_ADC_CH_MAX]; - unsigned int i, num_channels; + u32 lincalrdyw_mask, val; + int i, ret; + + lincalrdyw_mask = STM32H7_LINCALRDYW6; + for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) { + /* + * Write saved calibration data to shadow registers: + * Write CALFACT2, and set LINCALRDYW[6..1] bit to trigger + * data write. Then poll to wait for complete transfer. + */ + val = adc->lincalfact[i] << STM32H7_LINCALFACT_SHIFT; + writel(val, adc->regs + STM32H7_ADC_CALFACT2); + setbits_le32(adc->regs + STM32H7_ADC_CR, lincalrdyw_mask); + ret = readl_poll_sleep_timeout(adc->regs + STM32H7_ADC_CR, val, + val & lincalrdyw_mask, + 100, STM32_ADC_TIMEOUT_US); + if (ret) { + dev_err(dev, "Failed to write calfact\n"); + return ret; + } + + lincalrdyw_mask >>= 1; + } + + return 0; +} + +static int stm32_adc_selfcalib(struct udevice *dev) +{ + struct stm32_adc *adc = dev_get_priv(dev); + int ret; + bool lincal_done = false; + + /* Try to restore linear calibration */ + if (adc->cfg->has_linearcal) + lincal_done = stm32_adc_getenv_selfcalib(dev); + + /* + * Run offset calibration unconditionally. + * Run linear calibration if not already available. + */ + ret = stm32_adc_run_selfcalib(dev, !lincal_done); + if (ret) + return ret; + + ret = stm32_adc_enable(dev); + if (ret) + return ret; + + if (adc->cfg->has_linearcal) { + if (!lincal_done) { + ret = stm32_adc_read_selfcalib(dev); + if (ret) + goto disable; + + stm32_adc_save_selfcalib(dev); + } + + /* + * Always write linear calibration data to ADC. + * This allows to ensure that LINCALRDYWx bits are set when entering kernel + * + * - First boot: + * U-boot performs ADC linear calibration (& offset calibration) + * U-boot reads & saves linear calibration result in environment variable + * (Here LINCALRDYWx have been cleared due to the read procedure) + * U-boot writes back ADC linear calibration to set LINCALRDYWx bits, + * making the linear calibration available for the kernel. + * + * - Subsequent boot (environment set earlier): + * U-boot performs ADC offset calibration only + * U-boot reads ADC linear calibration from environment variable + * and writes back ADC linear calibration. + * + * - All boot: kernel steps + * * Case1: ADC calibrated by U-boot (LINCALRDYWx bits set) + * Read back the linear calibration from ADC registers and save it. + * * Case2: ADC not calibrated by U-boot + * Run a linear calibration and save it. + */ + ret = stm32_adc_write_selfcalib(dev); + if (ret) + goto disable; + } + + return ret; + +disable: + stm32_adc_stop(dev); + return ret; +} + +static int stm32_adc_get_legacy_chan_count(struct udevice *dev) +{ int ret; /* Retrieve single ended channels listed in device tree */ @@ -176,12 +502,16 @@ static int stm32_adc_chan_of_init(struct udevice *dev) dev_err(dev, "can't get st,adc-channels: %d\n", ret); return ret; } - num_channels = ret / sizeof(u32); - if (num_channels > adc->cfg->max_channels) { - dev_err(dev, "too many st,adc-channels: %d\n", num_channels); - return -EINVAL; - } + return (ret / sizeof(u32)); +} + +static int stm32_adc_legacy_chan_init(struct udevice *dev, unsigned int num_channels) +{ + struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); + struct stm32_adc *adc = dev_get_priv(dev); + u32 chans[STM32_ADC_CH_MAX]; + int i, ret; ret = dev_read_u32_array(dev, "st,adc-channels", chans, num_channels); if (ret < 0) { @@ -197,6 +527,69 @@ static int stm32_adc_chan_of_init(struct udevice *dev) uc_pdata->channel_mask |= 1 << chans[i]; } + return ret; +} + +static int stm32_adc_generic_chan_init(struct udevice *dev, unsigned int num_channels) +{ + struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); + struct stm32_adc *adc = dev_get_priv(dev); + ofnode child; + int val, ret; + + ofnode_for_each_subnode(child, dev_ofnode(dev)) { + ret = ofnode_read_u32(child, "reg", &val); + if (ret) { + dev_err(dev, "Missing channel index %d\n", ret); + return ret; + } + + if (val >= adc->cfg->max_channels) { + dev_err(dev, "Invalid channel %d\n", val); + return -EINVAL; + } + + uc_pdata->channel_mask |= 1 << val; + } + + return 0; +} + +static int stm32_adc_chan_of_init(struct udevice *dev) +{ + struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); + struct stm32_adc *adc = dev_get_priv(dev); + unsigned int num_channels; + int ret; + bool legacy = false; + + num_channels = dev_get_child_count(dev); + /* If no channels have been found, fallback to channels legacy properties. */ + if (!num_channels) { + legacy = true; + + ret = stm32_adc_get_legacy_chan_count(dev); + if (!ret) { + dev_err(dev, "No channel found\n"); + return -ENODATA; + } else if (ret < 0) { + return ret; + } + num_channels = ret; + } + + if (num_channels > adc->cfg->max_channels) { + dev_err(dev, "too many st,adc-channels: %d\n", num_channels); + return -EINVAL; + } + + if (legacy) + ret = stm32_adc_legacy_chan_init(dev, num_channels); + else + ret = stm32_adc_generic_chan_init(dev, num_channels); + if (ret < 0) + return ret; + uc_pdata->data_mask = (1 << adc->cfg->num_bits) - 1; uc_pdata->data_format = ADC_DATA_FORMAT_BIN; uc_pdata->data_timeout_us = 100000; @@ -209,7 +602,7 @@ static int stm32_adc_probe(struct udevice *dev) struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev)); struct stm32_adc *adc = dev_get_priv(dev); - int offset; + int offset, ret; offset = dev_read_u32_default(dev, "reg", -ENODATA); if (offset < 0) { @@ -224,7 +617,19 @@ static int stm32_adc_probe(struct udevice *dev) uc_pdata->vdd_microvolts = common->vref_uv; uc_pdata->vss_microvolts = 0; - return stm32_adc_chan_of_init(dev); + ret = stm32_adc_chan_of_init(dev); + if (ret < 0) + return ret; + + ret = stm32_adc_exit_pwr_down(dev); + if (ret < 0) + return ret; + + ret = stm32_adc_selfcalib(dev); + if (ret) + stm32_adc_enter_pwr_down(dev); + + return ret; } static const struct adc_ops stm32_adc_ops = { @@ -234,14 +639,28 @@ static const struct adc_ops stm32_adc_ops = { }; static const struct stm32_adc_cfg stm32h7_adc_cfg = { + .regs = &stm32h7_adc_regspec, .num_bits = 16, .max_channels = STM32_ADC_CH_MAX, + .has_boostmode = true, + .has_linearcal = true, + .has_presel = true, }; static const struct stm32_adc_cfg stm32mp1_adc_cfg = { + .regs = &stm32h7_adc_regspec, .num_bits = 16, .max_channels = STM32_ADC_CH_MAX, .has_vregready = true, + .has_boostmode = true, + .has_linearcal = true, + .has_presel = true, +}; + +static const struct stm32_adc_cfg stm32mp13_adc_cfg = { + .regs = &stm32mp13_adc_regspec, + .num_bits = 12, + .max_channels = STM32_ADC_CH_MAX - 1, }; static const struct udevice_id stm32_adc_ids[] = { @@ -249,6 +668,8 @@ static const struct udevice_id stm32_adc_ids[] = { .data = (ulong)&stm32h7_adc_cfg }, { .compatible = "st,stm32mp1-adc", .data = (ulong)&stm32mp1_adc_cfg }, + { .compatible = "st,stm32mp13-adc", + .data = (ulong)&stm32mp13_adc_cfg }, {} }; diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index baac8d281e..3769e75760 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -147,14 +147,29 @@ config CLK_ZYNQMP This clock driver adds support for clock realted settings for ZynqMP platform. +config CLK_STM32_CORE + bool "Enable RCC clock core driver for STM32MP" + depends on ARCH_STM32MP && CLK + config CLK_STM32MP1 bool "Enable RCC clock driver for STM32MP1" depends on ARCH_STM32MP && CLK - default y + default y if STM32MP15x help Enable the STM32 clock (RCC) driver. Enable support for manipulating STM32MP1's on-SoC clocks. +config CLK_STM32MP13 + bool "Enable RCC clock driver for STM32MP13" + depends on ARCH_STM32MP && CLK + default y if STM32MP13x + select CLK_CCF + select CLK_COMPOSITE_CCF + select CLK_STM32_CORE + help + Enable the STM32 clock (RCC) driver. Enable support for + manipulating STM32MP13's on-SoC clocks. + config CLK_CDCE9XX bool "Enable CDCD9XX clock driver" depends on CLK diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 711ae5bc29..4954ebf220 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -37,8 +37,10 @@ obj-$(CONFIG_CLK_RENESAS) += renesas/ obj-$(CONFIG_CLK_SCMI) += clk_scmi.o obj-$(CONFIG_CLK_SIFIVE) += sifive/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ +obj-$(CONFIG_CLK_STM32_CORE) += clk-stm32-core.o obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o obj-$(CONFIG_CLK_STM32MP1) += clk_stm32mp1.o +obj-$(CONFIG_CLK_STM32MP13) += clk-stm32mp13.o obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_CLK_VEXPRESS_OSC) += clk_vexpress_osc.o obj-$(CONFIG_CLK_ZYNQ) += clk_zynq.o diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index bb5351ebc0..6eb2b8133a 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -4,14 +4,17 @@ * Copyright 2019 NXP */ +#define LOG_CATEGORY UCLASS_CLK + #include -#include -#include +#include #include +#include +#include +#include #include #include #include -#include #include #include "clk.h" diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 9df50a5e72..7e8e62feee 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -9,14 +9,18 @@ * */ +#define LOG_CATEGORY UCLASS_CLK + #include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -190,7 +194,7 @@ static struct clk *_register_divider(struct device *dev, const char *name, if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { if (width + shift > 16) { - pr_warn("divider value exceeds LOWORD field\n"); + dev_warn(dev, "divider value exceeds LOWORD field\n"); return ERR_PTR(-EINVAL); } } diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 8d9823bdab..2a446788e1 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -5,17 +5,22 @@ * * Copyright (C) 2011 Sascha Hauer, Pengutronix */ + +#define LOG_CATEGORY UCLASS_CLK + #include -#include +#include #include +#include +#include +#include #include #include #include -#include -#include -#include "clk.h" #include +#include "clk.h" + #define UBOOT_DM_CLK_IMX_FIXED_FACTOR "ccf_clk_fixed_factor" static ulong clk_factor_recalc_rate(struct clk *clk) diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 006d3b6629..aa40daf3d7 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -7,18 +7,23 @@ * Gated clock implementation */ +#define LOG_CATEGORY UCLASS_CLK + #include -#include -#include +#include +#include #include +#include +#include #include +#include #include #include #include -#include -#include "clk.h" #include +#include "clk.h" + #define UBOOT_DM_CLK_GATE "clk_gate" /** @@ -123,7 +128,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name, if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { if (bit_idx > 15) { - pr_err("gate bit exceeds LOWORD field\n"); + dev_err(dev, "gate bit exceeds LOWORD field\n"); return ERR_PTR(-EINVAL); } } diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index f1becd20d8..b49946fbcd 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -21,17 +21,22 @@ * clock. */ +#define LOG_CATEGORY UCLASS_CLK + #include #include #include +#include +#include +#include #include +#include #include #include #include -#include -#include #include #include + #include "clk.h" #define UBOOT_DM_CLK_CCF_MUX "ccf_clk_mux" @@ -123,7 +128,7 @@ static int clk_mux_set_parent(struct clk *clk, struct clk *parent) index = clk_fetch_parent_index(clk, parent); if (index < 0) { - printf("Could not fetch index\n"); + log_err("Could not fetch index\n"); return index; } @@ -169,7 +174,7 @@ struct clk *clk_hw_register_mux_table(struct device *dev, const char *name, if (clk_mux_flags & CLK_MUX_HIWORD_MASK) { width = fls(mask) - ffs(mask) + 1; if (width + shift > 16) { - pr_err("mux value exceeds LOWORD field\n"); + dev_err(dev, "mux value exceeds LOWORD field\n"); return ERR_PTR(-EINVAL); } } diff --git a/drivers/clk/clk-stm32-core.c b/drivers/clk/clk-stm32-core.c new file mode 100644 index 0000000000..9df1025002 --- /dev/null +++ b/drivers/clk/clk-stm32-core.c @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#define LOG_CATEGORY UCLASS_CLK + +#include +#include +#include +#include +#include +#include +#include "clk-stm32-core.h" + +int stm32_rcc_init(struct device *dev, + const struct stm32_clock_match_data *data, + void __iomem *base) +{ + int i; + + for (i = 0; i < data->num_clocks; i++) { + const struct clock_config *cfg = &data->tab_clocks[i]; + struct clk *clk = ERR_PTR(-ENOENT); + + if (data->check_security) { + if ((*data->check_security)(base, cfg)) + continue; + } + + if (cfg->func) + clk = (*cfg->func)(NULL, data, base, NULL, cfg); + + if (IS_ERR(clk)) { + log_err("%s: failed to register clock %s\n", __func__, + cfg->name); + + return PTR_ERR(clk); + } + + clk->id = cfg->id; + } + + return 0; +} + +static const struct clk_ops *clk_dev_ops(struct udevice *dev) +{ + return (const struct clk_ops *)dev->driver->ops; +} + +static int stm32_clk_enable(struct clk *clk) +{ + const struct clk_ops *ops; + struct clk *clkp = NULL; + + if (!clk->id || clk_get_by_id(clk->id, &clkp)) + return -ENOENT; + + ops = clk_dev_ops(clkp->dev); + if (!ops->enable) + return 0; + + return ops->enable(clkp); +} + +static int stm32_clk_disable(struct clk *clk) +{ + const struct clk_ops *ops; + struct clk *clkp = NULL; + + if (!clk->id || clk_get_by_id(clk->id, &clkp)) + return -ENOENT; + + ops = clk_dev_ops(clkp->dev); + if (!ops->disable) + return 0; + + return ops->disable(clkp); +} + +static ulong stm32_clk_get_rate(struct clk *clk) +{ + const struct clk_ops *ops; + struct clk *clkp = NULL; + + if (!clk->id || clk_get_by_id(clk->id, &clkp)) + return -ENOENT; + + ops = clk_dev_ops(clkp->dev); + if (!ops->get_rate) + return -ENOSYS; + + return ops->get_rate(clkp); +} + +ulong stm32_clk_set_rate(struct clk *clk, unsigned long clk_rate) +{ + const struct clk_ops *ops; + struct clk *clkp = NULL; + + if (!clk->id || clk_get_by_id(clk->id, &clkp)) + return -ENOENT; + + ops = clk_dev_ops(clkp->dev); + if (!ops->set_rate) + return -ENOSYS; + + return ops->set_rate(clkp, clk_rate); +} + +int clk_stm32_get_by_name(const char *name, struct clk **clkp) +{ + struct udevice *dev; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_CLK, &uc); + if (ret) + return ret; + + uclass_foreach_dev(dev, uc) { + if (!strcmp(name, dev->name)) { + struct clk *clk = dev_get_clk_ptr(dev); + + if (clk) { + *clkp = clk; + return 0; + } + break; + } + } + + return -ENOENT; +} + +ulong clk_stm32_get_rate_by_name(const char *name) +{ + struct clk *clk; + + if (!clk_stm32_get_by_name(name, &clk)) + return clk_get_rate(clk); + + return 0; +} + +const struct clk_ops stm32_clk_ops = { + .enable = stm32_clk_enable, + .disable = stm32_clk_disable, + .get_rate = stm32_clk_get_rate, + .set_rate = stm32_clk_set_rate, +}; + +#define UBOOT_DM_CLK_STM32_SETCLR_GATE "clk_stm32_setclr_gate" + +#define RCC_MP_ENCLRR_OFFSET 4 + +static void clk_setclr_gate_endisable(struct clk *clk, int enable) +{ + struct clk_gate *gate = to_clk_gate(clk); + + if (enable) + writel(BIT(gate->bit_idx), gate->reg); + else + writel(BIT(gate->bit_idx), gate->reg + RCC_MP_ENCLRR_OFFSET); +} + +static int clk_setclr_gate_enable(struct clk *clk) +{ + clk_setclr_gate_endisable(clk, 1); + + return 0; +} + +static int clk_setclr_gate_disable(struct clk *clk) +{ + clk_setclr_gate_endisable(clk, 0); + + return 0; +} + +const struct clk_ops clk_stm32_setclr_gate_ops = { + .enable = clk_setclr_gate_enable, + .disable = clk_setclr_gate_disable, + .get_rate = clk_generic_get_rate, +}; + +struct clk *clk_stm32_register_setclr_gate(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock) +{ + struct clk_gate *gate; + struct clk *clk; + int ret; + + /* allocate the gate */ + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + /* struct clk_gate assignments */ + gate->reg = reg; + gate->bit_idx = bit_idx; + gate->flags = clk_gate_flags; + + clk = &gate->clk; + clk->flags = flags; + + ret = clk_register(clk, UBOOT_DM_CLK_STM32_SETCLR_GATE, name, + parent_name); + if (ret) { + kfree(gate); + return ERR_PTR(ret); + } + + return clk; +} + +U_BOOT_DRIVER(clk_stm32_setclr_gate) = { + .name = UBOOT_DM_CLK_STM32_SETCLR_GATE, + .id = UCLASS_CLK, + .ops = &clk_stm32_setclr_gate_ops, +}; + +struct clk *clk_stm32_register_composite(const char *name, + const char * const *parent_names, + int num_parents, + unsigned long flags, + void __iomem *base, + const struct stm32_mux_cfg *pcfg, + const struct stm32_div_cfg *dcfg, + const struct stm32_gate_cfg *gcfg) +{ + struct clk *clk = ERR_PTR(-ENOMEM); + struct clk_mux *mux = NULL; + struct clk_gate *gate = NULL; + struct clk_divider *div = NULL; + struct clk *mux_clk = NULL; + const struct clk_ops *mux_ops = NULL; + struct clk *gate_clk = NULL; + const struct clk_ops *gate_ops = NULL; + struct clk *div_clk = NULL; + const struct clk_ops *div_ops = NULL; + + if (pcfg) { + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + goto fail; + + mux->reg = base + pcfg->reg_off; + mux->shift = pcfg->shift; + mux->mask = BIT(pcfg->width) - 1; + mux->num_parents = pcfg->num_parents; + mux->flags = 0; + mux->parent_names = pcfg->parent_names; + + mux_clk = &mux->clk; + mux_ops = &clk_mux_ops; + } + + if (dcfg) { + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) + goto fail; + + div->reg = base + dcfg->reg_off; + div->shift = dcfg->shift; + div->width = dcfg->width; + div->width = dcfg->width; + div->flags = dcfg->div_flags; + div->table = dcfg->table; + } + + if (gcfg) { + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + goto fail; + + gate->reg = base + gcfg->reg_off; + gate->bit_idx = gcfg->bit_idx; + gate->flags = gcfg->gate_flags; + + gate_clk = &gate->clk; + gate_ops = &clk_gate_ops; + + if (gcfg->set_clr) + gate_ops = &clk_stm32_setclr_gate_ops; + } + + clk = clk_register_composite(NULL, name, + parent_names, num_parents, + mux_clk, mux_ops, + div_clk, div_ops, + gate_clk, gate_ops, + flags); + if (IS_ERR(clk)) + goto fail; + + return clk; + +fail: + kfree(gate); + kfree(div); + kfree(mux); + return ERR_CAST(clk); +} + +struct clk *_clk_stm32_gate_register(struct device *dev, + const struct stm32_clock_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg) +{ + struct stm32_clk_gate_cfg *clk_cfg = cfg->clock_cfg; + const struct stm32_gate_cfg *gate_cfg = &data->gates[clk_cfg->gate_id]; + struct clk *clk; + + if (gate_cfg->set_clr) { + clk = clk_stm32_register_setclr_gate(dev, cfg->name, + cfg->parent_name, + cfg->flags, + base + gate_cfg->reg_off, + gate_cfg->bit_idx, + gate_cfg->gate_flags, + lock); + } else { + clk = clk_register_gate(dev, cfg->name, cfg->parent_name, + cfg->flags, + base + gate_cfg->reg_off, + gate_cfg->bit_idx, + gate_cfg->gate_flags, + lock); + } + return clk; +} + +struct clk * +_clk_stm32_register_composite(struct device *dev, + const struct stm32_clock_match_data *data, + void __iomem *base, spinlock_t *lock, + const struct clock_config *cfg) +{ + struct stm32_clk_composite_cfg *composite = cfg->clock_cfg; + const struct stm32_mux_cfg *mux_cfg = NULL; + const struct stm32_gate_cfg *gate_cfg = NULL; + const struct stm32_div_cfg *div_cfg = NULL; + const char *const *parent_names; + int num_parents; + + if (composite->mux_id != NO_STM32_MUX) { + mux_cfg = &data->muxes[composite->mux_id]; + parent_names = mux_cfg->parent_names; + num_parents = mux_cfg->num_parents; + } else { + parent_names = &cfg->parent_name; + num_parents = 1; + } + + if (composite->gate_id != NO_STM32_GATE) + gate_cfg = &data->gates[composite->gate_id]; + + if (composite->div_id != NO_STM32_DIV) + div_cfg = &data->dividers[composite->div_id]; + + return clk_stm32_register_composite(cfg->name, parent_names, + num_parents, cfg->flags, base, + mux_cfg, div_cfg, gate_cfg); +} diff --git a/drivers/clk/clk-stm32-core.h b/drivers/clk/clk-stm32-core.h new file mode 100644 index 0000000000..9233b02c04 --- /dev/null +++ b/drivers/clk/clk-stm32-core.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) STMicroelectronics 2020 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +struct stm32_clock_match_data; + +struct stm32_mux_cfg { + const char * const *parent_names; + u8 num_parents; + u32 reg_off; + u8 shift; + u8 width; + u8 mux_flags; + u32 *table; +}; + +struct stm32_gate_cfg { + u32 reg_off; + u8 bit_idx; + u8 gate_flags; + u8 set_clr; +}; + +struct stm32_div_cfg { + u32 reg_off; + u8 shift; + u8 width; + u8 div_flags; + const struct clk_div_table *table; +}; + +struct stm32_composite_cfg { + int mux; + int gate; + int div; +}; + +struct clock_config { + unsigned long id; + const char *name; + const char *parent_name; + unsigned long flags; + int sec_id; + void *clock_cfg; + + struct clk *(*func)(struct device *dev, + const struct stm32_clock_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); +}; + +struct stm32_clock_match_data { + unsigned int num_clocks; + const struct clock_config *tab_clocks; + unsigned int maxbinding; + const struct stm32_gate_cfg *gates; + const struct stm32_mux_cfg *muxes; + const struct stm32_div_cfg *dividers; + + int (*check_security)(void __iomem *base, + const struct clock_config *cfg); +}; + +int stm32_rcc_init(struct device *dev, + const struct stm32_clock_match_data *data, + void __iomem *base); + +#define NO_ID 0xFFFF0000 + +#define NO_STM32_MUX -1 +#define NO_STM32_DIV -1 +#define NO_STM32_GATE -1 + +struct clk * +_clk_stm32_gate_register(struct device *dev, + const struct stm32_clock_match_data *data, + void __iomem *base, spinlock_t *lock, + const struct clock_config *cfg); + +struct clk * +_clk_stm32_register_composite(struct device *dev, + const struct stm32_clock_match_data *data, + void __iomem *base, spinlock_t *lock, + const struct clock_config *cfg); + +struct stm32_clk_gate_cfg { + int gate_id; +}; + +#define STM32_GATE(_id, _name, _parent, _flags, _gate_id, _sec_id)\ +{\ + .id = _id,\ + .sec_id = _sec_id,\ + .name = _name,\ + .parent_name = _parent,\ + .flags = _flags,\ + .clock_cfg = &(struct stm32_clk_gate_cfg) {\ + .gate_id = _gate_id,\ + },\ + .func = _clk_stm32_gate_register,\ +} + +struct stm32_clk_composite_cfg { + int gate_id; + int mux_id; + int div_id; +}; + +#define STM32_COMPOSITE(_id, _name, _flags, _sec_id,\ + _gate_id, _mux_id, _div_id)\ +{\ + .id = _id,\ + .name = _name,\ + .sec_id = _sec_id,\ + .flags = _flags,\ + .clock_cfg = &(struct stm32_clk_composite_cfg) {\ + .gate_id = _gate_id,\ + .mux_id = _mux_id,\ + .div_id = _div_id,\ + },\ + .func = _clk_stm32_register_composite,\ +} + +#define STM32_COMPOSITE_NOMUX(_id, _name, _parent, _flags, _sec_id,\ + _gate_id, _div_id)\ +{\ + .id = _id,\ + .name = _name,\ + .parent_name = _parent,\ + .sec_id = _sec_id,\ + .flags = _flags,\ + .clock_cfg = &(struct stm32_clk_composite_cfg) {\ + .gate_id = _gate_id,\ + .mux_id = NO_STM32_MUX,\ + .div_id = _div_id,\ + },\ + .func = _clk_stm32_register_composite,\ +} + +extern const struct clk_ops stm32_clk_ops; +extern const struct clk_ops clk_stm32_setclr_gate_ops; +ulong clk_stm32_get_rate_by_name(const char *name); +int clk_stm32_get_by_name(const char *name, struct clk **clkp); +struct clk *clk_stm32_register_setclr_gate(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock); + diff --git a/drivers/clk/clk-stm32mp13.c b/drivers/clk/clk-stm32mp13.c new file mode 100644 index 0000000000..bd82200e55 --- /dev/null +++ b/drivers/clk/clk-stm32mp13.c @@ -0,0 +1,844 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#define LOG_CATEGORY UCLASS_CLK + +#include +#include +#include +#include +#include +#include +#include + +#include "clk-stm32-core.h" +#include "stm32mp13_rcc.h" + +DECLARE_GLOBAL_DATA_PTR; + +struct stm32mp1_clk_priv { + fdt_addr_t base; +}; + +static const char * const adc12_src[] = { + "pll4_r", "ck_per", "pll3_q" +}; + +static const char * const dcmipp_src[] = { + "ck_axi", "pll2_q", "pll4_p", "ck_per", +}; + +static const char * const eth12_src[] = { + "pll4_p", "pll3_q" +}; + +static const char * const fdcan_src[] = { + "ck_hse", "pll3_q", "pll4_q", "pll4_r" +}; + +static const char * const fmc_src[] = { + "ck_axi", "pll3_r", "pll4_p", "ck_per" +}; + +static const char * const i2c12_src[] = { + "pclk1", "pll4_r", "ck_hsi", "ck_csi" +}; + +static const char * const i2c345_src[] = { + "pclk6", "pll4_r", "ck_hsi", "ck_csi" +}; + +static const char * const lptim1_src[] = { + "pclk1", "pll4_p", "pll3_q", "ck_lse", "ck_lsi", "ck_per" +}; + +static const char * const lptim23_src[] = { + "pclk3", "pll4_q", "ck_per", "ck_lse", "ck_lsi" +}; + +static const char * const lptim45_src[] = { + "pclk3", "pll4_p", "pll3_q", "ck_lse", "ck_lsi", "ck_per" +}; + +static const char * const mco1_src[] = { + "ck_hsi", "ck_hse", "ck_csi", "ck_lsi", "ck_lse" +}; + +static const char * const mco2_src[] = { + "ck_mpu", "ck_axi", "ck_mlahb", "pll4_p", "ck_hse", "ck_hsi" +}; + +static const char * const qspi_src[] = { + "ck_axi", "pll3_r", "pll4_p", "ck_per" +}; + +static const char * const rng1_src[] = { + "ck_csi", "pll4_r", "reserved", "ck_lsi" +}; + +static const char * const saes_src[] = { + "ck_axi", "ck_per", "pll4_r", "ck_lsi" +}; + +static const char * const sai1_src[] = { + "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "pll3_r" +}; + +static const char * const sai2_src[] = { + "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "spdif_ck_symb", "pll3_r" +}; + +static const char * const sdmmc12_src[] = { + "ck_axi", "pll3_r", "pll4_p", "ck_hsi" +}; + +static const char * const spdif_src[] = { + "pll4_p", "pll3_q", "ck_hsi" +}; + +static const char * const spi123_src[] = { + "pll4_p", "pll3_q", "i2s_ckin", "ck_per", "pll3_r" +}; + +static const char * const spi4_src[] = { + "pclk6", "pll4_q", "ck_hsi", "ck_csi", "ck_hse", "i2s_ckin" +}; + +static const char * const spi5_src[] = { + "pclk6", "pll4_q", "ck_hsi", "ck_csi", "ck_hse" +}; + +static const char * const stgen_src[] = { + "ck_hsi", "ck_hse" +}; + +static const char * const usart12_src[] = { + "pclk6", "pll3_q", "ck_hsi", "ck_csi", "pll4_q", "ck_hse" +}; + +static const char * const usart34578_src[] = { + "pclk1", "pll4_q", "ck_hsi", "ck_csi", "ck_hse" +}; + +static const char * const usart6_src[] = { + "pclk2", "pll4_q", "ck_hsi", "ck_csi", "ck_hse" +}; + +static const char * const usbo_src[] = { + "pll4_r", "ck_usbo_48m" +}; + +static const char * const usbphy_src[] = { + "ck_hse", "pll4_r", "clk-hse-div2" +}; + +enum enum_mux_cfg { + MUX_I2C12, + MUX_LPTIM45, + MUX_SPI23, + MUX_UART35, + MUX_UART78, + MUX_ADC1, + MUX_ADC2, + MUX_DCMIPP, + MUX_ETH1, + MUX_ETH2, + MUX_FDCAN, + MUX_FMC, + MUX_I2C3, + MUX_I2C4, + MUX_I2C5, + MUX_LPTIM1, + MUX_LPTIM2, + MUX_LPTIM3, + MUX_QSPI, + MUX_RNG1, + MUX_SAES, + MUX_SAI1, + MUX_SAI2, + MUX_SDMMC1, + MUX_SDMMC2, + MUX_SPDIF, + MUX_SPI1, + MUX_SPI4, + MUX_SPI5, + MUX_STGEN, + MUX_UART1, + MUX_UART2, + MUX_UART4, + MUX_UART6, + MUX_USBO, + MUX_USBPHY, + MUX_MCO1, + MUX_MCO2 +}; + +#define MUX_CFG(id, src, _offset, _shift, _witdh)[id] = {\ + .num_parents = ARRAY_SIZE(src),\ + .parent_names = src,\ + .reg_off = (_offset),\ + .shift = (_shift),\ + .width = (_witdh),\ +} + +static const struct stm32_mux_cfg stm32mp13_muxes[] = { + MUX_CFG(MUX_I2C12, i2c12_src, RCC_I2C12CKSELR, 0, 3), + MUX_CFG(MUX_LPTIM45, lptim45_src, RCC_LPTIM45CKSELR, 0, 3), + MUX_CFG(MUX_SPI23, spi123_src, RCC_SPI2S23CKSELR, 0, 3), + MUX_CFG(MUX_UART35, usart34578_src, RCC_UART35CKSELR, 0, 3), + MUX_CFG(MUX_UART78, usart34578_src, RCC_UART78CKSELR, 0, 3), + MUX_CFG(MUX_ADC1, adc12_src, RCC_ADC12CKSELR, 0, 2), + MUX_CFG(MUX_ADC2, adc12_src, RCC_ADC12CKSELR, 2, 2), + MUX_CFG(MUX_DCMIPP, dcmipp_src, RCC_DCMIPPCKSELR, 0, 2), + MUX_CFG(MUX_ETH1, eth12_src, RCC_ETH12CKSELR, 0, 2), + MUX_CFG(MUX_ETH2, eth12_src, RCC_ETH12CKSELR, 8, 2), + MUX_CFG(MUX_FDCAN, fdcan_src, RCC_FDCANCKSELR, 0, 2), + MUX_CFG(MUX_FMC, fmc_src, RCC_FMCCKSELR, 0, 2), + MUX_CFG(MUX_I2C3, i2c345_src, RCC_I2C345CKSELR, 0, 3), + MUX_CFG(MUX_I2C4, i2c345_src, RCC_I2C345CKSELR, 3, 3), + MUX_CFG(MUX_I2C5, i2c345_src, RCC_I2C345CKSELR, 6, 3), + MUX_CFG(MUX_LPTIM1, lptim1_src, RCC_LPTIM1CKSELR, 0, 3), + MUX_CFG(MUX_LPTIM2, lptim23_src, RCC_LPTIM23CKSELR, 0, 3), + MUX_CFG(MUX_LPTIM3, lptim23_src, RCC_LPTIM23CKSELR, 3, 3), + MUX_CFG(MUX_MCO1, mco1_src, RCC_MCO1CFGR, 0, 3), + MUX_CFG(MUX_MCO2, mco2_src, RCC_MCO2CFGR, 0, 3), + MUX_CFG(MUX_QSPI, qspi_src, RCC_QSPICKSELR, 0, 2), + MUX_CFG(MUX_RNG1, rng1_src, RCC_RNG1CKSELR, 0, 2), + MUX_CFG(MUX_SAES, saes_src, RCC_SAESCKSELR, 0, 2), + MUX_CFG(MUX_SAI1, sai1_src, RCC_SAI1CKSELR, 0, 3), + MUX_CFG(MUX_SAI2, sai2_src, RCC_SAI2CKSELR, 0, 3), + MUX_CFG(MUX_SDMMC1, sdmmc12_src, RCC_SDMMC12CKSELR, 0, 3), + MUX_CFG(MUX_SDMMC2, sdmmc12_src, RCC_SDMMC12CKSELR, 3, 3), + MUX_CFG(MUX_SPDIF, spdif_src, RCC_SPDIFCKSELR, 0, 2), + MUX_CFG(MUX_SPI1, spi123_src, RCC_SPI2S1CKSELR, 0, 3), + MUX_CFG(MUX_SPI4, spi4_src, RCC_SPI45CKSELR, 0, 3), + MUX_CFG(MUX_SPI5, spi5_src, RCC_SPI45CKSELR, 3, 3), + MUX_CFG(MUX_STGEN, stgen_src, RCC_STGENCKSELR, 0, 2), + MUX_CFG(MUX_UART1, usart12_src, RCC_UART12CKSELR, 0, 3), + MUX_CFG(MUX_UART2, usart12_src, RCC_UART12CKSELR, 3, 3), + MUX_CFG(MUX_UART4, usart34578_src, RCC_UART4CKSELR, 0, 3), + MUX_CFG(MUX_UART6, usart6_src, RCC_UART6CKSELR, 0, 3), + MUX_CFG(MUX_USBO, usbo_src, RCC_USBCKSELR, 4, 1), + MUX_CFG(MUX_USBPHY, usbphy_src, RCC_USBCKSELR, 0, 2), +}; + +enum enum_gate_cfg { + GATE_ZERO, /* reserved for no gate */ + GATE_MCO1, + GATE_MCO2, + GATE_DBGCK, + GATE_TRACECK, + GATE_DDRC1, + GATE_DDRC1LP, + GATE_DDRPHYC, + GATE_DDRPHYCLP, + GATE_DDRCAPB, + GATE_DDRCAPBLP, + GATE_AXIDCG, + GATE_DDRPHYCAPB, + GATE_DDRPHYCAPBLP, + GATE_TIM2, + GATE_TIM3, + GATE_TIM4, + GATE_TIM5, + GATE_TIM6, + GATE_TIM7, + GATE_LPTIM1, + GATE_SPI2, + GATE_SPI3, + GATE_USART3, + GATE_UART4, + GATE_UART5, + GATE_UART7, + GATE_UART8, + GATE_I2C1, + GATE_I2C2, + GATE_SPDIF, + GATE_TIM1, + GATE_TIM8, + GATE_SPI1, + GATE_USART6, + GATE_SAI1, + GATE_SAI2, + GATE_DFSDM, + GATE_ADFSDM, + GATE_FDCAN, + GATE_LPTIM2, + GATE_LPTIM3, + GATE_LPTIM4, + GATE_LPTIM5, + GATE_VREF, + GATE_DTS, + GATE_PMBCTRL, + GATE_HDP, + GATE_SYSCFG, + GATE_DCMIPP, + GATE_DDRPERFM, + GATE_IWDG2APB, + GATE_USBPHY, + GATE_STGENRO, + GATE_LTDC, + GATE_TZC, + GATE_ETZPC, + GATE_IWDG1APB, + GATE_BSEC, + GATE_STGENC, + GATE_USART1, + GATE_USART2, + GATE_SPI4, + GATE_SPI5, + GATE_I2C3, + GATE_I2C4, + GATE_I2C5, + GATE_TIM12, + GATE_TIM13, + GATE_TIM14, + GATE_TIM15, + GATE_TIM16, + GATE_TIM17, + GATE_DMA1, + GATE_DMA2, + GATE_DMAMUX1, + GATE_DMA3, + GATE_DMAMUX2, + GATE_ADC1, + GATE_ADC2, + GATE_USBO, + GATE_TSC, + GATE_GPIOA, + GATE_GPIOB, + GATE_GPIOC, + GATE_GPIOD, + GATE_GPIOE, + GATE_GPIOF, + GATE_GPIOG, + GATE_GPIOH, + GATE_GPIOI, + GATE_PKA, + GATE_SAES, + GATE_CRYP1, + GATE_HASH1, + GATE_RNG1, + GATE_BKPSRAM, + GATE_AXIMC, + GATE_MCE, + GATE_ETH1CK, + GATE_ETH1TX, + GATE_ETH1RX, + GATE_ETH1MAC, + GATE_FMC, + GATE_QSPI, + GATE_SDMMC1, + GATE_SDMMC2, + GATE_CRC1, + GATE_USBH, + GATE_ETH2CK, + GATE_ETH2TX, + GATE_ETH2RX, + GATE_ETH2MAC, + GATE_ETH1STP, + GATE_ETH2STP, + GATE_MDMA +}; + +#define GATE_CFG(id, _offset, _bit_idx, _offset_clr)[id] = {\ + .reg_off = (_offset),\ + .bit_idx = (_bit_idx),\ + .set_clr = (_offset_clr),\ +} + +static const struct stm32_gate_cfg stm32mp13_gates[] = { + GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 12, 0), + GATE_CFG(GATE_MCO2, RCC_MCO2CFGR, 12, 0), + GATE_CFG(GATE_DBGCK, RCC_DBGCFGR, 8, 0), + GATE_CFG(GATE_TRACECK, RCC_DBGCFGR, 9, 0), + GATE_CFG(GATE_DDRC1, RCC_DDRITFCR, 0, 0), + GATE_CFG(GATE_DDRC1LP, RCC_DDRITFCR, 1, 0), + GATE_CFG(GATE_DDRPHYC, RCC_DDRITFCR, 4, 0), + GATE_CFG(GATE_DDRPHYCLP, RCC_DDRITFCR, 5, 0), + GATE_CFG(GATE_DDRCAPB, RCC_DDRITFCR, 6, 0), + GATE_CFG(GATE_DDRCAPBLP, RCC_DDRITFCR, 7, 0), + GATE_CFG(GATE_AXIDCG, RCC_DDRITFCR, 8, 0), + GATE_CFG(GATE_DDRPHYCAPB, RCC_DDRITFCR, 9, 0), + GATE_CFG(GATE_DDRPHYCAPBLP, RCC_DDRITFCR, 10, 0), + GATE_CFG(GATE_TIM2, RCC_MP_APB1ENSETR, 0, 1), + GATE_CFG(GATE_TIM3, RCC_MP_APB1ENSETR, 1, 1), + GATE_CFG(GATE_TIM4, RCC_MP_APB1ENSETR, 2, 1), + GATE_CFG(GATE_TIM5, RCC_MP_APB1ENSETR, 3, 1), + GATE_CFG(GATE_TIM6, RCC_MP_APB1ENSETR, 4, 1), + GATE_CFG(GATE_TIM7, RCC_MP_APB1ENSETR, 5, 1), + GATE_CFG(GATE_LPTIM1, RCC_MP_APB1ENSETR, 9, 1), + GATE_CFG(GATE_SPI2, RCC_MP_APB1ENSETR, 11, 1), + GATE_CFG(GATE_SPI3, RCC_MP_APB1ENSETR, 12, 1), + GATE_CFG(GATE_USART3, RCC_MP_APB1ENSETR, 15, 1), + GATE_CFG(GATE_UART4, RCC_MP_APB1ENSETR, 16, 1), + GATE_CFG(GATE_UART5, RCC_MP_APB1ENSETR, 17, 1), + GATE_CFG(GATE_UART7, RCC_MP_APB1ENSETR, 18, 1), + GATE_CFG(GATE_UART8, RCC_MP_APB1ENSETR, 19, 1), + GATE_CFG(GATE_I2C1, RCC_MP_APB1ENSETR, 21, 1), + GATE_CFG(GATE_I2C2, RCC_MP_APB1ENSETR, 22, 1), + GATE_CFG(GATE_SPDIF, RCC_MP_APB1ENSETR, 26, 1), + GATE_CFG(GATE_TIM1, RCC_MP_APB2ENSETR, 0, 1), + GATE_CFG(GATE_TIM8, RCC_MP_APB2ENSETR, 1, 1), + GATE_CFG(GATE_SPI1, RCC_MP_APB2ENSETR, 8, 1), + GATE_CFG(GATE_USART6, RCC_MP_APB2ENSETR, 13, 1), + GATE_CFG(GATE_SAI1, RCC_MP_APB2ENSETR, 16, 1), + GATE_CFG(GATE_SAI2, RCC_MP_APB2ENSETR, 17, 1), + GATE_CFG(GATE_DFSDM, RCC_MP_APB2ENSETR, 20, 1), + GATE_CFG(GATE_ADFSDM, RCC_MP_APB2ENSETR, 21, 1), + GATE_CFG(GATE_FDCAN, RCC_MP_APB2ENSETR, 24, 1), + GATE_CFG(GATE_LPTIM2, RCC_MP_APB3ENSETR, 0, 1), + GATE_CFG(GATE_LPTIM3, RCC_MP_APB3ENSETR, 1, 1), + GATE_CFG(GATE_LPTIM4, RCC_MP_APB3ENSETR, 2, 1), + GATE_CFG(GATE_LPTIM5, RCC_MP_APB3ENSETR, 3, 1), + GATE_CFG(GATE_VREF, RCC_MP_APB3ENSETR, 13, 1), + GATE_CFG(GATE_DTS, RCC_MP_APB3ENSETR, 16, 1), + GATE_CFG(GATE_PMBCTRL, RCC_MP_APB3ENSETR, 17, 1), + GATE_CFG(GATE_HDP, RCC_MP_APB3ENSETR, 20, 1), + GATE_CFG(GATE_SYSCFG, RCC_MP_NS_APB3ENSETR, 0, 1), + GATE_CFG(GATE_DCMIPP, RCC_MP_APB4ENSETR, 1, 1), + GATE_CFG(GATE_DDRPERFM, RCC_MP_APB4ENSETR, 8, 1), + GATE_CFG(GATE_IWDG2APB, RCC_MP_APB4ENSETR, 15, 1), + GATE_CFG(GATE_USBPHY, RCC_MP_APB4ENSETR, 16, 1), + GATE_CFG(GATE_STGENRO, RCC_MP_APB4ENSETR, 20, 1), + GATE_CFG(GATE_LTDC, RCC_MP_NS_APB4ENSETR, 0, 1), + GATE_CFG(GATE_TZC, RCC_MP_APB5ENSETR, 11, 1), + GATE_CFG(GATE_ETZPC, RCC_MP_APB5ENSETR, 13, 1), + GATE_CFG(GATE_IWDG1APB, RCC_MP_APB5ENSETR, 15, 1), + GATE_CFG(GATE_BSEC, RCC_MP_APB5ENSETR, 16, 1), + GATE_CFG(GATE_STGENC, RCC_MP_APB5ENSETR, 20, 1), + GATE_CFG(GATE_USART1, RCC_MP_APB6ENSETR, 0, 1), + GATE_CFG(GATE_USART2, RCC_MP_APB6ENSETR, 1, 1), + GATE_CFG(GATE_SPI4, RCC_MP_APB6ENSETR, 2, 1), + GATE_CFG(GATE_SPI5, RCC_MP_APB6ENSETR, 3, 1), + GATE_CFG(GATE_I2C3, RCC_MP_APB6ENSETR, 4, 1), + GATE_CFG(GATE_I2C4, RCC_MP_APB6ENSETR, 5, 1), + GATE_CFG(GATE_I2C5, RCC_MP_APB6ENSETR, 6, 1), + GATE_CFG(GATE_TIM12, RCC_MP_APB6ENSETR, 7, 1), + GATE_CFG(GATE_TIM13, RCC_MP_APB6ENSETR, 8, 1), + GATE_CFG(GATE_TIM14, RCC_MP_APB6ENSETR, 9, 1), + GATE_CFG(GATE_TIM15, RCC_MP_APB6ENSETR, 10, 1), + GATE_CFG(GATE_TIM16, RCC_MP_APB6ENSETR, 11, 1), + GATE_CFG(GATE_TIM17, RCC_MP_APB6ENSETR, 12, 1), + GATE_CFG(GATE_DMA1, RCC_MP_AHB2ENSETR, 0, 1), + GATE_CFG(GATE_DMA2, RCC_MP_AHB2ENSETR, 1, 1), + GATE_CFG(GATE_DMAMUX1, RCC_MP_AHB2ENSETR, 2, 1), + GATE_CFG(GATE_DMA3, RCC_MP_AHB2ENSETR, 3, 1), + GATE_CFG(GATE_DMAMUX2, RCC_MP_AHB2ENSETR, 4, 1), + GATE_CFG(GATE_ADC1, RCC_MP_AHB2ENSETR, 5, 1), + GATE_CFG(GATE_ADC2, RCC_MP_AHB2ENSETR, 6, 1), + GATE_CFG(GATE_USBO, RCC_MP_AHB2ENSETR, 8, 1), + GATE_CFG(GATE_TSC, RCC_MP_AHB4ENSETR, 15, 1), + GATE_CFG(GATE_GPIOA, RCC_MP_NS_AHB4ENSETR, 0, 1), + GATE_CFG(GATE_GPIOB, RCC_MP_NS_AHB4ENSETR, 1, 1), + GATE_CFG(GATE_GPIOC, RCC_MP_NS_AHB4ENSETR, 2, 1), + GATE_CFG(GATE_GPIOD, RCC_MP_NS_AHB4ENSETR, 3, 1), + GATE_CFG(GATE_GPIOE, RCC_MP_NS_AHB4ENSETR, 4, 1), + GATE_CFG(GATE_GPIOF, RCC_MP_NS_AHB4ENSETR, 5, 1), + GATE_CFG(GATE_GPIOG, RCC_MP_NS_AHB4ENSETR, 6, 1), + GATE_CFG(GATE_GPIOH, RCC_MP_NS_AHB4ENSETR, 7, 1), + GATE_CFG(GATE_GPIOI, RCC_MP_NS_AHB4ENSETR, 8, 1), + GATE_CFG(GATE_PKA, RCC_MP_AHB5ENSETR, 2, 1), + GATE_CFG(GATE_SAES, RCC_MP_AHB5ENSETR, 3, 1), + GATE_CFG(GATE_CRYP1, RCC_MP_AHB5ENSETR, 4, 1), + GATE_CFG(GATE_HASH1, RCC_MP_AHB5ENSETR, 5, 1), + GATE_CFG(GATE_RNG1, RCC_MP_AHB5ENSETR, 6, 1), + GATE_CFG(GATE_BKPSRAM, RCC_MP_AHB5ENSETR, 8, 1), + GATE_CFG(GATE_AXIMC, RCC_MP_AHB5ENSETR, 16, 1), + GATE_CFG(GATE_MCE, RCC_MP_AHB6ENSETR, 1, 1), + GATE_CFG(GATE_ETH1CK, RCC_MP_AHB6ENSETR, 7, 1), + GATE_CFG(GATE_ETH1TX, RCC_MP_AHB6ENSETR, 8, 1), + GATE_CFG(GATE_ETH1RX, RCC_MP_AHB6ENSETR, 9, 1), + GATE_CFG(GATE_ETH1MAC, RCC_MP_AHB6ENSETR, 10, 1), + GATE_CFG(GATE_FMC, RCC_MP_AHB6ENSETR, 12, 1), + GATE_CFG(GATE_QSPI, RCC_MP_AHB6ENSETR, 14, 1), + GATE_CFG(GATE_SDMMC1, RCC_MP_AHB6ENSETR, 16, 1), + GATE_CFG(GATE_SDMMC2, RCC_MP_AHB6ENSETR, 17, 1), + GATE_CFG(GATE_CRC1, RCC_MP_AHB6ENSETR, 20, 1), + GATE_CFG(GATE_USBH, RCC_MP_AHB6ENSETR, 24, 1), + GATE_CFG(GATE_ETH2CK, RCC_MP_AHB6ENSETR, 27, 1), + GATE_CFG(GATE_ETH2TX, RCC_MP_AHB6ENSETR, 28, 1), + GATE_CFG(GATE_ETH2RX, RCC_MP_AHB6ENSETR, 29, 1), + GATE_CFG(GATE_ETH2MAC, RCC_MP_AHB6ENSETR, 30, 1), + GATE_CFG(GATE_ETH1STP, RCC_MP_AHB6LPENSETR, 11, 1), + GATE_CFG(GATE_ETH2STP, RCC_MP_AHB6LPENSETR, 31, 1), + GATE_CFG(GATE_MDMA, RCC_MP_NS_AHB6ENSETR, 0, 1), +}; + +static const struct clk_div_table ck_trace_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, + { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 }, + { 0 }, +}; + +enum enum_div_cfg { + DIV_MCO1, + DIV_MCO2, + DIV_TRACE, + DIV_ETH1PTP, + DIV_ETH2PTP, + LAST_DIV +}; + +#define DIV_CFG(id, _offset, _shift, _width, _flags, _table)[id] = {\ + .reg_off = _offset,\ + .shift = _shift,\ + .width = _width,\ + .div_flags = _flags,\ + .table = _table,\ +} + +static const struct stm32_div_cfg stm32mp13_dividers[LAST_DIV] = { + DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL), + DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL), + DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table), + DIV_CFG(DIV_ETH1PTP, RCC_ETH12CKSELR, 4, 4, 0, NULL), + DIV_CFG(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL), +}; + +struct clk_stm32_securiy { + u16 offset; + u8 bit_idx; +}; + +enum securit_clk { + SECF_NONE, + SECF_LPTIM2, + SECF_LPTIM3, + SECF_VREF, + SECF_DCMIPP, + SECF_USBPHY, + SECF_RTC, + SECF_TZC, + SECF_ETZPC, + SECF_IWDG1, + SECF_BSEC, + SECF_STGENC, + SECF_STGENRO, + SECF_USART1, + SECF_USART2, + SECF_SPI4, + SECF_SPI5, + SECF_I2C3, + SECF_I2C4, + SECF_I2C5, + SECF_TIM12, + SECF_TIM13, + SECF_TIM14, + SECF_TIM15, + SECF_TIM16, + SECF_TIM17, + SECF_DMA3, + SECF_DMAMUX2, + SECF_ADC1, + SECF_ADC2, + SECF_USBO, + SECF_TSC, + SECF_PKA, + SECF_SAES, + SECF_CRYP1, + SECF_HASH1, + SECF_RNG1, + SECF_BKPSRAM, + SECF_MCE, + SECF_FMC, + SECF_QSPI, + SECF_SDMMC1, + SECF_SDMMC2, + SECF_ETH1CK, + SECF_ETH1TX, + SECF_ETH1RX, + SECF_ETH1MAC, + SECF_ETH1STP, + SECF_ETH2CK, + SECF_ETH2TX, + SECF_ETH2RX, + SECF_ETH2MAC, + SECF_ETH2STP, + SECF_MCO1, + SECF_MCO2 +}; + +#define SECF(_sec_id, _offset, _bit_idx)[_sec_id] = {\ + .offset = _offset,\ + .bit_idx = _bit_idx,\ +} + +static const struct clk_stm32_securiy stm32mp13_security[] = { + SECF(SECF_LPTIM2, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM2SECF), + SECF(SECF_LPTIM3, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM3SECF), + SECF(SECF_VREF, RCC_APB3SECSR, RCC_APB3SECSR_VREFSECF), + SECF(SECF_DCMIPP, RCC_APB4SECSR, RCC_APB4SECSR_DCMIPPSECF), + SECF(SECF_USBPHY, RCC_APB4SECSR, RCC_APB4SECSR_USBPHYSECF), + SECF(SECF_RTC, RCC_APB5SECSR, RCC_APB5SECSR_RTCSECF), + SECF(SECF_TZC, RCC_APB5SECSR, RCC_APB5SECSR_TZCSECF), + SECF(SECF_ETZPC, RCC_APB5SECSR, RCC_APB5SECSR_ETZPCSECF), + SECF(SECF_IWDG1, RCC_APB5SECSR, RCC_APB5SECSR_IWDG1SECF), + SECF(SECF_BSEC, RCC_APB5SECSR, RCC_APB5SECSR_BSECSECF), + SECF(SECF_STGENC, RCC_APB5SECSR, RCC_APB5SECSR_STGENCSECF), + SECF(SECF_STGENRO, RCC_APB5SECSR, RCC_APB5SECSR_STGENROSECF), + SECF(SECF_USART1, RCC_APB6SECSR, RCC_APB6SECSR_USART1SECF), + SECF(SECF_USART2, RCC_APB6SECSR, RCC_APB6SECSR_USART2SECF), + SECF(SECF_SPI4, RCC_APB6SECSR, RCC_APB6SECSR_SPI4SECF), + SECF(SECF_SPI5, RCC_APB6SECSR, RCC_APB6SECSR_SPI5SECF), + SECF(SECF_I2C3, RCC_APB6SECSR, RCC_APB6SECSR_I2C3SECF), + SECF(SECF_I2C4, RCC_APB6SECSR, RCC_APB6SECSR_I2C4SECF), + SECF(SECF_I2C5, RCC_APB6SECSR, RCC_APB6SECSR_I2C5SECF), + SECF(SECF_TIM12, RCC_APB6SECSR, RCC_APB6SECSR_TIM12SECF), + SECF(SECF_TIM13, RCC_APB6SECSR, RCC_APB6SECSR_TIM13SECF), + SECF(SECF_TIM14, RCC_APB6SECSR, RCC_APB6SECSR_TIM14SECF), + SECF(SECF_TIM15, RCC_APB6SECSR, RCC_APB6SECSR_TIM15SECF), + SECF(SECF_TIM16, RCC_APB6SECSR, RCC_APB6SECSR_TIM16SECF), + SECF(SECF_TIM17, RCC_APB6SECSR, RCC_APB6SECSR_TIM17SECF), + SECF(SECF_DMA3, RCC_AHB2SECSR, RCC_AHB2SECSR_DMA3SECF), + SECF(SECF_DMAMUX2, RCC_AHB2SECSR, RCC_AHB2SECSR_DMAMUX2SECF), + SECF(SECF_ADC1, RCC_AHB2SECSR, RCC_AHB2SECSR_ADC1SECF), + SECF(SECF_ADC2, RCC_AHB2SECSR, RCC_AHB2SECSR_ADC2SECF), + SECF(SECF_USBO, RCC_AHB2SECSR, RCC_AHB2SECSR_USBOSECF), + SECF(SECF_TSC, RCC_AHB4SECSR, RCC_AHB4SECSR_TSCSECF), + SECF(SECF_PKA, RCC_AHB5SECSR, RCC_AHB5SECSR_PKASECF), + SECF(SECF_SAES, RCC_AHB5SECSR, RCC_AHB5SECSR_SAESSECF), + SECF(SECF_CRYP1, RCC_AHB5SECSR, RCC_AHB5SECSR_CRYP1SECF), + SECF(SECF_HASH1, RCC_AHB5SECSR, RCC_AHB5SECSR_HASH1SECF), + SECF(SECF_RNG1, RCC_AHB5SECSR, RCC_AHB5SECSR_RNG1SECF), + SECF(SECF_BKPSRAM, RCC_AHB5SECSR, RCC_AHB5SECSR_BKPSRAMSECF), + SECF(SECF_MCE, RCC_AHB6SECSR, RCC_AHB6SECSR_MCESECF), + SECF(SECF_FMC, RCC_AHB6SECSR, RCC_AHB6SECSR_FMCSECF), + SECF(SECF_QSPI, RCC_AHB6SECSR, RCC_AHB6SECSR_QSPISECF), + SECF(SECF_SDMMC1, RCC_AHB6SECSR, RCC_AHB6SECSR_SDMMC1SECF), + SECF(SECF_SDMMC2, RCC_AHB6SECSR, RCC_AHB6SECSR_SDMMC2SECF), + SECF(SECF_ETH1CK, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1CKSECF), + SECF(SECF_ETH1TX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1TXSECF), + SECF(SECF_ETH1RX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1RXSECF), + SECF(SECF_ETH1MAC, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1MACSECF), + SECF(SECF_ETH1STP, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1STPSECF), + SECF(SECF_ETH2CK, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2CKSECF), + SECF(SECF_ETH2TX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2TXSECF), + SECF(SECF_ETH2RX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2RXSECF), + SECF(SECF_ETH2MAC, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2MACSECF), + SECF(SECF_ETH2STP, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2STPSECF), + SECF(SECF_MCO1, RCC_SECCFGR, RCC_SECCFGR_MCO1SECF), + SECF(SECF_MCO2, RCC_SECCFGR, RCC_SECCFGR_MCO2SECF), +}; + +#define PCLK(_id, _name, _parent, _flags, _gate_id, _sec_id)\ + STM32_GATE(_id, _name, _parent, _flags, _gate_id, _sec_id) + +#define TIMER(_id, _name, _parent, _flags, _gate_id, _sec_id)\ + STM32_GATE(_id, _name, _parent, ((_flags) | CLK_SET_RATE_PARENT),\ + _gate_id, _sec_id) + +#define KCLK(_id, _name, _flags, _gate_id, _mux_id, _sec_id)\ + STM32_COMPOSITE(_id, _name, _flags, _sec_id,\ + _gate_id, _mux_id, NO_STM32_DIV) + +static const struct clock_config stm32mp13_clock_cfg[] = { + TIMER(TIM2_K, "tim2_k", "timg1_ck", 0, GATE_TIM2, SECF_NONE), + TIMER(TIM3_K, "tim3_k", "timg1_ck", 0, GATE_TIM3, SECF_NONE), + TIMER(TIM4_K, "tim4_k", "timg1_ck", 0, GATE_TIM4, SECF_NONE), + TIMER(TIM5_K, "tim5_k", "timg1_ck", 0, GATE_TIM5, SECF_NONE), + TIMER(TIM6_K, "tim6_k", "timg1_ck", 0, GATE_TIM6, SECF_NONE), + TIMER(TIM7_K, "tim7_k", "timg1_ck", 0, GATE_TIM7, SECF_NONE), + TIMER(TIM1_K, "tim1_k", "timg2_ck", 0, GATE_TIM1, SECF_NONE), + TIMER(TIM8_K, "tim8_k", "timg2_ck", 0, GATE_TIM8, SECF_NONE), + TIMER(TIM12_K, "tim12_k", "timg3_ck", 0, GATE_TIM12, SECF_TIM12), + TIMER(TIM13_K, "tim13_k", "timg3_ck", 0, GATE_TIM13, SECF_TIM13), + TIMER(TIM14_K, "tim14_k", "timg3_ck", 0, GATE_TIM14, SECF_TIM14), + TIMER(TIM15_K, "tim15_k", "timg3_ck", 0, GATE_TIM15, SECF_TIM15), + TIMER(TIM16_K, "tim16_k", "timg3_ck", 0, GATE_TIM16, SECF_TIM16), + TIMER(TIM17_K, "tim17_k", "timg3_ck", 0, GATE_TIM17, SECF_TIM17), + + /* Peripheral clocks */ + PCLK(SYSCFG, "syscfg", "pclk3", 0, GATE_SYSCFG, SECF_NONE), + PCLK(VREF, "vref", "pclk3", 0, GATE_VREF, SECF_VREF), + PCLK(PMBCTRL, "pmbctrl", "pclk3", 0, GATE_PMBCTRL, SECF_NONE), + PCLK(HDP, "hdp", "pclk3", 0, GATE_HDP, SECF_NONE), + PCLK(IWDG2, "iwdg2", "pclk4", 0, GATE_IWDG2APB, SECF_NONE), + PCLK(STGENRO, "stgenro", "pclk4", 0, GATE_STGENRO, SECF_STGENRO), + PCLK(TZPC, "tzpc", "pclk5", 0, GATE_TZC, SECF_TZC), + PCLK(IWDG1, "iwdg1", "pclk5", 0, GATE_IWDG1APB, SECF_IWDG1), + PCLK(BSEC, "bsec", "pclk5", 0, GATE_BSEC, SECF_BSEC), + PCLK(DMA1, "dma1", "ck_mlahb", 0, GATE_DMA1, SECF_NONE), + PCLK(DMA2, "dma2", "ck_mlahb", 0, GATE_DMA2, SECF_NONE), + PCLK(DMAMUX1, "dmamux1", "ck_mlahb", 0, GATE_DMAMUX1, SECF_NONE), + PCLK(DMAMUX2, "dmamux2", "ck_mlahb", 0, GATE_DMAMUX2, SECF_DMAMUX2), + PCLK(ADC1, "adc1", "ck_mlahb", 0, GATE_ADC1, SECF_ADC1), + PCLK(ADC2, "adc2", "ck_mlahb", 0, GATE_ADC2, SECF_ADC2), + PCLK(GPIOA, "gpioa", "pclk4", 0, GATE_GPIOA, SECF_NONE), + PCLK(GPIOB, "gpiob", "pclk4", 0, GATE_GPIOB, SECF_NONE), + PCLK(GPIOC, "gpioc", "pclk4", 0, GATE_GPIOC, SECF_NONE), + PCLK(GPIOD, "gpiod", "pclk4", 0, GATE_GPIOD, SECF_NONE), + PCLK(GPIOE, "gpioe", "pclk4", 0, GATE_GPIOE, SECF_NONE), + PCLK(GPIOF, "gpiof", "pclk4", 0, GATE_GPIOF, SECF_NONE), + PCLK(GPIOG, "gpiog", "pclk4", 0, GATE_GPIOG, SECF_NONE), + PCLK(GPIOH, "gpioh", "pclk4", 0, GATE_GPIOH, SECF_NONE), + PCLK(GPIOI, "gpioi", "pclk4", 0, GATE_GPIOI, SECF_NONE), + PCLK(TSC, "tsc", "pclk4", 0, GATE_TSC, SECF_TZC), + PCLK(PKA, "pka", "ck_axi", 0, GATE_PKA, SECF_PKA), + PCLK(CRYP1, "cryp1", "ck_axi", 0, GATE_CRYP1, SECF_CRYP1), + PCLK(HASH1, "hash1", "ck_axi", 0, GATE_HASH1, SECF_HASH1), + PCLK(BKPSRAM, "bkpsram", "ck_axi", 0, GATE_BKPSRAM, SECF_BKPSRAM), + PCLK(MDMA, "mdma", "ck_axi", 0, GATE_MDMA, SECF_NONE), + PCLK(ETH1TX, "eth1tx", "ck_axi", 0, GATE_ETH1TX, SECF_ETH1TX), + PCLK(ETH1RX, "eth1rx", "ck_axi", 0, GATE_ETH1RX, SECF_ETH1RX), + PCLK(ETH1MAC, "eth1mac", "ck_axi", 0, GATE_ETH1MAC, SECF_ETH1MAC), + PCLK(ETH2TX, "eth2tx", "ck_axi", 0, GATE_ETH2TX, SECF_ETH2TX), + PCLK(ETH2RX, "eth2rx", "ck_axi", 0, GATE_ETH2RX, SECF_ETH2RX), + PCLK(ETH2MAC, "eth2mac", "ck_axi", 0, GATE_ETH2MAC, SECF_ETH2MAC), + PCLK(CRC1, "crc1", "ck_axi", 0, GATE_CRC1, SECF_NONE), + PCLK(USBH, "usbh", "ck_axi", 0, GATE_USBH, SECF_NONE), + PCLK(DDRPERFM, "ddrperfm", "pclk4", 0, GATE_DDRPERFM, SECF_NONE), + PCLK(ETH1STP, "eth1stp", "ck_axi", 0, GATE_ETH1STP, SECF_ETH1STP), + PCLK(ETH2STP, "eth2stp", "ck_axi", 0, GATE_ETH2STP, SECF_ETH2STP), + + /* Kernel clocks */ + KCLK(SDMMC1_K, "sdmmc1_k", 0, GATE_SDMMC1, MUX_SDMMC1, SECF_SDMMC1), + KCLK(SDMMC2_K, "sdmmc2_k", 0, GATE_SDMMC2, MUX_SDMMC2, SECF_SDMMC2), + KCLK(FMC_K, "fmc_k", 0, GATE_FMC, MUX_FMC, SECF_FMC), + KCLK(QSPI_K, "qspi_k", 0, GATE_QSPI, MUX_QSPI, SECF_QSPI), + KCLK(SPI2_K, "spi2_k", 0, GATE_SPI2, MUX_SPI23, SECF_NONE), + KCLK(SPI3_K, "spi3_k", 0, GATE_SPI3, MUX_SPI23, SECF_NONE), + KCLK(I2C1_K, "i2c1_k", 0, GATE_I2C1, MUX_I2C12, SECF_NONE), + KCLK(I2C2_K, "i2c2_k", 0, GATE_I2C2, MUX_I2C12, SECF_NONE), + KCLK(LPTIM4_K, "lptim4_k", 0, GATE_LPTIM4, MUX_LPTIM45, SECF_NONE), + KCLK(LPTIM5_K, "lptim5_k", 0, GATE_LPTIM5, MUX_LPTIM45, SECF_NONE), + KCLK(USART3_K, "usart3_k", 0, GATE_USART3, MUX_UART35, SECF_NONE), + KCLK(UART5_K, "uart5_k", 0, GATE_UART5, MUX_UART35, SECF_NONE), + KCLK(UART7_K, "uart7_k", 0, GATE_UART7, MUX_UART78, SECF_NONE), + KCLK(UART8_K, "uart8_k", 0, GATE_UART8, MUX_UART78, SECF_NONE), + KCLK(RNG1_K, "rng1_k", 0, GATE_RNG1, MUX_RNG1, SECF_RNG1), + KCLK(USBPHY_K, "usbphy_k", 0, GATE_USBPHY, MUX_USBPHY, SECF_USBPHY), + KCLK(STGEN_K, "stgen_k", 0, GATE_STGENC, MUX_STGEN, SECF_STGENC), + KCLK(SPDIF_K, "spdif_k", 0, GATE_SPDIF, MUX_SPDIF, SECF_NONE), + KCLK(SPI1_K, "spi1_k", 0, GATE_SPI1, MUX_SPI1, SECF_NONE), + KCLK(SPI4_K, "spi4_k", 0, GATE_SPI4, MUX_SPI4, SECF_SPI4), + KCLK(SPI5_K, "spi5_k", 0, GATE_SPI5, MUX_SPI5, SECF_SPI5), + KCLK(I2C3_K, "i2c3_k", 0, GATE_I2C3, MUX_I2C3, SECF_I2C3), + KCLK(I2C4_K, "i2c4_k", 0, GATE_I2C4, MUX_I2C4, SECF_I2C4), + KCLK(I2C5_K, "i2c5_k", 0, GATE_I2C5, MUX_I2C5, SECF_I2C5), + KCLK(LPTIM1_K, "lptim1_k", 0, GATE_LPTIM1, MUX_LPTIM1, SECF_NONE), + KCLK(LPTIM2_K, "lptim2_k", 0, GATE_LPTIM2, MUX_LPTIM2, SECF_LPTIM2), + KCLK(LPTIM3_K, "lptim3_k", 0, GATE_LPTIM3, MUX_LPTIM3, SECF_LPTIM3), + KCLK(USART1_K, "usart1_k", 0, GATE_USART1, MUX_UART1, SECF_USART1), + KCLK(USART2_K, "usart2_k", 0, GATE_USART2, MUX_UART2, SECF_USART2), + KCLK(UART4_K, "uart4_k", 0, GATE_UART4, MUX_UART4, SECF_NONE), + KCLK(USART6_K, "uart6_k", 0, GATE_USART6, MUX_UART6, SECF_NONE), + KCLK(FDCAN_K, "fdcan_k", 0, GATE_FDCAN, MUX_FDCAN, SECF_NONE), + KCLK(SAI1_K, "sai1_k", 0, GATE_SAI1, MUX_SAI1, SECF_NONE), + KCLK(SAI2_K, "sai2_k", 0, GATE_SAI2, MUX_SAI2, SECF_NONE), + KCLK(ADC1_K, "adc1_k", 0, GATE_ADC1, MUX_ADC1, SECF_ADC1), + KCLK(ADC2_K, "adc2_k", 0, GATE_ADC2, MUX_ADC2, SECF_ADC2), + KCLK(DCMIPP_K, "dcmipp_k", 0, GATE_DCMIPP, MUX_DCMIPP, SECF_DCMIPP), + KCLK(ADFSDM_K, "adfsdm_k", 0, GATE_ADFSDM, MUX_SAI1, SECF_NONE), + KCLK(USBO_K, "usbo_k", 0, GATE_USBO, MUX_USBO, SECF_USBO), + KCLK(ETH1CK_K, "eth1ck_k", 0, GATE_ETH1CK, MUX_ETH1, SECF_ETH1CK), + KCLK(ETH2CK_K, "eth2ck_k", 0, GATE_ETH2CK, MUX_ETH2, SECF_ETH2CK), + KCLK(SAES_K, "saes_k", 0, GATE_SAES, MUX_SAES, SECF_SAES), + + STM32_GATE(DFSDM_K, "dfsdm_k", "ck_mlahb", 0, GATE_DFSDM, SECF_NONE), + STM32_GATE(LTDC_PX, "ltdc_px", "pll4_q", CLK_SET_RATE_PARENT, + GATE_LTDC, SECF_NONE), + + STM32_GATE(DTS_K, "dts_k", "ck_lse", 0, GATE_DTS, SECF_NONE), + + STM32_COMPOSITE(ETH1PTP_K, "eth1ptp_k", CLK_OPS_PARENT_ENABLE | + CLK_SET_RATE_NO_REPARENT, SECF_ETH1CK, + NO_STM32_GATE, MUX_ETH1, DIV_ETH1PTP), + + STM32_COMPOSITE(ETH2PTP_K, "eth2ptp_k", CLK_OPS_PARENT_ENABLE | + CLK_SET_RATE_NO_REPARENT, SECF_ETH2CK, + NO_STM32_GATE, MUX_ETH2, DIV_ETH2PTP), + + /* MCO clocks */ + STM32_COMPOSITE(CK_MCO1, "ck_mco1", CLK_OPS_PARENT_ENABLE | + CLK_SET_RATE_NO_REPARENT, SECF_MCO1, + GATE_MCO1, MUX_MCO1, DIV_MCO1), + + STM32_COMPOSITE(CK_MCO2, "ck_mco2", CLK_OPS_PARENT_ENABLE | + CLK_SET_RATE_NO_REPARENT, SECF_MCO2, + GATE_MCO2, MUX_MCO2, DIV_MCO2), + + /* Debug clocks */ + STM32_GATE(CK_DBG, "ck_sys_dbg", "ck_axi", CLK_IGNORE_UNUSED, + GATE_DBGCK, SECF_NONE), + + STM32_COMPOSITE_NOMUX(CK_TRACE, "ck_trace", "ck_axi", + CLK_OPS_PARENT_ENABLE, SECF_NONE, + GATE_TRACECK, DIV_TRACE), +}; + +static int stm32mp13_check_security(void __iomem *base, + const struct clock_config *cfg) +{ + int sec_id = cfg->sec_id; + int secured = 0; + + if (sec_id != SECF_NONE) { + const struct clk_stm32_securiy *secf; + + secf = &stm32mp13_security[sec_id]; + secured = !!(readl(base + secf->offset) & BIT(secf->bit_idx)); + } + + return secured; +} + +static const struct stm32_clock_match_data stm32mp13_data = { + .tab_clocks = stm32mp13_clock_cfg, + .num_clocks = ARRAY_SIZE(stm32mp13_clock_cfg), + .gates = stm32mp13_gates, + .muxes = stm32mp13_muxes, + .dividers = stm32mp13_dividers, + .check_security = &stm32mp13_check_security +}; + +static int stm32mp1_clk_probe(struct udevice *dev) +{ + fdt_addr_t base = dev_read_addr(dev->parent); + struct udevice *scmi; + + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* force SCMI probe to register all SCMI clocks */ + uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(scmi_clock), &scmi); + + stm32_rcc_init(NULL, &stm32mp13_data, (void __iomem *)base); + +#if defined(DEBUG) + /* display debug information for probe after relocation */ + if (gd->flags & GD_FLG_RELOC) + stm32mp1_clk_dump(priv); +#endif + gd->cpu_clk = clk_stm32_get_rate_by_name("ck_mpu"); + gd->bus_clk = clk_stm32_get_rate_by_name("ck_axi"); + + /* DDRPHYC father */ + gd->mem_clk = clk_stm32_get_rate_by_name("pll2_r"); + +#if defined(CONFIG_DISPLAY_CPUINFO) + if (gd->flags & GD_FLG_RELOC) { + char buf[32]; + + log_info("Clocks:\n"); + log_info("- MPU : %s MHz\n", strmhz(buf, gd->cpu_clk)); + log_info("- AXI : %s MHz\n", strmhz(buf, gd->bus_clk)); + log_info("- PER : %s MHz\n", + strmhz(buf, clk_stm32_get_rate_by_name("ck_per"))); + log_info("- DDR : %s MHz\n", strmhz(buf, gd->mem_clk)); + } +#endif /* CONFIG_DISPLAY_CPUINFO */ + + return 0; +} + +U_BOOT_DRIVER(stm32mp1_clock) = { + .name = "stm32mp13_clk", + .id = UCLASS_CLK, + .ops = &stm32_clk_ops, + .priv_auto = sizeof(struct stm32mp1_clk_priv), + .probe = stm32mp1_clk_probe, +}; diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index cea38a4c6e..a5f4142f6f 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -23,7 +24,6 @@ #include #include #include -#include static inline const struct clk_ops *clk_dev_ops(struct udevice *dev) { @@ -577,6 +577,19 @@ ulong clk_round_rate(struct clk *clk, ulong rate) return ops->round_rate(clk, rate); } +static void clk_get_priv(struct clk *clk, struct clk **clkp) +{ + *clkp = clk; + + /* get private clock struct associated to the provided clock */ + if (CONFIG_IS_ENABLED(CLK_CCF)) { + /* Take id 0 as a non-valid clk, such as dummy */ + if (clk->id) + clk_get_by_id(clk->id, clkp); + } +} + +/* clean cache, called with private clock struct */ static void clk_clean_rate_cache(struct clk *clk) { struct udevice *child_dev; @@ -596,19 +609,39 @@ static void clk_clean_rate_cache(struct clk *clk) ulong clk_set_rate(struct clk *clk, ulong rate) { const struct clk_ops *ops; + struct clk *clkp; debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate); if (!clk_valid(clk)) return 0; - ops = clk_dev_ops(clk->dev); - if (!ops->set_rate) - return -ENOSYS; + /* get private clock struct*/ + clk_get_priv(clk, &clkp); + + ops = clk_dev_ops(clkp->dev); + + if (!ops->set_rate) { + struct clk *pclk = NULL; + + if ((clkp->flags & CLK_SET_RATE_PARENT) == 0) + return -ENOSYS; + + pclk = clk_get_parent(clkp); + if (IS_ERR(pclk)) + return -ENODEV; + + ops = clk_dev_ops(pclk->dev); + + /* Clean up cached rates for us and all child clocks */ + clk_clean_rate_cache(pclk); + + return ops->set_rate(pclk, rate); + } /* Clean up cached rates for us and all child clocks */ - clk_clean_rate_cache(clk); + clk_clean_rate_cache(clkp); - return ops->set_rate(clk, rate); + return ops->set_rate(clkp, rate); } int clk_set_parent(struct clk *clk, struct clk *parent) @@ -653,7 +686,7 @@ int clk_enable(struct clk *clk) return 0; } if (clkp->dev->parent && - device_get_uclass_id(clkp->dev) == UCLASS_CLK) { + device_get_uclass_id(clkp->dev->parent) == UCLASS_CLK) { ret = clk_enable(dev_get_clk_ptr(clkp->dev->parent)); if (ret) { printf("Enable %s failed\n", @@ -727,7 +760,7 @@ int clk_disable(struct clk *clk) } if (clkp && clkp->dev->parent && - device_get_uclass_id(clkp->dev) == UCLASS_CLK) { + device_get_uclass_id(clkp->dev->parent) == UCLASS_CLK) { ret = clk_disable(dev_get_clk_ptr(clkp->dev->parent)); if (ret) { printf("Disable %s failed\n", diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 1efb7fe9f3..eff0fa134f 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4,14 +4,16 @@ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de */ +#define LOG_CATEGORY UCLASS_CLK + #include +#include #include #include #include #include #include #include -#include int clk_register(struct clk *clk, const char *drv_name, const char *name, const char *parent_name) @@ -22,24 +24,24 @@ int clk_register(struct clk *clk, const char *drv_name, ret = uclass_get_device_by_name(UCLASS_CLK, parent_name, &parent); if (ret) { - printf("%s: failed to get %s device (parent of %s)\n", - __func__, parent_name, name); + log_err("%s: failed to get %s device (parent of %s)\n", + __func__, parent_name, name); } else { - debug("%s: name: %s parent: %s [0x%p]\n", __func__, name, - parent->name, parent); + log_debug("%s: name: %s parent: %s [0x%p]\n", __func__, name, + parent->name, parent); } drv = lists_driver_lookup_name(drv_name); if (!drv) { - printf("%s: %s is not a valid driver name\n", - __func__, drv_name); + log_err("%s: %s is not a valid driver name\n", + __func__, drv_name); return -ENOENT; } ret = device_bind(parent, drv, name, NULL, ofnode_null(), &clk->dev); if (ret) { - printf("%s: CLK: %s driver bind error [%d]!\n", __func__, name, - ret); + log_err("%s: CLK: %s driver bind error [%d]!\n", __func__, name, + ret); return ret; } diff --git a/drivers/clk/clk_fixed_factor.c b/drivers/clk/clk_fixed_factor.c index e51f94a937..1379992d56 100644 --- a/drivers/clk/clk_fixed_factor.c +++ b/drivers/clk/clk_fixed_factor.c @@ -5,10 +5,13 @@ * Author: Anup Patel */ +#define LOG_CATEGORY UCLASS_CLK + #include #include #include #include +#include #include struct clk_fixed_factor { diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c index 325a9b2dcf..01a6d59af9 100644 --- a/drivers/clk/clk_fixed_rate.c +++ b/drivers/clk/clk_fixed_rate.c @@ -3,9 +3,12 @@ * Copyright (C) 2016 Masahiro Yamada */ +#define LOG_CATEGORY UCLASS_CLK + #include #include #include +#include #include #include diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c index 93a4819501..57022685e2 100644 --- a/drivers/clk/clk_scmi.c +++ b/drivers/clk/clk_scmi.c @@ -2,12 +2,61 @@ /* * Copyright (C) 2019-2020 Linaro Limited */ + +#define LOG_CATEGORY UCLASS_CLK + #include #include #include #include #include #include +#include + +static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks) +{ + struct scmi_clk_protocol_attr_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_CLOCK, + .message_id = SCMI_PROTOCOL_ATTRIBUTES, + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + *num_clocks = out.attributes & SCMI_CLK_PROTO_ATTR_COUNT_MASK; + + return 0; +} + +static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name) +{ + struct scmi_clk_attribute_in in = { + .clock_id = clkid, + }; + struct scmi_clk_attribute_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_CLOCK, + .message_id = SCMI_CLOCK_ATTRIBUTES, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + *name = out.clock_name; + + return 0; +} static int scmi_clk_gate(struct clk *clk, int enable) { @@ -21,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable) in, out); int ret; - ret = devm_scmi_process_msg(clk->dev->parent, &msg); + ret = devm_scmi_process_msg(clk->dev, &msg); if (ret) return ret; @@ -49,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk) in, out); int ret; - ret = devm_scmi_process_msg(clk->dev->parent, &msg); + ret = devm_scmi_process_msg(clk->dev, &msg); if (ret < 0) return ret; @@ -74,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) in, out); int ret; - ret = devm_scmi_process_msg(clk->dev->parent, &msg); + ret = devm_scmi_process_msg(clk->dev, &msg); if (ret < 0) return ret; @@ -85,6 +134,49 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) return scmi_clk_get_rate(clk); } +static int scmi_clk_probe(struct udevice *dev) +{ + struct clk *clk; + size_t num_clocks, i; + int ret; + + if (!CONFIG_IS_ENABLED(CLK_CCF)) + return 0; + + /* register CCF children: CLK UCLASS, no probed again */ + if (device_get_uclass_id(dev->parent) == UCLASS_CLK) + return 0; + + ret = scmi_clk_get_num_clock(dev, &num_clocks); + if (ret) + return ret; + + for (i = 0; i < num_clocks; i++) { + char *name; + + if (!scmi_clk_get_attibute(dev, i, &name)) { + char *clock_name = strdup(name); + + clk = kzalloc(sizeof(*clk), GFP_KERNEL); + if (!clk || !clock_name) + ret = -ENOMEM; + else + ret = clk_register(clk, dev->driver->name, + clock_name, dev->name); + + if (ret) { + free(clk); + free(clock_name); + return ret; + } + + clk_dm(i, clk); + } + } + + return 0; +} + static const struct clk_ops scmi_clk_ops = { .enable = scmi_clk_enable, .disable = scmi_clk_disable, @@ -96,4 +188,5 @@ U_BOOT_DRIVER(scmi_clock) = { .name = "scmi_clk", .id = UCLASS_CLK, .ops = &scmi_clk_ops, + .probe = &scmi_clk_probe, }; diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index 114192bb32..a02921c43a 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -27,12 +27,10 @@ DECLARE_GLOBAL_DATA_PTR; -#ifndef CONFIG_TFABOOT -#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) +#if defined(CONFIG_SPL_BUILD) /* activate clock tree initialization in the driver */ #define STM32MP1_CLOCK_TREE_INIT #endif -#endif #define MAX_HSI_HZ 64000000 @@ -964,6 +962,24 @@ static ulong stm32mp1_read_pll_freq(struct stm32mp1_clk_priv *priv, return dfout; } +static ulong stm32mp1_clk_get_by_name(const char *name) +{ + struct clk clk; + struct udevice *dev = NULL; + ulong clock = 0; + + if (!uclass_get_device_by_name(UCLASS_CLK, name, &dev)) { + if (clk_request(dev, &clk)) { + log_err("%s request", name); + } else { + clk.id = 0; + clock = clk_get_rate(&clk); + } + } + + return clock; +} + static ulong stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) { u32 reg; @@ -1129,24 +1145,11 @@ static ulong stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) break; /* other */ case _USB_PHY_48: - clock = 48000000; + clock = stm32mp1_clk_get_by_name("ck_usbo_48m"); break; case _DSI_PHY: - { - struct clk clk; - struct udevice *dev = NULL; - - if (!uclass_get_device_by_name(UCLASS_CLK, "ck_dsi_phy", - &dev)) { - if (clk_request(dev, &clk)) { - log_err("ck_dsi_phy request"); - } else { - clk.id = 0; - clock = clk_get_rate(&clk); - } - } + clock = stm32mp1_clk_get_by_name("ck_dsi_phy"); break; - } default: break; } diff --git a/drivers/clk/stm32mp13_rcc.h b/drivers/clk/stm32mp13_rcc.h new file mode 100644 index 0000000000..61b2293a9b --- /dev/null +++ b/drivers/clk/stm32mp13_rcc.h @@ -0,0 +1,1750 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + * + * Configuration settings for the STM32MP13x CPU + */ + +#ifndef STM32MP13_RCC_H +#define STM32MP13_RCC_H +/* RCC registers */ +#define RCC_SECCFGR 0x0 +#define RCC_MP_SREQSETR 0x100 +#define RCC_MP_SREQCLRR 0x104 +#define RCC_MP_APRSTCR 0x108 +#define RCC_MP_APRSTSR 0x10c +#define RCC_PWRLPDLYCR 0x110 +#define RCC_MP_GRSTCSETR 0x114 +#define RCC_BR_RSTSCLRR 0x118 +#define RCC_MP_RSTSSETR 0x11c +#define RCC_MP_RSTSCLRR 0x120 +#define RCC_MP_IWDGFZSETR 0x124 +#define RCC_MP_IWDGFZCLRR 0x128 +#define RCC_MP_CIER 0x200 +#define RCC_MP_CIFR 0x204 +#define RCC_BDCR 0x400 +#define RCC_RDLSICR 0x404 +#define RCC_OCENSETR 0x420 +#define RCC_OCENCLRR 0x424 +#define RCC_OCRDYR 0x428 +#define RCC_HSICFGR 0x440 +#define RCC_CSICFGR 0x444 +#define RCC_MCO1CFGR 0x460 +#define RCC_MCO2CFGR 0x464 +#define RCC_DBGCFGR 0x468 +#define RCC_RCK12SELR 0x480 +#define RCC_RCK3SELR 0x484 +#define RCC_RCK4SELR 0x488 +#define RCC_PLL1CR 0x4a0 +#define RCC_PLL1CFGR1 0x4a4 +#define RCC_PLL1CFGR2 0x4a8 +#define RCC_PLL1FRACR 0x4ac +#define RCC_PLL1CSGR 0x4b0 +#define RCC_PLL2CR 0x4d0 +#define RCC_PLL2CFGR1 0x4d4 +#define RCC_PLL2CFGR2 0x4d8 +#define RCC_PLL2FRACR 0x4dc +#define RCC_PLL2CSGR 0x4e0 +#define RCC_PLL3CR 0x500 +#define RCC_PLL3CFGR1 0x504 +#define RCC_PLL3CFGR2 0x508 +#define RCC_PLL3FRACR 0x50c +#define RCC_PLL3CSGR 0x510 +#define RCC_PLL4CR 0x520 +#define RCC_PLL4CFGR1 0x524 +#define RCC_PLL4CFGR2 0x528 +#define RCC_PLL4FRACR 0x52c +#define RCC_PLL4CSGR 0x530 +#define RCC_MPCKSELR 0x540 +#define RCC_ASSCKSELR 0x544 +#define RCC_MSSCKSELR 0x548 +#define RCC_CPERCKSELR 0x54c +#define RCC_RTCDIVR 0x560 +#define RCC_MPCKDIVR 0x564 +#define RCC_AXIDIVR 0x568 +#define RCC_MLAHBDIVR 0x56c +#define RCC_APB1DIVR 0x570 +#define RCC_APB2DIVR 0x574 +#define RCC_APB3DIVR 0x578 +#define RCC_APB4DIVR 0x57c +#define RCC_APB5DIVR 0x580 +#define RCC_APB6DIVR 0x584 +#define RCC_TIMG1PRER 0x5a0 +#define RCC_TIMG2PRER 0x5a4 +#define RCC_TIMG3PRER 0x5a8 +#define RCC_DDRITFCR 0x5c0 +#define RCC_I2C12CKSELR 0x600 +#define RCC_I2C345CKSELR 0x604 +#define RCC_SPI2S1CKSELR 0x608 +#define RCC_SPI2S23CKSELR 0x60c +#define RCC_SPI45CKSELR 0x610 +#define RCC_UART12CKSELR 0x614 +#define RCC_UART35CKSELR 0x618 +#define RCC_UART4CKSELR 0x61c +#define RCC_UART6CKSELR 0x620 +#define RCC_UART78CKSELR 0x624 +#define RCC_LPTIM1CKSELR 0x628 +#define RCC_LPTIM23CKSELR 0x62c +#define RCC_LPTIM45CKSELR 0x630 +#define RCC_SAI1CKSELR 0x634 +#define RCC_SAI2CKSELR 0x638 +#define RCC_FDCANCKSELR 0x63c +#define RCC_SPDIFCKSELR 0x640 +#define RCC_ADC12CKSELR 0x644 +#define RCC_SDMMC12CKSELR 0x648 +#define RCC_ETH12CKSELR 0x64c +#define RCC_USBCKSELR 0x650 +#define RCC_QSPICKSELR 0x654 +#define RCC_FMCCKSELR 0x658 +#define RCC_RNG1CKSELR 0x65c +#define RCC_STGENCKSELR 0x660 +#define RCC_DCMIPPCKSELR 0x664 +#define RCC_SAESCKSELR 0x668 +#define RCC_APB1RSTSETR 0x6a0 +#define RCC_APB1RSTCLRR 0x6a4 +#define RCC_APB2RSTSETR 0x6a8 +#define RCC_APB2RSTCLRR 0x6ac +#define RCC_APB3RSTSETR 0x6b0 +#define RCC_APB3RSTCLRR 0x6b4 +#define RCC_APB4RSTSETR 0x6b8 +#define RCC_APB4RSTCLRR 0x6bc +#define RCC_APB5RSTSETR 0x6c0 +#define RCC_APB5RSTCLRR 0x6c4 +#define RCC_APB6RSTSETR 0x6c8 +#define RCC_APB6RSTCLRR 0x6cc +#define RCC_AHB2RSTSETR 0x6d0 +#define RCC_AHB2RSTCLRR 0x6d4 +#define RCC_AHB4RSTSETR 0x6e0 +#define RCC_AHB4RSTCLRR 0x6e4 +#define RCC_AHB5RSTSETR 0x6e8 +#define RCC_AHB5RSTCLRR 0x6ec +#define RCC_AHB6RSTSETR 0x6f0 +#define RCC_AHB6RSTCLRR 0x6f4 +#define RCC_MP_APB1ENSETR 0x700 +#define RCC_MP_APB1ENCLRR 0x704 +#define RCC_MP_APB2ENSETR 0x708 +#define RCC_MP_APB2ENCLRR 0x70c +#define RCC_MP_APB3ENSETR 0x710 +#define RCC_MP_APB3ENCLRR 0x714 +#define RCC_MP_S_APB3ENSETR 0x718 +#define RCC_MP_S_APB3ENCLRR 0x71c +#define RCC_MP_NS_APB3ENSETR 0x720 +#define RCC_MP_NS_APB3ENCLRR 0x724 +#define RCC_MP_APB4ENSETR 0x728 +#define RCC_MP_APB4ENCLRR 0x72c +#define RCC_MP_S_APB4ENSETR 0x730 +#define RCC_MP_S_APB4ENCLRR 0x734 +#define RCC_MP_NS_APB4ENSETR 0x738 +#define RCC_MP_NS_APB4ENCLRR 0x73c +#define RCC_MP_APB5ENSETR 0x740 +#define RCC_MP_APB5ENCLRR 0x744 +#define RCC_MP_APB6ENSETR 0x748 +#define RCC_MP_APB6ENCLRR 0x74c +#define RCC_MP_AHB2ENSETR 0x750 +#define RCC_MP_AHB2ENCLRR 0x754 +#define RCC_MP_AHB4ENSETR 0x760 +#define RCC_MP_AHB4ENCLRR 0x764 +#define RCC_MP_S_AHB4ENSETR 0x768 +#define RCC_MP_S_AHB4ENCLRR 0x76c +#define RCC_MP_NS_AHB4ENSETR 0x770 +#define RCC_MP_NS_AHB4ENCLRR 0x774 +#define RCC_MP_AHB5ENSETR 0x778 +#define RCC_MP_AHB5ENCLRR 0x77c +#define RCC_MP_AHB6ENSETR 0x780 +#define RCC_MP_AHB6ENCLRR 0x784 +#define RCC_MP_S_AHB6ENSETR 0x788 +#define RCC_MP_S_AHB6ENCLRR 0x78c +#define RCC_MP_NS_AHB6ENSETR 0x790 +#define RCC_MP_NS_AHB6ENCLRR 0x794 +#define RCC_MP_APB1LPENSETR 0x800 +#define RCC_MP_APB1LPENCLRR 0x804 +#define RCC_MP_APB2LPENSETR 0x808 +#define RCC_MP_APB2LPENCLRR 0x80c +#define RCC_MP_APB3LPENSETR 0x810 +#define RCC_MP_APB3LPENCLRR 0x814 +#define RCC_MP_S_APB3LPENSETR 0x818 +#define RCC_MP_S_APB3LPENCLRR 0x81c +#define RCC_MP_NS_APB3LPENSETR 0x820 +#define RCC_MP_NS_APB3LPENCLRR 0x824 +#define RCC_MP_APB4LPENSETR 0x828 +#define RCC_MP_APB4LPENCLRR 0x82c +#define RCC_MP_S_APB4LPENSETR 0x830 +#define RCC_MP_S_APB4LPENCLRR 0x834 +#define RCC_MP_NS_APB4LPENSETR 0x838 +#define RCC_MP_NS_APB4LPENCLRR 0x83c +#define RCC_MP_APB5LPENSETR 0x840 +#define RCC_MP_APB5LPENCLRR 0x844 +#define RCC_MP_APB6LPENSETR 0x848 +#define RCC_MP_APB6LPENCLRR 0x84c +#define RCC_MP_AHB2LPENSETR 0x850 +#define RCC_MP_AHB2LPENCLRR 0x854 +#define RCC_MP_AHB4LPENSETR 0x858 +#define RCC_MP_AHB4LPENCLRR 0x85c +#define RCC_MP_S_AHB4LPENSETR 0x868 +#define RCC_MP_S_AHB4LPENCLRR 0x86c +#define RCC_MP_NS_AHB4LPENSETR 0x870 +#define RCC_MP_NS_AHB4LPENCLRR 0x874 +#define RCC_MP_AHB5LPENSETR 0x878 +#define RCC_MP_AHB5LPENCLRR 0x87c +#define RCC_MP_AHB6LPENSETR 0x880 +#define RCC_MP_AHB6LPENCLRR 0x884 +#define RCC_MP_S_AHB6LPENSETR 0x888 +#define RCC_MP_S_AHB6LPENCLRR 0x88c +#define RCC_MP_NS_AHB6LPENSETR 0x890 +#define RCC_MP_NS_AHB6LPENCLRR 0x894 +#define RCC_MP_S_AXIMLPENSETR 0x898 +#define RCC_MP_S_AXIMLPENCLRR 0x89c +#define RCC_MP_NS_AXIMLPENSETR 0x8a0 +#define RCC_MP_NS_AXIMLPENCLRR 0x8a4 +#define RCC_MP_MLAHBLPENSETR 0x8a8 +#define RCC_MP_MLAHBLPENCLRR 0x8ac +#define RCC_APB3SECSR 0x8c0 +#define RCC_APB4SECSR 0x8c4 +#define RCC_APB5SECSR 0x8c8 +#define RCC_APB6SECSR 0x8cc +#define RCC_AHB2SECSR 0x8d0 +#define RCC_AHB4SECSR 0x8d4 +#define RCC_AHB5SECSR 0x8d8 +#define RCC_AHB6SECSR 0x8dc +#define RCC_VERR 0xff4 +#define RCC_IDR 0xff8 +#define RCC_SIDR 0xffc + +/* RCC_SECCFGR register fields */ +#define RCC_SECCFGR_HSISEC BIT(0) +#define RCC_SECCFGR_CSISEC BIT(1) +#define RCC_SECCFGR_HSESEC BIT(2) +#define RCC_SECCFGR_LSISEC BIT(3) +#define RCC_SECCFGR_LSESEC BIT(4) +#define RCC_SECCFGR_PLL12SEC BIT(8) +#define RCC_SECCFGR_PLL3SEC BIT(9) +#define RCC_SECCFGR_PLL4SEC BIT(10) +#define RCC_SECCFGR_MPUSEC BIT(11) +#define RCC_SECCFGR_AXISEC BIT(12) +#define RCC_SECCFGR_MLAHBSEC BIT(13) +#define RCC_SECCFGR_APB3DIVSEC BIT(16) +#define RCC_SECCFGR_APB4DIVSEC BIT(17) +#define RCC_SECCFGR_APB5DIVSEC BIT(18) +#define RCC_SECCFGR_APB6DIVSEC BIT(19) +#define RCC_SECCFGR_TIMG3SEC BIT(20) +#define RCC_SECCFGR_CPERSEC BIT(21) +#define RCC_SECCFGR_MCO1SEC BIT(22) +#define RCC_SECCFGR_MCO2SEC BIT(23) +#define RCC_SECCFGR_STPSEC BIT(24) +#define RCC_SECCFGR_RSTSEC BIT(25) +#define RCC_SECCFGR_PWRSEC BIT(31) + +#define RCC_SECCFGR_MCO1SECF 22 +#define RCC_SECCFGR_MCO2SECF 23 + +/* RCC_MP_SREQSETR register fields */ +#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) + +/* RCC_MP_SREQCLRR register fields */ +#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) + +/* RCC_MP_APRSTCR register fields */ +#define RCC_MP_APRSTCR_RDCTLEN BIT(0) +#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK(14, 8) +#define RCC_MP_APRSTCR_RSTTO_SHIFT 8 + +/* RCC_MP_APRSTSR register fields */ +#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK(14, 8) +#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 + +/* RCC_PWRLPDLYCR register fields */ +#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) +#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 + +/* RCC_MP_GRSTCSETR register fields */ +#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) +#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) + +/* RCC_BR_RSTSCLRR register fields */ +#define RCC_BR_RSTSCLRR_PORRSTF BIT(0) +#define RCC_BR_RSTSCLRR_BORRSTF BIT(1) +#define RCC_BR_RSTSCLRR_PADRSTF BIT(2) +#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_BR_RSTSCLRR_VCPURSTF BIT(5) +#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) + +/* RCC_MP_RSTSSETR register fields */ +#define RCC_MP_RSTSSETR_PORRSTF BIT(0) +#define RCC_MP_RSTSSETR_BORRSTF BIT(1) +#define RCC_MP_RSTSSETR_PADRSTF BIT(2) +#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSSETR_VCORERSTF BIT(4) +#define RCC_MP_RSTSSETR_VCPURSTF BIT(5) +#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSSETR_STP2RSTF BIT(10) +#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSSETR_SPARE BIT(15) + +/* RCC_MP_RSTSCLRR register fields */ +#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MP_RSTSCLRR_VCPURSTF BIT(5) +#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSCLRR_STP2RSTF BIT(10) +#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSCLRR_SPARE BIT(15) + +/* RCC_MP_IWDGFZSETR register fields */ +#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) + +/* RCC_MP_IWDGFZCLRR register fields */ +#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) + +/* RCC_MP_CIER register fields */ +#define RCC_MP_CIER_LSIRDYIE BIT(0) +#define RCC_MP_CIER_LSERDYIE BIT(1) +#define RCC_MP_CIER_HSIRDYIE BIT(2) +#define RCC_MP_CIER_HSERDYIE BIT(3) +#define RCC_MP_CIER_CSIRDYIE BIT(4) +#define RCC_MP_CIER_PLL1DYIE BIT(8) +#define RCC_MP_CIER_PLL2DYIE BIT(9) +#define RCC_MP_CIER_PLL3DYIE BIT(10) +#define RCC_MP_CIER_PLL4DYIE BIT(11) +#define RCC_MP_CIER_LSECSSIE BIT(16) +#define RCC_MP_CIER_WKUPIE BIT(20) + +/* RCC_MP_CIFR register fields */ +#define RCC_MP_CIFR_LSIRDYF BIT(0) +#define RCC_MP_CIFR_LSERDYF BIT(1) +#define RCC_MP_CIFR_HSIRDYF BIT(2) +#define RCC_MP_CIFR_HSERDYF BIT(3) +#define RCC_MP_CIFR_CSIRDYF BIT(4) +#define RCC_MP_CIFR_PLL1DYF BIT(8) +#define RCC_MP_CIFR_PLL2DYF BIT(9) +#define RCC_MP_CIFR_PLL3DYF BIT(10) +#define RCC_MP_CIFR_PLL4DYF BIT(11) +#define RCC_MP_CIFR_LSECSSF BIT(16) +#define RCC_MP_CIFR_WKUPF BIT(20) + +/* RCC_BDCR register fields */ +#define RCC_BDCR_LSEON BIT(0) +#define RCC_BDCR_LSEBYP BIT(1) +#define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) +#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) +#define RCC_BDCR_LSECSSON BIT(8) +#define RCC_BDCR_LSECSSD BIT(9) +#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) +#define RCC_BDCR_RTCCKEN BIT(20) +#define RCC_BDCR_VSWRST BIT(31) +#define RCC_BDCR_LSEDRV_SHIFT 4 +#define RCC_BDCR_RTCSRC_SHIFT 16 + +/* RCC_RDLSICR register fields */ +#define RCC_RDLSICR_LSION BIT(0) +#define RCC_RDLSICR_LSIRDY BIT(1) +#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16) +#define RCC_RDLSICR_EADLY_MASK GENMASK(26, 24) +#define RCC_RDLSICR_SPARE_MASK GENMASK(31, 27) +#define RCC_RDLSICR_MRD_SHIFT 16 +#define RCC_RDLSICR_EADLY_SHIFT 24 +#define RCC_RDLSICR_SPARE_SHIFT 27 + +/* RCC_OCENSETR register fields */ +#define RCC_OCENSETR_HSION BIT(0) +#define RCC_OCENSETR_HSIKERON BIT(1) +#define RCC_OCENSETR_CSION BIT(4) +#define RCC_OCENSETR_CSIKERON BIT(5) +#define RCC_OCENSETR_DIGBYP BIT(7) +#define RCC_OCENSETR_HSEON BIT(8) +#define RCC_OCENSETR_HSEKERON BIT(9) +#define RCC_OCENSETR_HSEBYP BIT(10) +#define RCC_OCENSETR_HSECSSON BIT(11) + +/* RCC_OCENCLRR register fields */ +#define RCC_OCENCLRR_HSION BIT(0) +#define RCC_OCENCLRR_HSIKERON BIT(1) +#define RCC_OCENCLRR_CSION BIT(4) +#define RCC_OCENCLRR_CSIKERON BIT(5) +#define RCC_OCENCLRR_DIGBYP BIT(7) +#define RCC_OCENCLRR_HSEON BIT(8) +#define RCC_OCENCLRR_HSEKERON BIT(9) +#define RCC_OCENCLRR_HSEBYP BIT(10) + +/* RCC_OCRDYR register fields */ +#define RCC_OCRDYR_HSIRDY BIT(0) +#define RCC_OCRDYR_HSIDIVRDY BIT(2) +#define RCC_OCRDYR_CSIRDY BIT(4) +#define RCC_OCRDYR_HSERDY BIT(8) +#define RCC_OCRDYR_MPUCKRDY BIT(23) +#define RCC_OCRDYR_AXICKRDY BIT(24) + +/* RCC_HSICFGR register fields */ +#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) +#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) +#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16) +#define RCC_HSICFGR_HSIDIV_SHIFT 0 +#define RCC_HSICFGR_HSITRIM_SHIFT 8 +#define RCC_HSICFGR_HSICAL_SHIFT 16 + +/* RCC_CSICFGR register fields */ +#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) +#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) +#define RCC_CSICFGR_CSITRIM_SHIFT 8 +#define RCC_CSICFGR_CSICAL_SHIFT 16 + +/* RCC_MCO1CFGR register fields */ +#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK(2, 0) +#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK(7, 4) +#define RCC_MCO1CFGR_MCO1ON BIT(12) +#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 +#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 + +/* RCC_MCO2CFGR register fields */ +#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK(2, 0) +#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK(7, 4) +#define RCC_MCO2CFGR_MCO2ON BIT(12) +#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 +#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 + +/* RCC_DBGCFGR register fields */ +#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK(2, 0) +#define RCC_DBGCFGR_DBGCKEN BIT(8) +#define RCC_DBGCFGR_TRACECKEN BIT(9) +#define RCC_DBGCFGR_DBGRST BIT(12) +#define RCC_DBGCFGR_TRACEDIV_SHIFT 0 + +/* RCC_RCK12SELR register fields */ +#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK(1, 0) +#define RCC_RCK12SELR_PLL12SRCRDY BIT(31) +#define RCC_RCK12SELR_PLL12SRC_SHIFT 0 + +/* RCC_RCK3SELR register fields */ +#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK(1, 0) +#define RCC_RCK3SELR_PLL3SRCRDY BIT(31) +#define RCC_RCK3SELR_PLL3SRC_SHIFT 0 + +/* RCC_RCK4SELR register fields */ +#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK(1, 0) +#define RCC_RCK4SELR_PLL4SRCRDY BIT(31) +#define RCC_RCK4SELR_PLL4SRC_SHIFT 0 + +/* RCC_PLL1CR register fields */ +#define RCC_PLL1CR_PLLON BIT(0) +#define RCC_PLL1CR_PLL1RDY BIT(1) +#define RCC_PLL1CR_SSCG_CTRL BIT(2) +#define RCC_PLL1CR_DIVPEN BIT(4) +#define RCC_PLL1CR_DIVQEN BIT(5) +#define RCC_PLL1CR_DIVREN BIT(6) + +/* RCC_PLL1CFGR1 register fields */ +#define RCC_PLL1CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK(21, 16) +#define RCC_PLL1CFGR1_DIVN_SHIFT 0 +#define RCC_PLL1CFGR1_DIVM1_SHIFT 16 + +/* RCC_PLL1CFGR2 register fields */ +#define RCC_PLL1CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL1CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL1CFGR2_DIVP_SHIFT 0 +#define RCC_PLL1CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL1CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL1FRACR register fields */ +#define RCC_PLL1FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL1FRACR_FRACLE BIT(16) +#define RCC_PLL1FRACR_FRACV_SHIFT 3 + +/* RCC_PLL1CSGR register fields */ +#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL1CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL1CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL1CSGR_SSCG_MODE BIT(15) +#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL1CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL1CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL2CR register fields */ +#define RCC_PLL2CR_PLLON BIT(0) +#define RCC_PLL2CR_PLL2RDY BIT(1) +#define RCC_PLL2CR_SSCG_CTRL BIT(2) +#define RCC_PLL2CR_DIVPEN BIT(4) +#define RCC_PLL2CR_DIVQEN BIT(5) +#define RCC_PLL2CR_DIVREN BIT(6) + +/* RCC_PLL2CFGR1 register fields */ +#define RCC_PLL2CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK(21, 16) +#define RCC_PLL2CFGR1_DIVN_SHIFT 0 +#define RCC_PLL2CFGR1_DIVM2_SHIFT 16 + +/* RCC_PLL2CFGR2 register fields */ +#define RCC_PLL2CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL2CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL2CFGR2_DIVP_SHIFT 0 +#define RCC_PLL2CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL2CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL2FRACR register fields */ +#define RCC_PLL2FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL2FRACR_FRACLE BIT(16) +#define RCC_PLL2FRACR_FRACV_SHIFT 3 + +/* RCC_PLL2CSGR register fields */ +#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL2CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL2CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL2CSGR_SSCG_MODE BIT(15) +#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL2CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL2CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL3CR register fields */ +#define RCC_PLL3CR_PLLON BIT(0) +#define RCC_PLL3CR_PLL3RDY BIT(1) +#define RCC_PLL3CR_SSCG_CTRL BIT(2) +#define RCC_PLL3CR_DIVPEN BIT(4) +#define RCC_PLL3CR_DIVQEN BIT(5) +#define RCC_PLL3CR_DIVREN BIT(6) + +/* RCC_PLL3CFGR1 register fields */ +#define RCC_PLL3CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK(21, 16) +#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL3CFGR1_DIVN_SHIFT 0 +#define RCC_PLL3CFGR1_DIVM3_SHIFT 16 +#define RCC_PLL3CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL3CFGR2 register fields */ +#define RCC_PLL3CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL3CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL3CFGR2_DIVP_SHIFT 0 +#define RCC_PLL3CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL3CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL3FRACR register fields */ +#define RCC_PLL3FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL3FRACR_FRACLE BIT(16) +#define RCC_PLL3FRACR_FRACV_SHIFT 3 + +/* RCC_PLL3CSGR register fields */ +#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL3CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL3CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL3CSGR_SSCG_MODE BIT(15) +#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL3CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL3CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL4CR register fields */ +#define RCC_PLL4CR_PLLON BIT(0) +#define RCC_PLL4CR_PLL4RDY BIT(1) +#define RCC_PLL4CR_SSCG_CTRL BIT(2) +#define RCC_PLL4CR_DIVPEN BIT(4) +#define RCC_PLL4CR_DIVQEN BIT(5) +#define RCC_PLL4CR_DIVREN BIT(6) + +/* RCC_PLL4CFGR1 register fields */ +#define RCC_PLL4CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK(21, 16) +#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL4CFGR1_DIVN_SHIFT 0 +#define RCC_PLL4CFGR1_DIVM4_SHIFT 16 +#define RCC_PLL4CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL4CFGR2 register fields */ +#define RCC_PLL4CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL4CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL4CFGR2_DIVP_SHIFT 0 +#define RCC_PLL4CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL4CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL4FRACR register fields */ +#define RCC_PLL4FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL4FRACR_FRACLE BIT(16) +#define RCC_PLL4FRACR_FRACV_SHIFT 3 + +/* RCC_PLL4CSGR register fields */ +#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL4CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL4CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL4CSGR_SSCG_MODE BIT(15) +#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL4CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL4CSGR_INC_STEP_SHIFT 16 + +/* RCC_MPCKSELR register fields */ +#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0) +#define RCC_MPCKSELR_MPUSRCRDY BIT(31) +#define RCC_MPCKSELR_MPUSRC_SHIFT 0 + +/* RCC_ASSCKSELR register fields */ +#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) +#define RCC_ASSCKSELR_AXISSRCRDY BIT(31) +#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 + +/* RCC_MSSCKSELR register fields */ +#define RCC_MSSCKSELR_MLAHBSSRC_MASK GENMASK(1, 0) +#define RCC_MSSCKSELR_MLAHBSSRCRDY BIT(31) +#define RCC_MSSCKSELR_MLAHBSSRC_SHIFT 0 + +/* RCC_CPERCKSELR register fields */ +#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK(1, 0) +#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 + +/* RCC_RTCDIVR register fields */ +#define RCC_RTCDIVR_RTCDIV_MASK GENMASK(5, 0) +#define RCC_RTCDIVR_RTCDIV_SHIFT 0 + +/* RCC_MPCKDIVR register fields */ +#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK(3, 0) +#define RCC_MPCKDIVR_MPUDIVRDY BIT(31) +#define RCC_MPCKDIVR_MPUDIV_SHIFT 0 + +/* RCC_AXIDIVR register fields */ +#define RCC_AXIDIVR_AXIDIV_MASK GENMASK(2, 0) +#define RCC_AXIDIVR_AXIDIVRDY BIT(31) +#define RCC_AXIDIVR_AXIDIV_SHIFT 0 + +/* RCC_MLAHBDIVR register fields */ +#define RCC_MLAHBDIVR_MLAHBDIV_MASK GENMASK(3, 0) +#define RCC_MLAHBDIVR_MLAHBDIVRDY BIT(31) +#define RCC_MLAHBDIVR_MLAHBDIV_SHIFT 0 + +/* RCC_APB1DIVR register fields */ +#define RCC_APB1DIVR_APB1DIV_MASK GENMASK(2, 0) +#define RCC_APB1DIVR_APB1DIVRDY BIT(31) +#define RCC_APB1DIVR_APB1DIV_SHIFT 0 + +/* RCC_APB2DIVR register fields */ +#define RCC_APB2DIVR_APB2DIV_MASK GENMASK(2, 0) +#define RCC_APB2DIVR_APB2DIVRDY BIT(31) +#define RCC_APB2DIVR_APB2DIV_SHIFT 0 + +/* RCC_APB3DIVR register fields */ +#define RCC_APB3DIVR_APB3DIV_MASK GENMASK(2, 0) +#define RCC_APB3DIVR_APB3DIVRDY BIT(31) +#define RCC_APB3DIVR_APB3DIV_SHIFT 0 + +/* RCC_APB4DIVR register fields */ +#define RCC_APB4DIVR_APB4DIV_MASK GENMASK(2, 0) +#define RCC_APB4DIVR_APB4DIVRDY BIT(31) +#define RCC_APB4DIVR_APB4DIV_SHIFT 0 + +/* RCC_APB5DIVR register fields */ +#define RCC_APB5DIVR_APB5DIV_MASK GENMASK(2, 0) +#define RCC_APB5DIVR_APB5DIVRDY BIT(31) +#define RCC_APB5DIVR_APB5DIV_SHIFT 0 + +/* RCC_APB6DIVR register fields */ +#define RCC_APB6DIVR_APB6DIV_MASK GENMASK(2, 0) +#define RCC_APB6DIVR_APB6DIVRDY BIT(31) +#define RCC_APB6DIVR_APB6DIV_SHIFT 0 + +/* RCC_TIMG1PRER register fields */ +#define RCC_TIMG1PRER_TIMG1PRE BIT(0) +#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) + +/* RCC_TIMG2PRER register fields */ +#define RCC_TIMG2PRER_TIMG2PRE BIT(0) +#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) + +/* RCC_TIMG3PRER register fields */ +#define RCC_TIMG3PRER_TIMG3PRE BIT(0) +#define RCC_TIMG3PRER_TIMG3PRERDY BIT(31) + +/* RCC_DDRITFCR register fields */ +#define RCC_DDRITFCR_DDRC1EN BIT(0) +#define RCC_DDRITFCR_DDRC1LPEN BIT(1) +#define RCC_DDRITFCR_DDRPHYCEN BIT(4) +#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) +#define RCC_DDRITFCR_DDRCAPBEN BIT(6) +#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) +#define RCC_DDRITFCR_AXIDCGEN BIT(8) +#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) +#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) +#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK(13, 11) +#define RCC_DDRITFCR_DDRCAPBRST BIT(14) +#define RCC_DDRITFCR_DDRCAXIRST BIT(15) +#define RCC_DDRITFCR_DDRCORERST BIT(16) +#define RCC_DDRITFCR_DPHYAPBRST BIT(17) +#define RCC_DDRITFCR_DPHYRST BIT(18) +#define RCC_DDRITFCR_DPHYCTLRST BIT(19) +#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) +#define RCC_DDRITFCR_GSKPMOD BIT(23) +#define RCC_DDRITFCR_GSKPCTRL BIT(24) +#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK(27, 25) +#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK(31, 28) +#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 +#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 +#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 +#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 + +/* RCC_I2C12CKSELR register fields */ +#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0) +#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 + +/* RCC_I2C345CKSELR register fields */ +#define RCC_I2C345CKSELR_I2C3SRC_MASK GENMASK(2, 0) +#define RCC_I2C345CKSELR_I2C4SRC_MASK GENMASK(5, 3) +#define RCC_I2C345CKSELR_I2C5SRC_MASK GENMASK(8, 6) +#define RCC_I2C345CKSELR_I2C3SRC_SHIFT 0 +#define RCC_I2C345CKSELR_I2C4SRC_SHIFT 3 +#define RCC_I2C345CKSELR_I2C5SRC_SHIFT 6 + +/* RCC_SPI2S1CKSELR register fields */ +#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 + +/* RCC_SPI2S23CKSELR register fields */ +#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 + +/* RCC_SPI45CKSELR register fields */ +#define RCC_SPI45CKSELR_SPI4SRC_MASK GENMASK(2, 0) +#define RCC_SPI45CKSELR_SPI5SRC_MASK GENMASK(5, 3) +#define RCC_SPI45CKSELR_SPI4SRC_SHIFT 0 +#define RCC_SPI45CKSELR_SPI5SRC_SHIFT 3 + +/* RCC_UART12CKSELR register fields */ +#define RCC_UART12CKSELR_UART1SRC_MASK GENMASK(2, 0) +#define RCC_UART12CKSELR_UART2SRC_MASK GENMASK(5, 3) +#define RCC_UART12CKSELR_UART1SRC_SHIFT 0 +#define RCC_UART12CKSELR_UART2SRC_SHIFT 3 + +/* RCC_UART35CKSELR register fields */ +#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0) +#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 + +/* RCC_UART4CKSELR register fields */ +#define RCC_UART4CKSELR_UART4SRC_MASK GENMASK(2, 0) +#define RCC_UART4CKSELR_UART4SRC_SHIFT 0 + +/* RCC_UART6CKSELR register fields */ +#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0) +#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 + +/* RCC_UART78CKSELR register fields */ +#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0) +#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 + +/* RCC_LPTIM1CKSELR register fields */ +#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 + +/* RCC_LPTIM23CKSELR register fields */ +#define RCC_LPTIM23CKSELR_LPTIM2SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM23CKSELR_LPTIM3SRC_MASK GENMASK(5, 3) +#define RCC_LPTIM23CKSELR_LPTIM2SRC_SHIFT 0 +#define RCC_LPTIM23CKSELR_LPTIM3SRC_SHIFT 3 + +/* RCC_LPTIM45CKSELR register fields */ +#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 + +/* RCC_SAI1CKSELR register fields */ +#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK(2, 0) +#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 + +/* RCC_SAI2CKSELR register fields */ +#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK(2, 0) +#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 + +/* RCC_FDCANCKSELR register fields */ +#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK(1, 0) +#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 + +/* RCC_SPDIFCKSELR register fields */ +#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK(1, 0) +#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 + +/* RCC_ADC12CKSELR register fields */ +#define RCC_ADC12CKSELR_ADC1SRC_MASK GENMASK(1, 0) +#define RCC_ADC12CKSELR_ADC2SRC_MASK GENMASK(3, 2) +#define RCC_ADC12CKSELR_ADC1SRC_SHIFT 0 +#define RCC_ADC12CKSELR_ADC2SRC_SHIFT 2 + +/* RCC_SDMMC12CKSELR register fields */ +#define RCC_SDMMC12CKSELR_SDMMC1SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC12CKSELR_SDMMC2SRC_MASK GENMASK(5, 3) +#define RCC_SDMMC12CKSELR_SDMMC1SRC_SHIFT 0 +#define RCC_SDMMC12CKSELR_SDMMC2SRC_SHIFT 3 + +/* RCC_ETH12CKSELR register fields */ +#define RCC_ETH12CKSELR_ETH1SRC_MASK GENMASK(1, 0) +#define RCC_ETH12CKSELR_ETH1PTPDIV_MASK GENMASK(7, 4) +#define RCC_ETH12CKSELR_ETH2SRC_MASK GENMASK(9, 8) +#define RCC_ETH12CKSELR_ETH2PTPDIV_MASK GENMASK(15, 12) +#define RCC_ETH12CKSELR_ETH1SRC_SHIFT 0 +#define RCC_ETH12CKSELR_ETH1PTPDIV_SHIFT 4 +#define RCC_ETH12CKSELR_ETH2SRC_SHIFT 8 +#define RCC_ETH12CKSELR_ETH2PTPDIV_SHIFT 12 + +/* RCC_USBCKSELR register fields */ +#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) +#define RCC_USBCKSELR_USBOSRC BIT(4) +#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 + +/* RCC_QSPICKSELR register fields */ +#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0) +#define RCC_QSPICKSELR_QSPISRC_SHIFT 0 + +/* RCC_FMCCKSELR register fields */ +#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0) +#define RCC_FMCCKSELR_FMCSRC_SHIFT 0 + +/* RCC_RNG1CKSELR register fields */ +#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0) +#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 + +/* RCC_STGENCKSELR register fields */ +#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) +#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 + +/* RCC_DCMIPPCKSELR register fields */ +#define RCC_DCMIPPCKSELR_DCMIPPSRC_MASK GENMASK(1, 0) +#define RCC_DCMIPPCKSELR_DCMIPPSRC_SHIFT 0 + +/* RCC_SAESCKSELR register fields */ +#define RCC_SAESCKSELR_SAESSRC_MASK GENMASK(1, 0) +#define RCC_SAESCKSELR_SAESSRC_SHIFT 0 + +/* RCC_APB1RSTSETR register fields */ +#define RCC_APB1RSTSETR_TIM2RST BIT(0) +#define RCC_APB1RSTSETR_TIM3RST BIT(1) +#define RCC_APB1RSTSETR_TIM4RST BIT(2) +#define RCC_APB1RSTSETR_TIM5RST BIT(3) +#define RCC_APB1RSTSETR_TIM6RST BIT(4) +#define RCC_APB1RSTSETR_TIM7RST BIT(5) +#define RCC_APB1RSTSETR_LPTIM1RST BIT(9) +#define RCC_APB1RSTSETR_SPI2RST BIT(11) +#define RCC_APB1RSTSETR_SPI3RST BIT(12) +#define RCC_APB1RSTSETR_USART3RST BIT(15) +#define RCC_APB1RSTSETR_UART4RST BIT(16) +#define RCC_APB1RSTSETR_UART5RST BIT(17) +#define RCC_APB1RSTSETR_UART7RST BIT(18) +#define RCC_APB1RSTSETR_UART8RST BIT(19) +#define RCC_APB1RSTSETR_I2C1RST BIT(21) +#define RCC_APB1RSTSETR_I2C2RST BIT(22) +#define RCC_APB1RSTSETR_SPDIFRST BIT(26) + +/* RCC_APB1RSTCLRR register fields */ +#define RCC_APB1RSTCLRR_TIM2RST BIT(0) +#define RCC_APB1RSTCLRR_TIM3RST BIT(1) +#define RCC_APB1RSTCLRR_TIM4RST BIT(2) +#define RCC_APB1RSTCLRR_TIM5RST BIT(3) +#define RCC_APB1RSTCLRR_TIM6RST BIT(4) +#define RCC_APB1RSTCLRR_TIM7RST BIT(5) +#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) +#define RCC_APB1RSTCLRR_SPI2RST BIT(11) +#define RCC_APB1RSTCLRR_SPI3RST BIT(12) +#define RCC_APB1RSTCLRR_USART3RST BIT(15) +#define RCC_APB1RSTCLRR_UART4RST BIT(16) +#define RCC_APB1RSTCLRR_UART5RST BIT(17) +#define RCC_APB1RSTCLRR_UART7RST BIT(18) +#define RCC_APB1RSTCLRR_UART8RST BIT(19) +#define RCC_APB1RSTCLRR_I2C1RST BIT(21) +#define RCC_APB1RSTCLRR_I2C2RST BIT(22) +#define RCC_APB1RSTCLRR_SPDIFRST BIT(26) + +/* RCC_APB2RSTSETR register fields */ +#define RCC_APB2RSTSETR_TIM1RST BIT(0) +#define RCC_APB2RSTSETR_TIM8RST BIT(1) +#define RCC_APB2RSTSETR_SPI1RST BIT(8) +#define RCC_APB2RSTSETR_USART6RST BIT(13) +#define RCC_APB2RSTSETR_SAI1RST BIT(16) +#define RCC_APB2RSTSETR_SAI2RST BIT(17) +#define RCC_APB2RSTSETR_DFSDMRST BIT(20) +#define RCC_APB2RSTSETR_FDCANRST BIT(24) + +/* RCC_APB2RSTCLRR register fields */ +#define RCC_APB2RSTCLRR_TIM1RST BIT(0) +#define RCC_APB2RSTCLRR_TIM8RST BIT(1) +#define RCC_APB2RSTCLRR_SPI1RST BIT(8) +#define RCC_APB2RSTCLRR_USART6RST BIT(13) +#define RCC_APB2RSTCLRR_SAI1RST BIT(16) +#define RCC_APB2RSTCLRR_SAI2RST BIT(17) +#define RCC_APB2RSTCLRR_DFSDMRST BIT(20) +#define RCC_APB2RSTCLRR_FDCANRST BIT(24) + +/* RCC_APB3RSTSETR register fields */ +#define RCC_APB3RSTSETR_LPTIM2RST BIT(0) +#define RCC_APB3RSTSETR_LPTIM3RST BIT(1) +#define RCC_APB3RSTSETR_LPTIM4RST BIT(2) +#define RCC_APB3RSTSETR_LPTIM5RST BIT(3) +#define RCC_APB3RSTSETR_SYSCFGRST BIT(11) +#define RCC_APB3RSTSETR_VREFRST BIT(13) +#define RCC_APB3RSTSETR_DTSRST BIT(16) +#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) + +/* RCC_APB3RSTCLRR register fields */ +#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) +#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) +#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) +#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) +#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) +#define RCC_APB3RSTCLRR_VREFRST BIT(13) +#define RCC_APB3RSTCLRR_DTSRST BIT(16) +#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) + +/* RCC_APB4RSTSETR register fields */ +#define RCC_APB4RSTSETR_LTDCRST BIT(0) +#define RCC_APB4RSTSETR_DCMIPPRST BIT(1) +#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTSETR_USBPHYRST BIT(16) + +/* RCC_APB4RSTCLRR register fields */ +#define RCC_APB4RSTCLRR_LTDCRST BIT(0) +#define RCC_APB4RSTCLRR_DCMIPPRST BIT(1) +#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTCLRR_USBPHYRST BIT(16) + +/* RCC_APB5RSTSETR register fields */ +#define RCC_APB5RSTSETR_STGENRST BIT(20) + +/* RCC_APB5RSTCLRR register fields */ +#define RCC_APB5RSTCLRR_STGENRST BIT(20) + +/* RCC_APB6RSTSETR register fields */ +#define RCC_APB6RSTSETR_USART1RST BIT(0) +#define RCC_APB6RSTSETR_USART2RST BIT(1) +#define RCC_APB6RSTSETR_SPI4RST BIT(2) +#define RCC_APB6RSTSETR_SPI5RST BIT(3) +#define RCC_APB6RSTSETR_I2C3RST BIT(4) +#define RCC_APB6RSTSETR_I2C4RST BIT(5) +#define RCC_APB6RSTSETR_I2C5RST BIT(6) +#define RCC_APB6RSTSETR_TIM12RST BIT(7) +#define RCC_APB6RSTSETR_TIM13RST BIT(8) +#define RCC_APB6RSTSETR_TIM14RST BIT(9) +#define RCC_APB6RSTSETR_TIM15RST BIT(10) +#define RCC_APB6RSTSETR_TIM16RST BIT(11) +#define RCC_APB6RSTSETR_TIM17RST BIT(12) + +/* RCC_APB6RSTCLRR register fields */ +#define RCC_APB6RSTCLRR_USART1RST BIT(0) +#define RCC_APB6RSTCLRR_USART2RST BIT(1) +#define RCC_APB6RSTCLRR_SPI4RST BIT(2) +#define RCC_APB6RSTCLRR_SPI5RST BIT(3) +#define RCC_APB6RSTCLRR_I2C3RST BIT(4) +#define RCC_APB6RSTCLRR_I2C4RST BIT(5) +#define RCC_APB6RSTCLRR_I2C5RST BIT(6) +#define RCC_APB6RSTCLRR_TIM12RST BIT(7) +#define RCC_APB6RSTCLRR_TIM13RST BIT(8) +#define RCC_APB6RSTCLRR_TIM14RST BIT(9) +#define RCC_APB6RSTCLRR_TIM15RST BIT(10) +#define RCC_APB6RSTCLRR_TIM16RST BIT(11) +#define RCC_APB6RSTCLRR_TIM17RST BIT(12) + +/* RCC_AHB2RSTSETR register fields */ +#define RCC_AHB2RSTSETR_DMA1RST BIT(0) +#define RCC_AHB2RSTSETR_DMA2RST BIT(1) +#define RCC_AHB2RSTSETR_DMAMUX1RST BIT(2) +#define RCC_AHB2RSTSETR_DMA3RST BIT(3) +#define RCC_AHB2RSTSETR_DMAMUX2RST BIT(4) +#define RCC_AHB2RSTSETR_ADC1RST BIT(5) +#define RCC_AHB2RSTSETR_ADC2RST BIT(6) +#define RCC_AHB2RSTSETR_USBORST BIT(8) + +/* RCC_AHB2RSTCLRR register fields */ +#define RCC_AHB2RSTCLRR_DMA1RST BIT(0) +#define RCC_AHB2RSTCLRR_DMA2RST BIT(1) +#define RCC_AHB2RSTCLRR_DMAMUX1RST BIT(2) +#define RCC_AHB2RSTCLRR_DMA3RST BIT(3) +#define RCC_AHB2RSTCLRR_DMAMUX2RST BIT(4) +#define RCC_AHB2RSTCLRR_ADC1RST BIT(5) +#define RCC_AHB2RSTCLRR_ADC2RST BIT(6) +#define RCC_AHB2RSTCLRR_USBORST BIT(8) + +/* RCC_AHB4RSTSETR register fields */ +#define RCC_AHB4RSTSETR_GPIOARST BIT(0) +#define RCC_AHB4RSTSETR_GPIOBRST BIT(1) +#define RCC_AHB4RSTSETR_GPIOCRST BIT(2) +#define RCC_AHB4RSTSETR_GPIODRST BIT(3) +#define RCC_AHB4RSTSETR_GPIOERST BIT(4) +#define RCC_AHB4RSTSETR_GPIOFRST BIT(5) +#define RCC_AHB4RSTSETR_GPIOGRST BIT(6) +#define RCC_AHB4RSTSETR_GPIOHRST BIT(7) +#define RCC_AHB4RSTSETR_GPIOIRST BIT(8) +#define RCC_AHB4RSTSETR_TSCRST BIT(15) + +/* RCC_AHB4RSTCLRR register fields */ +#define RCC_AHB4RSTCLRR_GPIOARST BIT(0) +#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) +#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) +#define RCC_AHB4RSTCLRR_GPIODRST BIT(3) +#define RCC_AHB4RSTCLRR_GPIOERST BIT(4) +#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) +#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) +#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) +#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) +#define RCC_AHB4RSTCLRR_TSCRST BIT(15) + +/* RCC_AHB5RSTSETR register fields */ +#define RCC_AHB5RSTSETR_PKARST BIT(2) +#define RCC_AHB5RSTSETR_SAESRST BIT(3) +#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) +#define RCC_AHB5RSTSETR_HASH1RST BIT(5) +#define RCC_AHB5RSTSETR_RNG1RST BIT(6) +#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) + +/* RCC_AHB5RSTCLRR register fields */ +#define RCC_AHB5RSTCLRR_PKARST BIT(2) +#define RCC_AHB5RSTCLRR_SAESRST BIT(3) +#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) +#define RCC_AHB5RSTCLRR_HASH1RST BIT(5) +#define RCC_AHB5RSTCLRR_RNG1RST BIT(6) +#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) + +/* RCC_AHB6RSTSETR register fields */ +#define RCC_AHB6RSTSETR_MDMARST BIT(0) +#define RCC_AHB6RSTSETR_MCERST BIT(1) +#define RCC_AHB6RSTSETR_ETH1MACRST BIT(10) +#define RCC_AHB6RSTSETR_FMCRST BIT(12) +#define RCC_AHB6RSTSETR_QSPIRST BIT(14) +#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTSETR_CRC1RST BIT(20) +#define RCC_AHB6RSTSETR_USBHRST BIT(24) +#define RCC_AHB6RSTSETR_ETH2MACRST BIT(30) + +/* RCC_AHB6RSTCLRR register fields */ +#define RCC_AHB6RSTCLRR_MDMARST BIT(0) +#define RCC_AHB6RSTCLRR_MCERST BIT(1) +#define RCC_AHB6RSTCLRR_ETH1MACRST BIT(10) +#define RCC_AHB6RSTCLRR_FMCRST BIT(12) +#define RCC_AHB6RSTCLRR_QSPIRST BIT(14) +#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTCLRR_CRC1RST BIT(20) +#define RCC_AHB6RSTCLRR_USBHRST BIT(24) +#define RCC_AHB6RSTCLRR_ETH2MACRST BIT(30) + +/* RCC_MP_APB1ENSETR register fields */ +#define RCC_MP_APB1ENSETR_TIM2EN BIT(0) +#define RCC_MP_APB1ENSETR_TIM3EN BIT(1) +#define RCC_MP_APB1ENSETR_TIM4EN BIT(2) +#define RCC_MP_APB1ENSETR_TIM5EN BIT(3) +#define RCC_MP_APB1ENSETR_TIM6EN BIT(4) +#define RCC_MP_APB1ENSETR_TIM7EN BIT(5) +#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENSETR_SPI2EN BIT(11) +#define RCC_MP_APB1ENSETR_SPI3EN BIT(12) +#define RCC_MP_APB1ENSETR_USART3EN BIT(15) +#define RCC_MP_APB1ENSETR_UART4EN BIT(16) +#define RCC_MP_APB1ENSETR_UART5EN BIT(17) +#define RCC_MP_APB1ENSETR_UART7EN BIT(18) +#define RCC_MP_APB1ENSETR_UART8EN BIT(19) +#define RCC_MP_APB1ENSETR_I2C1EN BIT(21) +#define RCC_MP_APB1ENSETR_I2C2EN BIT(22) +#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) + +/* RCC_MP_APB1ENCLRR register fields */ +#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) +#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) +#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) +#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) +#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) +#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) +#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) +#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) +#define RCC_MP_APB1ENCLRR_USART3EN BIT(15) +#define RCC_MP_APB1ENCLRR_UART4EN BIT(16) +#define RCC_MP_APB1ENCLRR_UART5EN BIT(17) +#define RCC_MP_APB1ENCLRR_UART7EN BIT(18) +#define RCC_MP_APB1ENCLRR_UART8EN BIT(19) +#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) +#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) +#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) + +/* RCC_MP_APB2ENSETR register fields */ +#define RCC_MP_APB2ENSETR_TIM1EN BIT(0) +#define RCC_MP_APB2ENSETR_TIM8EN BIT(1) +#define RCC_MP_APB2ENSETR_SPI1EN BIT(8) +#define RCC_MP_APB2ENSETR_USART6EN BIT(13) +#define RCC_MP_APB2ENSETR_SAI1EN BIT(16) +#define RCC_MP_APB2ENSETR_SAI2EN BIT(17) +#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENSETR_FDCANEN BIT(24) + +/* RCC_MP_APB2ENCLRR register fields */ +#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) +#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) +#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) +#define RCC_MP_APB2ENCLRR_USART6EN BIT(13) +#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) +#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) +#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) + +/* RCC_MP_APB3ENSETR register fields */ +#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENSETR_VREFEN BIT(13) +#define RCC_MP_APB3ENSETR_DTSEN BIT(16) +#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENSETR_HDPEN BIT(20) + +/* RCC_MP_APB3ENCLRR register fields */ +#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENCLRR_VREFEN BIT(13) +#define RCC_MP_APB3ENCLRR_DTSEN BIT(16) +#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENCLRR_HDPEN BIT(20) + +/* RCC_MP_S_APB3ENSETR register fields */ +#define RCC_MP_S_APB3ENSETR_SYSCFGEN BIT(0) + +/* RCC_MP_S_APB3ENCLRR register fields */ +#define RCC_MP_S_APB3ENCLRR_SYSCFGEN BIT(0) + +/* RCC_MP_NS_APB3ENSETR register fields */ +#define RCC_MP_NS_APB3ENSETR_SYSCFGEN BIT(0) + +/* RCC_MP_NS_APB3ENCLRR register fields */ +#define RCC_MP_NS_APB3ENCLRR_SYSCFGEN BIT(0) + +/* RCC_MP_APB4ENSETR register fields */ +#define RCC_MP_APB4ENSETR_DCMIPPEN BIT(1) +#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENSETR_STGENROEN BIT(20) + +/* RCC_MP_APB4ENCLRR register fields */ +#define RCC_MP_APB4ENCLRR_DCMIPPEN BIT(1) +#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) + +/* RCC_MP_S_APB4ENSETR register fields */ +#define RCC_MP_S_APB4ENSETR_LTDCEN BIT(0) + +/* RCC_MP_S_APB4ENCLRR register fields */ +#define RCC_MP_S_APB4ENCLRR_LTDCEN BIT(0) + +/* RCC_MP_NS_APB4ENSETR register fields */ +#define RCC_MP_NS_APB4ENSETR_LTDCEN BIT(0) + +/* RCC_MP_NS_APB4ENCLRR register fields */ +#define RCC_MP_NS_APB4ENCLRR_LTDCEN BIT(0) + +/* RCC_MP_APB5ENSETR register fields */ +#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENSETR_TZCEN BIT(11) +#define RCC_MP_APB5ENSETR_ETZPCEN BIT(13) +#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENSETR_BSECEN BIT(16) +#define RCC_MP_APB5ENSETR_STGENCEN BIT(20) + +/* RCC_MP_APB5ENCLRR register fields */ +#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENCLRR_TZCEN BIT(11) +#define RCC_MP_APB5ENCLRR_ETZPCEN BIT(13) +#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENCLRR_BSECEN BIT(16) +#define RCC_MP_APB5ENCLRR_STGENCEN BIT(20) + +/* RCC_MP_APB6ENSETR register fields */ +#define RCC_MP_APB6ENSETR_USART1EN BIT(0) +#define RCC_MP_APB6ENSETR_USART2EN BIT(1) +#define RCC_MP_APB6ENSETR_SPI4EN BIT(2) +#define RCC_MP_APB6ENSETR_SPI5EN BIT(3) +#define RCC_MP_APB6ENSETR_I2C3EN BIT(4) +#define RCC_MP_APB6ENSETR_I2C4EN BIT(5) +#define RCC_MP_APB6ENSETR_I2C5EN BIT(6) +#define RCC_MP_APB6ENSETR_TIM12EN BIT(7) +#define RCC_MP_APB6ENSETR_TIM13EN BIT(8) +#define RCC_MP_APB6ENSETR_TIM14EN BIT(9) +#define RCC_MP_APB6ENSETR_TIM15EN BIT(10) +#define RCC_MP_APB6ENSETR_TIM16EN BIT(11) +#define RCC_MP_APB6ENSETR_TIM17EN BIT(12) + +/* RCC_MP_APB6ENCLRR register fields */ +#define RCC_MP_APB6ENCLRR_USART1EN BIT(0) +#define RCC_MP_APB6ENCLRR_USART2EN BIT(1) +#define RCC_MP_APB6ENCLRR_SPI4EN BIT(2) +#define RCC_MP_APB6ENCLRR_SPI5EN BIT(3) +#define RCC_MP_APB6ENCLRR_I2C3EN BIT(4) +#define RCC_MP_APB6ENCLRR_I2C4EN BIT(5) +#define RCC_MP_APB6ENCLRR_I2C5EN BIT(6) +#define RCC_MP_APB6ENCLRR_TIM12EN BIT(7) +#define RCC_MP_APB6ENCLRR_TIM13EN BIT(8) +#define RCC_MP_APB6ENCLRR_TIM14EN BIT(9) +#define RCC_MP_APB6ENCLRR_TIM15EN BIT(10) +#define RCC_MP_APB6ENCLRR_TIM16EN BIT(11) +#define RCC_MP_APB6ENCLRR_TIM17EN BIT(12) + +/* RCC_MP_AHB2ENSETR register fields */ +#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENSETR_DMAMUX1EN BIT(2) +#define RCC_MP_AHB2ENSETR_DMA3EN BIT(3) +#define RCC_MP_AHB2ENSETR_DMAMUX2EN BIT(4) +#define RCC_MP_AHB2ENSETR_ADC1EN BIT(5) +#define RCC_MP_AHB2ENSETR_ADC2EN BIT(6) +#define RCC_MP_AHB2ENSETR_USBOEN BIT(8) + +/* RCC_MP_AHB2ENCLRR register fields */ +#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENCLRR_DMAMUX1EN BIT(2) +#define RCC_MP_AHB2ENCLRR_DMA3EN BIT(3) +#define RCC_MP_AHB2ENCLRR_DMAMUX2EN BIT(4) +#define RCC_MP_AHB2ENCLRR_ADC1EN BIT(5) +#define RCC_MP_AHB2ENCLRR_ADC2EN BIT(6) +#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) + +/* RCC_MP_AHB4ENSETR register fields */ +#define RCC_MP_AHB4ENSETR_TSCEN BIT(15) + +/* RCC_MP_AHB4ENCLRR register fields */ +#define RCC_MP_AHB4ENCLRR_TSCEN BIT(15) + +/* RCC_MP_S_AHB4ENSETR register fields */ +#define RCC_MP_S_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_S_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_S_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_S_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_S_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_S_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_S_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_S_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_S_AHB4ENSETR_GPIOIEN BIT(8) + +/* RCC_MP_S_AHB4ENCLRR register fields */ +#define RCC_MP_S_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_S_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_S_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_S_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_S_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_S_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_S_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_S_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_S_AHB4ENCLRR_GPIOIEN BIT(8) + +/* RCC_MP_NS_AHB4ENSETR register fields */ +#define RCC_MP_NS_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_NS_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_NS_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_NS_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_NS_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_NS_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_NS_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_NS_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_NS_AHB4ENSETR_GPIOIEN BIT(8) + +/* RCC_MP_NS_AHB4ENCLRR register fields */ +#define RCC_MP_NS_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_NS_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_NS_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_NS_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_NS_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_NS_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_NS_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_NS_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_NS_AHB4ENCLRR_GPIOIEN BIT(8) + +/* RCC_MP_AHB5ENSETR register fields */ +#define RCC_MP_AHB5ENSETR_PKAEN BIT(2) +#define RCC_MP_AHB5ENSETR_SAESEN BIT(3) +#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) + +/* RCC_MP_AHB5ENCLRR register fields */ +#define RCC_MP_AHB5ENCLRR_PKAEN BIT(2) +#define RCC_MP_AHB5ENCLRR_SAESEN BIT(3) +#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) + +/* RCC_MP_AHB6ENSETR register fields */ +#define RCC_MP_AHB6ENSETR_MCEEN BIT(1) +#define RCC_MP_AHB6ENSETR_ETH1CKEN BIT(7) +#define RCC_MP_AHB6ENSETR_ETH1TXEN BIT(8) +#define RCC_MP_AHB6ENSETR_ETH1RXEN BIT(9) +#define RCC_MP_AHB6ENSETR_ETH1MACEN BIT(10) +#define RCC_MP_AHB6ENSETR_FMCEN BIT(12) +#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENSETR_USBHEN BIT(24) +#define RCC_MP_AHB6ENSETR_ETH2CKEN BIT(27) +#define RCC_MP_AHB6ENSETR_ETH2TXEN BIT(28) +#define RCC_MP_AHB6ENSETR_ETH2RXEN BIT(29) +#define RCC_MP_AHB6ENSETR_ETH2MACEN BIT(30) + +/* RCC_MP_AHB6ENCLRR register fields */ +#define RCC_MP_AHB6ENCLRR_MCEEN BIT(1) +#define RCC_MP_AHB6ENCLRR_ETH1CKEN BIT(7) +#define RCC_MP_AHB6ENCLRR_ETH1TXEN BIT(8) +#define RCC_MP_AHB6ENCLRR_ETH1RXEN BIT(9) +#define RCC_MP_AHB6ENCLRR_ETH1MACEN BIT(10) +#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) +#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) +#define RCC_MP_AHB6ENCLRR_ETH2CKEN BIT(27) +#define RCC_MP_AHB6ENCLRR_ETH2TXEN BIT(28) +#define RCC_MP_AHB6ENCLRR_ETH2RXEN BIT(29) +#define RCC_MP_AHB6ENCLRR_ETH2MACEN BIT(30) + +/* RCC_MP_S_AHB6ENSETR register fields */ +#define RCC_MP_S_AHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_S_AHB6ENCLRR register fields */ +#define RCC_MP_S_AHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MP_NS_AHB6ENSETR register fields */ +#define RCC_MP_NS_AHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_NS_AHB6ENCLRR register fields */ +#define RCC_MP_NS_AHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MP_APB1LPENSETR register fields */ +#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) + +/* RCC_MP_APB1LPENCLRR register fields */ +#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) + +/* RCC_MP_APB2LPENSETR register fields */ +#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) + +/* RCC_MP_APB2LPENCLRR register fields */ +#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) + +/* RCC_MP_APB3LPENSETR register fields */ +#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENSETR_DTSLPEN BIT(16) +#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_APB3LPENCLRR register fields */ +#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENCLRR_DTSLPEN BIT(16) +#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_S_APB3LPENSETR register fields */ +#define RCC_MP_S_APB3LPENSETR_SYSCFGLPEN BIT(0) + +/* RCC_MP_S_APB3LPENCLRR register fields */ +#define RCC_MP_S_APB3LPENCLRR_SYSCFGLPEN BIT(0) + +/* RCC_MP_NS_APB3LPENSETR register fields */ +#define RCC_MP_NS_APB3LPENSETR_SYSCFGLPEN BIT(0) + +/* RCC_MP_NS_APB3LPENCLRR register fields */ +#define RCC_MP_NS_APB3LPENCLRR_SYSCFGLPEN BIT(0) + +/* RCC_MP_APB4LPENSETR register fields */ +#define RCC_MP_APB4LPENSETR_DCMIPPLPEN BIT(1) +#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) + +/* RCC_MP_APB4LPENCLRR register fields */ +#define RCC_MP_APB4LPENCLRR_DCMIPPLPEN BIT(1) +#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) + +/* RCC_MP_S_APB4LPENSETR register fields */ +#define RCC_MP_S_APB4LPENSETR_LTDCLPEN BIT(0) + +/* RCC_MP_S_APB4LPENCLRR register fields */ +#define RCC_MP_S_APB4LPENCLRR_LTDCLPEN BIT(0) + +/* RCC_MP_NS_APB4LPENSETR register fields */ +#define RCC_MP_NS_APB4LPENSETR_LTDCLPEN BIT(0) + +/* RCC_MP_NS_APB4LPENCLRR register fields */ +#define RCC_MP_NS_APB4LPENCLRR_LTDCLPEN BIT(0) + +/* RCC_MP_APB5LPENSETR register fields */ +#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENSETR_TZCLPEN BIT(11) +#define RCC_MP_APB5LPENSETR_ETZPCLPEN BIT(13) +#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENSETR_STGENCLPEN BIT(20) +#define RCC_MP_APB5LPENSETR_STGENCSTPEN BIT(21) + +/* RCC_MP_APB5LPENCLRR register fields */ +#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENCLRR_TZCLPEN BIT(11) +#define RCC_MP_APB5LPENCLRR_ETZPCLPEN BIT(13) +#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENCLRR_STGENCLPEN BIT(20) +#define RCC_MP_APB5LPENCLRR_STGENCSTPEN BIT(21) + +/* RCC_MP_APB6LPENSETR register fields */ +#define RCC_MP_APB6LPENSETR_USART1LPEN BIT(0) +#define RCC_MP_APB6LPENSETR_USART2LPEN BIT(1) +#define RCC_MP_APB6LPENSETR_SPI4LPEN BIT(2) +#define RCC_MP_APB6LPENSETR_SPI5LPEN BIT(3) +#define RCC_MP_APB6LPENSETR_I2C3LPEN BIT(4) +#define RCC_MP_APB6LPENSETR_I2C4LPEN BIT(5) +#define RCC_MP_APB6LPENSETR_I2C5LPEN BIT(6) +#define RCC_MP_APB6LPENSETR_TIM12LPEN BIT(7) +#define RCC_MP_APB6LPENSETR_TIM13LPEN BIT(8) +#define RCC_MP_APB6LPENSETR_TIM14LPEN BIT(9) +#define RCC_MP_APB6LPENSETR_TIM15LPEN BIT(10) +#define RCC_MP_APB6LPENSETR_TIM16LPEN BIT(11) +#define RCC_MP_APB6LPENSETR_TIM17LPEN BIT(12) + +/* RCC_MP_APB6LPENCLRR register fields */ +#define RCC_MP_APB6LPENCLRR_USART1LPEN BIT(0) +#define RCC_MP_APB6LPENCLRR_USART2LPEN BIT(1) +#define RCC_MP_APB6LPENCLRR_SPI4LPEN BIT(2) +#define RCC_MP_APB6LPENCLRR_SPI5LPEN BIT(3) +#define RCC_MP_APB6LPENCLRR_I2C3LPEN BIT(4) +#define RCC_MP_APB6LPENCLRR_I2C4LPEN BIT(5) +#define RCC_MP_APB6LPENCLRR_I2C5LPEN BIT(6) +#define RCC_MP_APB6LPENCLRR_TIM12LPEN BIT(7) +#define RCC_MP_APB6LPENCLRR_TIM13LPEN BIT(8) +#define RCC_MP_APB6LPENCLRR_TIM14LPEN BIT(9) +#define RCC_MP_APB6LPENCLRR_TIM15LPEN BIT(10) +#define RCC_MP_APB6LPENCLRR_TIM16LPEN BIT(11) +#define RCC_MP_APB6LPENCLRR_TIM17LPEN BIT(12) + +/* RCC_MP_AHB2LPENSETR register fields */ +#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENSETR_DMAMUX1LPEN BIT(2) +#define RCC_MP_AHB2LPENSETR_DMA3LPEN BIT(3) +#define RCC_MP_AHB2LPENSETR_DMAMUX2LPEN BIT(4) +#define RCC_MP_AHB2LPENSETR_ADC1LPEN BIT(5) +#define RCC_MP_AHB2LPENSETR_ADC2LPEN BIT(6) +#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) + +/* RCC_MP_AHB2LPENCLRR register fields */ +#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENCLRR_DMAMUX1LPEN BIT(2) +#define RCC_MP_AHB2LPENCLRR_DMA3LPEN BIT(3) +#define RCC_MP_AHB2LPENCLRR_DMAMUX2LPEN BIT(4) +#define RCC_MP_AHB2LPENCLRR_ADC1LPEN BIT(5) +#define RCC_MP_AHB2LPENCLRR_ADC2LPEN BIT(6) +#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) + +/* RCC_MP_AHB4LPENSETR register fields */ +#define RCC_MP_AHB4LPENSETR_TSCLPEN BIT(15) + +/* RCC_MP_AHB4LPENCLRR register fields */ +#define RCC_MP_AHB4LPENCLRR_TSCLPEN BIT(15) + +/* RCC_MP_S_AHB4LPENSETR register fields */ +#define RCC_MP_S_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_S_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_S_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_S_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_S_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_S_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_S_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_S_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_S_AHB4LPENSETR_GPIOILPEN BIT(8) + +/* RCC_MP_S_AHB4LPENCLRR register fields */ +#define RCC_MP_S_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_S_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_S_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_S_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_S_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_S_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_S_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_S_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_S_AHB4LPENCLRR_GPIOILPEN BIT(8) + +/* RCC_MP_NS_AHB4LPENSETR register fields */ +#define RCC_MP_NS_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_NS_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_NS_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_NS_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_NS_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_NS_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_NS_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_NS_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_NS_AHB4LPENSETR_GPIOILPEN BIT(8) + +/* RCC_MP_NS_AHB4LPENCLRR register fields */ +#define RCC_MP_NS_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_NS_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOILPEN BIT(8) + +/* RCC_MP_AHB5LPENSETR register fields */ +#define RCC_MP_AHB5LPENSETR_PKALPEN BIT(2) +#define RCC_MP_AHB5LPENSETR_SAESLPEN BIT(3) +#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB5LPENCLRR register fields */ +#define RCC_MP_AHB5LPENCLRR_PKALPEN BIT(2) +#define RCC_MP_AHB5LPENCLRR_SAESLPEN BIT(3) +#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB6LPENSETR register fields */ +#define RCC_MP_AHB6LPENSETR_MCELPEN BIT(1) +#define RCC_MP_AHB6LPENSETR_ETH1CKLPEN BIT(7) +#define RCC_MP_AHB6LPENSETR_ETH1TXLPEN BIT(8) +#define RCC_MP_AHB6LPENSETR_ETH1RXLPEN BIT(9) +#define RCC_MP_AHB6LPENSETR_ETH1MACLPEN BIT(10) +#define RCC_MP_AHB6LPENSETR_ETH1STPEN BIT(11) +#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) +#define RCC_MP_AHB6LPENSETR_ETH2CKLPEN BIT(27) +#define RCC_MP_AHB6LPENSETR_ETH2TXLPEN BIT(28) +#define RCC_MP_AHB6LPENSETR_ETH2RXLPEN BIT(29) +#define RCC_MP_AHB6LPENSETR_ETH2MACLPEN BIT(30) +#define RCC_MP_AHB6LPENSETR_ETH2STPEN BIT(31) + +/* RCC_MP_AHB6LPENCLRR register fields */ +#define RCC_MP_AHB6LPENCLRR_MCELPEN BIT(1) +#define RCC_MP_AHB6LPENCLRR_ETH1CKLPEN BIT(7) +#define RCC_MP_AHB6LPENCLRR_ETH1TXLPEN BIT(8) +#define RCC_MP_AHB6LPENCLRR_ETH1RXLPEN BIT(9) +#define RCC_MP_AHB6LPENCLRR_ETH1MACLPEN BIT(10) +#define RCC_MP_AHB6LPENCLRR_ETH1STPEN BIT(11) +#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) +#define RCC_MP_AHB6LPENCLRR_ETH2CKLPEN BIT(27) +#define RCC_MP_AHB6LPENCLRR_ETH2TXLPEN BIT(28) +#define RCC_MP_AHB6LPENCLRR_ETH2RXLPEN BIT(29) +#define RCC_MP_AHB6LPENCLRR_ETH2MACLPEN BIT(30) +#define RCC_MP_AHB6LPENCLRR_ETH2STPEN BIT(31) + +/* RCC_MP_S_AHB6LPENSETR register fields */ +#define RCC_MP_S_AHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_S_AHB6LPENCLRR register fields */ +#define RCC_MP_S_AHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MP_NS_AHB6LPENSETR register fields */ +#define RCC_MP_NS_AHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_NS_AHB6LPENCLRR register fields */ +#define RCC_MP_NS_AHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MP_S_AXIMLPENSETR register fields */ +#define RCC_MP_S_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_S_AXIMLPENCLRR register fields */ +#define RCC_MP_S_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_NS_AXIMLPENSETR register fields */ +#define RCC_MP_NS_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_NS_AXIMLPENCLRR register fields */ +#define RCC_MP_NS_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_MLAHBLPENSETR register fields */ +#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENSETR_SRAM3LPEN BIT(2) + +/* RCC_MP_MLAHBLPENCLRR register fields */ +#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENCLRR_SRAM3LPEN BIT(2) + +/* RCC_APB3SECSR register fields */ +#define RCC_APB3SECSR_LPTIM2SECF 0 +#define RCC_APB3SECSR_LPTIM3SECF 1 +#define RCC_APB3SECSR_VREFSECF 13 + +/* RCC_APB4SECSR register fields */ +#define RCC_APB4SECSR_DCMIPPSECF 1 +#define RCC_APB4SECSR_USBPHYSECF 16 + +/* RCC_APB5SECSR register fields */ +#define RCC_APB5SECSR_RTCSECF 8 +#define RCC_APB5SECSR_TZCSECF 11 +#define RCC_APB5SECSR_ETZPCSECF 13 +#define RCC_APB5SECSR_IWDG1SECF 15 +#define RCC_APB5SECSR_BSECSECF 16 +#define RCC_APB5SECSR_STGENCSECF_MASK GENMASK(21, 20) +#define RCC_APB5SECSR_STGENCSECF 20 +#define RCC_APB5SECSR_STGENROSECF 21 + +/* RCC_APB6SECSR register fields */ +#define RCC_APB6SECSR_USART1SECF 0 +#define RCC_APB6SECSR_USART2SECF 1 +#define RCC_APB6SECSR_SPI4SECF 2 +#define RCC_APB6SECSR_SPI5SECF 3 +#define RCC_APB6SECSR_I2C3SECF 4 +#define RCC_APB6SECSR_I2C4SECF 5 +#define RCC_APB6SECSR_I2C5SECF 6 +#define RCC_APB6SECSR_TIM12SECF 7 +#define RCC_APB6SECSR_TIM13SECF 8 +#define RCC_APB6SECSR_TIM14SECF 9 +#define RCC_APB6SECSR_TIM15SECF 10 +#define RCC_APB6SECSR_TIM16SECF 11 +#define RCC_APB6SECSR_TIM17SECF 12 + +/* RCC_AHB2SECSR register fields */ +#define RCC_AHB2SECSR_DMA3SECF 3 +#define RCC_AHB2SECSR_DMAMUX2SECF 4 +#define RCC_AHB2SECSR_ADC1SECF 5 +#define RCC_AHB2SECSR_ADC2SECF 6 +#define RCC_AHB2SECSR_USBOSECF 8 + +/* RCC_AHB4SECSR register fields */ +#define RCC_AHB4SECSR_TSCSECF 15 + +/* RCC_AHB5SECSR register fields */ +#define RCC_AHB5SECSR_PKASECF 2 +#define RCC_AHB5SECSR_SAESSECF 3 +#define RCC_AHB5SECSR_CRYP1SECF 4 +#define RCC_AHB5SECSR_HASH1SECF 5 +#define RCC_AHB5SECSR_RNG1SECF 6 +#define RCC_AHB5SECSR_BKPSRAMSECF 8 + +/* RCC_AHB6SECSR register fields */ +#define RCC_AHB6SECSR_MCESECF 1 +#define RCC_AHB6SECSR_FMCSECF 12 +#define RCC_AHB6SECSR_QSPISECF 14 +#define RCC_AHB6SECSR_SDMMC1SECF 16 +#define RCC_AHB6SECSR_SDMMC2SECF 17 + +#define RCC_AHB6SECSR_ETH1SECF_MASK GENMASK(11, 7) +#define RCC_AHB6SECSR_ETH2SECF_MASK GENMASK(31, 27) +#define RCC_AHB6SECSR_ETH1SECF_SHIFT 7 +#define RCC_AHB6SECSR_ETH2SECF_SHIFT 27 + +#define RCC_AHB6SECSR_ETH1CKSECF 7 +#define RCC_AHB6SECSR_ETH1TXSECF 8 +#define RCC_AHB6SECSR_ETH1RXSECF 9 +#define RCC_AHB6SECSR_ETH1MACSECF 10 +#define RCC_AHB6SECSR_ETH1STPSECF 11 + +#define RCC_AHB6SECSR_ETH2CKSECF 27 +#define RCC_AHB6SECSR_ETH2TXSECF 28 +#define RCC_AHB6SECSR_ETH2RXSECF 29 +#define RCC_AHB6SECSR_ETH2MACSECF 30 +#define RCC_AHB6SECSR_ETH2STPSECF 31 + +/* RCC_VERR register fields */ +#define RCC_VERR_MINREV_MASK GENMASK(3, 0) +#define RCC_VERR_MAJREV_MASK GENMASK(7, 4) +#define RCC_VERR_MINREV_SHIFT 0 +#define RCC_VERR_MAJREV_SHIFT 4 + +/* RCC_IDR register fields */ +#define RCC_IDR_ID_MASK GENMASK(31, 0) +#define RCC_IDR_ID_SHIFT 0 + +/* RCC_SIDR register fields */ +#define RCC_SIDR_SID_MASK GENMASK(31, 0) +#define RCC_SIDR_SID_SHIFT 0 + +#endif /* STM32MP13_RCC_H */ diff --git a/drivers/core/device.c b/drivers/core/device.c index 29668f6fb3..6f84762ebd 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -1135,7 +1135,7 @@ int dev_enable_by_path(const char *path) if (ret) return ret; - return lists_bind_fdt(parent, node, NULL, false); + return lists_bind_fdt(parent, node, NULL, NULL, false); } #endif diff --git a/drivers/core/lists.c b/drivers/core/lists.c index e214306b90..c9cd74a484 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -182,7 +182,7 @@ static int driver_check_compatible(const struct udevice_id *of_match, } int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, - bool pre_reloc_only) + struct driver *drv, bool pre_reloc_only) { struct driver *driver = ll_entry_start(struct driver, driver); const int n_ents = ll_entry_count(struct driver, driver); @@ -225,6 +225,8 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, for (entry = driver; entry != driver + n_ents; entry++) { ret = driver_check_compatible(entry->of_match, &id, compat); + if ((drv) && (drv == entry)) + break; if (!ret) break; } diff --git a/drivers/core/root.c b/drivers/core/root.c index 78eee082c9..86f9776733 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -276,7 +276,7 @@ static int dm_scan_fdt_node(struct udevice *parent, ofnode parent_node, pr_debug(" - ignoring disabled device\n"); continue; } - err = lists_bind_fdt(parent, node, NULL, pre_reloc_only); + err = lists_bind_fdt(parent, node, NULL, NULL, pre_reloc_only); if (err && !ret) { ret = err; debug("%s: ret=%d\n", node_name, ret); diff --git a/drivers/demo/demo-uclass.c b/drivers/demo/demo-uclass.c index 815f8de645..09f9a47d4d 100644 --- a/drivers/demo/demo-uclass.c +++ b/drivers/demo/demo-uclass.c @@ -10,15 +10,11 @@ #include #include #include -#include #include #include -#include #include #include -DECLARE_GLOBAL_DATA_PTR; - UCLASS_DRIVER(demo) = { .name = "demo", .id = UCLASS_DEMO, @@ -67,10 +63,9 @@ int demo_set_light(struct udevice *dev, int light) int demo_parse_dt(struct udevice *dev) { struct dm_demo_pdata *pdata = dev_get_plat(dev); - int dn = dev_of_offset(dev); - pdata->sides = fdtdec_get_int(gd->fdt_blob, dn, "sides", 0); - pdata->colour = fdt_getprop(gd->fdt_blob, dn, "colour", NULL); + pdata->sides = dev_read_s32_default(dev, "sides", 0); + pdata->colour = dev_read_string(dev, "colour"); if (!pdata->sides || !pdata->colour) { debug("%s: Invalid device tree data\n", __func__); return -EINVAL; diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c index 0b7f17761f..cce9ce0845 100644 --- a/drivers/dfu/dfu_mtd.c +++ b/drivers/dfu/dfu_mtd.c @@ -18,6 +18,20 @@ static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size) return !do_div(size, mtd->erasesize); } +/* Logic taken from cmd/mtd.c:mtd_oob_write_is_empty() */ +static bool mtd_page_is_empty(struct mtd_oob_ops *op) +{ + int i; + + for (i = 0; i < op->len; i++) + if (op->datbuf[i] != 0xff) + return false; + + /* oob is not used, with MTD_OPS_AUTO_OOB & ooblen=0 */ + + return true; +} + static int mtd_block_op(enum dfu_op op, struct dfu_entity *dfu, u64 offset, void *buf, long *len) { @@ -129,8 +143,14 @@ static int mtd_block_op(enum dfu_op op, struct dfu_entity *dfu, if (op == DFU_OP_READ) ret = mtd_read_oob(mtd, off, &io_op); - else + else if (has_pages && dfu->data.mtd.ubi && mtd_page_is_empty(&io_op)) { + /* in case of ubi partition, do not write an empty page, only skip it */ + ret = 0; + io_op.retlen = mtd->writesize; + io_op.oobretlen = mtd->oobsize; + } else { ret = mtd_write_oob(mtd, off, &io_op); + } if (ret) { printf("Failure while %s at offset 0x%llx\n", diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig index c3a109beac..8cf85f0d7a 100644 --- a/drivers/firmware/scmi/Kconfig +++ b/drivers/firmware/scmi/Kconfig @@ -2,7 +2,7 @@ config SCMI_FIRMWARE bool "Enable SCMI support" select FIRMWARE select OF_TRANSLATE - depends on SANDBOX || DM_MAILBOX || ARM_SMCCC + depends on SANDBOX || DM_MAILBOX || ARM_SMCCC || OPTEE help System Control and Management Interface (SCMI) is a communication protocol that defines standard interfaces for power, performance @@ -14,6 +14,30 @@ config SCMI_FIRMWARE or a companion host in the CPU system. Communications between agent (client) and the SCMI server are - based on message exchange. Messages can be exchange over tranport + based on message exchange. Messages can be exchanged over transport channels as a mailbox device or an Arm SMCCC service with some piece of identified shared memory. + +config SCMI_AGENT_MAILBOX + bool "Enable SCMI agent mailbox" + depends on SCMI_FIRMWARE && DM_MAILBOX + default y + help + Enable the SCMI communication channel based on mailbox + for compatible "arm,scmi". + +config SCMI_AGENT_SMCCC + bool "Enable SCMI agent SMCCC" + depends on SCMI_FIRMWARE && ARM_SMCCC + default y + help + Enable the SCMI communication channel based on Arm SMCCC service for + compatible "arm,scmi-smc". + +config SCMI_AGENT_OPTEE + bool "Enable SCMI agent OP-TEE" + depends on SCMI_FIRMWARE && OPTEE + default y + help + Enable the SCMI communication channel based on OP-TEE transport + for compatible "linaro,scmi-optee". diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile index e1e0224066..b2ff483c75 100644 --- a/drivers/firmware/scmi/Makefile +++ b/drivers/firmware/scmi/Makefile @@ -1,5 +1,6 @@ obj-y += scmi_agent-uclass.o obj-y += smt.o -obj-$(CONFIG_ARM_SMCCC) += smccc_agent.o -obj-$(CONFIG_DM_MAILBOX) += mailbox_agent.o +obj-$(CONFIG_SCMI_AGENT_SMCCC) += smccc_agent.o +obj-$(CONFIG_SCMI_AGENT_MAILBOX) += mailbox_agent.o +obj-$(CONFIG_SCMI_AGENT_OPTEE) += optee_agent.o obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o sandbox-scmi_devices.o diff --git a/drivers/firmware/scmi/mailbox_agent.c b/drivers/firmware/scmi/mailbox_agent.c index ea35e7e09e..8e4af0c8fa 100644 --- a/drivers/firmware/scmi/mailbox_agent.c +++ b/drivers/firmware/scmi/mailbox_agent.c @@ -33,7 +33,7 @@ struct scmi_mbox_channel { static int scmi_mbox_process_msg(struct udevice *dev, struct scmi_msg *msg) { - struct scmi_mbox_channel *chan = dev_get_priv(dev); + struct scmi_mbox_channel *chan = dev_get_plat(dev); int ret; ret = scmi_write_msg_to_smt(dev, &chan->smt, msg); @@ -62,9 +62,9 @@ out: return ret; } -int scmi_mbox_probe(struct udevice *dev) +int scmi_mbox_of_to_plat(struct udevice *dev) { - struct scmi_mbox_channel *chan = dev_get_priv(dev); + struct scmi_mbox_channel *chan = dev_get_plat(dev); int ret; chan->timeout_us = TIMEOUT_US_10MS; @@ -72,17 +72,13 @@ int scmi_mbox_probe(struct udevice *dev) ret = mbox_get_by_index(dev, 0, &chan->mbox); if (ret) { dev_err(dev, "Failed to find mailbox: %d\n", ret); - goto out; + return ret; } ret = scmi_dt_get_smt_buffer(dev, &chan->smt); if (ret) dev_err(dev, "Failed to get shm resources: %d\n", ret); -out: - if (ret) - devm_kfree(dev, chan); - return ret; } @@ -99,7 +95,7 @@ U_BOOT_DRIVER(scmi_mbox) = { .name = "scmi-over-mailbox", .id = UCLASS_SCMI_AGENT, .of_match = scmi_mbox_ids, - .priv_auto = sizeof(struct scmi_mbox_channel), - .probe = scmi_mbox_probe, + .plat_auto = sizeof(struct scmi_mbox_channel), + .of_to_plat = scmi_mbox_of_to_plat, .ops = &scmi_mbox_ops, }; diff --git a/drivers/firmware/scmi/optee_agent.c b/drivers/firmware/scmi/optee_agent.c new file mode 100644 index 0000000000..1f26592234 --- /dev/null +++ b/drivers/firmware/scmi/optee_agent.c @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020-2021 Linaro Limited. + */ + +#define LOG_CATEGORY UCLASS_SCMI_AGENT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "smt.h" + +#define SCMI_SHM_SIZE 128 + +/** + * struct scmi_optee_channel - Description of an SCMI OP-TEE transport + * @channel_id: Channel identifier + * @smt: Shared memory buffer with synchronisation protocol + * @dyn_shm: True if using dynamically allocated shared memory + */ +struct scmi_optee_channel { + unsigned int channel_id; + struct scmi_smt smt; + bool dyn_shm; +}; + +/** + * struct channel_session - Aggreates SCMI service session context references + * @tee: OP-TEE device to invoke + * @tee_session: OP-TEE session identifier + * @tee_shm: Dynamically allocated OP-TEE shared memory, or NULL + * @channel_hdl: Channel handle provided by OP-TEE SCMI service + */ +struct channel_session { + struct udevice *tee; + u32 tee_session; + struct tee_shm *tee_shm; + u32 channel_hdl; +}; + +#define TA_SCMI_UUID { 0xa8cfe406, 0xd4f5, 0x4a2e, \ + { 0x9f, 0x8d, 0xa2, 0x5d, 0xc7, 0x54, 0xc0, 0x99 } } + +enum optee_smci_pta_cmd { + /* + * PTA_SCMI_CMD_CAPABILITIES - Get channel capabilities + * + * [out] value[0].a: Capability bit mask (enum pta_scmi_caps) + * [out] value[0].b: Extended capabilities or 0 + */ + PTA_SCMI_CMD_CAPABILITIES = 0, + + /* + * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL - Process SCMI message in SMT buffer + * + * [in] value[0].a: Channel handle + * + * Shared memory used for SCMI message/response exhange is expected + * already identified and bound to channel handle in both SCMI agent + * and SCMI server (OP-TEE) parts. + * The memory uses SMT header to carry SCMI meta-data (protocol ID and + * protocol message ID). + */ + PTA_SCMI_CMD_PROCESS_SMT_CHANNEL = 1, + + /* + * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE - Process SMT/SCMI message + * + * [in] value[0].a: Channel handle + * [in/out] memref[1]: Message/response buffer (SMT and SCMI payload) + * + * Shared memory used for SCMI message/response is a SMT buffer + * referenced by param[1]. It shall be 128 bytes large to fit response + * payload whatever message playload size. + * The memory uses SMT header to carry SCMI meta-data (protocol ID and + * protocol message ID). + */ + PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE = 2, + + /* + * PTA_SCMI_CMD_GET_CHANNEL - Get channel handle + * + * SCMI shm information are 0 if agent expects to use OP-TEE regular SHM + * + * [in] value[0].a: Channel identifier + * [out] value[0].a: Returned channel handle + * [in] value[0].b: Requested capabilities mask (enum pta_scmi_caps) + */ + PTA_SCMI_CMD_GET_CHANNEL = 3, +}; + +/* + * OP-TEE SCMI service capabilities bit flags (32bit) + * + * PTA_SCMI_CAPS_SMT_HEADER + * When set, OP-TEE supports command using SMT header protocol (SCMI shmem) in + * shared memory buffers to carry SCMI protocol synchronisation information. + */ +#define PTA_SCMI_CAPS_NONE 0 +#define PTA_SCMI_CAPS_SMT_HEADER BIT(0) + +static int open_channel(struct udevice *dev, struct channel_session *sess) +{ + const struct tee_optee_ta_uuid uuid = TA_SCMI_UUID; + struct scmi_optee_channel *chan = dev_get_plat(dev); + struct tee_open_session_arg sess_arg = { }; + struct tee_invoke_arg cmd_arg = { }; + struct tee_param param[1] = { }; + int ret; + + memset(sess, 0, sizeof(sess)); + + sess->tee = tee_find_device(NULL, NULL, NULL, NULL); + if (!sess->tee) + return -ENODEV; + + sess_arg.clnt_login = TEE_LOGIN_REE_KERNEL; + tee_optee_ta_uuid_to_octets(sess_arg.uuid, &uuid); + + ret = tee_open_session(sess->tee, &sess_arg, 0, NULL); + if (ret) { + dev_err(dev, "can't open session: %d\n", ret); + return ret; + } + + cmd_arg.func = PTA_SCMI_CMD_GET_CHANNEL; + cmd_arg.session = sess_arg.session; + + param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INOUT; + param[0].u.value.a = chan->channel_id; + param[0].u.value.b = PTA_SCMI_CAPS_SMT_HEADER; + + ret = tee_invoke_func(sess->tee, &cmd_arg, ARRAY_SIZE(param), param); + if (ret || cmd_arg.ret) { + dev_err(dev, "Invoke failed: %d, 0x%x\n", ret, cmd_arg.ret); + if (!ret) + ret = -EPROTO; + + tee_close_session(sess->tee, sess_arg.session); + return ret; + } + + sess->tee_session = sess_arg.session; + sess->channel_hdl = param[0].u.value.a; + + return 0; +} + +static void close_channel(struct channel_session *sess) +{ + tee_close_session(sess->tee, sess->tee_session); +} + +static int invoke_cmd(struct udevice *dev, struct channel_session *sess, + struct scmi_msg *msg) +{ + struct scmi_optee_channel *chan = dev_get_plat(dev); + struct tee_invoke_arg arg = { }; + struct tee_param param[2] = { }; + int ret; + + scmi_write_msg_to_smt(dev, &chan->smt, msg); + + arg.session = sess->tee_session; + param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; + param[0].u.value.a = sess->channel_hdl; + + if (chan->dyn_shm) { + arg.func = PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE; + param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT; + param[1].u.memref.shm = sess->tee_shm; + param[1].u.memref.size = SCMI_SHM_SIZE; + } else { + arg.func = PTA_SCMI_CMD_PROCESS_SMT_CHANNEL; + } + + ret = tee_invoke_func(sess->tee, &arg, ARRAY_SIZE(param), param); + if (ret || arg.ret) { + if (!ret) + ret = -EPROTO; + } else { + ret = scmi_read_resp_from_smt(dev, &chan->smt, msg); + } + + scmi_clear_smt_channel(&chan->smt); + + return ret; +} + +static int prepare_shm(struct udevice *dev, struct channel_session *sess) +{ + struct scmi_optee_channel *chan = dev_get_plat(dev); + int ret; + + /* Static shm is already prepared by the firmware: nothing to do */ + if (!chan->dyn_shm) + return 0; + + chan->smt.size = SCMI_SHM_SIZE; + + ret = tee_shm_alloc(sess->tee, chan->smt.size, 0, &sess->tee_shm); + if (ret) { + dev_err(dev, "Failed to allocated shmem: %d\n", ret); + return ret; + } + + chan->smt.buf = sess->tee_shm->addr; + + /* Initialize shm buffer for message exchanges */ + scmi_clear_smt_channel(&chan->smt); + + return 0; +} + +static void release_shm(struct udevice *dev, struct channel_session *sess) +{ + struct scmi_optee_channel *chan = dev_get_plat(dev); + + if (chan->dyn_shm) + tee_shm_free(sess->tee_shm); +} + +static int scmi_optee_process_msg(struct udevice *dev, struct scmi_msg *msg) +{ + struct channel_session sess; + int ret; + + ret = open_channel(dev, &sess); + if (ret) + return ret; + + ret = prepare_shm(dev, &sess); + if (ret) + goto out; + + ret = invoke_cmd(dev, &sess, msg); + + release_shm(dev, &sess); + +out: + close_channel(&sess); + + return ret; +} + +static int scmi_optee_of_to_plat(struct udevice *dev) +{ + struct scmi_optee_channel *chan = dev_get_plat(dev); + int ret; + + if (dev_read_u32(dev, "linaro,optee-channel-id", &chan->channel_id)) { + dev_err(dev, "Missing property linaro,optee-channel-id\n"); + return -EINVAL; + } + + if (dev_read_prop(dev, "shmem", NULL)) { + ret = scmi_dt_get_smt_buffer(dev, &chan->smt); + if (ret) { + dev_err(dev, "Failed to get smt resources: %d\n", ret); + return ret; + } + chan->dyn_shm = false; + } else { + chan->dyn_shm = true; + } + + return 0; +} + +static int scmi_optee_probe(struct udevice *dev) +{ + struct channel_session sess; + int ret; + + /* Check OP-TEE service acknowledges the SCMI channel */ + ret = open_channel(dev, &sess); + if (!ret) + close_channel(&sess); + + return ret; +} + +static const struct udevice_id scmi_optee_ids[] = { + { .compatible = "linaro,scmi-optee" }, + { } +}; + +static const struct scmi_agent_ops scmi_optee_ops = { + .process_msg = scmi_optee_process_msg, +}; + +U_BOOT_DRIVER(scmi_optee) = { + .name = "scmi-over-optee", + .id = UCLASS_SCMI_AGENT, + .of_match = scmi_optee_ids, + .plat_auto = sizeof(struct scmi_optee_channel), + .of_to_plat = scmi_optee_of_to_plat, + .probe = scmi_optee_probe, + .flags = DM_FLAG_OS_PREPARE, + .ops = &scmi_optee_ops, +}; diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c index 4b968205c2..f7fda101e4 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -19,51 +19,45 @@ * The sandbox SCMI agent driver simulates to some extend a SCMI message * processing. It simulates few of the SCMI services for some of the * SCMI protocols embedded in U-Boot. Currently: - * - SCMI clock protocol: emulate 2 agents each exposing few clocks - * - SCMI reset protocol: emulate 1 agent exposing a reset controller - * - SCMI voltage domain protocol: emulate 1 agent exposing 2 regulators + * - SCMI clock protocol emulates an agent exposing 2 clocks + * - SCMI reset protocol emulates an agent exposing a reset controller + * - SCMI voltage domain protocol emulates an agent exposing 2 regulators * - * Agent #0 simulates 2 clocks, 1 reset domain and 1 voltage domain. - * See IDs in scmi0_clk[]/scmi0_reset[] and "sandbox-scmi-agent@0" in test.dts. - * - * Agent #1 simulates 1 clock. - * See IDs in scmi1_clk[] and "sandbox-scmi-agent@1" in test.dts. + * As per DT bindings, the device node name shall be scmi. * * All clocks and regulators are default disabled and reset controller down. * - * This Driver exports sandbox_scmi_service_ctx() for the test sequence to + * This driver exports sandbox_scmi_service_ctx() for the test sequence to * get the state of the simulated services (clock state, rate, ...) and * check back-end device state reflects the request send through the * various uclass devices, as clocks and reset controllers. */ -#define SANDBOX_SCMI_AGENT_COUNT 2 - -static struct sandbox_scmi_clk scmi0_clk[] = { - { .id = 7, .rate = 1000 }, - { .id = 3, .rate = 333 }, +static struct sandbox_scmi_clk scmi_clk[] = { + { .rate = 333 }, + { .rate = 200 }, + { .rate = 1000 }, }; -static struct sandbox_scmi_reset scmi0_reset[] = { +static struct sandbox_scmi_reset scmi_reset[] = { { .id = 3 }, }; -static struct sandbox_scmi_voltd scmi0_voltd[] = { +static struct sandbox_scmi_voltd scmi_voltd[] = { { .id = 0, .voltage_uv = 3300000 }, - { .id = 1, .voltage_uv = 1800000 }, -}; - -static struct sandbox_scmi_clk scmi1_clk[] = { - { .id = 1, .rate = 44 }, + { .id = 6, .voltage_uv = 1800000 }, + /* + * Dummy unused regulators needed to be abled to + * expose voltage domain of highest ID (6). + */ + { .id = 1 }, + { .id = 2 }, + { .id = 3 }, + { .id = 4 }, + { .id = 5 }, }; -/* The list saves to simulted end devices references for test purpose */ -struct sandbox_scmi_agent *sandbox_scmi_agent_list[SANDBOX_SCMI_AGENT_COUNT]; - -static struct sandbox_scmi_service sandbox_scmi_service_state = { - .agent = sandbox_scmi_agent_list, - .agent_count = SANDBOX_SCMI_AGENT_COUNT, -}; +static struct sandbox_scmi_service sandbox_scmi_service_state; struct sandbox_scmi_service *sandbox_scmi_service_ctx(void) { @@ -74,9 +68,8 @@ static void debug_print_agent_state(struct udevice *dev, char *str) { struct sandbox_scmi_agent *agent = dev_get_priv(dev); - dev_dbg(dev, "Dump sandbox_scmi_agent %u: %s\n", agent->idx, str); - dev_dbg(dev, " scmi%u_clk (%zu): %d/%ld, %d/%ld, %d/%ld, ...\n", - agent->idx, + dev_dbg(dev, "Dump sandbox_scmi_agent: %s\n", str); + dev_dbg(dev, " scmi_clk (%zu): %d/%ld, %d/%ld, %d/%ld, ...\n", agent->clk_count, agent->clk_count ? agent->clk[0].enabled : -1, agent->clk_count ? agent->clk[0].rate : -1, @@ -84,13 +77,11 @@ static void debug_print_agent_state(struct udevice *dev, char *str) agent->clk_count > 1 ? agent->clk[1].rate : -1, agent->clk_count > 2 ? agent->clk[2].enabled : -1, agent->clk_count > 2 ? agent->clk[2].rate : -1); - dev_dbg(dev, " scmi%u_reset (%zu): %d, %d, ...\n", - agent->idx, + dev_dbg(dev, " scmi_reset (%zu): %d, %d, ...\n", agent->reset_count, agent->reset_count ? agent->reset[0].asserted : -1, agent->reset_count > 1 ? agent->reset[1].asserted : -1); - dev_dbg(dev, " scmi%u_voltd (%zu): %u/%d, %u/%d, ...\n", - agent->idx, + dev_dbg(dev, " scmi_voltd (%zu): %u/%d, %u/%d, ...\n", agent->voltd_count, agent->voltd_count ? agent->voltd[0].enabled : -1, agent->voltd_count ? agent->voltd[0].voltage_uv : -1, @@ -98,56 +89,32 @@ static void debug_print_agent_state(struct udevice *dev, char *str) agent->voltd_count ? agent->voltd[1].voltage_uv : -1); }; -static struct sandbox_scmi_clk *get_scmi_clk_state(uint agent_id, uint clock_id) +static struct sandbox_scmi_clk *get_scmi_clk_state(uint clock_id) { - struct sandbox_scmi_clk *target = NULL; - size_t target_count = 0; - size_t n; - - switch (agent_id) { - case 0: - target = scmi0_clk; - target_count = ARRAY_SIZE(scmi0_clk); - break; - case 1: - target = scmi1_clk; - target_count = ARRAY_SIZE(scmi1_clk); - break; - default: - return NULL; - } - - for (n = 0; n < target_count; n++) - if (target[n].id == clock_id) - return target + n; + if (clock_id < ARRAY_SIZE(scmi_clk)) + return scmi_clk + clock_id; return NULL; } -static struct sandbox_scmi_reset *get_scmi_reset_state(uint agent_id, - uint reset_id) +static struct sandbox_scmi_reset *get_scmi_reset_state(uint reset_id) { size_t n; - if (agent_id == 0) { - for (n = 0; n < ARRAY_SIZE(scmi0_reset); n++) - if (scmi0_reset[n].id == reset_id) - return scmi0_reset + n; - } + for (n = 0; n < ARRAY_SIZE(scmi_reset); n++) + if (scmi_reset[n].id == reset_id) + return scmi_reset + n; return NULL; } -static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint agent_id, - uint domain_id) +static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint domain_id) { size_t n; - if (agent_id == 0) { - for (n = 0; n < ARRAY_SIZE(scmi0_voltd); n++) - if (scmi0_voltd[n].id == domain_id) - return scmi0_voltd + n; - } + for (n = 0; n < ARRAY_SIZE(scmi_voltd); n++) + if (scmi_voltd[n].id == domain_id) + return scmi_voltd + n; return NULL; } @@ -156,10 +123,58 @@ static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint agent_id, * Sandbox SCMI agent ops */ +static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_clk_protocol_attr_out *out = NULL; + + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + out = (struct scmi_clk_protocol_attr_out *)msg->out_msg; + out->attributes = ARRAY_SIZE(scmi_clk); + out->status = SCMI_SUCCESS; + + return 0; +} + +static int sandbox_scmi_clock_attribs(struct udevice *dev, struct scmi_msg *msg) +{ + struct scmi_clk_attribute_in *in = NULL; + struct scmi_clk_attribute_out *out = NULL; + struct sandbox_scmi_clk *clk_state = NULL; + int ret; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + in = (struct scmi_clk_attribute_in *)msg->in_msg; + out = (struct scmi_clk_attribute_out *)msg->out_msg; + + clk_state = get_scmi_clk_state(in->clock_id); + if (!clk_state) { + dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); + + out->status = SCMI_NOT_FOUND; + } else { + memset(out, 0, sizeof(*out)); + + if (clk_state->enabled) + out->attributes = 1; + + ret = snprintf(out->clock_name, sizeof(out->clock_name), + "clk%u", in->clock_id); + assert(ret > 0 && ret < sizeof(out->clock_name)); + + out->status = SCMI_SUCCESS; + } + + return 0; +} static int sandbox_scmi_clock_rate_set(struct udevice *dev, struct scmi_msg *msg) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); struct scmi_clk_rate_set_in *in = NULL; struct scmi_clk_rate_set_out *out = NULL; struct sandbox_scmi_clk *clk_state = NULL; @@ -171,7 +186,7 @@ static int sandbox_scmi_clock_rate_set(struct udevice *dev, in = (struct scmi_clk_rate_set_in *)msg->in_msg; out = (struct scmi_clk_rate_set_out *)msg->out_msg; - clk_state = get_scmi_clk_state(agent->idx, in->clock_id); + clk_state = get_scmi_clk_state(in->clock_id); if (!clk_state) { dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); @@ -190,7 +205,6 @@ static int sandbox_scmi_clock_rate_set(struct udevice *dev, static int sandbox_scmi_clock_rate_get(struct udevice *dev, struct scmi_msg *msg) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); struct scmi_clk_rate_get_in *in = NULL; struct scmi_clk_rate_get_out *out = NULL; struct sandbox_scmi_clk *clk_state = NULL; @@ -202,7 +216,7 @@ static int sandbox_scmi_clock_rate_get(struct udevice *dev, in = (struct scmi_clk_rate_get_in *)msg->in_msg; out = (struct scmi_clk_rate_get_out *)msg->out_msg; - clk_state = get_scmi_clk_state(agent->idx, in->clock_id); + clk_state = get_scmi_clk_state(in->clock_id); if (!clk_state) { dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); @@ -219,7 +233,6 @@ static int sandbox_scmi_clock_rate_get(struct udevice *dev, static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); struct scmi_clk_state_in *in = NULL; struct scmi_clk_state_out *out = NULL; struct sandbox_scmi_clk *clk_state = NULL; @@ -231,7 +244,7 @@ static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg) in = (struct scmi_clk_state_in *)msg->in_msg; out = (struct scmi_clk_state_out *)msg->out_msg; - clk_state = get_scmi_clk_state(agent->idx, in->clock_id); + clk_state = get_scmi_clk_state(in->clock_id); if (!clk_state) { dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); @@ -249,7 +262,6 @@ static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg) static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); struct scmi_rd_attr_in *in = NULL; struct scmi_rd_attr_out *out = NULL; struct sandbox_scmi_reset *reset_state = NULL; @@ -261,7 +273,7 @@ static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg) in = (struct scmi_rd_attr_in *)msg->in_msg; out = (struct scmi_rd_attr_out *)msg->out_msg; - reset_state = get_scmi_reset_state(agent->idx, in->domain_id); + reset_state = get_scmi_reset_state(in->domain_id); if (!reset_state) { dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id); @@ -278,7 +290,6 @@ static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg) static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); struct scmi_rd_reset_in *in = NULL; struct scmi_rd_reset_out *out = NULL; struct sandbox_scmi_reset *reset_state = NULL; @@ -290,7 +301,7 @@ static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg) in = (struct scmi_rd_reset_in *)msg->in_msg; out = (struct scmi_rd_reset_out *)msg->out_msg; - reset_state = get_scmi_reset_state(agent->idx, in->domain_id); + reset_state = get_scmi_reset_state(in->domain_id); if (!reset_state) { dev_err(dev, "Unexpected reset domain ID %u\n", in->domain_id); @@ -319,9 +330,24 @@ static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg) return 0; } +static int sandbox_scmi_voltd_protocol_attribs(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_voltd_protocol_attr_out *out = NULL; + + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + out = (struct scmi_voltd_protocol_attr_out *)msg->out_msg; + + out->attributes = ARRAY_SIZE(scmi_voltd); + out->status = SCMI_SUCCESS; + + return 0; +} + static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); struct scmi_voltd_attr_in *in = NULL; struct scmi_voltd_attr_out *out = NULL; struct sandbox_scmi_voltd *voltd_state = NULL; @@ -333,7 +359,7 @@ static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg) in = (struct scmi_voltd_attr_in *)msg->in_msg; out = (struct scmi_voltd_attr_out *)msg->out_msg; - voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); + voltd_state = get_scmi_voltd_state(in->domain_id); if (!voltd_state) { dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); @@ -351,7 +377,6 @@ static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg) static int sandbox_scmi_voltd_config_set(struct udevice *dev, struct scmi_msg *msg) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); struct scmi_voltd_config_set_in *in = NULL; struct scmi_voltd_config_set_out *out = NULL; struct sandbox_scmi_voltd *voltd_state = NULL; @@ -363,7 +388,7 @@ static int sandbox_scmi_voltd_config_set(struct udevice *dev, in = (struct scmi_voltd_config_set_in *)msg->in_msg; out = (struct scmi_voltd_config_set_out *)msg->out_msg; - voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); + voltd_state = get_scmi_voltd_state(in->domain_id); if (!voltd_state) { dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); @@ -388,7 +413,6 @@ static int sandbox_scmi_voltd_config_set(struct udevice *dev, static int sandbox_scmi_voltd_config_get(struct udevice *dev, struct scmi_msg *msg) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); struct scmi_voltd_config_get_in *in = NULL; struct scmi_voltd_config_get_out *out = NULL; struct sandbox_scmi_voltd *voltd_state = NULL; @@ -400,7 +424,7 @@ static int sandbox_scmi_voltd_config_get(struct udevice *dev, in = (struct scmi_voltd_config_get_in *)msg->in_msg; out = (struct scmi_voltd_config_get_out *)msg->out_msg; - voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); + voltd_state = get_scmi_voltd_state(in->domain_id); if (!voltd_state) { dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); @@ -420,7 +444,6 @@ static int sandbox_scmi_voltd_config_get(struct udevice *dev, static int sandbox_scmi_voltd_level_set(struct udevice *dev, struct scmi_msg *msg) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); struct scmi_voltd_level_set_in *in = NULL; struct scmi_voltd_level_set_out *out = NULL; struct sandbox_scmi_voltd *voltd_state = NULL; @@ -432,7 +455,7 @@ static int sandbox_scmi_voltd_level_set(struct udevice *dev, in = (struct scmi_voltd_level_set_in *)msg->in_msg; out = (struct scmi_voltd_level_set_out *)msg->out_msg; - voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); + voltd_state = get_scmi_voltd_state(in->domain_id); if (!voltd_state) { dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); @@ -448,7 +471,6 @@ static int sandbox_scmi_voltd_level_set(struct udevice *dev, static int sandbox_scmi_voltd_level_get(struct udevice *dev, struct scmi_msg *msg) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); struct scmi_voltd_level_get_in *in = NULL; struct scmi_voltd_level_get_out *out = NULL; struct sandbox_scmi_voltd *voltd_state = NULL; @@ -460,7 +482,7 @@ static int sandbox_scmi_voltd_level_get(struct udevice *dev, in = (struct scmi_voltd_level_get_in *)msg->in_msg; out = (struct scmi_voltd_level_get_out *)msg->out_msg; - voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); + voltd_state = get_scmi_voltd_state(in->domain_id); if (!voltd_state) { dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); @@ -479,6 +501,10 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, switch (msg->protocol_id) { case SCMI_PROTOCOL_ID_CLOCK: switch (msg->message_id) { + case SCMI_PROTOCOL_ATTRIBUTES: + return sandbox_scmi_clock_protocol_attribs(dev, msg); + case SCMI_CLOCK_ATTRIBUTES: + return sandbox_scmi_clock_attribs(dev, msg); case SCMI_CLOCK_RATE_SET: return sandbox_scmi_clock_rate_set(dev, msg); case SCMI_CLOCK_RATE_GET: @@ -501,6 +527,8 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, break; case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: switch (msg->message_id) { + case SCMI_PROTOCOL_ATTRIBUTES: + return sandbox_scmi_voltd_protocol_attribs(dev, msg); case SCMI_VOLTAGE_DOMAIN_ATTRIBUTES: return sandbox_scmi_voltd_attribs(dev, msg); case SCMI_VOLTAGE_DOMAIN_CONFIG_SET: @@ -541,52 +569,41 @@ static int sandbox_scmi_test_remove(struct udevice *dev) { struct sandbox_scmi_agent *agent = dev_get_priv(dev); + if (agent != sandbox_scmi_service_ctx()->agent) + return -EINVAL; + debug_print_agent_state(dev, "removed"); /* We only need to dereference the agent in the context */ - sandbox_scmi_service_ctx()->agent[agent->idx] = NULL; + sandbox_scmi_service_ctx()->agent = NULL; return 0; } static int sandbox_scmi_test_probe(struct udevice *dev) { - static const char basename[] = "sandbox-scmi-agent@"; + static const char basename[] = "scmi"; struct sandbox_scmi_agent *agent = dev_get_priv(dev); - const size_t basename_size = sizeof(basename) - 1; - if (strncmp(basename, dev->name, basename_size)) + if (strcmp(basename, dev->name)) return -ENOENT; - switch (dev->name[basename_size]) { - case '0': - *agent = (struct sandbox_scmi_agent){ - .idx = 0, - .clk = scmi0_clk, - .clk_count = ARRAY_SIZE(scmi0_clk), - .reset = scmi0_reset, - .reset_count = ARRAY_SIZE(scmi0_reset), - .voltd = scmi0_voltd, - .voltd_count = ARRAY_SIZE(scmi0_voltd), - }; - break; - case '1': - *agent = (struct sandbox_scmi_agent){ - .idx = 1, - .clk = scmi1_clk, - .clk_count = ARRAY_SIZE(scmi1_clk), - }; - break; - default: - dev_err(dev, "%s(): Unexpected agent ID %s\n", - __func__, dev->name + basename_size); - return -ENOENT; - } + if (sandbox_scmi_service_ctx()->agent) + return -EINVAL; + + *agent = (struct sandbox_scmi_agent){ + .clk = scmi_clk, + .clk_count = ARRAY_SIZE(scmi_clk), + .reset = scmi_reset, + .reset_count = ARRAY_SIZE(scmi_reset), + .voltd = scmi_voltd, + .voltd_count = ARRAY_SIZE(scmi_voltd), + }; debug_print_agent_state(dev, "probed"); /* Save reference for tests purpose */ - sandbox_scmi_service_ctx()->agent[agent->idx] = agent; + sandbox_scmi_service_ctx()->agent = agent; return 0; }; diff --git a/drivers/firmware/scmi/sandbox-scmi_devices.c b/drivers/firmware/scmi/sandbox-scmi_devices.c index 66a6792881..9baeb469ec 100644 --- a/drivers/firmware/scmi/sandbox-scmi_devices.c +++ b/drivers/firmware/scmi/sandbox-scmi_devices.c @@ -23,7 +23,7 @@ * and reset controllers. */ -#define SCMI_TEST_DEVICES_CLK_COUNT 3 +#define SCMI_TEST_DEVICES_CLK_COUNT 2 #define SCMI_TEST_DEVICES_RD_COUNT 1 #define SCMI_TEST_DEVICES_VOLTD_COUNT 2 @@ -135,7 +135,7 @@ U_BOOT_DRIVER(sandbox_scmi_devices) = { .name = "sandbox-scmi_devices", .id = UCLASS_MISC, .of_match = sandbox_scmi_devices_ids, - .priv_auto = sizeof(struct sandbox_scmi_device_priv), + .priv_auto = sizeof(struct sandbox_scmi_device_priv), .remove = sandbox_scmi_devices_remove, .probe = sandbox_scmi_devices_probe, }; diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 4f5870b483..3819f2fa99 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -116,10 +116,23 @@ static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev) int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg) { - const struct scmi_agent_ops *ops = transport_dev_ops(dev); + const struct scmi_agent_ops *ops; + struct udevice *parent = dev; + + /* Find related SCMI agent device */ + do { + parent = dev_get_parent(parent); + } while (parent && device_get_uclass_id(parent) != UCLASS_SCMI_AGENT); + + if (!parent) { + dev_err(dev, "Invalid SCMI device, agent not found\n"); + return -ENODEV; + } + + ops = transport_dev_ops(parent); if (ops->process_msg) - return ops->process_msg(dev, msg); + return ops->process_msg(parent, msg); return -EPROTONOSUPPORT; } diff --git a/drivers/firmware/scmi/smccc_agent.c b/drivers/firmware/scmi/smccc_agent.c index f185891e8f..5e166ca93e 100644 --- a/drivers/firmware/scmi/smccc_agent.c +++ b/drivers/firmware/scmi/smccc_agent.c @@ -32,7 +32,7 @@ struct scmi_smccc_channel { static int scmi_smccc_process_msg(struct udevice *dev, struct scmi_msg *msg) { - struct scmi_smccc_channel *chan = dev_get_priv(dev); + struct scmi_smccc_channel *chan = dev_get_plat(dev); struct arm_smccc_res res; int ret; @@ -51,9 +51,9 @@ static int scmi_smccc_process_msg(struct udevice *dev, struct scmi_msg *msg) return ret; } -static int scmi_smccc_probe(struct udevice *dev) +static int scmi_smccc_of_to_plat(struct udevice *dev) { - struct scmi_smccc_channel *chan = dev_get_priv(dev); + struct scmi_smccc_channel *chan = dev_get_plat(dev); u32 func_id; int ret; @@ -65,12 +65,10 @@ static int scmi_smccc_probe(struct udevice *dev) chan->func_id = func_id; ret = scmi_dt_get_smt_buffer(dev, &chan->smt); - if (ret) { + if (ret) dev_err(dev, "Failed to get smt resources: %d\n", ret); - return ret; - } - return 0; + return ret; } static const struct udevice_id scmi_smccc_ids[] = { @@ -86,7 +84,7 @@ U_BOOT_DRIVER(scmi_smccc) = { .name = "scmi-over-smccc", .id = UCLASS_SCMI_AGENT, .of_match = scmi_smccc_ids, - .priv_auto = sizeof(struct scmi_smccc_channel), - .probe = scmi_smccc_probe, + .plat_auto = sizeof(struct scmi_smccc_channel), + .of_to_plat = scmi_smccc_of_to_plat, .ops = &scmi_smccc_ops, }; diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c index 125c237551..e150fe3429 100644 --- a/drivers/gpio/stm32_gpio.c +++ b/drivers/gpio/stm32_gpio.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -20,6 +19,8 @@ #include #include +#include "stm32_gpio_priv.h" + #define STM32_GPIOS_PER_BANK 16 #define MODE_BITS(gpio_pin) ((gpio_pin) * 2) @@ -32,6 +33,9 @@ #define OTYPE_BITS(gpio_pin) (gpio_pin) #define OTYPE_MSK 1 +#define SECCFG_BITS(gpio_pin) (gpio_pin) +#define SECCFG_MSK 1 + static void stm32_gpio_set_moder(struct stm32_gpio_regs *regs, int idx, int mode) @@ -82,38 +86,43 @@ static enum stm32_gpio_pupd stm32_gpio_get_pupd(struct stm32_gpio_regs *regs, return (readl(®s->pupdr) >> PUPD_BITS(idx)) & PUPD_MASK; } -/* - * convert gpio offset to gpio index taking into account gpio holes - * into gpio bank - */ -int stm32_offset_to_index(struct udevice *dev, unsigned int offset) +static bool stm32_gpio_is_mapped(struct udevice *dev, int offset) +{ + struct stm32_gpio_priv *priv = dev_get_priv(dev); + + return !!(priv->gpio_range & BIT(offset)); +} + +static int stm32_gpio_request(struct udevice *dev, unsigned offset, const char *label) { struct stm32_gpio_priv *priv = dev_get_priv(dev); - unsigned int idx = 0; - int i; - - for (i = 0; i < STM32_GPIOS_PER_BANK; i++) { - if (priv->gpio_range & BIT(i)) { - if (idx == offset) - return idx; - idx++; - } + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct stm32_gpio_regs *regs = priv->regs; + ulong drv_data = dev_get_driver_data(dev); + + if (!stm32_gpio_is_mapped(dev, offset)) + return -ENXIO; + + /* Deny request access if IO is secured */ + if ((drv_data & STM32_GPIO_FLAG_SEC_CTRL) && + ((readl(®s->seccfgr) >> SECCFG_BITS(offset)) & SECCFG_MSK)) { + dev_err(dev, "Failed to get secure IO %s %d @ %p\n", + uc_priv->bank_name, offset, regs); + return -EACCES; } - /* shouldn't happen */ - return -EINVAL; + + return 0; } static int stm32_gpio_direction_input(struct udevice *dev, unsigned offset) { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; - int idx; - idx = stm32_offset_to_index(dev, offset); - if (idx < 0) - return idx; + if (!stm32_gpio_is_mapped(dev, offset)) + return -ENXIO; - stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_IN); + stm32_gpio_set_moder(regs, offset, STM32_GPIO_MODE_IN); return 0; } @@ -123,15 +132,13 @@ static int stm32_gpio_direction_output(struct udevice *dev, unsigned offset, { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; - int idx; - idx = stm32_offset_to_index(dev, offset); - if (idx < 0) - return idx; + if (!stm32_gpio_is_mapped(dev, offset)) + return -ENXIO; - stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT); + stm32_gpio_set_moder(regs, offset, STM32_GPIO_MODE_OUT); - writel(BSRR_BIT(idx, value), ®s->bsrr); + writel(BSRR_BIT(offset, value), ®s->bsrr); return 0; } @@ -140,26 +147,22 @@ static int stm32_gpio_get_value(struct udevice *dev, unsigned offset) { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; - int idx; - idx = stm32_offset_to_index(dev, offset); - if (idx < 0) - return idx; + if (!stm32_gpio_is_mapped(dev, offset)) + return -ENXIO; - return readl(®s->idr) & BIT(idx) ? 1 : 0; + return readl(®s->idr) & BIT(offset) ? 1 : 0; } static int stm32_gpio_set_value(struct udevice *dev, unsigned offset, int value) { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; - int idx; - idx = stm32_offset_to_index(dev, offset); - if (idx < 0) - return idx; + if (!stm32_gpio_is_mapped(dev, offset)) + return -ENXIO; - writel(BSRR_BIT(idx, value), ®s->bsrr); + writel(BSRR_BIT(offset, value), ®s->bsrr); return 0; } @@ -170,14 +173,12 @@ static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset) struct stm32_gpio_regs *regs = priv->regs; int bits_index; int mask; - int idx; u32 mode; - idx = stm32_offset_to_index(dev, offset); - if (idx < 0) - return idx; + if (!stm32_gpio_is_mapped(dev, offset)) + return GPIOF_UNKNOWN; - bits_index = MODE_BITS(idx); + bits_index = MODE_BITS(offset); mask = MODE_BITS_MASK << bits_index; mode = (readl(®s->moder) & mask) >> bits_index; @@ -196,30 +197,28 @@ static int stm32_gpio_set_flags(struct udevice *dev, unsigned int offset, { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; - int idx; - idx = stm32_offset_to_index(dev, offset); - if (idx < 0) - return idx; + if (!stm32_gpio_is_mapped(dev, offset)) + return -ENXIO; if (flags & GPIOD_IS_OUT) { bool value = flags & GPIOD_IS_OUT_ACTIVE; if (flags & GPIOD_OPEN_DRAIN) - stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_OD); + stm32_gpio_set_otype(regs, offset, STM32_GPIO_OTYPE_OD); else - stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_PP); + stm32_gpio_set_otype(regs, offset, STM32_GPIO_OTYPE_PP); - stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT); - writel(BSRR_BIT(idx, value), ®s->bsrr); + stm32_gpio_set_moder(regs, offset, STM32_GPIO_MODE_OUT); + writel(BSRR_BIT(offset, value), ®s->bsrr); } else if (flags & GPIOD_IS_IN) { - stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_IN); + stm32_gpio_set_moder(regs, offset, STM32_GPIO_MODE_IN); } if (flags & GPIOD_PULL_UP) - stm32_gpio_set_pupd(regs, idx, STM32_GPIO_PUPD_UP); + stm32_gpio_set_pupd(regs, offset, STM32_GPIO_PUPD_UP); else if (flags & GPIOD_PULL_DOWN) - stm32_gpio_set_pupd(regs, idx, STM32_GPIO_PUPD_DOWN); + stm32_gpio_set_pupd(regs, offset, STM32_GPIO_PUPD_DOWN); return 0; } @@ -229,19 +228,17 @@ static int stm32_gpio_get_flags(struct udevice *dev, unsigned int offset, { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; - int idx; ulong dir_flags = 0; - idx = stm32_offset_to_index(dev, offset); - if (idx < 0) - return idx; + if (!stm32_gpio_is_mapped(dev, offset)) + return -ENXIO; - switch (stm32_gpio_get_moder(regs, idx)) { + switch (stm32_gpio_get_moder(regs, offset)) { case STM32_GPIO_MODE_OUT: dir_flags |= GPIOD_IS_OUT; - if (stm32_gpio_get_otype(regs, idx) == STM32_GPIO_OTYPE_OD) + if (stm32_gpio_get_otype(regs, offset) == STM32_GPIO_OTYPE_OD) dir_flags |= GPIOD_OPEN_DRAIN; - if (readl(®s->idr) & BIT(idx)) + if (readl(®s->idr) & BIT(offset)) dir_flags |= GPIOD_IS_OUT_ACTIVE; break; case STM32_GPIO_MODE_IN: @@ -250,7 +247,7 @@ static int stm32_gpio_get_flags(struct udevice *dev, unsigned int offset, default: break; } - switch (stm32_gpio_get_pupd(regs, idx)) { + switch (stm32_gpio_get_pupd(regs, offset)) { case STM32_GPIO_PUPD_UP: dir_flags |= GPIOD_PULL_UP; break; @@ -266,6 +263,7 @@ static int stm32_gpio_get_flags(struct udevice *dev, unsigned int offset, } static const struct dm_gpio_ops gpio_stm32_ops = { + .request = stm32_gpio_request, .direction_input = stm32_gpio_direction_input, .direction_output = stm32_gpio_direction_output, .get_value = stm32_gpio_get_value, @@ -303,17 +301,14 @@ static int gpio_stm32_probe(struct udevice *dev) if (!ret && args.args_count < 3) return -EINVAL; - if (ret == -ENOENT) { - uc_priv->gpio_count = STM32_GPIOS_PER_BANK; + uc_priv->gpio_count = STM32_GPIOS_PER_BANK; + if (ret == -ENOENT) priv->gpio_range = GENMASK(STM32_GPIOS_PER_BANK - 1, 0); - } while (ret != -ENOENT) { priv->gpio_range |= GENMASK(args.args[2] + args.args[0] - 1, args.args[0]); - uc_priv->gpio_count += args.args[2]; - ret = dev_read_phandle_with_args(dev, "gpio-ranges", NULL, 3, ++i, &args); if (!ret && args.args_count < 3) diff --git a/arch/arm/include/asm/arch-stm32/gpio.h b/drivers/gpio/stm32_gpio_priv.h similarity index 87% rename from arch/arm/include/asm/arch-stm32/gpio.h rename to drivers/gpio/stm32_gpio_priv.h index 233ce278a7..d89e9b8ed6 100644 --- a/arch/arm/include/asm/arch-stm32/gpio.h +++ b/drivers/gpio/stm32_gpio_priv.h @@ -4,8 +4,8 @@ * Author(s): Vikas Manocha, for STMicroelectronics. */ -#ifndef _GPIO_H_ -#define _GPIO_H_ +#ifndef _STM32_GPIO_PRIV_H_ +#define _STM32_GPIO_PRIV_H_ enum stm32_gpio_mode { STM32_GPIO_MODE_IN = 0, @@ -51,6 +51,8 @@ enum stm32_gpio_af { STM32_GPIO_AF15 }; +#define STM32_GPIO_FLAG_SEC_CTRL BIT(0) + struct stm32_gpio_dsc { u8 port; u8 pin; @@ -74,6 +76,9 @@ struct stm32_gpio_regs { u32 bsrr; /* GPIO port bit set/reset */ u32 lckr; /* GPIO port configuration lock */ u32 afr[2]; /* GPIO alternate function */ + u32 brr; /* GPIO port bit reset */ + u32 rfu; /* Reserved */ + u32 seccfgr; /* GPIO secure configuration */ }; struct stm32_gpio_priv { @@ -81,6 +86,4 @@ struct stm32_gpio_priv { unsigned int gpio_range; }; -int stm32_offset_to_index(struct udevice *dev, unsigned int offset); - -#endif /* _GPIO_H_ */ +#endif /* _STM32_GPIO_PRIV_H_ */ diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 7b04a09de0..bf2a6c9b4b 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -45,6 +45,8 @@ struct stm32_i2c_regs { /* STM32 I2C control 1 */ #define STM32_I2C_CR1_ANFOFF BIT(12) +#define STM32_I2C_CR1_DNF_MASK GENMASK(11, 8) +#define STM32_I2C_CR1_DNF(n) (((n) & 0xf) << 8) #define STM32_I2C_CR1_ERRIE BIT(7) #define STM32_I2C_CR1_TCIE BIT(6) #define STM32_I2C_CR1_STOPIE BIT(5) @@ -105,10 +107,8 @@ struct stm32_i2c_regs { #define STM32_I2C_MAX_LEN 0xff -#define STM32_I2C_DNF_DEFAULT 0 -#define STM32_I2C_DNF_MAX 16 +#define STM32_I2C_DNF_MAX 15 -#define STM32_I2C_ANALOG_FILTER_ENABLE 1 #define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ #define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ @@ -156,9 +156,8 @@ struct stm32_i2c_spec { * @clock_src: I2C clock source frequency (Hz) * @rise_time: Rise time (ns) * @fall_time: Fall time (ns) - * @dnf: Digital filter coefficient (0-16) + * @dnf: value of digital filter to apply * @analog_filter: Analog filter delay (On/Off) - * @fmp_clr_offset: Fast Mode Plus clear register offset from set register */ struct stm32_i2c_setup { u32 speed_freq; @@ -167,6 +166,13 @@ struct stm32_i2c_setup { u32 fall_time; u8 dnf; bool analog_filter; +}; + +/** + * struct stm32_i2c_data - driver data for I2C configuration by compatible + * @fmp_clr_offset: Fast Mode Plus clear register offset from set register + */ +struct stm32_i2c_data { u32 fmp_clr_offset; }; @@ -197,16 +203,18 @@ struct stm32_i2c_timings { * @regmap_sreg: register address for setting Fast Mode Plus bits * @regmap_creg: register address for clearing Fast Mode Plus bits * @regmap_mask: mask for Fast Mode Plus bits + * @dnf_dt: value of digital filter requested via dt */ struct stm32_i2c_priv { struct stm32_i2c_regs *regs; struct clk clk; - struct stm32_i2c_setup *setup; + struct stm32_i2c_setup setup; u32 speed; struct regmap *regmap; u32 regmap_sreg; u32 regmap_creg; u32 regmap_mask; + u32 dnf_dt; }; static const struct stm32_i2c_spec i2c_specs[] = { @@ -251,21 +259,18 @@ static const struct stm32_i2c_spec i2c_specs[] = { }, }; -static const struct stm32_i2c_setup stm32f7_setup = { - .rise_time = STM32_I2C_RISE_TIME_DEFAULT, - .fall_time = STM32_I2C_FALL_TIME_DEFAULT, - .dnf = STM32_I2C_DNF_DEFAULT, - .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE, +static const struct stm32_i2c_data stm32f7_data = { + .fmp_clr_offset = 0x00, }; -static const struct stm32_i2c_setup stm32mp15_setup = { - .rise_time = STM32_I2C_RISE_TIME_DEFAULT, - .fall_time = STM32_I2C_FALL_TIME_DEFAULT, - .dnf = STM32_I2C_DNF_DEFAULT, - .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE, +static const struct stm32_i2c_data stm32mp15_data = { .fmp_clr_offset = 0x40, }; +static const struct stm32_i2c_data stm32mp13_data = { + .fmp_clr_offset = 0x4, +}; + static int stm32_i2c_check_device_busy(struct stm32_i2c_priv *i2c_priv) { struct stm32_i2c_regs *regs = i2c_priv->regs; @@ -506,14 +511,13 @@ static int stm32_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, return 0; } -static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, +static int stm32_i2c_compute_solutions(u32 i2cclk, + struct stm32_i2c_setup *setup, const struct stm32_i2c_spec *specs, struct list_head *solutions) { struct stm32_i2c_timings *v; u32 p_prev = STM32_PRESC_MAX; - u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, - setup->clock_src); u32 af_delay_min, af_delay_max; u16 p, l, a; int sdadel_min, sdadel_max, scldel_min; @@ -581,7 +585,8 @@ static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, return ret; } -static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup, +static int stm32_i2c_choose_solution(u32 i2cclk, + struct stm32_i2c_setup *setup, const struct stm32_i2c_spec *specs, struct list_head *solutions, struct stm32_i2c_timings *s) @@ -590,8 +595,6 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup, u32 i2cbus = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, setup->speed_freq); u32 clk_error_prev = i2cbus; - u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, - setup->clock_src); u32 clk_min, clk_max; u32 af_delay_min; u32 dnf_delay; @@ -678,12 +681,13 @@ static const struct stm32_i2c_spec *get_specs(u32 rate) } static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, - struct stm32_i2c_setup *setup, struct stm32_i2c_timings *output) { + struct stm32_i2c_setup *setup = &i2c_priv->setup; const struct stm32_i2c_spec *specs; struct stm32_i2c_timings *v, *_v; struct list_head solutions; + u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, setup->clock_src); int ret; specs = get_specs(setup->speed_freq); @@ -701,6 +705,8 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, return -EINVAL; } + /* Analog and Digital Filters */ + setup->dnf = DIV_ROUND_CLOSEST(i2c_priv->dnf_dt, i2cclk); if (setup->dnf > STM32_I2C_DNF_MAX) { log_err("DNF out of bound %d/%d\n", setup->dnf, STM32_I2C_DNF_MAX); @@ -708,11 +714,11 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, } INIT_LIST_HEAD(&solutions); - ret = stm32_i2c_compute_solutions(setup, specs, &solutions); + ret = stm32_i2c_compute_solutions(i2cclk, setup, specs, &solutions); if (ret) goto exit; - ret = stm32_i2c_choose_solution(setup, specs, &solutions, output); + ret = stm32_i2c_choose_solution(i2cclk, setup, specs, &solutions, output); if (ret) goto exit; @@ -745,7 +751,7 @@ static u32 get_lower_rate(u32 rate) static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv, struct stm32_i2c_timings *timing) { - struct stm32_i2c_setup *setup = i2c_priv->setup; + struct stm32_i2c_setup *setup = &i2c_priv->setup; int ret = 0; setup->speed_freq = i2c_priv->speed; @@ -757,7 +763,7 @@ static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv, } do { - ret = stm32_i2c_compute_timing(i2c_priv, setup, timing); + ret = stm32_i2c_compute_timing(i2c_priv, timing); if (ret) { log_debug("failed to compute I2C timings.\n"); if (setup->speed_freq > I2C_SPEED_STANDARD_RATE) { @@ -839,10 +845,15 @@ static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv) writel(timing, ®s->timingr); /* Enable I2C */ - if (i2c_priv->setup->analog_filter) + if (i2c_priv->setup.analog_filter) clrbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF); else setbits_le32(®s->cr1, STM32_I2C_CR1_ANFOFF); + + /* Program the Digital Filter */ + clrsetbits_le32(®s->cr1, STM32_I2C_CR1_DNF_MASK, + STM32_I2C_CR1_DNF(i2c_priv->setup.dnf)); + setbits_le32(®s->cr1, STM32_I2C_CR1_PE); return 0; @@ -903,21 +914,26 @@ clk_free: static int stm32_of_to_plat(struct udevice *dev) { + const struct stm32_i2c_data *data; struct stm32_i2c_priv *i2c_priv = dev_get_priv(dev); u32 rise_time, fall_time; int ret; - i2c_priv->setup = (struct stm32_i2c_setup *)dev_get_driver_data(dev); - if (!i2c_priv->setup) + data = (const struct stm32_i2c_data *)dev_get_driver_data(dev); + if (!data) return -EINVAL; - rise_time = dev_read_u32_default(dev, "i2c-scl-rising-time-ns", 0); - if (rise_time) - i2c_priv->setup->rise_time = rise_time; + rise_time = dev_read_u32_default(dev, "i2c-scl-rising-time-ns", + STM32_I2C_RISE_TIME_DEFAULT); + + fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns", + STM32_I2C_FALL_TIME_DEFAULT); + + i2c_priv->dnf_dt = dev_read_u32_default(dev, "i2c-digital-filter-width-ns", 0); + if (!dev_read_bool(dev, "i2c-digital-filter")) + i2c_priv->dnf_dt = 0; - fall_time = dev_read_u32_default(dev, "i2c-scl-falling-time-ns", 0); - if (fall_time) - i2c_priv->setup->fall_time = fall_time; + i2c_priv->setup.analog_filter = dev_read_bool(dev, "i2c-analog-filter"); /* Optional */ i2c_priv->regmap = syscon_regmap_lookup_by_phandle(dev, @@ -930,8 +946,7 @@ static int stm32_of_to_plat(struct udevice *dev) return ret; i2c_priv->regmap_sreg = fmp[1]; - i2c_priv->regmap_creg = fmp[1] + - i2c_priv->setup->fmp_clr_offset; + i2c_priv->regmap_creg = fmp[1] + data->fmp_clr_offset; i2c_priv->regmap_mask = fmp[2]; } @@ -944,8 +959,9 @@ static const struct dm_i2c_ops stm32_i2c_ops = { }; static const struct udevice_id stm32_i2c_of_match[] = { - { .compatible = "st,stm32f7-i2c", .data = (ulong)&stm32f7_setup }, - { .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32mp15_setup }, + { .compatible = "st,stm32f7-i2c", .data = (ulong)&stm32f7_data }, + { .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32mp15_data }, + { .compatible = "st,stm32mp13-i2c", .data = (ulong)&stm32mp13_data }, {} }; diff --git a/drivers/misc/imx8/scu.c b/drivers/misc/imx8/scu.c index 035a600f71..4ab5cb4bf1 100644 --- a/drivers/misc/imx8/scu.c +++ b/drivers/misc/imx8/scu.c @@ -219,7 +219,7 @@ static int imx8_scu_bind(struct udevice *dev) debug("%s(dev=%p)\n", __func__, dev); ofnode_for_each_subnode(node, dev_ofnode(dev)) { - ret = lists_bind_fdt(dev, node, &child, true); + ret = lists_bind_fdt(dev, node, &child, NULL, true); if (ret) return ret; debug("bind child dev %s\n", child->name); diff --git a/drivers/misc/stm32_rcc.c b/drivers/misc/stm32_rcc.c index f14d6e26d9..b816503bfa 100644 --- a/drivers/misc/stm32_rcc.c +++ b/drivers/misc/stm32_rcc.c @@ -39,6 +39,11 @@ struct stm32_rcc_clk stm32_rcc_clk_mp1 = { .soc = STM32MP1, }; +struct stm32_rcc_clk stm32_rcc_clk_mp13 = { + .drv_name = "stm32mp13_clk", + .soc = STM32MP1, +}; + static int stm32_rcc_bind(struct udevice *dev) { struct udevice *child; @@ -79,6 +84,7 @@ static const struct udevice_id stm32_rcc_ids[] = { {.compatible = "st,stm32f746-rcc", .data = (ulong)&stm32_rcc_clk_f7 }, {.compatible = "st,stm32h743-rcc", .data = (ulong)&stm32_rcc_clk_h7 }, {.compatible = "st,stm32mp1-rcc", .data = (ulong)&stm32_rcc_clk_mp1 }, + {.compatible = "st,stm32mp13-rcc", .data = (ulong)&stm32_rcc_clk_mp13 }, { } }; diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c index d23b7d9729..eab94c7b60 100644 --- a/drivers/mmc/mmc_write.c +++ b/drivers/mmc/mmc_write.c @@ -102,7 +102,7 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt) "The erase range would be change to " "0x" LBAF "~0x" LBAF "\n\n", mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1), - ((start + blkcnt + mmc->erase_grp_size) + ((start + blkcnt + mmc->erase_grp_size - 1) & ~(mmc->erase_grp_size - 1)) - 1); while (blk < blkcnt) { diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c index a3cdf7bcd9..1bfe82a0ba 100644 --- a/drivers/mmc/stm32_sdmmc2.c +++ b/drivers/mmc/stm32_sdmmc2.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -29,9 +30,6 @@ struct stm32_sdmmc2_plat { struct mmc_config cfg; struct mmc mmc; -}; - -struct stm32_sdmmc2_priv { fdt_addr_t base; struct clk clk; struct reset_ctl reset_ctl; @@ -207,7 +205,7 @@ static void stm32_sdmmc2_start_data(struct udevice *dev, struct mmc_data *data, struct stm32_sdmmc2_ctx *ctx) { - struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); u32 data_ctrl, idmabase0; /* Configure the SDMMC DPSM (Data Path State Machine) */ @@ -223,10 +221,10 @@ static void stm32_sdmmc2_start_data(struct udevice *dev, } /* Set the SDMMC DataLength value */ - writel(ctx->data_length, priv->base + SDMMC_DLEN); + writel(ctx->data_length, plat->base + SDMMC_DLEN); /* Write to SDMMC DCTRL */ - writel(data_ctrl, priv->base + SDMMC_DCTRL); + writel(data_ctrl, plat->base + SDMMC_DCTRL); /* Cache align */ ctx->cache_start = rounddown(idmabase0, ARCH_DMA_MINALIGN); @@ -241,19 +239,19 @@ static void stm32_sdmmc2_start_data(struct udevice *dev, flush_dcache_range(ctx->cache_start, ctx->cache_end); /* Enable internal DMA */ - writel(idmabase0, priv->base + SDMMC_IDMABASE0); - writel(SDMMC_IDMACTRL_IDMAEN, priv->base + SDMMC_IDMACTRL); + writel(idmabase0, plat->base + SDMMC_IDMABASE0); + writel(SDMMC_IDMACTRL_IDMAEN, plat->base + SDMMC_IDMACTRL); } static void stm32_sdmmc2_start_cmd(struct udevice *dev, struct mmc_cmd *cmd, u32 cmd_param, struct stm32_sdmmc2_ctx *ctx) { - struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); u32 timeout = 0; - if (readl(priv->base + SDMMC_CMD) & SDMMC_CMD_CPSMEN) - writel(0, priv->base + SDMMC_CMD); + if (readl(plat->base + SDMMC_CMD) & SDMMC_CMD_CPSMEN) + writel(0, plat->base + SDMMC_CMD); cmd_param |= cmd->cmdidx | SDMMC_CMD_CPSMEN; if (cmd->resp_type & MMC_RSP_PRESENT) { @@ -276,30 +274,30 @@ static void stm32_sdmmc2_start_cmd(struct udevice *dev, if (ctx->data_length) { timeout = SDMMC_CMD_TIMEOUT; } else { - writel(0, priv->base + SDMMC_DCTRL); + writel(0, plat->base + SDMMC_DCTRL); if (cmd->resp_type & MMC_RSP_BUSY) timeout = SDMMC_CMD_TIMEOUT; } /* Set the SDMMC Data TimeOut value */ - writel(timeout, priv->base + SDMMC_DTIMER); + writel(timeout, plat->base + SDMMC_DTIMER); /* Clear flags */ - writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR); + writel(SDMMC_ICR_STATIC_FLAGS, plat->base + SDMMC_ICR); /* Set SDMMC argument value */ - writel(cmd->cmdarg, priv->base + SDMMC_ARG); + writel(cmd->cmdarg, plat->base + SDMMC_ARG); /* Set SDMMC command parameters */ - writel(cmd_param, priv->base + SDMMC_CMD); + writel(cmd_param, plat->base + SDMMC_CMD); } static int stm32_sdmmc2_end_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct stm32_sdmmc2_ctx *ctx) { - struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); u32 mask = SDMMC_STA_CTIMEOUT; u32 status; int ret; @@ -313,7 +311,7 @@ static int stm32_sdmmc2_end_cmd(struct udevice *dev, } /* Polling status register */ - ret = readl_poll_timeout(priv->base + SDMMC_STA, status, status & mask, + ret = readl_poll_timeout(plat->base + SDMMC_STA, status, status & mask, 10000); if (ret < 0) { @@ -338,11 +336,11 @@ static int stm32_sdmmc2_end_cmd(struct udevice *dev, } if (status & SDMMC_STA_CMDREND && cmd->resp_type & MMC_RSP_PRESENT) { - cmd->response[0] = readl(priv->base + SDMMC_RESP1); + cmd->response[0] = readl(plat->base + SDMMC_RESP1); if (cmd->resp_type & MMC_RSP_136) { - cmd->response[1] = readl(priv->base + SDMMC_RESP2); - cmd->response[2] = readl(priv->base + SDMMC_RESP3); - cmd->response[3] = readl(priv->base + SDMMC_RESP4); + cmd->response[1] = readl(plat->base + SDMMC_RESP2); + cmd->response[2] = readl(plat->base + SDMMC_RESP3); + cmd->response[3] = readl(plat->base + SDMMC_RESP4); } /* Wait for BUSYD0END flag if busy status is detected */ @@ -351,7 +349,7 @@ static int stm32_sdmmc2_end_cmd(struct udevice *dev, mask = SDMMC_STA_DTIMEOUT | SDMMC_STA_BUSYD0END; /* Polling status register */ - ret = readl_poll_timeout(priv->base + SDMMC_STA, + ret = readl_poll_timeout(plat->base + SDMMC_STA, status, status & mask, SDMMC_BUSYD0END_TIMEOUT_US); @@ -379,7 +377,7 @@ static int stm32_sdmmc2_end_data(struct udevice *dev, struct mmc_data *data, struct stm32_sdmmc2_ctx *ctx) { - struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); u32 mask = SDMMC_STA_DCRCFAIL | SDMMC_STA_DTIMEOUT | SDMMC_STA_IDMATE | SDMMC_STA_DATAEND; u32 status; @@ -389,9 +387,9 @@ static int stm32_sdmmc2_end_data(struct udevice *dev, else mask |= SDMMC_STA_TXUNDERR; - status = readl(priv->base + SDMMC_STA); + status = readl(plat->base + SDMMC_STA); while (!(status & mask)) - status = readl(priv->base + SDMMC_STA); + status = readl(plat->base + SDMMC_STA); /* * Need invalidate the dcache again to avoid any @@ -403,7 +401,7 @@ static int stm32_sdmmc2_end_data(struct udevice *dev, if (status & SDMMC_STA_DCRCFAIL) { dev_dbg(dev, "error SDMMC_STA_DCRCFAIL (0x%x) for cmd %d\n", status, cmd->cmdidx); - if (readl(priv->base + SDMMC_DCOUNT)) + if (readl(plat->base + SDMMC_DCOUNT)) ctx->dpsm_abort = true; return -EILSEQ; } @@ -442,7 +440,7 @@ static int stm32_sdmmc2_end_data(struct udevice *dev, static int stm32_sdmmc2_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) { - struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); struct stm32_sdmmc2_ctx ctx; u32 cmdat = data ? SDMMC_CMD_CMDTRANS : 0; int ret, retry = 3; @@ -469,9 +467,9 @@ retry_cmd: ret = stm32_sdmmc2_end_data(dev, cmd, data, &ctx); /* Clear flags */ - writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR); + writel(SDMMC_ICR_STATIC_FLAGS, plat->base + SDMMC_ICR); if (data) - writel(0x0, priv->base + SDMMC_IDMACTRL); + writel(0x0, plat->base + SDMMC_IDMACTRL); /* * To stop Data Path State Machine, a stop_transmission command @@ -492,7 +490,7 @@ retry_cmd: SDMMC_CMD_CMDSTOP, &ctx); stm32_sdmmc2_end_cmd(dev, &stop_cmd, &ctx); - writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR); + writel(SDMMC_ICR_STATIC_FLAGS, plat->base + SDMMC_ICR); } if ((ret != -ETIMEDOUT) && (ret != 0) && retry) { @@ -511,15 +509,15 @@ retry_cmd: * This will reset the SDMMC to the reset state and the CPSM and DPSM * to the Idle state. SDMMC is disabled, Signals Hiz. */ -static void stm32_sdmmc2_reset(struct stm32_sdmmc2_priv *priv) +static void stm32_sdmmc2_reset(struct stm32_sdmmc2_plat *plat) { /* Reset */ - reset_assert(&priv->reset_ctl); + reset_assert(&plat->reset_ctl); udelay(2); - reset_deassert(&priv->reset_ctl); + reset_deassert(&plat->reset_ctl); /* init the needed SDMMC register after reset */ - writel(priv->pwr_reg_msk, priv->base + SDMMC_POWER); + writel(plat->pwr_reg_msk, plat->base + SDMMC_POWER); } /* @@ -528,13 +526,13 @@ static void stm32_sdmmc2_reset(struct stm32_sdmmc2_priv *priv) * SDMMC_CMD and SDMMC_CK are driven low, to prevent the card from being * supplied through the signal lines. */ -static void stm32_sdmmc2_pwrcycle(struct stm32_sdmmc2_priv *priv) +static void stm32_sdmmc2_pwrcycle(struct stm32_sdmmc2_plat *plat) { - if ((readl(priv->base + SDMMC_POWER) & SDMMC_POWER_PWRCTRL_MASK) == + if ((readl(plat->base + SDMMC_POWER) & SDMMC_POWER_PWRCTRL_MASK) == SDMMC_POWER_PWRCTRL_CYCLE) return; - stm32_sdmmc2_reset(priv); + stm32_sdmmc2_reset(plat); } /* @@ -543,10 +541,10 @@ static void stm32_sdmmc2_pwrcycle(struct stm32_sdmmc2_priv *priv) * Reset => Power-Cycle => Power-Off => Power * PWRCTRL=10 PWCTRL=00 PWCTRL=11 */ -static void stm32_sdmmc2_pwron(struct stm32_sdmmc2_priv *priv) +static void stm32_sdmmc2_pwron(struct stm32_sdmmc2_plat *plat) { u32 pwrctrl = - readl(priv->base + SDMMC_POWER) & SDMMC_POWER_PWRCTRL_MASK; + readl(plat->base + SDMMC_POWER) & SDMMC_POWER_PWRCTRL_MASK; if (pwrctrl == SDMMC_POWER_PWRCTRL_ON) return; @@ -555,21 +553,21 @@ static void stm32_sdmmc2_pwron(struct stm32_sdmmc2_priv *priv) * it is the reset state here = the only managed by the driver */ if (pwrctrl == SDMMC_POWER_PWRCTRL_OFF) { - writel(SDMMC_POWER_PWRCTRL_CYCLE | priv->pwr_reg_msk, - priv->base + SDMMC_POWER); + writel(SDMMC_POWER_PWRCTRL_CYCLE | plat->pwr_reg_msk, + plat->base + SDMMC_POWER); } /* * the remaining case is SDMMC_POWER_PWRCTRL_CYCLE * switch to Power-Off state: SDMCC disable, signals drive 1 */ - writel(SDMMC_POWER_PWRCTRL_OFF | priv->pwr_reg_msk, - priv->base + SDMMC_POWER); + writel(SDMMC_POWER_PWRCTRL_OFF | plat->pwr_reg_msk, + plat->base + SDMMC_POWER); /* After the 1ms delay set the SDMMC to power-on */ mdelay(1); - writel(SDMMC_POWER_PWRCTRL_ON | priv->pwr_reg_msk, - priv->base + SDMMC_POWER); + writel(SDMMC_POWER_PWRCTRL_ON | plat->pwr_reg_msk, + plat->base + SDMMC_POWER); /* during the first 74 SDMMC_CK cycles the SDMMC is still disabled. */ } @@ -578,18 +576,18 @@ static void stm32_sdmmc2_pwron(struct stm32_sdmmc2_priv *priv) static int stm32_sdmmc2_set_ios(struct udevice *dev) { struct mmc *mmc = mmc_get_mmc_dev(dev); - struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); u32 desired = mmc->clock; - u32 sys_clock = clk_get_rate(&priv->clk); + u32 sys_clock = clk_get_rate(&plat->clk); u32 clk = 0; dev_dbg(dev, "bus_with = %d, clock = %d\n", mmc->bus_width, mmc->clock); if (mmc->clk_disable) - stm32_sdmmc2_pwrcycle(priv); + stm32_sdmmc2_pwrcycle(plat); else - stm32_sdmmc2_pwron(priv); + stm32_sdmmc2_pwron(plat); /* * clk_div = 0 => command and data generated on SDMMCCLK falling edge @@ -599,7 +597,7 @@ static int stm32_sdmmc2_set_ios(struct udevice *dev) * SDMMCCLK falling edge */ if (desired && ((sys_clock > desired) || - IS_RISING_EDGE(priv->clk_reg_msk))) { + IS_RISING_EDGE(plat->clk_reg_msk))) { clk = DIV_ROUND_UP(sys_clock, 2 * desired); if (clk > SDMMC_CLKCR_CLKDIV_MAX) clk = SDMMC_CLKCR_CLKDIV_MAX; @@ -610,30 +608,30 @@ static int stm32_sdmmc2_set_ios(struct udevice *dev) if (mmc->bus_width == 8) clk |= SDMMC_CLKCR_WIDBUS_8; - writel(clk | priv->clk_reg_msk | SDMMC_CLKCR_HWFC_EN, - priv->base + SDMMC_CLKCR); + writel(clk | plat->clk_reg_msk | SDMMC_CLKCR_HWFC_EN, + plat->base + SDMMC_CLKCR); return 0; } static int stm32_sdmmc2_getcd(struct udevice *dev) { - struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); dev_dbg(dev, "%s called\n", __func__); - if (dm_gpio_is_valid(&priv->cd_gpio)) - return dm_gpio_get_value(&priv->cd_gpio); + if (dm_gpio_is_valid(&plat->cd_gpio)) + return dm_gpio_get_value(&plat->cd_gpio); return 1; } static int stm32_sdmmc2_host_power_cycle(struct udevice *dev) { - struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); - writel(SDMMC_POWER_PWRCTRL_CYCLE | priv->pwr_reg_msk, - priv->base + SDMMC_POWER); + writel(SDMMC_POWER_PWRCTRL_CYCLE | plat->pwr_reg_msk, + plat->base + SDMMC_POWER); return 0; } @@ -645,64 +643,127 @@ static const struct dm_mmc_ops stm32_sdmmc2_ops = { .host_power_cycle = stm32_sdmmc2_host_power_cycle, }; -static int stm32_sdmmc2_probe(struct udevice *dev) +static int stm32_sdmmc2_of_to_plat(struct udevice *dev) { - struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); - struct stm32_sdmmc2_priv *priv = dev_get_priv(dev); struct mmc_config *cfg = &plat->cfg; int ret; - priv->base = dev_read_addr(dev); - if (priv->base == FDT_ADDR_T_NONE) + plat->base = dev_read_addr(dev); + if (plat->base == FDT_ADDR_T_NONE) return -EINVAL; if (dev_read_bool(dev, "st,neg-edge")) - priv->clk_reg_msk |= SDMMC_CLKCR_NEGEDGE; + plat->clk_reg_msk |= SDMMC_CLKCR_NEGEDGE; if (dev_read_bool(dev, "st,sig-dir")) - priv->pwr_reg_msk |= SDMMC_POWER_DIRPOL; + plat->pwr_reg_msk |= SDMMC_POWER_DIRPOL; if (dev_read_bool(dev, "st,use-ckin")) - priv->clk_reg_msk |= SDMMC_CLKCR_SELCLKRX_CKIN; + plat->clk_reg_msk |= SDMMC_CLKCR_SELCLKRX_CKIN; - ret = clk_get_by_index(dev, 0, &priv->clk); + cfg->f_min = 400000; + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + cfg->name = "STM32 SD/MMC"; + cfg->host_caps = 0; + cfg->f_max = 52000000; + ret = mmc_of_parse(dev, cfg); if (ret) return ret; - ret = clk_enable(&priv->clk); + ret = clk_get_by_index(dev, 0, &plat->clk); if (ret) - goto clk_free; + return ret; - ret = reset_get_by_index(dev, 0, &priv->reset_ctl); - if (ret) - goto clk_disable; + ret = reset_get_by_index(dev, 0, &plat->reset_ctl); + if (ret) { + clk_free(&plat->clk); + return ret; + } - gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, + gpio_request_by_name(dev, "cd-gpios", 0, &plat->cd_gpio, GPIOD_IS_IN); - cfg->f_min = 400000; - cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; - cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - cfg->name = "STM32 SD/MMC"; + return 0; +} - cfg->host_caps = 0; - cfg->f_max = 52000000; - mmc_of_parse(dev, cfg); +static int stm32_sdmmc2_probe_level_translator(struct udevice *dev) +{ + struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); + struct gpio_desc cmd_gpio; + struct gpio_desc ck_gpio; + struct gpio_desc ckin_gpio; + int clk_hi, clk_lo, ret; - upriv->mmc = &plat->mmc; + ret = gpio_request_by_name(dev, "st,cmd-gpios", 0, &cmd_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + if (ret) + goto exit_cmd; + + ret = gpio_request_by_name(dev, "st,ck-gpios", 0, &ck_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + if (ret) + goto exit_ck; + + ret = gpio_request_by_name(dev, "st,ckin-gpios", 0, &ckin_gpio, + GPIOD_IS_IN); + if (ret) + goto exit_ckin; + + /* All GPIOs are valid, test whether level translator works */ + + /* Sample CKIN */ + clk_hi = !!dm_gpio_get_value(&ckin_gpio); + + /* Set CK low */ + dm_gpio_set_value(&ck_gpio, 0); + + /* Sample CKIN */ + clk_lo = !!dm_gpio_get_value(&ckin_gpio); + + /* Tristate all */ + dm_gpio_set_dir_flags(&cmd_gpio, GPIOD_IS_IN); + dm_gpio_set_dir_flags(&ck_gpio, GPIOD_IS_IN); + + /* Level translator is present if CK signal is propagated to CKIN */ + if (!clk_hi || clk_lo) + plat->clk_reg_msk &= ~SDMMC_CLKCR_SELCLKRX_CKIN; + + dm_gpio_free(dev, &ckin_gpio); + +exit_ckin: + dm_gpio_free(dev, &ck_gpio); +exit_ck: + dm_gpio_free(dev, &cmd_gpio); +exit_cmd: + pinctrl_select_state(dev, "default"); - /* SDMMC init */ - stm32_sdmmc2_reset(priv); return 0; +} -clk_disable: - clk_disable(&priv->clk); -clk_free: - clk_free(&priv->clk); +static int stm32_sdmmc2_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); + int ret; - return ret; + ret = clk_enable(&plat->clk); + if (ret) { + clk_free(&plat->clk); + return ret; + } + + upriv->mmc = &plat->mmc; + + if (plat->clk_reg_msk & SDMMC_CLKCR_SELCLKRX_CKIN) + stm32_sdmmc2_probe_level_translator(dev); + + /* SDMMC init */ + stm32_sdmmc2_reset(plat); + + return 0; } -static int stm32_sdmmc_bind(struct udevice *dev) +static int stm32_sdmmc2_bind(struct udevice *dev) { struct stm32_sdmmc2_plat *plat = dev_get_plat(dev); @@ -720,7 +781,7 @@ U_BOOT_DRIVER(stm32_sdmmc2) = { .of_match = stm32_sdmmc2_ids, .ops = &stm32_sdmmc2_ops, .probe = stm32_sdmmc2_probe, - .bind = stm32_sdmmc_bind, - .priv_auto = sizeof(struct stm32_sdmmc2_priv), + .bind = stm32_sdmmc2_bind, + .of_to_plat = stm32_sdmmc2_of_to_plat, .plat_auto = sizeof(struct stm32_sdmmc2_plat), }; diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index b303fabe0f..ed69ea114e 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -109,6 +109,13 @@ config HBMC_AM654 This is the driver for HyperBus controller on TI's AM65x and other SoCs +config STM32_FLASH + bool "STM32 MCU Flash driver" + depends on ARCH_STM32 + help + This is the driver of embedded flash for some STMicroelectronics + STM32 MCU. + source "drivers/mtd/nand/Kconfig" source "drivers/mtd/spi/Kconfig" diff --git a/drivers/mtd/altera_qspi.c b/drivers/mtd/altera_qspi.c index 7bac599a54..d31391f36a 100644 --- a/drivers/mtd/altera_qspi.c +++ b/drivers/mtd/altera_qspi.c @@ -153,7 +153,6 @@ static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr) putc('\n'); instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; instr->state = MTD_ERASE_FAILED; - mtd_erase_callback(instr); return -EIO; } flash = pdata->base + addr; @@ -177,7 +176,6 @@ static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr) writel(stat, ®s->isr); /* clear isr */ instr->fail_addr = addr; instr->state = MTD_ERASE_FAILED; - mtd_erase_callback(instr); return -EIO; } if (flash_verbose) @@ -189,7 +187,6 @@ static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr) addr += mtd->erasesize; } instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); return 0; } diff --git a/drivers/mtd/cfi_mtd.c b/drivers/mtd/cfi_mtd.c index 78293caa2f..2295bb7220 100644 --- a/drivers/mtd/cfi_mtd.c +++ b/drivers/mtd/cfi_mtd.c @@ -58,7 +58,6 @@ static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) } instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); return 0; } diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 684bc94998..af3c4765c4 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -338,14 +338,6 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) return -EINVAL; } -static void concat_erase_callback(struct erase_info *instr) -{ - /* Nothing to do here in U-Boot */ -#ifndef __UBOOT__ - wake_up((wait_queue_head_t *) instr->priv); -#endif -} - static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase) { int err; @@ -358,7 +350,6 @@ static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase) init_waitqueue_head(&waitq); erase->mtd = mtd; - erase->callback = concat_erase_callback; erase->priv = (unsigned long) &waitq; /* @@ -498,8 +489,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) if (err) return err; - if (instr->callback) - instr->callback(instr); return 0; } diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 582129d0df..37c5b6386e 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -906,13 +906,6 @@ void __put_mtd_device(struct mtd_info *mtd) } EXPORT_SYMBOL_GPL(__put_mtd_device); -/* - * Erase is an asynchronous operation. Device drivers are supposed - * to call instr->callback() whenever the operation completes, even - * if it completes with a failure. - * Callers are supposed to pass a callback function and wait for it - * to be called before writing to the block. - */ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) { if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr) @@ -922,7 +915,6 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; if (!instr->len) { instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); return 0; } return mtd->_erase(mtd, instr); diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index aa58f722da..a435ce6d07 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -446,26 +446,15 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr) int ret; instr->addr += mtd->offset; + ret = mtd->parent->_erase(mtd->parent, instr); - if (ret) { - if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) - instr->fail_addr -= mtd->offset; - instr->addr -= mtd->offset; - } - return ret; -} + if (ret && instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) + instr->fail_addr -= mtd->offset; -void mtd_erase_callback(struct erase_info *instr) -{ - if (instr->mtd->_erase == part_erase) { - if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) - instr->fail_addr -= instr->mtd->offset; - instr->addr -= instr->mtd->offset; - } - if (instr->callback) - instr->callback(instr); + instr->addr -= mtd->offset; + + return ret; } -EXPORT_SYMBOL_GPL(mtd_erase_callback); static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index b1fd779884..10fb1ea654 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3602,10 +3602,6 @@ erase_exit: chip->select_chip(mtd, -1); nand_release_device(mtd); - /* Do call back function */ - if (!ret) - mtd_erase_callback(instr); - /* Return more or less happy */ return ret; } diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index e17f1f8975..4c4ded1def 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -148,6 +149,7 @@ struct stm32_fmc2_timings { struct stm32_fmc2_nand { struct nand_chip chip; struct stm32_fmc2_timings timings; + struct gpio_desc wp_gpio; int ncs; int cs_used[FMC2_MAX_CE]; }; @@ -823,6 +825,9 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node) nand->cs_used[i] = cs[i]; } + gpio_request_by_name_nodev(node, "wp-gpios", 0, &nand->wp_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + nand->chip.flash_node = node; return 0; @@ -971,6 +976,10 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev) chip->ecc.size = FMC2_ECC_STEP_SIZE; chip->ecc.strength = FMC2_ECC_BCH8; + /* Disable Write Protect */ + if (dm_gpio_is_valid(&nand->wp_gpio)) + dm_gpio_set_value(&nand->wp_gpio, 0); + ret = nand_scan_ident(mtd, nand->ncs, NULL); if (ret) return ret; diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 09daa0dd36..bb93a9a1e9 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -1836,9 +1836,6 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) erase_exit: ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; - /* Do call back function */ - if (!ret) - mtd_erase_callback(instr); /* Deselect and wake up anyone waiting on the device */ onenand_release_device(mtd); diff --git a/drivers/mtd/spi/sf_mtd.c b/drivers/mtd/spi/sf_mtd.c index 04de868080..0aed28a52b 100644 --- a/drivers/mtd/spi/sf_mtd.c +++ b/drivers/mtd/spi/sf_mtd.c @@ -46,7 +46,6 @@ static int spi_flash_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) } instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); return 0; } diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index f1b4e5ea8e..ef846a8ced 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -908,30 +908,40 @@ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) { struct spi_nor *nor = mtd_to_spi_nor(mtd); + bool addr_known = false; u32 addr, len, rem; - int ret; + int ret, err; dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr, (long long)instr->len); - if (!instr->len) - return 0; - div_u64_rem(instr->len, mtd->erasesize, &rem); - if (rem) - return -EINVAL; + if (rem) { + ret = -EINVAL; + goto err; + } addr = instr->addr; len = instr->len; + instr->state = MTD_ERASING; + addr_known = true; + while (len) { WATCHDOG_RESET(); + if (ctrlc()) { + addr_known = false; + ret = -EINTR; + goto erase_err; + } #ifdef CONFIG_SPI_FLASH_BAR ret = write_bar(nor, addr); if (ret < 0) - return ret; + goto erase_err; #endif - write_enable(nor); + ret = write_enable(nor); + if (ret < 0) + goto erase_err; ret = spi_nor_erase_sector(nor, addr); if (ret < 0) @@ -945,11 +955,24 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) goto erase_err; } + addr_known = false; erase_err: #ifdef CONFIG_SPI_FLASH_BAR - ret = clean_bar(nor); + err = clean_bar(nor); + if (!ret) + ret = err; #endif - write_disable(nor); + err = write_disable(nor); + if (!ret) + ret = err; + +err: + if (ret) { + instr->fail_addr = addr_known ? addr : MTD_FAIL_ADDR_UNKNOWN; + instr->state = MTD_ERASE_FAILED; + } else { + instr->state = MTD_ERASE_DONE; + } return ret; } @@ -1665,9 +1688,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); - if (!len) - return 0; - for (i = 0; i < len; ) { ssize_t written; loff_t addr = to + i; diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index b8b878b918..14be95b74b 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -304,18 +304,6 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, return err; } -/** - * erase_callback - MTD erasure call-back. - * @ei: MTD erase information object. - * - * Note, even though MTD erase interface is asynchronous, all the current - * implementations are synchronous anyway. - */ -static void erase_callback(struct erase_info *ei) -{ - wake_up_interruptible((wait_queue_head_t *)ei->priv); -} - /** * do_sync_erase - synchronously erase a physical eraseblock. * @ubi: UBI device description object @@ -346,7 +334,6 @@ retry: ei.mtd = ubi->mtd; ei.addr = (loff_t)pnum * ubi->peb_size; ei.len = ubi->peb_size; - ei.callback = erase_callback; ei.priv = (unsigned long)&wq; err = mtd_erase(ubi->mtd, &ei); diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 585101804d..21bb0c47e1 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #ifdef CONFIG_ARCH_IMX8M #include @@ -53,6 +54,7 @@ #endif #include #include +#include /* Core registers */ @@ -210,6 +212,7 @@ struct eqos_dma_regs { #define EQOS_DMA_SYSBUS_MODE_BLEN4 BIT(1) #define EQOS_DMA_CH0_CONTROL_DSL_SHIFT 18 +#define EQOS_DMA_CH0_CONTROL_DSL_MAX 7 #define EQOS_DMA_CH0_CONTROL_PBLX8 BIT(16) #define EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT 16 @@ -274,9 +277,11 @@ struct eqos_config { struct eqos_ops *ops; }; +struct eqos_priv; + struct eqos_ops { - void (*eqos_inval_desc)(void *desc); - void (*eqos_flush_desc)(void *desc); + void (*eqos_inval_desc)(struct eqos_priv *eqos, void *desc); + void (*eqos_flush_desc)(struct eqos_priv *eqos, void *desc); void (*eqos_inval_buffer)(void *buf, size_t size); void (*eqos_flush_buffer)(void *buf, size_t size); int (*eqos_probe_resources)(struct udevice *dev); @@ -286,6 +291,7 @@ struct eqos_ops { int (*eqos_stop_clks)(struct udevice *dev); int (*eqos_start_clks)(struct udevice *dev); int (*eqos_calibrate_pads)(struct udevice *dev); + int (*eqos_phy_power_on)(struct udevice *dev); int (*eqos_disable_calibration)(struct udevice *dev); int (*eqos_set_tx_clk_speed)(struct udevice *dev); ulong (*eqos_get_tick_clk_rate)(struct udevice *dev); @@ -319,6 +325,10 @@ struct eqos_priv { bool started; bool reg_access_ok; bool clk_ck_enabled; + bool use_cached_mem; +#ifdef CONFIG_DM_REGULATOR + struct udevice *phy_supply; +#endif }; /* @@ -341,15 +351,38 @@ struct eqos_priv { */ static void *eqos_alloc_descs(struct eqos_priv *eqos, unsigned int num) { + void *descs = NULL; + ulong desc_pad; + + /* + * if descriptors can to be cache-line aligned with the DSL = + * "Descriptor Skip Length" field of the DMA channel control register + */ eqos->desc_size = ALIGN(sizeof(struct eqos_desc), (unsigned int)ARCH_DMA_MINALIGN); + desc_pad = (eqos->desc_size - sizeof(struct eqos_desc)) / + eqos->config->axi_bus_width; + if (desc_pad <= EQOS_DMA_CH0_CONTROL_DSL_MAX) { + eqos->use_cached_mem = true; + descs = memalign(eqos->desc_size, num * eqos->desc_size); + } else { + eqos->use_cached_mem = false; + eqos->desc_size = sizeof(struct eqos_desc); +#ifdef CONFIG_SYS_NONCACHED_MEMORY + descs = (void *)noncached_alloc(num * eqos->desc_size, ARCH_DMA_MINALIGN); +#else + log_err("DMA descriptors with cached memory."); +#endif + } - return memalign(eqos->desc_size, num * eqos->desc_size); + return descs; } -static void eqos_free_descs(void *descs) +static void eqos_free_descs(struct eqos_priv *eqos) { - free(descs); + if (eqos->use_cached_mem) + free(eqos->descs); + /* memory allocated by noncached_alloc() can't be freed */ } static struct eqos_desc *eqos_get_desc(struct eqos_priv *eqos, @@ -359,22 +392,24 @@ static struct eqos_desc *eqos_get_desc(struct eqos_priv *eqos, ((rx ? EQOS_DESCRIPTORS_TX : 0) + num) * eqos->desc_size; } -static void eqos_inval_desc_generic(void *desc) +static void eqos_inval_desc_generic(struct eqos_priv *eqos, void *desc) { unsigned long start = (unsigned long)desc; unsigned long end = ALIGN(start + sizeof(struct eqos_desc), ARCH_DMA_MINALIGN); - invalidate_dcache_range(start, end); + if (eqos->use_cached_mem) + invalidate_dcache_range(start, end); } -static void eqos_flush_desc_generic(void *desc) +static void eqos_flush_desc_generic(struct eqos_priv *eqos, void *desc) { unsigned long start = (unsigned long)desc; unsigned long end = ALIGN(start + sizeof(struct eqos_desc), ARCH_DMA_MINALIGN); - flush_dcache_range(start, end); + if (eqos->use_cached_mem) + flush_dcache_range(start, end); } static void eqos_inval_buffer_tegra186(void *buf, size_t size) @@ -649,6 +684,27 @@ static int eqos_stop_clks_stm32(struct udevice *dev) return 0; } +static int eqos_phy_power_on_stm32(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + int ret; + + debug("%s(dev=%p):\n", __func__, dev); + +#ifdef CONFIG_DM_REGULATOR + if (eqos->phy_supply) { + ret = regulator_set_enable(eqos->phy_supply, true); + if (ret) { + printf("%s: Error enabling phy supply\n", dev->name); + return ret; + } + } +#endif + + debug("%s: OK\n", __func__); + return 0; +} + static int eqos_start_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -1045,6 +1101,12 @@ static int eqos_start(struct udevice *dev) eqos->tx_desc_idx = 0; eqos->rx_desc_idx = 0; + ret = eqos->config->ops->eqos_phy_power_on(dev); + if (ret < 0) { + pr_err("eqos_phy_power_on() failed: %d", ret); + goto err; + } + ret = eqos->config->ops->eqos_start_clks(dev); if (ret < 0) { pr_err("eqos_start_clks() failed: %d", ret); @@ -1268,12 +1330,17 @@ static int eqos_start(struct udevice *dev) EQOS_MAX_PACKET_SIZE << EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT); - desc_pad = (eqos->desc_size - sizeof(struct eqos_desc)) / - eqos->config->axi_bus_width; + setbits_le32(&eqos->dma_regs->ch0_control, EQOS_DMA_CH0_CONTROL_PBLX8); - setbits_le32(&eqos->dma_regs->ch0_control, - EQOS_DMA_CH0_CONTROL_PBLX8 | - (desc_pad << EQOS_DMA_CH0_CONTROL_DSL_SHIFT)); + /* "Descriptor Skip Length" field of the DMA channel control register */ + if (eqos->use_cached_mem) { + desc_pad = (eqos->desc_size - sizeof(struct eqos_desc)) / + eqos->config->axi_bus_width; + setbits_le32(&eqos->dma_regs->ch0_control, + desc_pad << EQOS_DMA_CH0_CONTROL_DSL_SHIFT); + if (desc_pad > EQOS_DMA_CH0_CONTROL_DSL_MAX) + dev_dbg(dev, "DMA_CH0_CONTROL.DSL overflow"); + } /* * Burst length must be < 1/2 FIFO size. @@ -1306,7 +1373,7 @@ static int eqos_start(struct udevice *dev) for (i = 0; i < EQOS_DESCRIPTORS_TX; i++) { struct eqos_desc *tx_desc = eqos_get_desc(eqos, i, false); - eqos->config->ops->eqos_flush_desc(tx_desc); + eqos->config->ops->eqos_flush_desc(eqos, tx_desc); } for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) { @@ -1315,7 +1382,7 @@ static int eqos_start(struct udevice *dev) (i * EQOS_MAX_PACKET_SIZE)); rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; mb(); - eqos->config->ops->eqos_flush_desc(rx_desc); + eqos->config->ops->eqos_flush_desc(eqos, rx_desc); eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf + (i * EQOS_MAX_PACKET_SIZE), EQOS_MAX_PACKET_SIZE); @@ -1446,13 +1513,13 @@ static int eqos_send(struct udevice *dev, void *packet, int length) */ mb(); tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; - eqos->config->ops->eqos_flush_desc(tx_desc); + eqos->config->ops->eqos_flush_desc(eqos, tx_desc); writel((ulong)eqos_get_desc(eqos, eqos->tx_desc_idx, false), &eqos->dma_regs->ch0_txdesc_tail_pointer); for (i = 0; i < 1000000; i++) { - eqos->config->ops->eqos_inval_desc(tx_desc); + eqos->config->ops->eqos_inval_desc(eqos, tx_desc); if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN)) return 0; udelay(1); @@ -1472,7 +1539,7 @@ static int eqos_recv(struct udevice *dev, int flags, uchar **packetp) debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags); rx_desc = eqos_get_desc(eqos, eqos->rx_desc_idx, true); - eqos->config->ops->eqos_inval_desc(rx_desc); + eqos->config->ops->eqos_inval_desc(eqos, rx_desc); if (rx_desc->des3 & EQOS_DESC3_OWN) { debug("%s: RX packet not available\n", __func__); return -EAGAIN; @@ -1510,7 +1577,7 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) rx_desc->des0 = 0; mb(); - eqos->config->ops->eqos_flush_desc(rx_desc); + eqos->config->ops->eqos_flush_desc(eqos, rx_desc); eqos->config->ops->eqos_inval_buffer(packet, length); rx_desc->des0 = (u32)(ulong)packet; rx_desc->des1 = 0; @@ -1521,7 +1588,7 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) */ mb(); rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; - eqos->config->ops->eqos_flush_desc(rx_desc); + eqos->config->ops->eqos_flush_desc(eqos, rx_desc); writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); @@ -1596,7 +1663,7 @@ static int eqos_remove_resources_core(struct udevice *dev) free(eqos->rx_pkt); free(eqos->rx_dma_buf); free(eqos->tx_dma_buf); - eqos_free_descs(eqos->descs); + eqos_free_descs(eqos); debug("%s: OK\n", __func__); return 0; @@ -1676,7 +1743,7 @@ err_free_reset_eqos: /* board-specific Ethernet Interface initializations. */ __weak int board_interface_eth_init(struct udevice *dev, - phy_interface_t interface_type) + phy_interface_t interface_type, ulong rate) { return 0; } @@ -1686,6 +1753,7 @@ static int eqos_probe_resources_stm32(struct udevice *dev) struct eqos_priv *eqos = dev_get_priv(dev); int ret; phy_interface_t interface; + ulong rate = 0; debug("%s(dev=%p):\n", __func__, dev); @@ -1696,7 +1764,15 @@ static int eqos_probe_resources_stm32(struct udevice *dev) return -EINVAL; } - ret = board_interface_eth_init(dev, interface); + /* Get ETH_CLK clocks (optional) */ + ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); + if (ret) + debug("No phy clock provided %d", ret); + else + rate = clk_get_rate(&eqos->clk_ck); + + /* Initialize the soc for the PHY configuration */ + ret = board_interface_eth_init(dev, interface, rate); if (ret) return -EINVAL; @@ -1720,10 +1796,14 @@ static int eqos_probe_resources_stm32(struct udevice *dev) goto err_free_clk_rx; } - /* Get ETH_CLK clocks (optional) */ - ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); - if (ret) - pr_warn("No phy clock provided %d", ret); +#ifdef CONFIG_DM_REGULATOR + /* check presence of optional regulator */ + ret = device_get_supply_regulator(dev, "phy-supply", &eqos->phy_supply); + if (ret && ret != -ENOENT) { + pr_err("device_get_supply_regulator failed: %d", ret); + goto err_free_clk_rx; + } +#endif debug("%s: OK\n", __func__); return 0; @@ -1945,6 +2025,7 @@ static struct eqos_ops eqos_tegra186_ops = { .eqos_stop_clks = eqos_stop_clks_tegra186, .eqos_start_clks = eqos_start_clks_tegra186, .eqos_calibrate_pads = eqos_calibrate_pads_tegra186, + .eqos_phy_power_on = eqos_null_ops, .eqos_disable_calibration = eqos_disable_calibration_tegra186, .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186, .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186 @@ -1973,6 +2054,7 @@ static struct eqos_ops eqos_stm32_ops = { .eqos_stop_clks = eqos_stop_clks_stm32, .eqos_start_clks = eqos_start_clks_stm32, .eqos_calibrate_pads = eqos_null_ops, + .eqos_phy_power_on = eqos_phy_power_on_stm32, .eqos_disable_calibration = eqos_null_ops, .eqos_set_tx_clk_speed = eqos_null_ops, .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 @@ -1989,6 +2071,17 @@ static const struct eqos_config __maybe_unused eqos_stm32_config = { .ops = &eqos_stm32_ops }; +static const struct eqos_config eqos_stm32mp13_config = { + .reg_access_always_ok = false, + .mdio_wait = 10000, + .swr_wait = 50, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .axi_bus_width = EQOS_AXI_WIDTH_32, + .interface = eqos_get_interface_stm32, + .ops = &eqos_stm32_ops +}; + static struct eqos_ops eqos_imx_ops = { .eqos_inval_desc = eqos_inval_desc_generic, .eqos_flush_desc = eqos_flush_desc_generic, @@ -2001,6 +2094,7 @@ static struct eqos_ops eqos_imx_ops = { .eqos_stop_clks = eqos_null_ops, .eqos_start_clks = eqos_null_ops, .eqos_calibrate_pads = eqos_null_ops, + .eqos_phy_power_on = eqos_null_ops, .eqos_disable_calibration = eqos_null_ops, .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_imx, .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_imx @@ -2029,6 +2123,10 @@ static const struct udevice_id eqos_ids[] = { .compatible = "st,stm32mp1-dwmac", .data = (ulong)&eqos_stm32_config }, + { + .compatible = "st,stm32mp13-dwmac", + .data = (ulong)&eqos_stm32mp13_config + }, #endif #if IS_ENABLED(CONFIG_DWC_ETH_QOS_IMX) { diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index 02d859a039..bd185d9994 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -17,6 +18,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -24,6 +28,7 @@ /* USBPHYC registers */ #define STM32_USBPHYC_PLL 0x0 #define STM32_USBPHYC_MISC 0x8 +#define STM32_USBPHYC_TUNE(X) (0x10C + ((X) * 0x100)) /* STM32_USBPHYC_PLL bit fields */ #define PLLNDIV GENMASK(6, 0) @@ -40,6 +45,26 @@ /* STM32_USBPHYC_MISC bit fields */ #define SWITHOST BIT(0) +/* STM32_USBPHYC_TUNE bit fields */ +#define INCURREN BIT(0) +#define INCURRINT BIT(1) +#define LFSCAPEN BIT(2) +#define HSDRVSLEW BIT(3) +#define HSDRVDCCUR BIT(4) +#define HSDRVDCLEV BIT(5) +#define HSDRVCURINCR BIT(6) +#define FSDRVRFADJ BIT(7) +#define HSDRVRFRED BIT(8) +#define HSDRVCHKITRM GENMASK(12, 9) +#define HSDRVCHKZTRM GENMASK(14, 13) +#define OTPCOMP GENMASK(19, 15) +#define SQLCHCTL GENMASK(21, 20) +#define HDRXGNEQEN BIT(22) +#define HSRXOFF GENMASK(24, 23) +#define HSFALLPREEM BIT(25) +#define SHTCCTCTLPROT BIT(26) +#define STAGSEL BIT(27) + #define MAX_PHYS 2 /* max 100 us for PLL lock and 100 us for PHY init */ @@ -49,6 +74,62 @@ #define PLL_INFF_MIN_RATE 19200000 /* in Hz */ #define PLL_INFF_MAX_RATE 38400000 /* in Hz */ +enum boosting_vals { + BOOST_1000_UA = 1000, + BOOST_2000_UA = 2000, +}; + +enum dc_level_vals { + DC_MINUS_5_TO_7_MV, + DC_PLUS_5_TO_7_MV, + DC_PLUS_10_TO_14_MV, + DC_MAX, +}; + +enum current_trim { + CUR_NOMINAL, + CUR_PLUS_1_56_PCT, + CUR_PLUS_3_12_PCT, + CUR_PLUS_4_68_PCT, + CUR_PLUS_6_24_PCT, + CUR_PLUS_7_8_PCT, + CUR_PLUS_9_36_PCT, + CUR_PLUS_10_92_PCT, + CUR_PLUS_12_48_PCT, + CUR_PLUS_14_04_PCT, + CUR_PLUS_15_6_PCT, + CUR_PLUS_17_16_PCT, + CUR_PLUS_19_01_PCT, + CUR_PLUS_20_58_PCT, + CUR_PLUS_22_16_PCT, + CUR_PLUS_23_73_PCT, + CUR_MAX, +}; + +enum impedance_trim { + IMP_NOMINAL, + IMP_MINUS_2_OHMS, + IMP_MINUS_4_OMHS, + IMP_MINUS_6_OHMS, + IMP_MAX, +}; + +enum squelch_level { + SQLCH_NOMINAL, + SQLCH_PLUS_7_MV, + SQLCH_MINUS_5_MV, + SQLCH_PLUS_14_MV, + SQLCH_MAX, +}; + +enum rx_offset { + NO_RX_OFFSET, + RX_OFFSET_PLUS_5_MV, + RX_OFFSET_PLUS_10_MV, + RX_OFFSET_MINUS_5_MV, + RX_OFFSET_MAX, +}; + struct pll_params { u8 ndiv; u16 frac; @@ -65,6 +146,7 @@ struct stm32_usbphyc { bool init; bool powered; } phys[MAX_PHYS]; + int n_pll_cons; }; static void stm32_usbphyc_get_pll_params(u32 clk_rate, @@ -124,18 +206,6 @@ static int stm32_usbphyc_pll_init(struct stm32_usbphyc *usbphyc) return 0; } -static bool stm32_usbphyc_is_init(struct stm32_usbphyc *usbphyc) -{ - int i; - - for (i = 0; i < MAX_PHYS; i++) { - if (usbphyc->phys[i].init) - return true; - } - - return false; -} - static bool stm32_usbphyc_is_powered(struct stm32_usbphyc *usbphyc) { int i; @@ -148,18 +218,17 @@ static bool stm32_usbphyc_is_powered(struct stm32_usbphyc *usbphyc) return false; } -static int stm32_usbphyc_phy_init(struct phy *phy) +static int stm32_usbphyc_pll_enable(struct stm32_usbphyc *usbphyc) { - struct stm32_usbphyc *usbphyc = dev_get_priv(phy->dev); - struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id; bool pllen = readl(usbphyc->base + STM32_USBPHYC_PLL) & PLLEN ? true : false; int ret; - dev_dbg(phy->dev, "phy ID = %lu\n", phy->id); - /* Check if one phy port has already configured the pll */ - if (pllen && stm32_usbphyc_is_init(usbphyc)) - goto initialized; + /* Check if one consumer has already configured the pll */ + if (pllen && usbphyc->n_pll_cons) { + usbphyc->n_pll_cons++; + return 0; + } if (usbphyc->vdda1v1) { ret = regulator_set_enable(usbphyc->vdda1v1, true); @@ -190,23 +259,19 @@ static int stm32_usbphyc_phy_init(struct phy *phy) if (!(readl(usbphyc->base + STM32_USBPHYC_PLL) & PLLEN)) return -EIO; -initialized: - usbphyc_phy->init = true; + usbphyc->n_pll_cons++; return 0; } -static int stm32_usbphyc_phy_exit(struct phy *phy) +static int stm32_usbphyc_pll_disable(struct stm32_usbphyc *usbphyc) { - struct stm32_usbphyc *usbphyc = dev_get_priv(phy->dev); - struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id; int ret; - dev_dbg(phy->dev, "phy ID = %lu\n", phy->id); - usbphyc_phy->init = false; + usbphyc->n_pll_cons--; - /* Check if other phy port requires pllen */ - if (stm32_usbphyc_is_init(usbphyc)) + /* Check if other consumer requires pllen */ + if (usbphyc->n_pll_cons) return 0; clrbits_le32(usbphyc->base + STM32_USBPHYC_PLL, PLLEN); @@ -235,6 +300,42 @@ static int stm32_usbphyc_phy_exit(struct phy *phy) return 0; } +static int stm32_usbphyc_phy_init(struct phy *phy) +{ + struct stm32_usbphyc *usbphyc = dev_get_priv(phy->dev); + struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id; + int ret; + + dev_dbg(phy->dev, "phy ID = %lu\n", phy->id); + if (usbphyc_phy->init) + return 0; + + ret = stm32_usbphyc_pll_enable(usbphyc); + if (ret) + return log_ret(ret); + + usbphyc_phy->init = true; + + return 0; +} + +static int stm32_usbphyc_phy_exit(struct phy *phy) +{ + struct stm32_usbphyc *usbphyc = dev_get_priv(phy->dev); + struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id; + int ret; + + dev_dbg(phy->dev, "phy ID = %lu\n", phy->id); + if (!usbphyc_phy->init) + return 0; + + ret = stm32_usbphyc_pll_disable(usbphyc); + + usbphyc_phy->init = false; + + return log_ret(ret); +} + static int stm32_usbphyc_phy_power_on(struct phy *phy) { struct stm32_usbphyc *usbphyc = dev_get_priv(phy->dev); @@ -271,7 +372,7 @@ static int stm32_usbphyc_phy_power_off(struct phy *phy) return 0; if (usbphyc_phy->vbus) { - ret = regulator_set_enable(usbphyc_phy->vbus, false); + ret = regulator_set_enable_if_allowed(usbphyc_phy->vbus, false); if (ret) return ret; } @@ -327,6 +428,90 @@ static int stm32_usbphyc_of_xlate(struct phy *phy, return 0; } +static void stm32_usbphyc_tuning(struct udevice *dev, ofnode node, u32 index) +{ + struct stm32_usbphyc *usbphyc = dev_get_priv(dev); + u32 reg = STM32_USBPHYC_TUNE(index); + u32 otpcomp, val, tune = 0; + int ret; + + /* Backup OTP compensation code */ + otpcomp = FIELD_GET(OTPCOMP, readl(usbphyc->base + reg)); + + ret = ofnode_read_u32(node, "st,current-boost-microamp", &val); + if (!ret && (val == BOOST_1000_UA || val == BOOST_2000_UA)) { + val = (val == BOOST_2000_UA) ? 1 : 0; + tune |= INCURREN | FIELD_PREP(INCURRINT, val); + } else if (ret != -EINVAL) { + dev_warn(dev, "phy%d: invalid st,current-boost-microamp value\n", index); + } + + if (!ofnode_read_bool(node, "st,no-lsfs-fb-cap")) + tune |= LFSCAPEN; + + if (ofnode_read_bool(node, "st,decrease-hs-slew-rate")) + tune |= HSDRVSLEW; + + ret = ofnode_read_u32(node, "st,tune-hs-dc-level", &val); + if (!ret && val < DC_MAX) { + if (val == DC_MINUS_5_TO_7_MV) { + tune |= HSDRVDCCUR; + } else { + val = (val == DC_PLUS_10_TO_14_MV) ? 1 : 0; + tune |= HSDRVCURINCR | FIELD_PREP(HSDRVDCLEV, val); + } + } else if (ret != -EINVAL) { + dev_warn(dev, "phy%d: invalid st,tune-hs-dc-level value\n", index); + } + + if (ofnode_read_bool(node, "st,enable-fs-rftime-tuning")) + tune |= FSDRVRFADJ; + + if (ofnode_read_bool(node, "st,enable-hs-rftime-reduction")) + tune |= HSDRVRFRED; + + ret = ofnode_read_u32(node, "st,trim-hs-current", &val); + if (!ret && val < CUR_MAX) + tune |= FIELD_PREP(HSDRVCHKITRM, val); + else if (ret != -EINVAL) + dev_warn(dev, "phy%d: invalid st,trim-hs-current value\n", index); + + ret = ofnode_read_u32(node, "st,trim-hs-impedance", &val); + if (!ret && val < IMP_MAX) + tune |= FIELD_PREP(HSDRVCHKZTRM, val); + else if (ret != -EINVAL) + dev_warn(dev, "phy%d: invalid trim-hs-impedance value\n", index); + + ret = ofnode_read_u32(node, "st,tune-squelch-level", &val); + if (!ret && val < SQLCH_MAX) + tune |= FIELD_PREP(SQLCHCTL, val); + else if (ret != -EINVAL) + dev_warn(dev, "phy%d: invalid st,tune-squelch-level value\n", index); + + if (ofnode_read_bool(node, "st,enable-hs-rx-gain-eq")) + tune |= HDRXGNEQEN; + + ret = ofnode_read_u32(node, "st,tune-hs-rx-offset", &val); + if (!ret && val < RX_OFFSET_MAX) + tune |= FIELD_PREP(HSRXOFF, val); + else if (ret != -EINVAL) + dev_warn(dev, "phy%d: invalid st,tune-hs-rx-offset value\n", index); + + if (ofnode_read_bool(node, "st,no-hs-ftime-ctrl")) + tune |= HSFALLPREEM; + + if (!ofnode_read_bool(node, "st,no-lsfs-sc")) + tune |= SHTCCTCTLPROT; + + if (ofnode_read_bool(node, "st,enable-hs-tx-staggering")) + tune |= STAGSEL; + + /* Restore OTP compensation code */ + tune |= FIELD_PREP(OTPCOMP, otpcomp); + + writel(tune, usbphyc->base + reg); +} + static const struct phy_ops stm32_usbphyc_phy_ops = { .init = stm32_usbphyc_phy_init, .exit = stm32_usbphyc_phy_exit, @@ -335,12 +520,22 @@ static const struct phy_ops stm32_usbphyc_phy_ops = { .of_xlate = stm32_usbphyc_of_xlate, }; +static int stm32_usbphyc_bind(struct udevice *dev) +{ + int ret; + + ret = device_bind_driver_to_node(dev, "stm32-usbphyc-clk", "ck_usbo_48m", + dev_ofnode(dev), NULL); + + return log_ret(ret); +} + static int stm32_usbphyc_probe(struct udevice *dev) { struct stm32_usbphyc *usbphyc = dev_get_priv(dev); struct reset_ctl reset; - ofnode node; - int i, ret; + ofnode node, connector; + int ret; usbphyc->base = dev_read_addr(dev); if (usbphyc->base == FDT_ADDR_T_NONE) @@ -378,14 +573,22 @@ static int stm32_usbphyc_probe(struct udevice *dev) return ret; } - /* - * parse all PHY subnodes in order to populate regulator associated - * to each PHY port - */ - node = dev_read_first_subnode(dev); - for (i = 0; i < MAX_PHYS; i++) { - struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + i; + /* parse all PHY subnodes to populate regulator associated to each PHY port */ + dev_for_each_subnode(node, dev) { + fdt_addr_t phy_id; + struct stm32_usbphyc_phy *usbphyc_phy; + + phy_id = ofnode_read_u32_default(node, "reg", FDT_ADDR_T_NONE); + if (phy_id >= MAX_PHYS) { + dev_err(dev, "invalid reg value %lx for %s\n", + phy_id, ofnode_get_name(node)); + return -ENOENT; + } + /* Configure phy tuning */ + stm32_usbphyc_tuning(dev, node, phy_id); + + usbphyc_phy = usbphyc->phys + phy_id; usbphyc_phy->init = false; usbphyc_phy->powered = false; ret = stm32_usbphyc_get_regulator(node, "phy-supply", @@ -395,12 +598,12 @@ static int stm32_usbphyc_probe(struct udevice *dev) return ret; } - ret = stm32_usbphyc_get_regulator(node, "vbus-supply", - &usbphyc_phy->vbus); - if (ret) - usbphyc_phy->vbus = NULL; - - node = dev_read_next_subnode(node); + usbphyc_phy->vbus = NULL; + connector = ofnode_find_subnode(node, "connector"); + if (ofnode_valid(connector)) { + ret = stm32_usbphyc_get_regulator(connector, "vbus-supply", + &usbphyc_phy->vbus); + } } /* Check if second port has to be used for host controller */ @@ -420,6 +623,70 @@ U_BOOT_DRIVER(stm32_usb_phyc) = { .id = UCLASS_PHY, .of_match = stm32_usbphyc_of_match, .ops = &stm32_usbphyc_phy_ops, + .bind = stm32_usbphyc_bind, .probe = stm32_usbphyc_probe, .priv_auto = sizeof(struct stm32_usbphyc), }; + +struct stm32_usbphyc_clk { + bool enable; +}; + +static ulong stm32_usbphyc_clk48_get_rate(struct clk *clk) +{ + return 48000000; +} + +static int stm32_usbphyc_clk48_enable(struct clk *clk) +{ + struct stm32_usbphyc_clk *usbphyc_clk = dev_get_priv(clk->dev); + struct stm32_usbphyc *usbphyc; + int ret; + + if (usbphyc_clk->enable) + return 0; + + usbphyc = dev_get_priv(clk->dev->parent); + + /* ck_usbo_48m is generated by usbphyc PLL */ + ret = stm32_usbphyc_pll_enable(usbphyc); + if (ret) + return ret; + + usbphyc_clk->enable = true; + + return 0; +} + +static int stm32_usbphyc_clk48_disable(struct clk *clk) +{ + struct stm32_usbphyc_clk *usbphyc_clk = dev_get_priv(clk->dev); + struct stm32_usbphyc *usbphyc; + int ret; + + if (!usbphyc_clk->enable) + return 0; + + usbphyc = dev_get_priv(clk->dev->parent); + + ret = stm32_usbphyc_pll_disable(usbphyc); + if (ret) + return ret; + + usbphyc_clk->enable = false; + + return 0; +} + +const struct clk_ops usbphyc_clk48_ops = { + .get_rate = stm32_usbphyc_clk48_get_rate, + .enable = stm32_usbphyc_clk48_enable, + .disable = stm32_usbphyc_clk48_disable, +}; + +U_BOOT_DRIVER(stm32_usb_phyc_clk) = { + .name = "stm32-usbphyc-clk", + .id = UCLASS_CLK, + .ops = &usbphyc_clk48_ops, + .priv_auto = sizeof(struct stm32_usbphyc_clk), +}; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 30eaa376c8..96c661f5fb 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -185,6 +185,14 @@ config PINCTRL_INTEL driver which must be separately enabled. The driver supports setting pins on start-up and changing the GPIO attributes. +config PINCTRL_MCP23017 + bool "Microchip MCP23017 pinctrl driver" + help + I2C driver for Microchip MCP23017 16-Bit I/O Expander. + The driver is controlled by a device tree node which contains both + the GPIO definitions and pin control functions for each available + multiplex function. + config PINCTRL_PIC32 bool "Microchip PIC32 pin-control and pin-mux driver" depends on DM && MACH_PIC32 diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 05b71f2f13..dbc83db058 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl_pic32.o obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/ obj-$(CONFIG_PINCTRL_K210) += pinctrl-kendryte.o +obj-$(CONFIG_PINCTRL_MCP23017) += pinctrl-mcp23017.o obj-$(CONFIG_PINCTRL_MESON) += meson/ obj-$(CONFIG_PINCTRL_MTK) += mediatek/ obj-$(CONFIG_PINCTRL_MSCC) += mscc/ diff --git a/drivers/pinctrl/pinctrl-mcp23017.c b/drivers/pinctrl/pinctrl-mcp23017.c new file mode 100644 index 0000000000..78eb9086c0 --- /dev/null +++ b/drivers/pinctrl/pinctrl-mcp23017.c @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + * + * Driver for Microchip MCP23017 16-Bit I/O Expander with I2C interface + */ + +#define LOG_CATEGORY UCLASS_PINCTRL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* register offset for IOCON.BANK = 0, the normal mode at reset */ +#define MCP_REG_IODIR 0x00 /* init/reset: all ones */ +#define MCP_REG_IOCON 0x0A +#define IOCON_SEQOP BIT(5) +#define MCP_REG_GPPU 0x0C +#define MCP_REG_GPIO 0x12 + +#define MCP_REG_SIZE 8 +#define MCP_MAX_GPIO 16 + +static int mcp23017_read(struct udevice *dev, uint offset) +{ + return dm_i2c_reg_read(dev_get_parent(dev), offset); +} + +static int mcp23017_write(struct udevice *dev, uint reg, unsigned int val) +{ + dev_dbg(dev, "%s reg = 0x%x val = 0x%x\n", __func__, reg, val); + + return dm_i2c_reg_write(dev_get_parent(dev), reg, val); +} + +static int mcp23017_read_reg(struct udevice *dev, u8 reg, uint offset) +{ + u8 mask = BIT(offset); + int ret; + + ret = mcp23017_read(dev, reg); + + dev_dbg(dev, "%s reg = 0x%x offset = %d ret = 0x%x mask = 0x%x\n", + __func__, reg, offset, ret, mask); + + return ret < 0 ? ret : !!(ret & mask); +} + +static int mcp23017_write_reg(struct udevice *dev, u8 reg, uint offset, + uint val) +{ + u8 mask = BIT(offset); + int ret; + + ret = mcp23017_read(dev, reg); + if (ret < 0) + return ret; + ret = (ret & ~mask) | (val ? mask : 0); + + return mcp23017_write(dev, reg, ret); +} + +static int mcp23017_conf_set_gppu(struct udevice *dev, unsigned int offset, + uint pupd) +{ + int reg = MCP_REG_GPPU + offset / MCP_REG_SIZE; + int bit = offset % MCP_REG_SIZE; + + return mcp23017_write_reg(dev, reg, bit, pupd); +} + +static int mcp23017_conf_get_gppu(struct udevice *dev, unsigned int offset) +{ + int reg = MCP_REG_GPPU + offset / MCP_REG_SIZE; + int bit = offset % MCP_REG_SIZE; + int ret = mcp23017_read_reg(dev, reg, bit); + + return ret; +} + +static int mcp23017_gpio_get(struct udevice *dev, unsigned int offset) +{ + int reg = MCP_REG_GPIO + offset / MCP_REG_SIZE; + int bit = offset % MCP_REG_SIZE; + int ret = mcp23017_read_reg(dev, reg, bit); + + return ret; +} + +static int mcp23017_gpio_set(struct udevice *dev, unsigned int offset, int value) +{ + int reg = MCP_REG_GPIO + offset / MCP_REG_SIZE; + int bit = offset % MCP_REG_SIZE; + + return mcp23017_write_reg(dev, reg, bit, value); +} + +static int mcp23017_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + int ret; + int reg = MCP_REG_IODIR + offset / MCP_REG_SIZE; + int bit = offset % MCP_REG_SIZE; + + ret = mcp23017_read_reg(dev, reg, bit); + + if (ret < 0) + return ret; + /* On mcp23017, gpio pins direction is (0)output, (1)input. */ + return ret ? GPIOF_INPUT : GPIOF_OUTPUT; +} + +static int mcp23017_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + int reg = MCP_REG_IODIR + offset / MCP_REG_SIZE; + int bit = offset % MCP_REG_SIZE; + + return mcp23017_write_reg(dev, reg, bit, 1); +} + +static int mcp23017_gpio_direction_output(struct udevice *dev, + unsigned int offset, int value) +{ + int reg = MCP_REG_IODIR + offset / MCP_REG_SIZE; + int bit = offset % MCP_REG_SIZE; + int ret = mcp23017_gpio_set(dev, offset, value); + + if (ret < 0) + return ret; + + return mcp23017_write_reg(dev, reg, bit, 0); +} + +static int mcp23017_gpio_set_flags(struct udevice *dev, unsigned int offset, + ulong flags) +{ + int ret = -ENOTSUPP; + + if (flags & GPIOD_IS_OUT) { + bool value = flags & GPIOD_IS_OUT_ACTIVE; + + if (flags & GPIOD_OPEN_SOURCE) + return -ENOTSUPP; + if (flags & GPIOD_OPEN_DRAIN) + return -ENOTSUPP; + ret = mcp23017_gpio_direction_output(dev, offset, value); + } else if (flags & GPIOD_IS_IN) { + ret = mcp23017_gpio_direction_input(dev, offset); + if (ret) + return ret; + if (flags & GPIOD_PULL_UP) { + ret = mcp23017_conf_set_gppu(dev, offset, 1); + if (ret) + return ret; + } else { + ret = mcp23017_conf_set_gppu(dev, offset, 0); + if (ret) + return ret; + } + } + + return ret; +} + +static int mcp23017_gpio_get_flags(struct udevice *dev, unsigned int offset, + ulong *flags) +{ + ulong dir_flags = 0; + int ret; + + if (mcp23017_gpio_get_function(dev, offset) == GPIOF_OUTPUT) { + dir_flags |= GPIOD_IS_OUT; + + ret = mcp23017_gpio_get(dev, offset); + if (ret < 0) + return ret; + if (ret) + dir_flags |= GPIOD_IS_OUT_ACTIVE; + } else { + dir_flags |= GPIOD_IS_IN; + + ret = mcp23017_conf_get_gppu(dev, offset); + if (ret < 0) + return ret; + if (ret == 1) + dir_flags |= GPIOD_PULL_UP; + } + *flags = dir_flags; + + return 0; +} + +static int mcp23017_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + uc_priv->bank_name = "mcp_gpio"; + uc_priv->gpio_count = MCP_MAX_GPIO; + + return 0; +} + +static const struct dm_gpio_ops mcp23017_gpio_ops = { + .set_value = mcp23017_gpio_set, + .get_value = mcp23017_gpio_get, + .get_function = mcp23017_gpio_get_function, + .direction_input = mcp23017_gpio_direction_input, + .direction_output = mcp23017_gpio_direction_output, + .set_flags = mcp23017_gpio_set_flags, + .get_flags = mcp23017_gpio_get_flags, +}; + +U_BOOT_DRIVER(mcp23017_gpio) = { + .name = "mcp23017-gpio", + .id = UCLASS_GPIO, + .probe = mcp23017_gpio_probe, + .ops = &mcp23017_gpio_ops, +}; + +#if CONFIG_IS_ENABLED(PINCONF) +static const struct pinconf_param mcp23017_pinctrl_conf_params[] = { + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 0 }, + { "output-high", PIN_CONFIG_OUTPUT, 1 }, + { "output-low", PIN_CONFIG_OUTPUT, 0 }, +}; + +static int mcp23017_pinctrl_conf_set(struct udevice *dev, unsigned int pin, + unsigned int param, unsigned int arg) +{ + int ret, dir; + + /* directly call the generic gpio function, only based on i2c parent */ + dir = mcp23017_gpio_get_function(dev, pin); + + if (dir < 0) + return dir; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: + ret = mcp23017_conf_set_gppu(dev, pin, 1); + break; + case PIN_CONFIG_OUTPUT: + ret = mcp23017_gpio_direction_output(dev, pin, arg); + break; + default: + return -ENOTSUPP; + } + + return ret; +} +#endif + +static int mcp23017_pinctrl_get_pins_count(struct udevice *dev) +{ + return MCP_MAX_GPIO; +} + +static char pin_name[PINNAME_SIZE]; +static const char *mcp23017_pinctrl_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + snprintf(pin_name, PINNAME_SIZE, "mcp_gpio%u", selector); + + return pin_name; +} + +static const char *mcp23017_pinctrl_get_pin_conf(struct udevice *dev, + unsigned int pin, int func) +{ + int pupd; + + pupd = mcp23017_conf_get_gppu(dev, pin); + if (pupd < 0) + return ""; + + if (pupd) + return "bias-pull-up"; + else + return ""; +} + +static int mcp23017_pinctrl_get_pin_muxing(struct udevice *dev, + unsigned int selector, + char *buf, int size) +{ + int func; + + func = mcp23017_gpio_get_function(dev, selector); + if (func < 0) + return func; + + snprintf(buf, size, "%s ", func == GPIOF_INPUT ? "input" : "output"); + + strlcat(buf, mcp23017_pinctrl_get_pin_conf(dev, selector, func), size); + + return 0; +} + +const struct pinctrl_ops mcp23017_pinctrl_ops = { + .get_pins_count = mcp23017_pinctrl_get_pins_count, + .get_pin_name = mcp23017_pinctrl_get_pin_name, + .set_state = pinctrl_generic_set_state, + .get_pin_muxing = mcp23017_pinctrl_get_pin_muxing, +#if CONFIG_IS_ENABLED(PINCONF) + .pinconf_set = mcp23017_pinctrl_conf_set, + .pinconf_num_params = ARRAY_SIZE(mcp23017_pinctrl_conf_params), + .pinconf_params = mcp23017_pinctrl_conf_params, +#endif +}; + +U_BOOT_DRIVER(mcp23017_pinctrl) = { + .name = "mcp23017-pinctrl", + .id = UCLASS_PINCTRL, + .ops = &mcp23017_pinctrl_ops, +}; + +static int mcp23017_bind(struct udevice *dev) +{ + int ret; + + ret = device_bind_driver_to_node(dev, "mcp23017-pinctrl", "mcp23017-pinctrl", + dev_ofnode(dev), NULL); + if (ret) + return ret; + + return device_bind_driver_to_node(dev, "mcp23017-gpio", "mcp23017-gpio", + dev_ofnode(dev), NULL); +} + +static int mcp23017_chip_init(struct udevice *dev) +{ + int ret, iocon; + + ret = dm_i2c_reg_read(dev, MCP_REG_IOCON); + dev_dbg(dev, "reg = 0x%x val = 0x%x\n", MCP_REG_IOCON, ret); + if (ret < 0) { + dev_err(dev, "Can't read MCP23017 IOCON register (%d)\n", ret); + return ret; + } + + /* deactivate Sequential mode if activated */ + if (ret & IOCON_SEQOP) { + iocon = ret & ~IOCON_SEQOP; + + ret = dm_i2c_reg_write(dev, MCP_REG_IOCON, iocon); + if (ret < 0) { + dev_err(dev, "can't write IOCON register (%d)\n", ret); + } else { + /* mcp23017 has IOCON twice, make sure they are in sync */ + ret = dm_i2c_reg_write(dev, MCP_REG_IOCON + 1, iocon); + if (ret < 0) + dev_err(dev, "can't write IOCON register (%d)\n", ret); + } + } + + return ret; +} + +static int mcp23017_probe(struct udevice *dev) +{ + struct udevice *vdd; + struct reset_ctl reset; + int ret; + + if (CONFIG_IS_ENABLED(DM_REGULATOR)) { + ret = device_get_supply_regulator(dev, "vdd-supply", &vdd); + if (ret && ret != -ENOENT) { + dev_err(dev, "vdd regulator error:%d\n", ret); + return ret; + } + if (!ret) { + ret = regulator_set_enable(vdd, true); + if (ret) { + dev_err(dev, "vdd enable failed: %d\n", ret); + return ret; + } + } + } + + ret = reset_get_by_index(dev, 0, &reset); + if (!ret) { + reset_assert(&reset); + udelay(2); + reset_deassert(&reset); + } + + return mcp23017_chip_init(dev); +} + +static const struct udevice_id mcp23017_match[] = { + { .compatible = "microchip,mcp23017", }, +}; + +U_BOOT_DRIVER(mcp23017) = { + .name = "mcp23017", + .id = UCLASS_I2C_GENERIC, + .of_match = of_match_ptr(mcp23017_match), + .probe = mcp23017_probe, + .bind = mcp23017_bind, +}; diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index fe7a59d431..509e2a80e9 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -5,8 +5,12 @@ * Driver for STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander * based on Linux driver : pinctrl/pinctrl-stmfx.c */ + +#define LOG_CATEGORY UCLASS_PINCTRL + #include #include +#include #include #include #include diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c index 6c98538f56..9c88101145 100644 --- a/drivers/pinctrl/pinctrl_stm32.c +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -10,9 +10,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -20,12 +20,15 @@ #include #include +#include "../gpio/stm32_gpio_priv.h" + #define MAX_PINS_ONE_IP 70 #define MODE_BITS_MASK 3 #define OSPEED_MASK 3 #define PUPD_MASK 3 #define OTYPE_MSK 1 #define AFR_MASK 0xF +#define SECCFG_MSK 1 struct stm32_pinctrl_priv { struct hwspinlock hws; @@ -38,16 +41,21 @@ struct stm32_gpio_bank { struct list_head list; }; +struct stm32_pinctrl_data { + bool secure_control; +}; + +static int stm32_pinctrl_get_access(struct udevice *gpio_dev, unsigned int gpio_idx); + #ifndef CONFIG_SPL_BUILD static char pin_name[PINNAME_SIZE]; -#define PINMUX_MODE_COUNT 5 -static const char * const pinmux_mode[PINMUX_MODE_COUNT] = { - "gpio input", - "gpio output", - "analog", - "unknown", - "alt function", +static const char * const pinmux_mode[GPIOF_COUNT] = { + [GPIOF_INPUT] = "gpio input", + [GPIOF_OUTPUT] = "gpio output", + [GPIOF_UNUSED] = "analog", + [GPIOF_UNKNOWN] = "unknown", + [GPIOF_FUNC] = "alt function", }; static const char * const pinmux_bias[] = { @@ -157,10 +165,7 @@ static struct udevice *stm32_pinctrl_get_gpio_dev(struct udevice *dev, * we found the bank, convert pin selector to * gpio bank index */ - *idx = stm32_offset_to_index(gpio_bank->gpio_dev, - selector - pin_count); - if (IS_ERR_VALUE(*idx)) - return NULL; + *idx = selector - pin_count; return gpio_bank->gpio_dev; } @@ -211,6 +216,12 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev, if (!gpio_dev) return -ENODEV; + /* Check access protection */ + if (stm32_pinctrl_get_access(gpio_dev, gpio_idx)) { + snprintf(buf, size, "NO ACCESS"); + return 0; + } + mode = gpio_get_raw_function(gpio_dev, gpio_idx, &label); dev_dbg(dev, "selector = %d gpio_idx = %d mode = %d\n", selector, gpio_idx, mode); @@ -220,8 +231,6 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev, switch (mode) { case GPIOF_UNKNOWN: - /* should never happen */ - return -EINVAL; case GPIOF_UNUSED: snprintf(buf, size, "%s", pinmux_mode[mode]); break; @@ -246,6 +255,20 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev, #endif +static int stm32_pinctrl_get_access(struct udevice *gpio_dev, unsigned int gpio_idx) +{ + struct stm32_gpio_priv *priv = dev_get_priv(gpio_dev); + struct stm32_gpio_regs *regs = priv->regs; + ulong drv_data = dev_get_driver_data(gpio_dev); + + /* Deny request access if IO is secured */ + if ((drv_data & STM32_GPIO_FLAG_SEC_CTRL) && + ((readl(®s->seccfgr) >> gpio_idx) & SECCFG_MSK)) + return -EACCES; + + return 0; +} + static int stm32_pinctrl_probe(struct udevice *dev) { struct stm32_pinctrl_priv *priv = dev_get_priv(dev); @@ -266,11 +289,20 @@ static int stm32_gpio_config(struct gpio_desc *desc, const struct stm32_gpio_ctl *ctl) { struct stm32_gpio_priv *priv = dev_get_priv(desc->dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc->dev); struct stm32_gpio_regs *regs = priv->regs; struct stm32_pinctrl_priv *ctrl_priv; int ret; u32 index; + /* Check access protection */ + ret = stm32_pinctrl_get_access(desc->dev, desc->offset); + if (ret) { + dev_err(desc->dev, "Failed to get secure IO %s %d @ %p\n", + uc_priv->bank_name, desc->offset, regs); + return ret; + } + if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 || ctl->pupd > 2 || ctl->speed > 3) return -EINVAL; @@ -404,8 +436,25 @@ static int stm32_pinctrl_bind(struct udevice *dev) { ofnode node; const char *name; + struct driver *drv; + const struct stm32_pinctrl_data *drv_data; + ulong gpio_data = 0; int ret; + drv = lists_driver_lookup_name("gpio_stm32"); + if (!drv) { + debug("Cannot find driver 'gpio_stm32'\n"); + return -ENOENT; + } + + drv_data = (const struct stm32_pinctrl_data *)dev_get_driver_data(dev); + if (!drv_data) { + debug("Cannot find driver data\n"); + return -EINVAL; + } + if (drv_data->secure_control) + gpio_data = STM32_GPIO_FLAG_SEC_CTRL; + dev_for_each_subnode(node, dev) { dev_dbg(dev, "bind %s\n", ofnode_get_name(node)); @@ -421,8 +470,7 @@ static int stm32_pinctrl_bind(struct udevice *dev) return -EINVAL; /* Bind each gpio node */ - ret = device_bind_driver_to_node(dev, "gpio_stm32", - name, node, NULL); + ret = device_bind_with_driver_data(dev, drv, name, gpio_data, node, NULL); if (ret) return ret; @@ -485,14 +533,23 @@ static struct pinctrl_ops stm32_pinctrl_ops = { #endif }; +static const struct stm32_pinctrl_data stm32_pinctrl_no_sec = { + .secure_control = false, +}; + +static const struct stm32_pinctrl_data stm32_pinctrl_with_sec = { + .secure_control = true, +}; + static const struct udevice_id stm32_pinctrl_ids[] = { - { .compatible = "st,stm32f429-pinctrl" }, - { .compatible = "st,stm32f469-pinctrl" }, - { .compatible = "st,stm32f746-pinctrl" }, - { .compatible = "st,stm32f769-pinctrl" }, - { .compatible = "st,stm32h743-pinctrl" }, - { .compatible = "st,stm32mp157-pinctrl" }, - { .compatible = "st,stm32mp157-z-pinctrl" }, + { .compatible = "st,stm32f429-pinctrl", .data = (ulong)&stm32_pinctrl_no_sec }, + { .compatible = "st,stm32f469-pinctrl", .data = (ulong)&stm32_pinctrl_no_sec }, + { .compatible = "st,stm32f746-pinctrl", .data = (ulong)&stm32_pinctrl_no_sec }, + { .compatible = "st,stm32f769-pinctrl", .data = (ulong)&stm32_pinctrl_no_sec }, + { .compatible = "st,stm32h743-pinctrl", .data = (ulong)&stm32_pinctrl_no_sec }, + { .compatible = "st,stm32mp157-pinctrl", .data = (ulong)&stm32_pinctrl_no_sec }, + { .compatible = "st,stm32mp157-z-pinctrl", .data = (ulong)&stm32_pinctrl_no_sec }, + { .compatible = "st,stm32mp135-pinctrl", .data = (ulong)&stm32_pinctrl_with_sec }, { } }; diff --git a/drivers/power/regulator/scmi_regulator.c b/drivers/power/regulator/scmi_regulator.c index b3142bf4e1..5e2eb6e365 100644 --- a/drivers/power/regulator/scmi_regulator.c +++ b/drivers/power/regulator/scmi_regulator.c @@ -2,6 +2,9 @@ /* * Copyright (C) 2020-2021 Linaro Limited */ + +#define LOG_CATEGORY UCLASS_REGULATOR + #include #include #include @@ -14,12 +17,19 @@ #include #include +/* Voltage domain IDs must fit in 16bit */ +#define VOLTD_INVALID_DOMAIN_ID UINT32_MAX + /** * struct scmi_regulator_platdata - Platform data for a scmi voltage domain regulator * @domain_id: ID representing the regulator for the related SCMI agent + * @voltd_name: String ID representing the regulator in the SCMI server + * @supply: Regulator supply or NULL */ struct scmi_regulator_platdata { u32 domain_id; + const char *voltd_name; + struct udevice *supply; }; static int scmi_voltd_set_enable(struct udevice *dev, bool enable) @@ -35,7 +45,13 @@ static int scmi_voltd_set_enable(struct udevice *dev, bool enable) in, out); int ret; - ret = devm_scmi_process_msg(dev->parent->parent, &msg); + if (pdata->supply && enable) { + ret = regulator_set_enable(pdata->supply, true); + if (ret) + return ret; + } + + ret = devm_scmi_process_msg(dev, &msg); if (ret) return ret; @@ -58,7 +74,7 @@ static int scmi_voltd_get_enable(struct udevice *dev) in, out); int ret; - ret = devm_scmi_process_msg(dev->parent->parent, &msg); + ret = devm_scmi_process_msg(dev, &msg); if (ret < 0) return ret; @@ -82,7 +98,7 @@ static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV) in, out); int ret; - ret = devm_scmi_process_msg(dev->parent->parent, &msg); + ret = devm_scmi_process_msg(dev, &msg); if (ret < 0) return ret; @@ -101,7 +117,7 @@ static int scmi_voltd_get_voltage_level(struct udevice *dev) in, out); int ret; - ret = devm_scmi_process_msg(dev->parent->parent, &msg); + ret = devm_scmi_process_msg(dev, &msg); if (ret < 0) return ret; @@ -112,6 +128,11 @@ static int scmi_voltd_get_voltage_level(struct udevice *dev) return out.voltage_level; } +static bool voltd_name_is_valid(char *name) +{ + return strnlen(name, SCMI_VOLTD_NAME_LEN) < SCMI_VOLTD_NAME_LEN; +} + static int scmi_regulator_of_to_plat(struct udevice *dev) { struct scmi_regulator_platdata *pdata = dev_get_plat(dev); @@ -119,13 +140,81 @@ static int scmi_regulator_of_to_plat(struct udevice *dev) reg = dev_read_addr(dev); if (reg == FDT_ADDR_T_NONE) + pdata->domain_id = VOLTD_INVALID_DOMAIN_ID; + else + pdata->domain_id = (u32)reg; + + pdata->voltd_name = dev_read_string(dev, "voltd-name"); + if (pdata->voltd_name && + !voltd_name_is_valid((char *)pdata->voltd_name)) { + dev_dbg(dev, "oversized voltd-name\n"); return -EINVAL; + } - pdata->domain_id = (u32)reg; + if (!pdata->voltd_name && pdata->domain_id == VOLTD_INVALID_DOMAIN_ID) { + dev_dbg(dev, "OF node %s: missing reg or voltd-name property\n", + dev->name); + return -EINVAL; + } return 0; } +static int voltd_count(struct udevice *dev, size_t *count) +{ + struct scmi_voltd_protocol_attr_out out = { 0 }; + struct scmi_msg scmi_msg = { + .protocol_id = SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, + .message_id = SCMI_PROTOCOL_ATTRIBUTES, + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + ret = devm_scmi_process_msg(dev, &scmi_msg); + if (ret < 0) + return ret; + + *count = out.attributes; + + return 0; +} + +static int voltd_name_to_domain_id(struct udevice *dev, + struct scmi_regulator_platdata *pdata) +{ + struct scmi_voltd_attr_in in = { 0 }; + struct scmi_voltd_attr_out out = { 0 }; + struct scmi_msg scmi_msg = { + .protocol_id = SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, + .message_id = SCMI_VOLTAGE_DOMAIN_ATTRIBUTES, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + size_t count, n; + + ret = voltd_count(dev, &count); + if (ret) + return ret; + + for (n = 0; n < count; n++) { + in.domain_id = n; + scmi_msg.out_msg_sz = sizeof(out); + + ret = devm_scmi_process_msg(dev, &scmi_msg); + if (!ret && voltd_name_is_valid(out.name) && + !strcmp(pdata->voltd_name, out.name)) { + pdata->domain_id = n; + return 0; + } + } + + return -ENOENT; +} + static int scmi_regulator_probe(struct udevice *dev) { struct scmi_regulator_platdata *pdata = dev_get_plat(dev); @@ -139,19 +228,41 @@ static int scmi_regulator_probe(struct udevice *dev) .out_msg = (u8 *)&out, .out_msg_sz = sizeof(out), }; + struct udevice *supply; int ret; + if (pdata->domain_id == VOLTD_INVALID_DOMAIN_ID) { + ret = voltd_name_to_domain_id(dev, pdata); + if (ret) + return ret; + } + /* Check voltage domain is known from SCMI server */ in.domain_id = pdata->domain_id; - ret = devm_scmi_process_msg(dev->parent->parent, &scmi_msg); + ret = devm_scmi_process_msg(dev, &scmi_msg); if (ret) { dev_err(dev, "Failed to query voltage domain %u: %d\n", pdata->domain_id, ret); return -ENXIO; } - return 0; + if (!pdata->voltd_name) { + if (!voltd_name_is_valid(out.name)) + return -EINVAL; + + pdata->voltd_name = strdup(out.name); + } + + dev_dbg(dev, "voltd %u: \"%s\"\n", pdata->domain_id, pdata->voltd_name); + + ret = device_get_supply_regulator(dev, "regulator-supply", &supply); + if (!ret) + pdata->supply = supply; + if (ret == -ENOENT) + ret = 0; + + return ret; } static const struct dm_regulator_ops scmi_voltd_ops = { diff --git a/drivers/power/regulator/stm32-vrefbuf.c b/drivers/power/regulator/stm32-vrefbuf.c index c37998a4ba..b49dbe84ea 100644 --- a/drivers/power/regulator/stm32-vrefbuf.c +++ b/drivers/power/regulator/stm32-vrefbuf.c @@ -32,13 +32,21 @@ struct stm32_vrefbuf { void __iomem *base; struct clk clk; struct udevice *vdda_supply; + const int *voltages; }; -static const int stm32_vrefbuf_voltages[] = { +#define STM32_VOLTAGE_TABLE_SIZE 4 + +static const int stm32_vrefbuf_voltages[STM32_VOLTAGE_TABLE_SIZE] = { /* Matches resp. VRS = 000b, 001b, 010b, 011b */ 2500000, 2048000, 1800000, 1500000, }; +static const int stm32mp13_vrefbuf_voltages[STM32_VOLTAGE_TABLE_SIZE] = { + /* Matches resp. VRS = 000b, 001b, 010b, 011b */ + 2500000, 2048000, 1800000, 1650000, +}; + static int stm32_vrefbuf_set_enable(struct udevice *dev, bool enable) { struct stm32_vrefbuf *priv = dev_get_priv(dev); @@ -92,8 +100,8 @@ static int stm32_vrefbuf_set_value(struct udevice *dev, int uV) struct stm32_vrefbuf *priv = dev_get_priv(dev); unsigned int i; - for (i = 0; i < ARRAY_SIZE(stm32_vrefbuf_voltages); i++) { - if (uV == stm32_vrefbuf_voltages[i]) { + for (i = 0; i < STM32_VOLTAGE_TABLE_SIZE; i++) { + if (uV == priv->voltages[i]) { clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_VRS, i << STM32_VRS_SHIFT); return 0; @@ -111,7 +119,7 @@ static int stm32_vrefbuf_get_value(struct udevice *dev) val = readl(priv->base + STM32_VREFBUF_CSR) & STM32_VRS; val >>= STM32_VRS_SHIFT; - return stm32_vrefbuf_voltages[val]; + return priv->voltages[val]; } static const struct dm_regulator_ops stm32_vrefbuf_ops = { @@ -128,6 +136,12 @@ static int stm32_vrefbuf_probe(struct udevice *dev) priv->base = dev_read_addr_ptr(dev); + priv->voltages = (const int *)dev_get_driver_data(dev); + if (!priv->voltages) { + debug("Cannot find driver data\n"); + return -EINVAL; + } + ret = clk_get_by_index(dev, 0, &priv->clk); if (ret) { dev_err(dev, "Can't get clock: %d\n", ret); @@ -157,7 +171,8 @@ static int stm32_vrefbuf_probe(struct udevice *dev) } static const struct udevice_id stm32_vrefbuf_ids[] = { - { .compatible = "st,stm32-vrefbuf" }, + { .compatible = "st,stm32-vrefbuf", .data = (ulong)&stm32_vrefbuf_voltages }, + { .compatible = "st,stm32mp13-vrefbuf", .data = (ulong)&stm32mp13_vrefbuf_voltages }, { } }; diff --git a/drivers/ram/stm32mp1/Makefile b/drivers/ram/stm32mp1/Makefile index e1e9135603..71ded6bed4 100644 --- a/drivers/ram/stm32mp1/Makefile +++ b/drivers/ram/stm32mp1/Makefile @@ -8,7 +8,6 @@ obj-y += stm32mp1_ddr.o obj-$(CONFIG_STM32MP1_DDR_INTERACTIVE) += stm32mp1_interactive.o obj-$(CONFIG_STM32MP1_DDR_TESTS) += stm32mp1_tests.o -obj-$(CONFIG_STM32MP1_DDR_TUNING) += stm32mp1_tuning.o ifneq ($(DDR_INTERACTIVE),) CFLAGS_stm32mp1_interactive.o += -DCONFIG_STM32MP1_DDR_INTERACTIVE_FORCE=y diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.c b/drivers/ram/stm32mp1/stm32mp1_ddr.c index 0457166b12..4d78aa5cb1 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ddr.c +++ b/drivers/ram/stm32mp1/stm32mp1_ddr.c @@ -68,7 +68,6 @@ struct reg_desc { #define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */ #define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */ -#define DDRPHY_REG_CAL_SIZE 12 /* st,phy-cal */ #define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg) static const struct reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = { @@ -178,22 +177,6 @@ static const struct reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = { DDRPHY_REG_TIMING(mr3), }; -#define DDRPHY_REG_CAL(x) DDRPHY_REG(x, stm32mp1_ddrphy_cal) -static const struct reg_desc ddrphy_cal[DDRPHY_REG_CAL_SIZE] = { - DDRPHY_REG_CAL(dx0dllcr), - DDRPHY_REG_CAL(dx0dqtr), - DDRPHY_REG_CAL(dx0dqstr), - DDRPHY_REG_CAL(dx1dllcr), - DDRPHY_REG_CAL(dx1dqtr), - DDRPHY_REG_CAL(dx1dqstr), - DDRPHY_REG_CAL(dx2dllcr), - DDRPHY_REG_CAL(dx2dqtr), - DDRPHY_REG_CAL(dx2dqstr), - DDRPHY_REG_CAL(dx3dllcr), - DDRPHY_REG_CAL(dx3dqtr), - DDRPHY_REG_CAL(dx3dqstr), -}; - /************************************************************** * DYNAMIC REGISTERS: only used for debug purpose (read/modify) **************************************************************/ @@ -218,12 +201,24 @@ static const struct reg_desc ddrphy_dyn[] = { DDRPHY_REG_DYN(zq0sr1), DDRPHY_REG_DYN(dx0gsr0), DDRPHY_REG_DYN(dx0gsr1), + DDRPHY_REG_DYN(dx0dllcr), + DDRPHY_REG_DYN(dx0dqtr), + DDRPHY_REG_DYN(dx0dqstr), DDRPHY_REG_DYN(dx1gsr0), DDRPHY_REG_DYN(dx1gsr1), + DDRPHY_REG_DYN(dx1dllcr), + DDRPHY_REG_DYN(dx1dqtr), + DDRPHY_REG_DYN(dx1dqstr), DDRPHY_REG_DYN(dx2gsr0), DDRPHY_REG_DYN(dx2gsr1), + DDRPHY_REG_DYN(dx2dllcr), + DDRPHY_REG_DYN(dx2dqtr), + DDRPHY_REG_DYN(dx2dqstr), DDRPHY_REG_DYN(dx3gsr0), DDRPHY_REG_DYN(dx3gsr1), + DDRPHY_REG_DYN(dx3dllcr), + DDRPHY_REG_DYN(dx3dqtr), + DDRPHY_REG_DYN(dx3dqstr), }; #define DDRPHY_REG_DYN_SIZE ARRAY_SIZE(ddrphy_dyn) @@ -240,7 +235,6 @@ enum reg_type { REG_MAP, REGPHY_REG, REGPHY_TIMING, - REGPHY_CAL, #ifdef CONFIG_STM32MP1_DDR_INTERACTIVE /* dynamic registers => managed in driver or not changed, * can be dumped in interactive mode @@ -264,8 +258,6 @@ struct ddr_reg_info { enum base_type base; }; -#define DDRPHY_REG_CAL(x) DDRPHY_REG(x, stm32mp1_ddrphy_cal) - const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = { [REG_REG] = { "static", ddr_reg, DDRCTL_REG_REG_SIZE, DDR_BASE}, @@ -279,8 +271,6 @@ const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = { "static", ddrphy_reg, DDRPHY_REG_REG_SIZE, DDRPHY_BASE}, [REGPHY_TIMING] = { "timing", ddrphy_timing, DDRPHY_REG_TIMING_SIZE, DDRPHY_BASE}, -[REGPHY_CAL] = { - "cal", ddrphy_cal, DDRPHY_REG_CAL_SIZE, DDRPHY_BASE}, #ifdef CONFIG_STM32MP1_DDR_INTERACTIVE [REG_DYN] = { "dyn", ddr_dyn, DDR_REG_DYN_SIZE, DDR_BASE}, @@ -456,9 +446,6 @@ static u32 get_par_addr(const struct stm32mp1_ddr_config *config, case REGPHY_TIMING: par_addr = (u32)&config->p_timing; break; - case REGPHY_CAL: - par_addr = (u32)&config->p_cal; - break; case REG_DYN: case REGPHY_DYN: case REG_TYPE_NB: @@ -570,7 +557,7 @@ static void ddrphy_idone_wait(struct stm32mp1_ddrphy *phy) (u32)&phy->pgsr, pgsr, ret); } -void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, u32 pir) +static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, u32 pir) { pir |= DDRPHYC_PIR_INIT; writel(pir, &phy->pir); @@ -639,7 +626,7 @@ static void wait_operating_mode(struct ddr_info *priv, int mode) log_debug("[0x%08x] stat = 0x%08x\n", (u32)&priv->ctl->stat, stat); } -void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) +static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) { start_sw_done(ctl); /* quasi-dynamic register update*/ @@ -650,8 +637,8 @@ void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) wait_sw_done_ack(ctl); } -void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, - u32 rfshctl3, u32 pwrctl) +static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, + u32 rfshctl3, u32 pwrctl) { start_sw_done(ctl); if (!(rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH)) @@ -774,8 +761,6 @@ start: */ set_reg(priv, REGPHY_REG, &config->p_reg); set_reg(priv, REGPHY_TIMING, &config->p_timing); - if (config->p_cal_present) - set_reg(priv, REGPHY_CAL, &config->p_cal); if (INTERACTIVE(STEP_PHY_INIT)) goto start; @@ -810,32 +795,32 @@ start: wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); - if (config->p_cal_present) { - log_debug("DDR DQS training skipped.\n"); - } else { - log_debug("DDR DQS training : "); + log_debug("DDR DQS training : "); /* 8. Disable Auto refresh and power down by setting * - RFSHCTL3.dis_au_refresh = 1 * - PWRCTL.powerdown_en = 0 * - DFIMISC.dfiinit_complete_en = 0 */ - stm32mp1_refresh_disable(priv->ctl); + stm32mp1_refresh_disable(priv->ctl); /* 9. Program PUBL PGCR to enable refresh during training and rank to train * not done => keep the programed value in PGCR */ /* 10. configure PUBL PIR register to specify which training step to run */ - /* warning : RVTRN is not supported by this PUBL */ - stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN); + /* RVTRN is excuted only on LPDDR2/LPDDR3 */ + if (config->c_reg.mstr & DDRCTRL_MSTR_DDR3) + pir = DDRPHYC_PIR_QSTRN; + else + pir = DDRPHYC_PIR_QSTRN | DDRPHYC_PIR_RVTRN; + stm32mp1_ddrphy_init(priv->phy, pir); /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */ - ddrphy_idone_wait(priv->phy); + ddrphy_idone_wait(priv->phy); /* 12. set back registers in step 8 to the orginal values if desidered */ - stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3, - config->c_reg.pwrctl); - } /* if (config->p_cal_present) */ + stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3, + config->c_reg.pwrctl); /* enable uMCTL2 AXI port 0 and 1 */ setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.h b/drivers/ram/stm32mp1/stm32mp1_ddr.h index 4998f04439..861efff92b 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ddr.h +++ b/drivers/ram/stm32mp1/stm32mp1_ddr.h @@ -140,21 +140,6 @@ struct stm32mp1_ddrphy_timing { u32 mr3; }; -struct stm32mp1_ddrphy_cal { - u32 dx0dllcr; - u32 dx0dqtr; - u32 dx0dqstr; - u32 dx1dllcr; - u32 dx1dqtr; - u32 dx1dqstr; - u32 dx2dllcr; - u32 dx2dqtr; - u32 dx2dqstr; - u32 dx3dllcr; - u32 dx3dqtr; - u32 dx3dqstr; -}; - struct stm32mp1_ddr_info { const char *name; u32 speed; /* in kHZ */ @@ -169,16 +154,9 @@ struct stm32mp1_ddr_config { struct stm32mp1_ddrctrl_perf c_perf; struct stm32mp1_ddrphy_reg p_reg; struct stm32mp1_ddrphy_timing p_timing; - struct stm32mp1_ddrphy_cal p_cal; - bool p_cal_present; }; int stm32mp1_ddr_clk_enable(struct ddr_info *priv, u32 mem_speed); -void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, u32 pir); -void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl); -void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, - u32 rfshctl3, - u32 pwrctl); void stm32mp1_ddr_init( struct ddr_info *priv, diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h b/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h index 3c8885a965..f1a26e31f6 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h +++ b/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h @@ -6,8 +6,9 @@ #ifndef _RAM_STM32MP1_DDR_REGS_H #define _RAM_STM32MP1_DDR_REGS_H -/* DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL) registers */ #include + +/* DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL) registers */ struct stm32mp1_ddrctl { u32 mstr ; /* 0x0 Master*/ u32 stat; /* 0x4 Operating Mode Status*/ @@ -238,6 +239,7 @@ struct stm32mp1_ddrphy { #define DDRCTRL_MSTR_LPDDR2 BIT(2) #define DDRCTRL_MSTR_LPDDR3 BIT(3) #define DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK GENMASK(13, 12) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_SHIFT 12 #define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL (0 << 12) #define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF (1 << 12) #define DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER (2 << 12) @@ -275,25 +277,6 @@ struct stm32mp1_ddrphy { #define DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0) -#define DDRCTRL_DBG1_DIS_HIF BIT(1) - -#define DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY BIT(29) -#define DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY BIT(28) -#define DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY BIT(26) -#define DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH GENMASK(12, 8) -#define DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH GENMASK(4, 0) -#define DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY \ - (DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY | \ - DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY) -#define DDRCTRL_DBGCAM_DBG_Q_DEPTH \ - (DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY | \ - DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH | \ - DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH) - -#define DDRCTRL_DBGCMD_RANK0_REFRESH BIT(0) - -#define DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY BIT(0) - #define DDRCTRL_SWCTL_SW_DONE BIT(0) #define DDRCTRL_SWSTAT_SW_DONE_ACK BIT(0) @@ -309,13 +292,9 @@ struct stm32mp1_ddrphy { #define DDRPHYC_PIR_DRAMRST BIT(5) #define DDRPHYC_PIR_DRAMINIT BIT(6) #define DDRPHYC_PIR_QSTRN BIT(7) +#define DDRPHYC_PIR_RVTRN BIT(8) #define DDRPHYC_PIR_ICPC BIT(16) #define DDRPHYC_PIR_ZCALBYP BIT(30) -#define DDRPHYC_PIR_INITSTEPS_MASK GENMASK(31, 7) - -#define DDRPHYC_PGCR_DFTCMP BIT(2) -#define DDRPHYC_PGCR_PDDISDX BIT(24) -#define DDRPHYC_PGCR_RFSHDT_MASK GENMASK(28, 25) #define DDRPHYC_PGSR_IDONE BIT(0) #define DDRPHYC_PGSR_DTERR BIT(5) @@ -324,43 +303,6 @@ struct stm32mp1_ddrphy { #define DDRPHYC_PGSR_RVERR BIT(8) #define DDRPHYC_PGSR_RVEIRR BIT(9) -#define DDRPHYC_DLLGCR_BPS200 BIT(23) - -#define DDRPHYC_ACDLLCR_DLLDIS BIT(31) - -#define DDRPHYC_ZQ0CRN_ZDATA_MASK GENMASK(27, 0) -#define DDRPHYC_ZQ0CRN_ZDATA_SHIFT 0 -#define DDRPHYC_ZQ0CRN_ZDEN BIT(28) - -#define DDRPHYC_DXNGCR_DXEN BIT(0) - -#define DDRPHYC_DXNDLLCR_DLLSRST BIT(30) -#define DDRPHYC_DXNDLLCR_DLLDIS BIT(31) -#define DDRPHYC_DXNDLLCR_SDPHASE_MASK GENMASK(17, 14) -#define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT 14 - -#define DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit) (4 * (bit)) -#define DDRPHYC_DXNDQTR_DQDLY_MASK GENMASK(3, 0) -#define DDRPHYC_DXNDQTR_DQDLY_LOW_MASK GENMASK(1, 0) -#define DDRPHYC_DXNDQTR_DQDLY_HIGH_MASK GENMASK(3, 2) - -#define DDRPHYC_DXNDQSTR_DQSDLY_MASK GENMASK(22, 20) -#define DDRPHYC_DXNDQSTR_DQSDLY_SHIFT 20 -#define DDRPHYC_DXNDQSTR_DQSNDLY_MASK GENMASK(25, 23) -#define DDRPHYC_DXNDQSTR_DQSNDLY_SHIFT 23 -#define DDRPHYC_DXNDQSTR_R0DGSL_MASK GENMASK(2, 0) -#define DDRPHYC_DXNDQSTR_R0DGSL_SHIFT 0 -#define DDRPHYC_DXNDQSTR_R0DGPS_MASK GENMASK(13, 12) -#define DDRPHYC_DXNDQSTR_R0DGPS_SHIFT 12 - -#define DDRPHYC_BISTRR_BDXSEL_MASK GENMASK(22, 19) -#define DDRPHYC_BISTRR_BDXSEL_SHIFT 19 - -#define DDRPHYC_BISTGSR_BDDONE BIT(0) -#define DDRPHYC_BISTGSR_BDXERR BIT(2) - -#define DDRPHYC_BISTWCSR_DXWCNT_SHIFT 16 - /* PWR registers */ #define PWR_CR3 0x00C #define PWR_CR3_DDRSRDIS BIT(11) diff --git a/drivers/ram/stm32mp1/stm32mp1_interactive.c b/drivers/ram/stm32mp1/stm32mp1_interactive.c index 8c2310ac90..f0fe7e61e3 100644 --- a/drivers/ram/stm32mp1/stm32mp1_interactive.c +++ b/drivers/ram/stm32mp1/stm32mp1_interactive.c @@ -32,7 +32,6 @@ enum ddr_command { DDR_CMD_NEXT, DDR_CMD_GO, DDR_CMD_TEST, - DDR_CMD_TUNING, DDR_CMD_UNKNOWN, }; @@ -59,9 +58,6 @@ enum ddr_command stm32mp1_get_command(char *cmd, int argc) [DDR_CMD_GO] = "go", #ifdef CONFIG_STM32MP1_DDR_TESTS [DDR_CMD_TEST] = "test", -#endif -#ifdef CONFIG_STM32MP1_DDR_TUNING - [DDR_CMD_TUNING] = "tuning", #endif }; /* min and max number of argument */ @@ -78,9 +74,6 @@ enum ddr_command stm32mp1_get_command(char *cmd, int argc) [DDR_CMD_GO] = { 0, 0 }, #ifdef CONFIG_STM32MP1_DDR_TESTS [DDR_CMD_TEST] = { 0, 255 }, -#endif -#ifdef CONFIG_STM32MP1_DDR_TUNING - [DDR_CMD_TUNING] = { 0, 255 }, #endif }; int i; @@ -111,7 +104,7 @@ static void stm32mp1_do_usage(void) "help displays help\n" "info displays DDR information\n" "info changes DDR information\n" - " with = step, name, size, speed or cal\n" + " with = step, name, size or speed\n" "freq displays the DDR PHY frequency in kHz\n" "freq changes the DDR PHY frequency\n" "param [type|reg] prints input parameters\n" @@ -125,14 +118,11 @@ static void stm32mp1_do_usage(void) "reset reboots machine\n" #ifdef CONFIG_STM32MP1_DDR_TESTS "test [help] | [...] lists (with help) or executes test \n" -#endif -#ifdef CONFIG_STM32MP1_DDR_TUNING - "tuning [help] | [...] lists (with help) or execute tuning \n" #endif "\nwith for [type|reg]:\n" " all registers if absent\n" " = ctl, phy\n" - " or one category (static, timing, map, perf, cal, dyn)\n" + " or one category (static, timing, map, perf, dyn)\n" " = name of the register\n" }; @@ -165,7 +155,6 @@ static void stm32mp1_do_info(struct ddr_info *priv, printf("name = %s\n", config->info.name); printf("size = 0x%x\n", config->info.size); printf("speed = %d kHz\n", config->info.speed); - printf("cal = %d\n", config->p_cal_present); return; } @@ -214,16 +203,6 @@ static void stm32mp1_do_info(struct ddr_info *priv, } return; } - if (!strcmp(argv[1], "cal")) { - if (strict_strtoul(argv[2], 10, &value) < 0 || - (value != 0 && value != 1)) { - printf("invalid value %s\n", argv[2]); - } else { - config->p_cal_present = value; - printf("cal = %d\n", config->p_cal_present); - } - return; - } printf("argument %s invalid\n", argv[1]); } @@ -322,7 +301,7 @@ end: return step; } -#if defined(CONFIG_STM32MP1_DDR_TESTS) || defined(CONFIG_STM32MP1_DDR_TUNING) +#if defined(CONFIG_STM32MP1_DDR_TESTS) static const char * const s_result[] = { [TEST_PASSED] = "Pass", [TEST_FAILED] = "Failed", @@ -479,16 +458,6 @@ bool stm32mp1_ddr_interactive(void *priv, stm32mp1_ddr_subcmd(priv, argc, argv, test, test_nb); break; #endif - -#ifdef CONFIG_STM32MP1_DDR_TUNING - case DDR_CMD_TUNING: - if (!stm32mp1_check_step(step, STEP_DDR_READY)) - continue; - stm32mp1_ddr_subcmd(priv, argc, argv, - tuning, tuning_nb); - break; -#endif - default: break; } diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c index 26f0b4f1ea..a6c19af972 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ram.c +++ b/drivers/ram/stm32mp1/stm32mp1_ram.c @@ -16,6 +16,12 @@ #include #include #include "stm32mp1_ddr.h" +#include "stm32mp1_ddr_regs.h" + +/* DDR subsystem configuration */ +struct stm32mp1_ddr_cfg { + u8 nb_bytes; /* MEMC_DRAM_DATA_WIDTH */ +}; static const char *const clkname[] = { "ddrc1", @@ -82,7 +88,7 @@ static ofnode stm32mp1_ddr_get_ofnode(struct udevice *dev) return dev_ofnode(dev); } -static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev) +static int stm32mp1_ddr_setup(struct udevice *dev) { struct ddr_info *priv = dev_get_priv(dev); int ret; @@ -95,26 +101,22 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev) { .name = x, \ .offset = offsetof(struct stm32mp1_ddr_config, y), \ .size = sizeof(config.y) / sizeof(u32), \ - .present = z, \ } #define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x, NULL) #define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x, NULL) -#define PHY_PARAM_OPT(x) PARAM("st,phy-"#x, p_##x, &config.p_##x##_present) const struct { const char *name; /* name in DT */ const u32 offset; /* offset in config struct */ const u32 size; /* size of parameters */ - bool * const present; /* presence indication for opt */ } param[] = { CTL_PARAM(reg), CTL_PARAM(timing), CTL_PARAM(map), CTL_PARAM(perf), PHY_PARAM(reg), - PHY_PARAM(timing), - PHY_PARAM_OPT(cal) + PHY_PARAM(timing) }; config.info.speed = ofnode_read_u32_default(node, "st,mem-speed", 0); @@ -133,25 +135,11 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev) param[idx].size); dev_dbg(dev, "%s: %s[0x%x] = %d\n", __func__, param[idx].name, param[idx].size, ret); - if (ret && - (ret != -FDT_ERR_NOTFOUND || !param[idx].present)) { + if (ret) { dev_err(dev, "Cannot read %s, error=%d\n", param[idx].name, ret); return -EINVAL; } - if (param[idx].present) { - /* save presence of optional parameters */ - *param[idx].present = true; - if (ret == -FDT_ERR_NOTFOUND) { - *param[idx].present = false; -#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE - /* reset values if used later */ - memset((void *)((u32)&config + - param[idx].offset), - 0, param[idx].size * sizeof(u32)); -#endif - } - } } ret = clk_get_by_name(dev, "axidcg", &axidcg); @@ -183,6 +171,186 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev) return 0; } +static u8 get_data_bus_width(struct stm32mp1_ddrctl *ctl) +{ + u32 reg = readl(&ctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK; + u8 data_bus_width = reg >> DDRCTRL_MSTR_DATA_BUS_WIDTH_SHIFT; + + return data_bus_width; +} + +static u8 get_nb_bank(struct stm32mp1_ddrctl *ctl) +{ + /* Count bank address bits */ + u8 bits = 0; + u32 reg, val; + + reg = readl(&ctl->addrmap1); + /* addrmap1.addrmap_bank_b1 */ + val = (reg & GENMASK(5, 0)) >> 0; + if (val <= 31) + bits++; + /* addrmap1.addrmap_bank_b2 */ + val = (reg & GENMASK(13, 8)) >> 8; + if (val <= 31) + bits++; + /* addrmap1.addrmap_bank_b3 */ + val = (reg & GENMASK(21, 16)) >> 16; + if (val <= 31) + bits++; + + return bits; +} + +static u8 get_nb_col(struct stm32mp1_ddrctl *ctl, u8 data_bus_width) +{ + u8 bits; + u32 reg, val; + + /* Count column address bits, start at 2 for b0 and b1 (fixed) */ + bits = 2; + + reg = readl(&ctl->addrmap2); + /* addrmap2.addrmap_col_b2 */ + val = (reg & GENMASK(3, 0)) >> 0; + if (val <= 7) + bits++; + /* addrmap2.addrmap_col_b3 */ + val = (reg & GENMASK(11, 8)) >> 8; + if (val <= 7) + bits++; + /* addrmap2.addrmap_col_b4 */ + val = (reg & GENMASK(19, 16)) >> 16; + if (val <= 7) + bits++; + /* addrmap2.addrmap_col_b5 */ + val = (reg & GENMASK(27, 24)) >> 24; + if (val <= 7) + bits++; + + reg = readl(&ctl->addrmap3); + /* addrmap3.addrmap_col_b6 */ + val = (reg & GENMASK(4, 0)) >> 0; + if (val <= 7) + bits++; + /* addrmap3.addrmap_col_b7 */ + val = (reg & GENMASK(12, 8)) >> 8; + if (val <= 7) + bits++; + /* addrmap3.addrmap_col_b8 */ + val = (reg & GENMASK(20, 16)) >> 16; + if (val <= 7) + bits++; + /* addrmap3.addrmap_col_b9 */ + val = (reg & GENMASK(28, 24)) >> 24; + if (val <= 7) + bits++; + + reg = readl(&ctl->addrmap4); + /* addrmap4.addrmap_col_b10 */ + val = (reg & GENMASK(4, 0)) >> 0; + if (val <= 7) + bits++; + /* addrmap4.addrmap_col_b11 */ + val = (reg & GENMASK(12, 8)) >> 8; + if (val <= 7) + bits++; + + /* + * column bits shift up: + * 1 when half the data bus is used (data_bus_width = 1) + * 2 when a quarter the data bus is used (data_bus_width = 2) + * nothing to do for full data bus (data_bus_width = 0) + */ + bits += data_bus_width; + + return bits; +} + +static u8 get_nb_row(struct stm32mp1_ddrctl *ctl) +{ + /* Count row address bits */ + u8 bits = 0; + u32 reg, val; + + reg = readl(&ctl->addrmap5); + /* addrmap5.addrmap_row_b0 */ + val = (reg & GENMASK(3, 0)) >> 0; + if (val <= 11) + bits++; + /* addrmap5.addrmap_row_b1 */ + val = (reg & GENMASK(11, 8)) >> 8; + if (val <= 11) + bits++; + /* addrmap5.addrmap_row_b2_10 */ + val = (reg & GENMASK(19, 16)) >> 16; + if (val <= 11) + bits += 9; + else + printf("warning: addrmap5.addrmap_row_b2_10 not supported\n"); + /* addrmap5.addrmap_row_b11 */ + val = (reg & GENMASK(27, 24)) >> 24; + if (val <= 11) + bits++; + + reg = readl(&ctl->addrmap6); + /* addrmap6.addrmap_row_b12 */ + val = (reg & GENMASK(3, 0)) >> 0; + if (val <= 11) + bits++; + /* addrmap6.addrmap_row_b13 */ + val = (reg & GENMASK(11, 8)) >> 8; + if (val <= 11) + bits++; + /* addrmap6.addrmap_row_b14 */ + val = (reg & GENMASK(19, 16)) >> 16; + if (val <= 11) + bits++; + /* addrmap6.addrmap_row_b15 */ + val = (reg & GENMASK(27, 24)) >> 24; + if (val <= 11) + bits++; + + if (reg & BIT(31)) + printf("warning: LPDDR3_6GB_12GB is not supported\n"); + + return bits; +} + +/* + * stm32mp1_ddr_size + * + * Get the current DRAM size from the DDR CTL registers + * + * @return: DRAM size + */ +u32 stm32mp1_ddr_size(struct udevice *dev) +{ + u8 nb_bit; + u32 ddr_size; + u8 data_bus_width; + struct ddr_info *priv = dev_get_priv(dev); + struct stm32mp1_ddrctl *ctl = priv->ctl; + struct stm32mp1_ddr_cfg *cfg = (struct stm32mp1_ddr_cfg *)dev_get_driver_data(dev); + const u8 nb_bytes = cfg->nb_bytes; + + data_bus_width = get_data_bus_width(ctl); + nb_bit = get_nb_bank(ctl) + get_nb_col(ctl, data_bus_width) + + get_nb_row(ctl); + if (nb_bit > 32) { + nb_bit = 32; + debug("invalid DDR configuration: %d bits\n", nb_bit); + } + + ddr_size = (nb_bytes >> data_bus_width) << nb_bit; + if (ddr_size > STM32_DDR_SIZE) { + ddr_size = STM32_DDR_SIZE; + debug("invalid DDR configuration: size = %x\n", ddr_size); + } + + return ddr_size; +} + static int stm32mp1_ddr_probe(struct udevice *dev) { struct ddr_info *priv = dev_get_priv(dev); @@ -202,17 +370,16 @@ static int stm32mp1_ddr_probe(struct udevice *dev) priv->info.base = STM32_DDR_BASE; -#if !defined(CONFIG_TFABOOT) && \ - (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)) - priv->info.size = 0; - ret = stm32mp1_ddr_setup(dev); + if (IS_ENABLED(CONFIG_SPL_BUILD)) { + priv->info.size = 0; + ret = stm32mp1_ddr_setup(dev); + + return log_ret(ret); + } + + priv->info.size = stm32mp1_ddr_size(dev); - return log_ret(ret); -#else - ofnode node = stm32mp1_ddr_get_ofnode(dev); - priv->info.size = ofnode_read_u32_default(node, "st,mem-size", 0); return 0; -#endif } static int stm32mp1_ddr_get_info(struct udevice *dev, struct ram_info *info) @@ -228,8 +395,17 @@ static struct ram_ops stm32mp1_ddr_ops = { .get_info = stm32mp1_ddr_get_info, }; +static const struct stm32mp1_ddr_cfg stm32mp13x_ddr_cfg = { + .nb_bytes = 2, +}; + +static const struct stm32mp1_ddr_cfg stm32mp15x_ddr_cfg = { + .nb_bytes = 4, +}; + static const struct udevice_id stm32mp1_ddr_ids[] = { - { .compatible = "st,stm32mp1-ddr" }, + { .compatible = "st,stm32mp1-ddr", .data = (ulong)&stm32mp15x_ddr_cfg}, + { .compatible = "st,stm32mp13-ddr", .data = (ulong)&stm32mp13x_ddr_cfg}, { } }; diff --git a/drivers/ram/stm32mp1/stm32mp1_tests.h b/drivers/ram/stm32mp1/stm32mp1_tests.h index 55f5d6d93b..8436780790 100644 --- a/drivers/ram/stm32mp1/stm32mp1_tests.h +++ b/drivers/ram/stm32mp1/stm32mp1_tests.h @@ -28,7 +28,4 @@ struct test_desc { extern const struct test_desc test[]; extern const int test_nb; -extern const struct test_desc tuning[]; -extern const int tuning_nb; - #endif diff --git a/drivers/ram/stm32mp1/stm32mp1_tuning.c b/drivers/ram/stm32mp1/stm32mp1_tuning.c deleted file mode 100644 index c8cd7c3cea..0000000000 --- a/drivers/ram/stm32mp1/stm32mp1_tuning.c +++ /dev/null @@ -1,1540 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause -/* - * Copyright (C) 2019, STMicroelectronics - All Rights Reserved - */ - -#define LOG_CATEGORY UCLASS_RAM - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "stm32mp1_ddr_regs.h" -#include "stm32mp1_ddr.h" -#include "stm32mp1_tests.h" - -#define MAX_DQS_PHASE_IDX _144deg -#define MAX_DQS_UNIT_IDX 7 -#define MAX_GSL_IDX 5 -#define MAX_GPS_IDX 3 - -/* Number of bytes used in this SW. ( min 1--> max 4). */ -#define NUM_BYTES 4 - -enum dqs_phase_enum { - _36deg = 0, - _54deg = 1, - _72deg = 2, - _90deg = 3, - _108deg = 4, - _126deg = 5, - _144deg = 6 -}; - -/* BIST Result struct */ -struct BIST_result { - /* Overall test result: - * 0 Fail (any bit failed) , - * 1 Success (All bits success) - */ - bool test_result; - /* 1: true, all fail / 0: False, not all bits fail */ - bool all_bits_fail; - bool bit_i_test_result[8]; /* 0 fail / 1 success */ -}; - -/* a struct that defines tuning parameters of a byte. */ -struct tuning_position { - u8 phase; /* DQS phase */ - u8 unit; /* DQS unit delay */ - u32 bits_delay; /* Bits deskew in this byte */ -}; - -/* 36deg, 54deg, 72deg, 90deg, 108deg, 126deg, 144deg */ -const u8 dx_dll_phase[7] = {3, 2, 1, 0, 14, 13, 12}; - -static u8 BIST_error_max = 1; -static u32 BIST_seed = 0x1234ABCD; - -static u8 get_nb_bytes(struct stm32mp1_ddrctl *ctl) -{ - u32 data_bus = readl(&ctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK; - u8 nb_bytes = NUM_BYTES; - - switch (data_bus) { - case DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF: - nb_bytes /= 2; - break; - case DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER: - nb_bytes /= 4; - break; - default: - break; - } - - return nb_bytes; -} - -static u8 get_nb_bank(struct stm32mp1_ddrctl *ctl) -{ - /* Count bank address bits */ - u8 bits = 0; - u32 reg, val; - - reg = readl(&ctl->addrmap1); - /* addrmap1.addrmap_bank_b1 */ - val = (reg & GENMASK(5, 0)) >> 0; - if (val <= 31) - bits++; - /* addrmap1.addrmap_bank_b2 */ - val = (reg & GENMASK(13, 8)) >> 8; - if (val <= 31) - bits++; - /* addrmap1.addrmap_bank_b3 */ - val = (reg & GENMASK(21, 16)) >> 16; - if (val <= 31) - bits++; - - return bits; -} - -static u8 get_nb_col(struct stm32mp1_ddrctl *ctl) -{ - u8 bits; - u32 reg, val; - - /* Count column address bits, start at 2 for b0 and b1 (fixed) */ - bits = 2; - - reg = readl(&ctl->addrmap2); - /* addrmap2.addrmap_col_b2 */ - val = (reg & GENMASK(3, 0)) >> 0; - if (val <= 7) - bits++; - /* addrmap2.addrmap_col_b3 */ - val = (reg & GENMASK(11, 8)) >> 8; - if (val <= 7) - bits++; - /* addrmap2.addrmap_col_b4 */ - val = (reg & GENMASK(19, 16)) >> 16; - if (val <= 7) - bits++; - /* addrmap2.addrmap_col_b5 */ - val = (reg & GENMASK(27, 24)) >> 24; - if (val <= 7) - bits++; - - reg = readl(&ctl->addrmap3); - /* addrmap3.addrmap_col_b6 */ - val = (reg & GENMASK(3, 0)) >> 0; - if (val <= 7) - bits++; - /* addrmap3.addrmap_col_b7 */ - val = (reg & GENMASK(11, 8)) >> 8; - if (val <= 7) - bits++; - /* addrmap3.addrmap_col_b8 */ - val = (reg & GENMASK(19, 16)) >> 16; - if (val <= 7) - bits++; - /* addrmap3.addrmap_col_b9 */ - val = (reg & GENMASK(27, 24)) >> 24; - if (val <= 7) - bits++; - - reg = readl(&ctl->addrmap4); - /* addrmap4.addrmap_col_b10 */ - val = (reg & GENMASK(3, 0)) >> 0; - if (val <= 7) - bits++; - /* addrmap4.addrmap_col_b11 */ - val = (reg & GENMASK(11, 8)) >> 8; - if (val <= 7) - bits++; - - return bits; -} - -static u8 get_nb_row(struct stm32mp1_ddrctl *ctl) -{ - /* Count row address bits */ - u8 bits = 0; - u32 reg, val; - - reg = readl(&ctl->addrmap5); - /* addrmap5.addrmap_row_b0 */ - val = (reg & GENMASK(3, 0)) >> 0; - if (val <= 11) - bits++; - /* addrmap5.addrmap_row_b1 */ - val = (reg & GENMASK(11, 8)) >> 8; - if (val <= 11) - bits++; - /* addrmap5.addrmap_row_b2_10 */ - val = (reg & GENMASK(19, 16)) >> 16; - if (val <= 11) - bits += 9; - else - printf("warning: addrmap5.addrmap_row_b2_10 not supported\n"); - /* addrmap5.addrmap_row_b11 */ - val = (reg & GENMASK(27, 24)) >> 24; - if (val <= 11) - bits++; - - reg = readl(&ctl->addrmap6); - /* addrmap6.addrmap_row_b12 */ - val = (reg & GENMASK(3, 0)) >> 0; - if (val <= 7) - bits++; - /* addrmap6.addrmap_row_b13 */ - val = (reg & GENMASK(11, 8)) >> 8; - if (val <= 7) - bits++; - /* addrmap6.addrmap_row_b14 */ - val = (reg & GENMASK(19, 16)) >> 16; - if (val <= 7) - bits++; - /* addrmap6.addrmap_row_b15 */ - val = (reg & GENMASK(27, 24)) >> 24; - if (val <= 7) - bits++; - - return bits; -} - -static void itm_soft_reset(struct stm32mp1_ddrphy *phy) -{ - stm32mp1_ddrphy_init(phy, DDRPHYC_PIR_ITMSRST); -} - -/* Read DQ unit delay register and provides the retrieved value for DQS - * We are assuming that we have the same delay when clocking - * by DQS and when clocking by DQSN - */ -static u8 DQ_unit_index(struct stm32mp1_ddrphy *phy, u8 byte, u8 bit) -{ - u32 index; - u32 addr = DXNDQTR(phy, byte); - - /* We are assuming that we have the same delay when clocking by DQS - * and when clocking by DQSN : use only the low bits - */ - index = (readl(addr) >> DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit)) - & DDRPHYC_DXNDQTR_DQDLY_LOW_MASK; - - log_debug("[%x]: %x => DQ unit index = %x\n", addr, readl(addr), index); - - return index; -} - -/* Sets the DQS phase delay for a byte lane. - *phase delay is specified by giving the index of the desired delay - * in the dx_dll_phase array. - */ -static void DQS_phase_delay(struct stm32mp1_ddrphy *phy, u8 byte, u8 phase_idx) -{ - u8 sdphase_val = 0; - - /* Write DXNDLLCR.SDPHASE = dx_dll_phase(phase_index); */ - sdphase_val = dx_dll_phase[phase_idx]; - clrsetbits_le32(DXNDLLCR(phy, byte), - DDRPHYC_DXNDLLCR_SDPHASE_MASK, - sdphase_val << DDRPHYC_DXNDLLCR_SDPHASE_SHIFT); -} - -/* Sets the DQS unit delay for a byte lane. - * unit delay is specified by giving the index of the desired delay - * for dgsdly and dqsndly (same value). - */ -static void DQS_unit_delay(struct stm32mp1_ddrphy *phy, - u8 byte, u8 unit_dly_idx) -{ - /* Write the same value in DXNDQSTR.DQSDLY and DXNDQSTR.DQSNDLY */ - clrsetbits_le32(DXNDQSTR(phy, byte), - DDRPHYC_DXNDQSTR_DQSDLY_MASK | - DDRPHYC_DXNDQSTR_DQSNDLY_MASK, - (unit_dly_idx << DDRPHYC_DXNDQSTR_DQSDLY_SHIFT) | - (unit_dly_idx << DDRPHYC_DXNDQSTR_DQSNDLY_SHIFT)); - - /* After changing this value, an ITM soft reset (PIR.ITMSRST=1, - * plus PIR.INIT=1) must be issued. - */ - stm32mp1_ddrphy_init(phy, DDRPHYC_PIR_ITMSRST); -} - -/* Sets the DQ unit delay for a bit line in particular byte lane. - * unit delay is specified by giving the desired delay - */ -static void set_DQ_unit_delay(struct stm32mp1_ddrphy *phy, - u8 byte, u8 bit, - u8 dq_delay_index) -{ - u8 dq_bit_delay_val = dq_delay_index | (dq_delay_index << 2); - - /* same value on delay for clock DQ an DQS_b */ - clrsetbits_le32(DXNDQTR(phy, byte), - DDRPHYC_DXNDQTR_DQDLY_MASK - << DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit), - dq_bit_delay_val << DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit)); -} - -static void set_r0dgsl_delay(struct stm32mp1_ddrphy *phy, - u8 byte, u8 r0dgsl_idx) -{ - clrsetbits_le32(DXNDQSTR(phy, byte), - DDRPHYC_DXNDQSTR_R0DGSL_MASK, - r0dgsl_idx << DDRPHYC_DXNDQSTR_R0DGSL_SHIFT); -} - -static void set_r0dgps_delay(struct stm32mp1_ddrphy *phy, - u8 byte, u8 r0dgps_idx) -{ - clrsetbits_le32(DXNDQSTR(phy, byte), - DDRPHYC_DXNDQSTR_R0DGPS_MASK, - r0dgps_idx << DDRPHYC_DXNDQSTR_R0DGPS_SHIFT); -} - -/* Basic BIST configuration for data lane tests. */ -static void config_BIST(struct stm32mp1_ddrctl *ctl, - struct stm32mp1_ddrphy *phy) -{ - u8 nb_bank = get_nb_bank(ctl); - u8 nb_row = get_nb_row(ctl); - u8 nb_col = get_nb_col(ctl); - - /* Selects the SDRAM bank address to be used during BIST. */ - u32 bbank = 0; - /* Selects the SDRAM row address to be used during BIST. */ - u32 brow = 0; - /* Selects the SDRAM column address to be used during BIST. */ - u32 bcol = 0; - /* Selects the value by which the SDRAM address is incremented - * for each write/read access. - */ - u32 bainc = 0x00000008; - /* Specifies the maximum SDRAM rank to be used during BIST. - * The default value is set to maximum ranks minus 1. - * must be 0 with single rank - */ - u32 bmrank = 0; - /* Selects the SDRAM rank to be used during BIST. - * must be 0 with single rank - */ - u32 brank = 0; - - /* Specifies the maximum SDRAM bank address to be used during - * BIST before the address & increments to the next rank. - */ - u32 bmbank = (1 << nb_bank) - 1; - /* Specifies the maximum SDRAM row address to be used during - * BIST before the address & increments to the next bank. - */ - u32 bmrow = (1 << nb_row) - 1; - /* Specifies the maximum SDRAM column address to be used during - * BIST before the address & increments to the next row. - */ - u32 bmcol = (1 << nb_col) - 1; - - u32 bmode_conf = 0x00000001; /* DRam mode */ - u32 bdxen_conf = 0x00000001; /* BIST on Data byte */ - u32 bdpat_conf = 0x00000002; /* Select LFSR pattern */ - - /*Setup BIST for DRAM mode, and LFSR-random data pattern.*/ - /*Write BISTRR.BMODE = 1?b1;*/ - /*Write BISTRR.BDXEN = 1?b1;*/ - /*Write BISTRR.BDPAT = 2?b10;*/ - - /* reset BIST */ - writel(0x3, &phy->bistrr); - - writel((bmode_conf << 3) | (bdxen_conf << 14) | (bdpat_conf << 17), - &phy->bistrr); - - /*Setup BIST Word Count*/ - /*Write BISTWCR.BWCNT = 16?b0008;*/ - writel(0x00000200, &phy->bistwcr); /* A multiple of BL/2 */ - - writel(bcol | (brow << 12) | (bbank << 28), &phy->bistar0); - writel(brank | (bmrank << 2) | (bainc << 4), &phy->bistar1); - writel(bmcol | (bmrow << 12) | (bmbank << 28), &phy->bistar2); -} - -/* Select the Byte lane to be tested by BIST. */ -static void BIST_datx8_sel(struct stm32mp1_ddrphy *phy, u8 datx8) -{ - clrsetbits_le32(&phy->bistrr, - DDRPHYC_BISTRR_BDXSEL_MASK, - datx8 << DDRPHYC_BISTRR_BDXSEL_SHIFT); - - /*(For example, selecting Byte Lane 3, BISTRR.BDXSEL = 4?b0011)*/ - /* Write BISTRR.BDXSEL = datx8; */ -} - -/* Perform BIST Write_Read test on a byte lane and return test result. */ -static void BIST_test(struct stm32mp1_ddrphy *phy, u8 byte, - struct BIST_result *bist) -{ - bool result = true; /* BIST_SUCCESS */ - u32 cnt = 0; - u32 error = 0; - u32 val; - int ret; - - bist->test_result = true; - -run: - itm_soft_reset(phy); - - /*Perform BIST Reset*/ - /* Write BISTRR.BINST = 3?b011; */ - clrsetbits_le32(&phy->bistrr, - 0x00000007, - 0x00000003); - - /*Re-seed LFSR*/ - /* Write BISTLSR.SEED = 32'h1234ABCD; */ - if (BIST_seed) - writel(BIST_seed, &phy->bistlsr); - else - writel(rand(), &phy->bistlsr); - - /* some delay to reset BIST */ - udelay(10); - - /*Perform BIST Run*/ - clrsetbits_le32(&phy->bistrr, - 0x00000007, - 0x00000001); - /* Write BISTRR.BINST = 3?b001; */ - - /* poll on BISTGSR.BDONE and wait max 1000 us */ - ret = readl_poll_timeout(&phy->bistgsr, val, - val & DDRPHYC_BISTGSR_BDDONE, 1000); - - if (ret < 0) { - printf("warning: BIST timeout\n"); - result = false; /* BIST_FAIL; */ - /*Perform BIST Stop */ - clrsetbits_le32(&phy->bistrr, 0x00000007, 0x00000002); - } else { - /*Check if received correct number of words*/ - /* if (Read BISTWCSR.DXWCNT = Read BISTWCR.BWCNT) */ - if (((readl(&phy->bistwcsr)) >> DDRPHYC_BISTWCSR_DXWCNT_SHIFT) - == readl(&phy->bistwcr)) { - /*Determine if there is a data comparison error*/ - /* if (Read BISTGSR.BDXERR = 1?b0) */ - if (readl(&phy->bistgsr) & DDRPHYC_BISTGSR_BDXERR) - result = false; /* BIST_FAIL; */ - else - result = true; /* BIST_SUCCESS; */ - } else { - result = false; /* BIST_FAIL; */ - } - } - - /* loop while success */ - cnt++; - if (result && cnt != 1000) - goto run; - - if (!result) - error++; - - if (error < BIST_error_max) { - if (cnt != 1000) - goto run; - bist->test_result = true; - } else { - bist->test_result = false; - } -} - -/* After running the deskew algo, this function applies the new DQ delays - * by reading them from the array "deskew_delay"and writing in PHY registers. - * The bits that are not deskewed parfectly (too much skew on them, - * or data eye very wide) are marked in the array deskew_non_converge. - */ -static void apply_deskew_results(struct stm32mp1_ddrphy *phy, u8 byte, - u8 deskew_delay[NUM_BYTES][8], - u8 deskew_non_converge[NUM_BYTES][8]) -{ - u8 bit_i; - u8 index; - - for (bit_i = 0; bit_i < 8; bit_i++) { - set_DQ_unit_delay(phy, byte, bit_i, deskew_delay[byte][bit_i]); - index = DQ_unit_index(phy, byte, bit_i); - log_debug("Byte %d ; bit %d : The new DQ delay (%d) index=%d [delta=%d, 3 is the default]", - byte, bit_i, deskew_delay[byte][bit_i], - index, index - 3); - printf("Byte %d, bit %d, DQ delay = %d", - byte, bit_i, deskew_delay[byte][bit_i]); - if (deskew_non_converge[byte][bit_i] == 1) - log_debug(" - not converged : still more skew"); - printf("\n"); - } -} - -/* DQ Bit de-skew algorithm. - * Deskews data lines as much as possible. - * 1. Add delay to DQS line until finding the failure - * (normally a hold time violation) - * 2. Reduce DQS line by small steps until finding the very first time - * we go back to "Pass" condition. - * 3. For each DQ line, Reduce DQ delay until finding the very first failure - * (normally a hold time fail) - * 4. When all bits are at their first failure delay, we can consider them - * aligned. - * Handle conrer situation (Can't find Pass-fail, or fail-pass transitions - * at any step) - * TODO Provide a return Status. Improve doc - */ -static enum test_result bit_deskew(struct stm32mp1_ddrctl *ctl, - struct stm32mp1_ddrphy *phy, char *string) -{ - /* New DQ delay value (index), set during Deskew algo */ - u8 deskew_delay[NUM_BYTES][8]; - /*If there is still skew on a bit, mark this bit. */ - u8 deskew_non_converge[NUM_BYTES][8]; - struct BIST_result result; - s8 dqs_unit_delay_index = 0; - u8 datx8 = 0; - u8 bit_i = 0; - s8 phase_idx = 0; - s8 bit_i_delay_index = 0; - u8 success = 0; - struct tuning_position last_right_ok; - u8 force_stop = 0; - u8 fail_found; - u8 error = 0; - u8 nb_bytes = get_nb_bytes(ctl); - /* u8 last_pass_dqs_unit = 0; */ - - memset(deskew_delay, 0, sizeof(deskew_delay)); - memset(deskew_non_converge, 0, sizeof(deskew_non_converge)); - - /*Disable DQS Drift Compensation*/ - clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP); - /*Disable all bytes*/ - /* Disable automatic power down of DLL and IOs when disabling - * a byte (To avoid having to add programming and delay - * for a DLL re-lock when later re-enabling a disabled Byte Lane) - */ - clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_PDDISDX); - - /* Disable all data bytes */ - clrbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN); - clrbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN); - clrbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN); - clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN); - - /* Config the BIST block */ - config_BIST(ctl, phy); - log_debug("BIST Config done.\n"); - - /* Train each byte */ - for (datx8 = 0; datx8 < nb_bytes; datx8++) { - if (ctrlc()) { - sprintf(string, "interrupted at byte %d/%d, error=%d", - datx8 + 1, nb_bytes, error); - return TEST_FAILED; - } - log_debug("\n======================\n"); - log_debug("Start deskew byte %d .\n", datx8); - log_debug("======================\n"); - /* Enable Byte (DXNGCR, bit DXEN) */ - setbits_le32(DXNGCR(phy, datx8), DDRPHYC_DXNGCR_DXEN); - - /* Select the byte lane for comparison of read data */ - BIST_datx8_sel(phy, datx8); - - /* Set all DQDLYn to maximum value. All bits within the byte - * will be delayed with DQSTR = 2 instead of max = 3 - * to avoid inter bits fail influence - */ - writel(0xAAAAAAAA, DXNDQTR(phy, datx8)); - - /* Set the DQS phase delay to 90 DEG (default). - * What is defined here is the index of the desired config - * in the PHASE array. - */ - phase_idx = _90deg; - - /* Set DQS unit delay to the max value. */ - dqs_unit_delay_index = MAX_DQS_UNIT_IDX; - DQS_unit_delay(phy, datx8, dqs_unit_delay_index); - DQS_phase_delay(phy, datx8, phase_idx); - - /* Issue a DLL soft reset */ - clrbits_le32(DXNDLLCR(phy, datx8), DDRPHYC_DXNDLLCR_DLLSRST); - setbits_le32(DXNDLLCR(phy, datx8), DDRPHYC_DXNDLLCR_DLLSRST); - - /* Test this typical init condition */ - BIST_test(phy, datx8, &result); - success = result.test_result; - - /* If the test pass in this typical condition, - * start the algo with it. - * Else, look for Pass init condition - */ - if (!success) { - log_debug("Fail at init condtion. Let's look for a good init condition.\n"); - success = 0; /* init */ - /* Make sure we start with a PASS condition before - * looking for a fail condition. - * Find the first PASS PHASE condition - */ - - /* escape if we find a PASS */ - log_debug("increase Phase idx\n"); - while (!success && (phase_idx <= MAX_DQS_PHASE_IDX)) { - DQS_phase_delay(phy, datx8, phase_idx); - BIST_test(phy, datx8, &result); - success = result.test_result; - phase_idx++; - } - /* if ended with success - * ==>> Restore the fist success condition - */ - if (success) - phase_idx--; /* because it ended with ++ */ - } - if (ctrlc()) { - sprintf(string, "interrupted at byte %d/%d, error=%d", - datx8 + 1, nb_bytes, error); - return TEST_FAILED; - } - /* We couldn't find a successful condition, its seems - * we have hold violation, lets try reduce DQS_unit Delay - */ - if (!success) { - /* We couldn't find a successful condition, its seems - * we have hold violation, lets try reduce DQS_unit - * Delay - */ - log_debug("Still fail. Try decrease DQS Unit delay\n"); - - phase_idx = 0; - dqs_unit_delay_index = 0; - DQS_phase_delay(phy, datx8, phase_idx); - - /* escape if we find a PASS */ - while (!success && - (dqs_unit_delay_index <= - MAX_DQS_UNIT_IDX)) { - DQS_unit_delay(phy, datx8, - dqs_unit_delay_index); - BIST_test(phy, datx8, &result); - success = result.test_result; - dqs_unit_delay_index++; - } - if (success) { - /* Restore the first success condition*/ - dqs_unit_delay_index--; - /* last_pass_dqs_unit = dqs_unit_delay_index;*/ - DQS_unit_delay(phy, datx8, - dqs_unit_delay_index); - } else { - /* No need to continue, - * there is no pass region. - */ - force_stop = 1; - } - } - - /* There is an initial PASS condition - * Look for the first failing condition by PHASE stepping. - * This part of the algo can finish without converging. - */ - if (force_stop) { - printf("Result: Failed "); - printf("[Cannot Deskew lines, "); - printf("there is no PASS region]\n"); - error++; - continue; - } - if (ctrlc()) { - sprintf(string, "interrupted at byte %d/%d, error=%d", - datx8 + 1, nb_bytes, error); - return TEST_FAILED; - } - - log_debug("there is a pass region for phase idx %d\n", - phase_idx); - log_debug("Step1: Find the first failing condition\n"); - /* Look for the first failing condition by PHASE stepping. - * This part of the algo can finish without converging. - */ - - /* escape if we find a fail (hold time violation) - * condition at any bit or if out of delay range. - */ - while (success && (phase_idx <= MAX_DQS_PHASE_IDX)) { - DQS_phase_delay(phy, datx8, phase_idx); - BIST_test(phy, datx8, &result); - success = result.test_result; - phase_idx++; - } - if (ctrlc()) { - sprintf(string, "interrupted at byte %d/%d, error=%d", - datx8 + 1, nb_bytes, error); - return TEST_FAILED; - } - - /* if the loop ended with a failing condition at any bit, - * lets look for the first previous success condition by unit - * stepping (minimal delay) - */ - if (!success) { - log_debug("Fail region (PHASE) found phase idx %d\n", - phase_idx); - log_debug("Let's look for first success by DQS Unit steps\n"); - /* This part, the algo always converge */ - phase_idx--; - - /* escape if we find a success condition - * or if out of delay range. - */ - while (!success && dqs_unit_delay_index >= 0) { - DQS_unit_delay(phy, datx8, - dqs_unit_delay_index); - BIST_test(phy, datx8, &result); - success = result.test_result; - dqs_unit_delay_index--; - } - /* if the loop ended with a success condition, - * the last delay Right OK (before hold violation) - * condition is then defined as following: - */ - if (success) { - /* Hold the dely parameters of the the last - * delay Right OK condition. - * -1 to get back to current condition - */ - last_right_ok.phase = phase_idx; - /*+1 to get back to current condition */ - last_right_ok.unit = dqs_unit_delay_index + 1; - last_right_ok.bits_delay = 0xFFFFFFFF; - log_debug("Found %d\n", dqs_unit_delay_index); - } else { - /* the last OK condition is then with the - * previous phase_idx. - * -2 instead of -1 because at the last - * iteration of the while(), - * we incremented phase_idx - */ - last_right_ok.phase = phase_idx - 1; - /* Nominal+1. Because we want the previous - * delay after reducing the phase delay. - */ - last_right_ok.unit = 1; - last_right_ok.bits_delay = 0xFFFFFFFF; - log_debug("Not Found : try previous phase %d\n", - phase_idx - 1); - - DQS_phase_delay(phy, datx8, phase_idx - 1); - dqs_unit_delay_index = 0; - success = true; - while (success && - (dqs_unit_delay_index < - MAX_DQS_UNIT_IDX)) { - DQS_unit_delay(phy, datx8, - dqs_unit_delay_index); - BIST_test(phy, datx8, &result); - success = result.test_result; - dqs_unit_delay_index++; - log_debug("dqs_unit_delay_index = %d, result = %d\n", - dqs_unit_delay_index, success); - } - - if (!success) { - last_right_ok.unit = - dqs_unit_delay_index - 1; - } else { - last_right_ok.unit = 0; - log_debug("ERROR: failed region not FOUND"); - } - } - } else { - /* we can't find a failing condition at all bits - * ==> Just hold the last test condition - * (the max DQS delay) - * which is the most likely, - * the closest to a hold violation - * If we can't find a Fail condition after - * the Pass region, stick at this position - * In order to have max chances to find a fail - * when reducing DQ delays. - */ - last_right_ok.phase = MAX_DQS_PHASE_IDX; - last_right_ok.unit = MAX_DQS_UNIT_IDX; - last_right_ok.bits_delay = 0xFFFFFFFF; - log_debug("Can't find the a fail condition\n"); - } - - /* step 2: - * if we arrive at this stage, it means that we found the last - * Right OK condition (by tweeking the DQS delay). Or we simply - * pushed DQS delay to the max - * This means that by reducing the delay on some DQ bits, - * we should find a failing condition. - */ - printf("Byte %d, DQS unit = %d, phase = %d\n", - datx8, last_right_ok.unit, last_right_ok.phase); - log_debug("Step2, unit = %d, phase = %d, bits delay=%x\n", - last_right_ok.unit, last_right_ok.phase, - last_right_ok.bits_delay); - - /* Restore the last_right_ok condtion. */ - DQS_unit_delay(phy, datx8, last_right_ok.unit); - DQS_phase_delay(phy, datx8, last_right_ok.phase); - writel(last_right_ok.bits_delay, DXNDQTR(phy, datx8)); - - /* train each bit - * reduce delay on each bit, and perform a write/read test - * and stop at the very first time it fails. - * the goal is the find the first failing condition - * for each bit. - * When we achieve this condition< for all the bits, - * we are sure they are aligned (+/- step resolution) - */ - fail_found = 0; - for (bit_i = 0; bit_i < 8; bit_i++) { - if (ctrlc()) { - sprintf(string, - "interrupted at byte %d/%d, error=%d", - datx8 + 1, nb_bytes, error); - return error; - } - log_debug("deskewing bit %d:\n", bit_i); - success = 1; /* init */ - /* Set all DQDLYn to maximum value. - * Only bit_i will be down-delayed - * ==> if we have a fail, it will be definitely - * from bit_i - */ - writel(0xFFFFFFFF, DXNDQTR(phy, datx8)); - /* Arriving at this stage, - * we have a success condition with delay = 3; - */ - bit_i_delay_index = 3; - - /* escape if bit delay is out of range or - * if a fatil occurs - */ - while ((bit_i_delay_index >= 0) && success) { - set_DQ_unit_delay(phy, datx8, - bit_i, - bit_i_delay_index); - BIST_test(phy, datx8, &result); - success = result.test_result; - bit_i_delay_index--; - } - - /* if escape with a fail condition - * ==> save this position for bit_i - */ - if (!success) { - /* save the delay position. - * Add 1 because the while loop ended with a --, - * and that we need to hold the last success - * delay - */ - deskew_delay[datx8][bit_i] = - bit_i_delay_index + 2; - if (deskew_delay[datx8][bit_i] > 3) - deskew_delay[datx8][bit_i] = 3; - - /* A flag that states we found at least a fail - * at one bit. - */ - fail_found = 1; - log_debug("Fail found on bit %d, for delay = %d => deskew[%d][%d] = %d\n", - bit_i, bit_i_delay_index + 1, - datx8, bit_i, - deskew_delay[datx8][bit_i]); - } else { - /* if we can find a success condition by - * back-delaying this bit, just set the delay - * to 0 (the best deskew - * possible) and mark the bit. - */ - deskew_delay[datx8][bit_i] = 0; - /* set a flag that will be used later - * in the report. - */ - deskew_non_converge[datx8][bit_i] = 1; - log_debug("Fail not found on bit %d => deskew[%d][%d] = %d\n", - bit_i, datx8, bit_i, - deskew_delay[datx8][bit_i]); - } - } - log_debug("**********byte %d tuning complete************\n", - datx8); - /* If we can't find any failure by back delaying DQ lines, - * hold the default values - */ - if (!fail_found) { - for (bit_i = 0; bit_i < 8; bit_i++) - deskew_delay[datx8][bit_i] = 0; - log_debug("The Deskew algorithm can't converge, there is too much margin in your design. Good job!\n"); - } - - apply_deskew_results(phy, datx8, deskew_delay, - deskew_non_converge); - /* Restore nominal value for DQS delay */ - DQS_phase_delay(phy, datx8, 3); - DQS_unit_delay(phy, datx8, 3); - /* disable byte after byte bits deskew */ - clrbits_le32(DXNGCR(phy, datx8), DDRPHYC_DXNGCR_DXEN); - } /* end of byte deskew */ - - /* re-enable all data bytes */ - setbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN); - setbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN); - setbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN); - setbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN); - - if (error) { - sprintf(string, "error = %d", error); - return TEST_FAILED; - } - - return TEST_PASSED; -} /* end function */ - -/* Trim DQS timings and set it in the centre of data eye. - * Look for a PPPPF region, then look for a FPPP region and finally select - * the mid of the FPPPPPF region - */ -static enum test_result eye_training(struct stm32mp1_ddrctl *ctl, - struct stm32mp1_ddrphy *phy, char *string) -{ - /*Stores the DQS trim values (PHASE index, unit index) */ - u8 eye_training_val[NUM_BYTES][2]; - u8 byte = 0; - struct BIST_result result; - s8 dqs_unit_delay_index = 0; - s8 phase_idx = 0; - s8 dqs_unit_delay_index_pass = 0; - s8 phase_idx_pass = 0; - u8 success = 0; - u8 left_phase_bound_found, right_phase_bound_found; - u8 left_unit_bound_found, right_unit_bound_found; - u8 left_bound_found, right_bound_found; - struct tuning_position left_bound, right_bound; - u8 error = 0; - u8 nb_bytes = get_nb_bytes(ctl); - - /*Disable DQS Drift Compensation*/ - clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP); - /*Disable all bytes*/ - /* Disable automatic power down of DLL and IOs when disabling a byte - * (To avoid having to add programming and delay - * for a DLL re-lock when later re-enabling a disabled Byte Lane) - */ - clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_PDDISDX); - - /*Disable all data bytes */ - clrbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN); - clrbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN); - clrbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN); - clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN); - - /* Config the BIST block */ - config_BIST(ctl, phy); - - for (byte = 0; byte < nb_bytes; byte++) { - if (ctrlc()) { - sprintf(string, "interrupted at byte %d/%d, error=%d", - byte + 1, nb_bytes, error); - return TEST_FAILED; - } - right_bound.phase = 0; - right_bound.unit = 0; - - left_bound.phase = 0; - left_bound.unit = 0; - - left_phase_bound_found = 0; - right_phase_bound_found = 0; - - left_unit_bound_found = 0; - right_unit_bound_found = 0; - - left_bound_found = 0; - right_bound_found = 0; - - /* Enable Byte (DXNGCR, bit DXEN) */ - setbits_le32(DXNGCR(phy, byte), DDRPHYC_DXNGCR_DXEN); - - /* Select the byte lane for comparison of read data */ - BIST_datx8_sel(phy, byte); - - /* Set DQS phase delay to the nominal value. */ - phase_idx = _90deg; - phase_idx_pass = phase_idx; - - /* Set DQS unit delay to the nominal value. */ - dqs_unit_delay_index = 3; - dqs_unit_delay_index_pass = dqs_unit_delay_index; - success = 0; - - log_debug("STEP0: Find Init delay\n"); - /* STEP0: Find Init delay: a delay that put the system - * in a "Pass" condition then (TODO) update - * dqs_unit_delay_index_pass & phase_idx_pass - */ - DQS_unit_delay(phy, byte, dqs_unit_delay_index); - DQS_phase_delay(phy, byte, phase_idx); - BIST_test(phy, byte, &result); - success = result.test_result; - /* If we have a fail in the nominal condition */ - if (!success) { - /* Look at the left */ - while (phase_idx >= 0 && !success) { - phase_idx--; - DQS_phase_delay(phy, byte, phase_idx); - BIST_test(phy, byte, &result); - success = result.test_result; - } - } - if (!success) { - /* if we can't find pass condition, - * then look at the right - */ - phase_idx = _90deg; - while (phase_idx <= MAX_DQS_PHASE_IDX && - !success) { - phase_idx++; - DQS_phase_delay(phy, byte, - phase_idx); - BIST_test(phy, byte, &result); - success = result.test_result; - } - } - /* save the pass condition */ - if (success) { - phase_idx_pass = phase_idx; - } else { - printf("Result: Failed "); - printf("[Cannot DQS timings, "); - printf("there is no PASS region]\n"); - error++; - continue; - } - - if (ctrlc()) { - sprintf(string, "interrupted at byte %d/%d, error=%d", - byte + 1, nb_bytes, error); - return TEST_FAILED; - } - log_debug("STEP1: Find LEFT PHASE DQS Bound\n"); - /* STEP1: Find LEFT PHASE DQS Bound */ - while ((phase_idx >= 0) && - (phase_idx <= MAX_DQS_PHASE_IDX) && - !left_phase_bound_found) { - DQS_unit_delay(phy, byte, - dqs_unit_delay_index); - DQS_phase_delay(phy, byte, - phase_idx); - BIST_test(phy, byte, &result); - success = result.test_result; - - /*TODO: Manage the case were at the beginning - * there is already a fail - */ - if (!success) { - /* the last pass condition */ - left_bound.phase = ++phase_idx; - left_phase_bound_found = 1; - } else if (success) { - phase_idx--; - } - } - if (!left_phase_bound_found) { - left_bound.phase = 0; - phase_idx = 0; - } - /* If not found, lets take 0 */ - - if (ctrlc()) { - sprintf(string, "interrupted at byte %d/%d, error=%d", - byte + 1, nb_bytes, error); - return TEST_FAILED; - } - log_debug("STEP2: Find UNIT left bound\n"); - /* STEP2: Find UNIT left bound */ - while ((dqs_unit_delay_index >= 0) && - !left_unit_bound_found) { - DQS_unit_delay(phy, byte, - dqs_unit_delay_index); - DQS_phase_delay(phy, byte, phase_idx); - BIST_test(phy, byte, &result); - success = result.test_result; - if (!success) { - left_bound.unit = - ++dqs_unit_delay_index; - left_unit_bound_found = 1; - left_bound_found = 1; - } else if (success) { - dqs_unit_delay_index--; - } - } - - /* If not found, lets take 0 */ - if (!left_unit_bound_found) - left_bound.unit = 0; - - if (ctrlc()) { - sprintf(string, "interrupted at byte %d/%d, error=%d", - byte + 1, nb_bytes, error); - return TEST_FAILED; - } - log_debug("STEP3: Find PHase right bound\n"); - /* STEP3: Find PHase right bound, start with "pass" - * condition - */ - - /* Set DQS phase delay to the pass value. */ - phase_idx = phase_idx_pass; - - /* Set DQS unit delay to the pass value. */ - dqs_unit_delay_index = dqs_unit_delay_index_pass; - - while ((phase_idx <= MAX_DQS_PHASE_IDX) && - !right_phase_bound_found) { - DQS_unit_delay(phy, byte, - dqs_unit_delay_index); - DQS_phase_delay(phy, byte, phase_idx); - BIST_test(phy, byte, &result); - success = result.test_result; - if (!success) { - /* the last pass condition */ - right_bound.phase = --phase_idx; - right_phase_bound_found = 1; - } else if (success) { - phase_idx++; - } - } - - /* If not found, lets take the max value */ - if (!right_phase_bound_found) { - right_bound.phase = MAX_DQS_PHASE_IDX; - phase_idx = MAX_DQS_PHASE_IDX; - } - - if (ctrlc()) { - sprintf(string, "interrupted at byte %d/%d, error=%d", - byte + 1, nb_bytes, error); - return TEST_FAILED; - } - log_debug("STEP4: Find UNIT right bound\n"); - /* STEP4: Find UNIT right bound */ - while ((dqs_unit_delay_index <= MAX_DQS_UNIT_IDX) && - !right_unit_bound_found) { - DQS_unit_delay(phy, byte, - dqs_unit_delay_index); - DQS_phase_delay(phy, byte, phase_idx); - BIST_test(phy, byte, &result); - success = result.test_result; - if (!success) { - right_bound.unit = - --dqs_unit_delay_index; - right_unit_bound_found = 1; - right_bound_found = 1; - } else if (success) { - dqs_unit_delay_index++; - } - } - /* If not found, lets take the max value */ - if (!right_unit_bound_found) - right_bound.unit = MAX_DQS_UNIT_IDX; - - /* If we found a regular FAil Pass FAil pattern - * FFPPPPPPFF - * OR PPPPPFF Or FFPPPPP - */ - - if (left_bound_found || right_bound_found) { - eye_training_val[byte][0] = (right_bound.phase + - left_bound.phase) / 2; - eye_training_val[byte][1] = (right_bound.unit + - left_bound.unit) / 2; - - /* If we already lost 1/2PHASE Tuning, - * let's try to recover by ++ on unit - */ - if (((right_bound.phase + left_bound.phase) % 2 == 1) && - eye_training_val[byte][1] != MAX_DQS_UNIT_IDX) - eye_training_val[byte][1]++; - log_debug("** found phase : %d - %d & unit %d - %d\n", - right_bound.phase, left_bound.phase, - right_bound.unit, left_bound.unit); - log_debug("** calculating mid region: phase: %d unit: %d (nominal is 3)\n", - eye_training_val[byte][0], - eye_training_val[byte][1]); - } else { - /* PPPPPPPPPP, we're already good. - * Set nominal values. - */ - eye_training_val[byte][0] = 3; - eye_training_val[byte][1] = 3; - } - DQS_phase_delay(phy, byte, eye_training_val[byte][0]); - DQS_unit_delay(phy, byte, eye_training_val[byte][1]); - - printf("Byte %d, DQS unit = %d, phase = %d\n", - byte, - eye_training_val[byte][1], - eye_training_val[byte][0]); - } - - if (error) { - sprintf(string, "error = %d", error); - return TEST_FAILED; - } - - return TEST_PASSED; -} - -static void display_reg_results(struct stm32mp1_ddrphy *phy, u8 byte) -{ - u8 i = 0; - - printf("Byte %d Dekew result, bit0 delay, bit1 delay...bit8 delay\n ", - byte); - - for (i = 0; i < 8; i++) - printf("%d ", DQ_unit_index(phy, byte, i)); - printf("\n"); - - printf("dxndllcr: [%08x] val:%08x\n", - DXNDLLCR(phy, byte), - readl(DXNDLLCR(phy, byte))); - printf("dxnqdstr: [%08x] val:%08x\n", - DXNDQSTR(phy, byte), - readl(DXNDQSTR(phy, byte))); - printf("dxndqtr: [%08x] val:%08x\n", - DXNDQTR(phy, byte), - readl(DXNDQTR(phy, byte))); -} - -/* analyse the dgs gating log table, and determine the midpoint.*/ -static u8 set_midpoint_read_dqs_gating(struct stm32mp1_ddrphy *phy, u8 byte, - u8 dqs_gating[NUM_BYTES] - [MAX_GSL_IDX + 1] - [MAX_GPS_IDX + 1]) -{ - /* stores the dqs gate values (gsl index, gps index) */ - u8 dqs_gate_values[NUM_BYTES][2]; - u8 gsl_idx, gps_idx = 0; - u8 left_bound_idx[2] = {0, 0}; - u8 right_bound_idx[2] = {0, 0}; - u8 left_bound_found = 0; - u8 right_bound_found = 0; - u8 intermittent = 0; - u8 value; - - for (gsl_idx = 0; gsl_idx <= MAX_GSL_IDX; gsl_idx++) { - for (gps_idx = 0; gps_idx <= MAX_GPS_IDX; gps_idx++) { - value = dqs_gating[byte][gsl_idx][gps_idx]; - if (value == 1 && left_bound_found == 0) { - left_bound_idx[0] = gsl_idx; - left_bound_idx[1] = gps_idx; - left_bound_found = 1; - } else if (value == 0 && - left_bound_found == 1 && - !right_bound_found) { - if (gps_idx == 0) { - right_bound_idx[0] = gsl_idx - 1; - right_bound_idx[1] = MAX_GPS_IDX; - } else { - right_bound_idx[0] = gsl_idx; - right_bound_idx[1] = gps_idx - 1; - } - right_bound_found = 1; - } else if (value == 1 && - right_bound_found == 1) { - intermittent = 1; - } - } - } - - /* if only ppppppp is found, there is no mid region. */ - if (left_bound_idx[0] == 0 && left_bound_idx[1] == 0 && - right_bound_idx[0] == 0 && right_bound_idx[1] == 0) - intermittent = 1; - - /*if we found a regular fail pass fail pattern ffppppppff - * or pppppff or ffppppp - */ - if (!intermittent) { - /*if we found a regular fail pass fail pattern ffppppppff - * or pppppff or ffppppp - */ - if (left_bound_found || right_bound_found) { - log_debug("idx0(%d): %d %d idx1(%d) : %d %d\n", - left_bound_found, - right_bound_idx[0], left_bound_idx[0], - right_bound_found, - right_bound_idx[1], left_bound_idx[1]); - dqs_gate_values[byte][0] = - (right_bound_idx[0] + left_bound_idx[0]) / 2; - dqs_gate_values[byte][1] = - (right_bound_idx[1] + left_bound_idx[1]) / 2; - /* if we already lost 1/2gsl tuning, - * let's try to recover by ++ on gps - */ - if (((right_bound_idx[0] + - left_bound_idx[0]) % 2 == 1) && - dqs_gate_values[byte][1] != MAX_GPS_IDX) - dqs_gate_values[byte][1]++; - /* if we already lost 1/2gsl tuning and gps is on max*/ - else if (((right_bound_idx[0] + - left_bound_idx[0]) % 2 == 1) && - dqs_gate_values[byte][1] == MAX_GPS_IDX) { - dqs_gate_values[byte][1] = 0; - dqs_gate_values[byte][0]++; - } - /* if we have gsl left and write limit too close - * (difference=1) - */ - if (((right_bound_idx[0] - left_bound_idx[0]) == 1)) { - dqs_gate_values[byte][1] = (left_bound_idx[1] + - right_bound_idx[1] + - 4) / 2; - if (dqs_gate_values[byte][1] >= 4) { - dqs_gate_values[byte][0] = - right_bound_idx[0]; - dqs_gate_values[byte][1] -= 4; - } else { - dqs_gate_values[byte][0] = - left_bound_idx[0]; - } - } - log_debug("*******calculating mid region: system latency: %d phase: %d********\n", - dqs_gate_values[byte][0], - dqs_gate_values[byte][1]); - log_debug("*******the nominal values were system latency: 0 phase: 2*******\n"); - } - } else { - /* if intermitant, restore defaut values */ - log_debug("dqs gating:no regular fail/pass/fail found. defaults values restored.\n"); - dqs_gate_values[byte][0] = 0; - dqs_gate_values[byte][1] = 2; - } - set_r0dgsl_delay(phy, byte, dqs_gate_values[byte][0]); - set_r0dgps_delay(phy, byte, dqs_gate_values[byte][1]); - printf("Byte %d, R0DGSL = %d, R0DGPS = %d\n", - byte, dqs_gate_values[byte][0], dqs_gate_values[byte][1]); - - /* return 0 if intermittent or if both left_bound - * and right_bound are not found - */ - return !(intermittent || (left_bound_found && right_bound_found)); -} - -static enum test_result read_dqs_gating(struct stm32mp1_ddrctl *ctl, - struct stm32mp1_ddrphy *phy, - char *string) -{ - /* stores the log of pass/fail */ - u8 dqs_gating[NUM_BYTES][MAX_GSL_IDX + 1][MAX_GPS_IDX + 1]; - u8 byte, gsl_idx, gps_idx = 0; - struct BIST_result result; - u8 success = 0; - u8 nb_bytes = get_nb_bytes(ctl); - - memset(dqs_gating, 0x0, sizeof(dqs_gating)); - - /*disable dqs drift compensation*/ - clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP); - /*disable all bytes*/ - /* disable automatic power down of dll and ios when disabling a byte - * (to avoid having to add programming and delay - * for a dll re-lock when later re-enabling a disabled byte lane) - */ - clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_PDDISDX); - - /* disable all data bytes */ - clrbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN); - clrbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN); - clrbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN); - clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN); - - /* config the bist block */ - config_BIST(ctl, phy); - - for (byte = 0; byte < nb_bytes; byte++) { - if (ctrlc()) { - sprintf(string, "interrupted at byte %d/%d", - byte + 1, nb_bytes); - return TEST_FAILED; - } - /* enable byte x (dxngcr, bit dxen) */ - setbits_le32(DXNGCR(phy, byte), DDRPHYC_DXNGCR_DXEN); - - /* select the byte lane for comparison of read data */ - BIST_datx8_sel(phy, byte); - for (gsl_idx = 0; gsl_idx <= MAX_GSL_IDX; gsl_idx++) { - for (gps_idx = 0; gps_idx <= MAX_GPS_IDX; gps_idx++) { - if (ctrlc()) { - sprintf(string, - "interrupted at byte %d/%d", - byte + 1, nb_bytes); - return TEST_FAILED; - } - /* write cfg to dxndqstr */ - set_r0dgsl_delay(phy, byte, gsl_idx); - set_r0dgps_delay(phy, byte, gps_idx); - - BIST_test(phy, byte, &result); - success = result.test_result; - if (success) - dqs_gating[byte][gsl_idx][gps_idx] = 1; - itm_soft_reset(phy); - } - } - set_midpoint_read_dqs_gating(phy, byte, dqs_gating); - /* dummy reads */ - readl(0xc0000000); - readl(0xc0000000); - } - - /* re-enable drift compensation */ - /* setbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP); */ - return TEST_PASSED; -} - -/**************************************************************** - * TEST - **************************************************************** - */ -static enum test_result do_read_dqs_gating(struct stm32mp1_ddrctl *ctl, - struct stm32mp1_ddrphy *phy, - char *string, int argc, - char *argv[]) -{ - u32 rfshctl3 = readl(&ctl->rfshctl3); - u32 pwrctl = readl(&ctl->pwrctl); - u32 derateen = readl(&ctl->derateen); - enum test_result res; - - writel(0x0, &ctl->derateen); - stm32mp1_refresh_disable(ctl); - - res = read_dqs_gating(ctl, phy, string); - - stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl); - writel(derateen, &ctl->derateen); - - return res; -} - -static enum test_result do_bit_deskew(struct stm32mp1_ddrctl *ctl, - struct stm32mp1_ddrphy *phy, - char *string, int argc, char *argv[]) -{ - u32 rfshctl3 = readl(&ctl->rfshctl3); - u32 pwrctl = readl(&ctl->pwrctl); - u32 derateen = readl(&ctl->derateen); - enum test_result res; - - writel(0x0, &ctl->derateen); - stm32mp1_refresh_disable(ctl); - - res = bit_deskew(ctl, phy, string); - - stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl); - writel(derateen, &ctl->derateen); - - return res; -} - -static enum test_result do_eye_training(struct stm32mp1_ddrctl *ctl, - struct stm32mp1_ddrphy *phy, - char *string, int argc, char *argv[]) -{ - u32 rfshctl3 = readl(&ctl->rfshctl3); - u32 pwrctl = readl(&ctl->pwrctl); - u32 derateen = readl(&ctl->derateen); - enum test_result res; - - writel(0x0, &ctl->derateen); - stm32mp1_refresh_disable(ctl); - - res = eye_training(ctl, phy, string); - - stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl); - writel(derateen, &ctl->derateen); - - return res; -} - -static enum test_result do_display(struct stm32mp1_ddrctl *ctl, - struct stm32mp1_ddrphy *phy, - char *string, int argc, char *argv[]) -{ - int byte; - u8 nb_bytes = get_nb_bytes(ctl); - - for (byte = 0; byte < nb_bytes; byte++) - display_reg_results(phy, byte); - - return TEST_PASSED; -} - -static enum test_result do_bist_config(struct stm32mp1_ddrctl *ctl, - struct stm32mp1_ddrphy *phy, - char *string, int argc, char *argv[]) -{ - unsigned long value; - - if (argc > 0) { - if (strict_strtoul(argv[0], 0, &value) < 0) { - sprintf(string, "invalid nbErr %s", argv[0]); - return TEST_FAILED; - } - BIST_error_max = value; - } - if (argc > 1) { - if (strict_strtoul(argv[1], 0, &value) < 0) { - sprintf(string, "invalid Seed %s", argv[1]); - return TEST_FAILED; - } - BIST_seed = value; - } - printf("Bist.nbErr = %d\n", BIST_error_max); - if (BIST_seed) - printf("Bist.Seed = 0x%x\n", BIST_seed); - else - printf("Bist.Seed = random\n"); - - return TEST_PASSED; -} - -/**************************************************************** - * TEST Description - **************************************************************** - */ - -const struct test_desc tuning[] = { - {do_read_dqs_gating, "Read DQS gating", - "software read DQS Gating", "", 0 }, - {do_bit_deskew, "Bit de-skew", "", "", 0 }, - {do_eye_training, "Eye Training", "or DQS training", "", 0 }, - {do_display, "Display registers", "", "", 0 }, - {do_bist_config, "Bist config", "[nbErr] [seed]", - "configure Bist test", 2}, -}; - -const int tuning_nb = ARRAY_SIZE(tuning); diff --git a/drivers/reboot-mode/reboot-mode-uclass.c b/drivers/reboot-mode/reboot-mode-uclass.c index bb7a355fbf..2b38aa26b8 100644 --- a/drivers/reboot-mode/reboot-mode-uclass.c +++ b/drivers/reboot-mode/reboot-mode-uclass.c @@ -10,8 +10,6 @@ #include #include -DECLARE_GLOBAL_DATA_PTR; - int dm_reboot_mode_update(struct udevice *dev) { struct reboot_mode_ops *ops = reboot_mode_get_ops(dev); @@ -66,25 +64,20 @@ int dm_reboot_mode_pre_probe(struct udevice *dev) return -EINVAL; #if CONFIG_IS_ENABLED(OF_CONTROL) - const int node = dev_of_offset(dev); const char *mode_prefix = "mode-"; const int mode_prefix_len = strlen(mode_prefix); - int property; + struct ofprop property; const u32 *propvalue; const char *propname; - plat_data->env_variable = fdt_getprop(gd->fdt_blob, - node, - "u-boot,env-variable", - NULL); + plat_data->env_variable = dev_read_string(dev, "u-boot,env-variable"); if (!plat_data->env_variable) plat_data->env_variable = "reboot-mode"; plat_data->count = 0; - fdt_for_each_property_offset(property, gd->fdt_blob, node) { - propvalue = fdt_getprop_by_offset(gd->fdt_blob, - property, &propname, NULL); + dev_for_each_property(property, dev) { + propvalue = dev_read_prop_by_prop(&property, &propname, NULL); if (!propvalue) { dev_err(dev, "Could not get the value for property %s\n", propname); @@ -100,9 +93,8 @@ int dm_reboot_mode_pre_probe(struct udevice *dev) struct reboot_mode_mode *next = plat_data->modes; - fdt_for_each_property_offset(property, gd->fdt_blob, node) { - propvalue = fdt_getprop_by_offset(gd->fdt_blob, - property, &propname, NULL); + dev_for_each_property(property, dev) { + propvalue = dev_read_prop_by_prop(&property, &propname, NULL); if (!propvalue) { dev_err(dev, "Could not get the value for property %s\n", propname); diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 24e536463b..a911da84b3 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -12,6 +12,14 @@ config REMOTEPROC bool depends on DM +config REMOTEPROC_OPTEE + bool "Support for the remoteproc in OPTEE" + depends on REMOTEPROC + depends on OPTEE + help + Say y here to support remote processor firmware management by the + trusted execution environment. + # Please keep the configuration alphabetically sorted. config K3_SYSTEM_CONTROLLER bool "Support for TI' K3 System Controller" diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index f0e83451d6..ad260acd66 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -5,6 +5,7 @@ # obj-$(CONFIG_$(SPL_)REMOTEPROC) += rproc-uclass.o rproc-elf-loader.o +obj-$(CONFIG_REMOTEPROC_OPTEE) += rproc-optee.o # Remote proc drivers - Please keep this list alphabetically sorted. obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o diff --git a/drivers/remoteproc/rproc-optee.c b/drivers/remoteproc/rproc-optee.c new file mode 100644 index 0000000000..6d33b9fd4a --- /dev/null +++ b/drivers/remoteproc/rproc-optee.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) STMicroelectronics 2020 - All Rights Reserved + * Authors: Arnaud Pouliquen + */ + +#define LOG_CATEGORY UCLASS_REMOTEPROC + +#include +#include +#include +#include +#include +#include + +#define TA_REMOTEPROC_UUID { 0x80a4c275, 0x0a47, 0x4905, \ + { 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08} } + +/* The function IDs implemented in the associated TA */ + +/* + * Authentication of the firmware and load in the remote processor memory. + * + * [in] params[0].value.a: unique 32bit identifier of the firmware + * [in] params[1].memref: buffer containing the image of the firmware + */ +#define TA_RPROC_FW_CMD_LOAD_FW 1 + +/* + * Start the remote processor. + * + * [in] params[0].value.a: unique 32bit identifier of the firmware + */ +#define TA_RPROC_FW_CMD_START_FW 2 + +/* + * Stop the remote processor. + * + * [in] params[0].value.a: unique 32bit identifier of the firmware + */ +#define TA_RPROC_FW_CMD_STOP_FW 3 + +/* + * Return the physical address of the resource table, or 0 if not found + * No check is done to verify that the address returned is accessible by the + * non secure world. If the resource table is loaded in a protected memory, + * then accesses from non-secure world will likely fail. + * + * [in] params[0].value.a: unique 32bit identifier of the firmware + * [out] params[1].value.a: 32bit LSB resource table memory address + * [out] params[1].value.b: 32bit MSB resource table memory address + * [out] params[2].value.a: 32bit LSB resource table memory size + * [out] params[2].value.b: 32bit MSB resource table memory size + */ +#define TA_RPROC_FW_CMD_GET_RSC_TABLE 4 + +/* + * Get remote processor firmware core dump. If found, return either + * TEE_SUCCESS on successful completion or TEE_ERROR_SHORT_BUFFER if output + * buffer is too short to store the core dump. + * + * [in] params[0].value.a: unique 32bit identifier of the firmware + * [out] params[1].memref: Core dump, if found + */ +#define TA_RPROC_FW_CMD_GET_COREDUMP 5 + +static void prepare_args(struct rproc_optee *trproc, int cmd, + struct tee_invoke_arg *arg, uint num_param, + struct tee_param *param) +{ + memset(arg, 0, sizeof(*arg)); + memset(param, 0, num_param * sizeof(*param)); + + arg->func = cmd; + arg->session = trproc->session; + + param[0] = (struct tee_param) { + .attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT, + .u.value.a = trproc->fw_id, + }; +} + +int rproc_optee_load(struct rproc_optee *trproc, ulong addr, ulong size) +{ + struct tee_invoke_arg arg; + struct tee_param param[2]; + struct tee_shm *fw_shm; + int rc; + + rc = tee_shm_register(trproc->tee, (void *)addr, size, 0, &fw_shm); + if (rc) + return rc; + + prepare_args(trproc, TA_RPROC_FW_CMD_LOAD_FW, &arg, 2, param); + + /* Provide the address and size of the firmware image */ + param[1] = (struct tee_param){ + .attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT, + .u.memref = { + .shm = fw_shm, + .size = size, + .shm_offs = 0, + }, + }; + + rc = tee_invoke_func(trproc->tee, &arg, 2, param); + if (rc < 0 || arg.ret != 0) { + dev_err(trproc->tee, + "TA_RPROC_FW_CMD_LOAD_FW invoke failed TEE err: %x, err:%x\n", + arg.ret, rc); + if (!rc) + rc = -EIO; + } + + tee_shm_free(fw_shm); + + return rc; +} + +int rproc_optee_get_rsc_table(struct rproc_optee *trproc, phys_addr_t *rsc_addr, + phys_size_t *rsc_size) +{ + struct tee_invoke_arg arg; + struct tee_param param[3]; + int rc; + + prepare_args(trproc, TA_RPROC_FW_CMD_GET_RSC_TABLE, &arg, 3, param); + + param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT; + param[2].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT; + + rc = tee_invoke_func(trproc->tee, &arg, 3, param); + if (rc < 0 || arg.ret != 0) { + dev_err(trproc->tee, + "TA_RPROC_FW_CMD_GET_RSC_TABLE invoke failed TEE err: %x, err:%x\n", + arg.ret, rc); + if (!rc) + rc = -EIO; + + return rc; + } + + *rsc_size = (phys_size_t) + (param[2].u.value.b << 32 | param[2].u.value.a); + *rsc_addr = (phys_addr_t) + (param[1].u.value.b << 32 | param[1].u.value.a); + + return 0; +} + +int rproc_optee_start(struct rproc_optee *trproc) +{ + struct tee_invoke_arg arg; + struct tee_param param; + int rc; + + prepare_args(trproc, TA_RPROC_FW_CMD_START_FW, &arg, 1, ¶m); + + rc = tee_invoke_func(trproc->tee, &arg, 1, ¶m); + if (rc < 0 || arg.ret != 0) { + dev_err(trproc->tee, + "TA_RPROC_FW_CMD_START_FW invoke failed TEE err: %x, err:%x\n", + arg.ret, rc); + if (!rc) + rc = -EIO; + } + + return rc; +} + +int rproc_optee_stop(struct rproc_optee *trproc) +{ + struct tee_invoke_arg arg; + struct tee_param param; + int rc; + + prepare_args(trproc, TA_RPROC_FW_CMD_STOP_FW, &arg, 1, ¶m); + + rc = tee_invoke_func(trproc->tee, &arg, 1, ¶m); + if (rc < 0 || arg.ret != 0) { + dev_err(trproc->tee, + "TA_RPROC_FW_CMD_STOP_FW invoke failed TEE err: %x, err:%x\n", + arg.ret, rc); + if (!rc) + rc = -EIO; + } + + return rc; +} + +int rproc_optee_open(struct rproc_optee *trproc) +{ + struct udevice *tee = NULL; + const struct tee_optee_ta_uuid uuid = TA_REMOTEPROC_UUID; + struct tee_open_session_arg arg = { }; + int rc; + + if (!trproc) + return -EINVAL; + + tee = tee_find_device(tee, NULL, NULL, NULL); + if (!tee) + return -ENODEV; + + tee_optee_ta_uuid_to_octets(arg.uuid, &uuid); + rc = tee_open_session(tee, &arg, 0, NULL); + if (rc < 0 || arg.ret != 0) { + if (!rc) + rc = -EIO; + return rc; + } + + trproc->tee = tee; + trproc->session = arg.session; + + return 0; +} + +int rproc_optee_close(struct rproc_optee *trproc) +{ + int rc; + + if (!trproc->tee) + return -ENODEV; + + rc = tee_close_session(trproc->tee, trproc->session); + if (rc) + return rc; + + trproc->tee = NULL; + trproc->session = 0; + + return 0; + +} diff --git a/drivers/remoteproc/rproc-uclass.c b/drivers/remoteproc/rproc-uclass.c index 64c47c1e72..87e1ec7ad7 100644 --- a/drivers/remoteproc/rproc-uclass.c +++ b/drivers/remoteproc/rproc-uclass.c @@ -9,19 +9,15 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ #include #include -#include #include #include #include -#include #include #include #include #include #include -DECLARE_GLOBAL_DATA_PTR; - /** * for_each_remoteproc_device() - iterate through the list of rproc devices * @fn: check function to call per match, if this function returns fail, @@ -121,21 +117,13 @@ static int rproc_pre_probe(struct udevice *dev) if (!dev_get_plat(dev)) { #if CONFIG_IS_ENABLED(OF_CONTROL) - int node = dev_of_offset(dev); - const void *blob = gd->fdt_blob; bool tmp; - if (!blob) { - debug("'%s' no dt?\n", dev->name); - return -EINVAL; - } debug("'%s': using fdt\n", dev->name); - uc_pdata->name = fdt_getprop(blob, node, - "remoteproc-name", NULL); + uc_pdata->name = dev_read_string(dev, "remoteproc-name"); /* Default is internal memory mapped */ uc_pdata->mem_type = RPROC_INTERNAL_MEMORY_MAPPED; - tmp = fdtdec_get_bool(blob, node, - "remoteproc-internal-memory-mapped"); + tmp = dev_read_bool(dev, "remoteproc-internal-memory-mapped"); if (tmp) uc_pdata->mem_type = RPROC_INTERNAL_MEMORY_MAPPED; #else diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c index 4c5f24857e..0dd46ee951 100644 --- a/drivers/remoteproc/stm32_copro.c +++ b/drivers/remoteproc/stm32_copro.c @@ -10,11 +10,14 @@ #include #include #include +#include #include #include #include #include +#define STM32MP15_M4_FW_ID 0 + /** * struct stm32_copro_privdata - power processor private data * @reset_ctl: reset controller handle @@ -25,6 +28,7 @@ struct stm32_copro_privdata { struct reset_ctl reset_ctl; struct reset_ctl hold_boot; ulong rsc_table_addr; + struct rproc_optee trproc; }; /** @@ -34,10 +38,16 @@ struct stm32_copro_privdata { */ static int stm32_copro_probe(struct udevice *dev) { - struct stm32_copro_privdata *priv; + struct stm32_copro_privdata *priv = dev_get_priv(dev); + struct rproc_optee *trproc = &priv->trproc; int ret; - priv = dev_get_priv(dev); + trproc->fw_id = (u32)dev_get_driver_data(dev); + ret = rproc_optee_open(trproc); + if (!ret) { + dev_info(dev, "delegate the firmware management to OPTEE\n"); + return 0; + } ret = reset_get_by_name(dev, "mcu_rst", &priv->reset_ctl); if (ret) { @@ -56,6 +66,22 @@ static int stm32_copro_probe(struct udevice *dev) return 0; } +/** + * stm32_copro_optee_remove() - Close the rproc trusted application session + * @dev: corresponding STM32 remote processor device + * @return 0 if all went ok, else corresponding -ve error + */ +static int stm32_copro_remove(struct udevice *dev) +{ + struct stm32_copro_privdata *priv = dev_get_priv(dev); + struct rproc_optee *trproc = &priv->trproc; + + if (trproc->tee) + return rproc_optee_close(trproc); + + return 0; +} + /** * stm32_copro_device_to_virt() - Convert device address to virtual address * @dev: corresponding STM32 remote processor device @@ -93,11 +119,13 @@ static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da, */ static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) { - struct stm32_copro_privdata *priv; + struct stm32_copro_privdata *priv = dev_get_priv(dev); + struct rproc_optee *trproc = &priv->trproc; ulong rsc_table_size; int ret; - priv = dev_get_priv(dev); + if (trproc->tee) + return rproc_optee_load(trproc, addr, size); ret = reset_assert(&priv->hold_boot); if (ret) { @@ -127,25 +155,39 @@ static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) */ static int stm32_copro_start(struct udevice *dev) { - struct stm32_copro_privdata *priv; + struct stm32_copro_privdata *priv = dev_get_priv(dev); + struct rproc_optee *trproc = &priv->trproc; + phys_size_t rsc_size; int ret; - priv = dev_get_priv(dev); - - ret = reset_deassert(&priv->hold_boot); - if (ret) { - dev_err(dev, "Unable to deassert hold boot (ret=%d)\n", ret); - return ret; + if (trproc->tee) { + ret = rproc_optee_get_rsc_table(trproc, &priv->rsc_table_addr, + &rsc_size); + if (ret) + return ret; + + ret = rproc_optee_start(trproc); + if (ret) + return ret; + + } else { + ret = reset_deassert(&priv->hold_boot); + if (ret) { + dev_err(dev, "Unable to deassert hold boot (ret=%d)\n", + ret); + return ret; + } + + /* + * Once copro running, reset hold boot flag to avoid copro + * rebooting autonomously (error should never occur) + */ + ret = reset_assert(&priv->hold_boot); + if (ret) + dev_err(dev, "Unable to assert hold boot (ret=%d)\n", + ret); } - /* - * Once copro running, reset hold boot flag to avoid copro - * rebooting autonomously (error should never occur) - */ - ret = reset_assert(&priv->hold_boot); - if (ret) - dev_err(dev, "Unable to assert hold boot (ret=%d)\n", ret); - /* indicates that copro is running */ writel(TAMP_COPRO_STATE_CRUN, TAMP_COPRO_STATE); /* Store rsc_address in bkp register */ @@ -161,21 +203,29 @@ static int stm32_copro_start(struct udevice *dev) */ static int stm32_copro_reset(struct udevice *dev) { - struct stm32_copro_privdata *priv; + struct stm32_copro_privdata *priv = dev_get_priv(dev); + struct rproc_optee *trproc = &priv->trproc; int ret; - priv = dev_get_priv(dev); - - ret = reset_assert(&priv->hold_boot); - if (ret) { - dev_err(dev, "Unable to assert hold boot (ret=%d)\n", ret); - return ret; - } - ret = reset_assert(&priv->reset_ctl); - if (ret) { - dev_err(dev, "Unable to assert reset line (ret=%d)\n", ret); - return ret; + if (trproc->tee) { + ret = rproc_optee_stop(trproc); + if (ret) + return ret; + } else { + ret = reset_assert(&priv->hold_boot); + if (ret) { + dev_err(dev, "Unable to assert hold boot (ret=%d)\n", + ret); + return ret; + } + + ret = reset_assert(&priv->reset_ctl); + if (ret) { + dev_err(dev, "Unable to assert reset line (ret=%d)\n", + ret); + return ret; + } } writel(TAMP_COPRO_STATE_OFF, TAMP_COPRO_STATE); @@ -213,7 +263,7 @@ static const struct dm_rproc_ops stm32_copro_ops = { }; static const struct udevice_id stm32_copro_ids[] = { - {.compatible = "st,stm32mp1-m4"}, + { .compatible = "st,stm32mp1-m4", .data = STM32MP15_M4_FW_ID }, {} }; @@ -223,5 +273,7 @@ U_BOOT_DRIVER(stm32_copro) = { .id = UCLASS_REMOTEPROC, .ops = &stm32_copro_ops, .probe = stm32_copro_probe, - .priv_auto = sizeof(struct stm32_copro_privdata), + .remove = stm32_copro_remove, + .priv_auto = sizeof(struct stm32_copro_privdata), + .flags = DM_FLAG_OS_PREPARE, }; diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c index 1bff8075ee..850cb18886 100644 --- a/drivers/reset/reset-scmi.c +++ b/drivers/reset/reset-scmi.c @@ -2,6 +2,9 @@ /* * Copyright (C) 2019-2020 Linaro Limited */ + +#define LOG_CATEGORY UCLASS_RESET + #include #include #include @@ -23,7 +26,7 @@ static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert) in, out); int ret; - ret = devm_scmi_process_msg(rst->dev->parent, &msg); + ret = devm_scmi_process_msg(rst->dev, &msg); if (ret) return ret; @@ -55,7 +58,7 @@ static int scmi_reset_request(struct reset_ctl *rst) * We don't really care about the attribute, just check * the reset domain exists. */ - ret = devm_scmi_process_msg(rst->dev->parent, &msg); + ret = devm_scmi_process_msg(rst->dev, &msg); if (ret) return ret; diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig index 94915d45b3..34fb9993f2 100644 --- a/drivers/rng/Kconfig +++ b/drivers/rng/Kconfig @@ -31,6 +31,15 @@ config RNG_MSM This driver provides support for the Random Number Generator hardware found on Qualcomm SoCs. +config RNG_OPTEE + bool "OP-TEE based Random Number Generator support" + depends on DM_RNG && OPTEE + help + This driver provides support for the OP-TEE based Random Number + Generator on ARM SoCs where hardware entropy sources are not + accessible to normal world but reserved and used by the OP-TEE + to avoid the weakness of a software PRNG. + config RNG_STM32MP1 bool "Enable random number generator for STM32MP1" depends on ARCH_STM32MP diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile index 39f7ee3f03..435b3b965a 100644 --- a/drivers/rng/Makefile +++ b/drivers/rng/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_DM_RNG) += rng-uclass.o obj-$(CONFIG_RNG_MESON) += meson-rng.o obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o obj-$(CONFIG_RNG_MSM) += msm_rng.o +obj-$(CONFIG_RNG_OPTEE) += optee_rng.o obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o obj-$(CONFIG_RNG_IPROC200) += iproc_rng200.o diff --git a/drivers/rng/optee_rng.c b/drivers/rng/optee_rng.c new file mode 100644 index 0000000000..aa8ce864d3 --- /dev/null +++ b/drivers/rng/optee_rng.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + */ +#define LOG_CATEGORY UCLASS_RNG + +#include + +#include +#include +#include +#include +#include + +#define TEE_ERROR_HEALTH_TEST_FAIL 0x00000001 + +/* + * TA_CMD_GET_ENTROPY - Get Entropy from RNG + * + * param[0] (inout memref) - Entropy buffer memory reference + * param[1] unused + * param[2] unused + * param[3] unused + * + * Result: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_NOT_SUPPORTED - Requested entropy size greater than size of pool + * TEE_ERROR_HEALTH_TEST_FAIL - Continuous health testing failed + */ +#define TA_CMD_GET_ENTROPY 0x0 + +#define MAX_ENTROPY_REQ_SZ SZ_4K + +#define TA_HWRNG_UUID { 0xab7a617c, 0xb8e7, 0x4d8f, \ + { 0x83, 0x01, 0xd0, 0x9b, 0x61, 0x03, 0x6b, 0x64 } } + +/** open_session_ta_hwrng() - Open session with hwrng Trusted App + * + * @dev: device + * @session_id: return the RNG TA session identifier + * Return: 0 if ok + */ +static int open_session_ta_hwrng(struct udevice *dev, u32 *session_id) +{ + const struct tee_optee_ta_uuid uuid = TA_HWRNG_UUID; + struct tee_open_session_arg sess_arg = {0}; + int ret; + + /* Open session with hwrng Trusted App */ + tee_optee_ta_uuid_to_octets(sess_arg.uuid, &uuid); + sess_arg.clnt_login = TEE_LOGIN_PUBLIC; + + ret = tee_open_session(dev->parent, &sess_arg, 0, NULL); + if (ret || sess_arg.ret) { + if (!ret) + ret = -EIO; + return ret; + } + + *session_id = sess_arg.session; + return 0; +} + +/** + * get_optee_rng_data() - read RNG data from OP-TEE TA + * + * @dev: device + * @session_id: the RNG TA session identifier + * @entropy_shm_pool: shared memory pool used for TEE message + * @buf: buffer to receive data + * @size: size of buffer, limited by entropy_shm_pool size + * Return: 0 if ok + */ +static int get_optee_rng_data(struct udevice *dev, u32 session_id, + struct tee_shm *entropy_shm_pool, + void *buf, size_t *size) +{ + int ret = 0; + struct tee_invoke_arg arg = {0}; + struct tee_param param = {0}; + + /* Invoke TA_CMD_GET_ENTROPY function of Trusted App */ + arg.func = TA_CMD_GET_ENTROPY; + arg.session = session_id; + + /* Fill invoke cmd params */ + param.attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT; + param.u.memref.shm = entropy_shm_pool; + param.u.memref.size = *size; + + ret = tee_invoke_func(dev->parent, &arg, 1, ¶m); + if (ret || arg.ret) { + if (!ret) + ret = -EPROTO; + dev_err(dev, "TA_CMD_GET_ENTROPY invoke err: %d 0x%x\n", ret, arg.ret); + *size = 0; + + return ret; + } + + memcpy(buf, param.u.memref.shm->addr, param.u.memref.size); + *size = param.u.memref.size; + + return 0; +} + +/** + * optee_rng_read() - rng read ops for OP-TEE RNG device + * + * @dev: device + * @buf: buffer to receive data + * @len: size of buffer + * Return: 0 if ok + */ +static int optee_rng_read(struct udevice *dev, void *buf, size_t len) +{ + size_t read = 0, rng_size = 0; + struct tee_shm *entropy_shm_pool; + u8 *data = buf; + int ret; + u32 session_id = 0; + + ret = open_session_ta_hwrng(dev, &session_id); + if (ret) { + dev_err(dev, "can't open session: %d\n", ret); + return ret; + } + + ret = tee_shm_alloc(dev->parent, MAX_ENTROPY_REQ_SZ, 0, &entropy_shm_pool); + if (ret) { + dev_err(dev, "tee_shm_alloc failed: %d\n", ret); + goto session_close; + } + + while (read < len) { + rng_size = min(len - read, (size_t)MAX_ENTROPY_REQ_SZ); + ret = get_optee_rng_data(dev, session_id, entropy_shm_pool, data, &rng_size); + if (ret) + goto shm_free; + data += rng_size; + read += rng_size; + } + +shm_free: + tee_shm_free(entropy_shm_pool); + +session_close: + tee_close_session(dev->parent, session_id); + + return ret; +} + +/** + * optee_rng_probe() - probe function for OP-TEE RNG device + * + * @dev: device + * Return: 0 if ok + */ +static int optee_rng_probe(struct udevice *dev) +{ + int ret; + u32 session_id; + + ret = open_session_ta_hwrng(dev, &session_id); + if (ret) { + dev_err(dev, "can't open session: %d\n", ret); + return ret; + } + tee_close_session(dev->parent, session_id); + + return 0; +} + +static const struct dm_rng_ops optee_rng_ops = { + .read = optee_rng_read, +}; + +U_BOOT_DRIVER(optee_rng) = { + .name = "optee-rng", + .id = UCLASS_RNG, + .ops = &optee_rng_ops, + .probe = optee_rng_probe, +}; diff --git a/drivers/rng/stm32mp1_rng.c b/drivers/rng/stm32mp1_rng.c index 8ea00e3e89..89da78c6c8 100644 --- a/drivers/rng/stm32mp1_rng.c +++ b/drivers/rng/stm32mp1_rng.c @@ -18,22 +18,28 @@ #include #include -#define RNG_CR 0x00 -#define RNG_CR_RNGEN BIT(2) -#define RNG_CR_CED BIT(5) +#define RNG_CR 0x00 +#define RNG_CR_RNGEN BIT(2) +#define RNG_CR_CED BIT(5) +#define RNG_CR_CONDRST BIT(30) -#define RNG_SR 0x04 -#define RNG_SR_SEIS BIT(6) -#define RNG_SR_CEIS BIT(5) -#define RNG_SR_SECS BIT(2) -#define RNG_SR_DRDY BIT(0) +#define RNG_SR 0x04 +#define RNG_SR_SEIS BIT(6) +#define RNG_SR_CEIS BIT(5) +#define RNG_SR_SECS BIT(2) +#define RNG_SR_DRDY BIT(0) -#define RNG_DR 0x08 +#define RNG_DR 0x08 + +struct stm32_rng_data { + bool has_cond_reset; +}; struct stm32_rng_plat { fdt_addr_t base; struct clk clk; struct reset_ctl rst; + const struct stm32_rng_data *data; }; static int stm32_rng_read(struct udevice *dev, void *data, size_t len) @@ -83,18 +89,36 @@ static int stm32_rng_read(struct udevice *dev, void *data, size_t len) static int stm32_rng_init(struct stm32_rng_plat *pdata) { int err; + u32 cr, sr; err = clk_enable(&pdata->clk); if (err) return err; + cr = readl(pdata->base + RNG_CR); + /* Disable CED */ - writel(RNG_CR_RNGEN | RNG_CR_CED, pdata->base + RNG_CR); + cr |= RNG_CR_CED; + if (pdata->data->has_cond_reset) { + cr |= RNG_CR_CONDRST; + writel(cr, pdata->base + RNG_CR); + cr &= ~RNG_CR_CONDRST; + writel(cr, pdata->base + RNG_CR); + err = readl_poll_timeout(pdata->base + RNG_CR, cr, + (!(cr & RNG_CR_CONDRST)), 10000); + if (err) + return err; + } /* clear error indicators */ writel(0, pdata->base + RNG_SR); - return 0; + cr |= RNG_CR_RNGEN; + writel(cr, pdata->base + RNG_CR); + + err = readl_poll_timeout(pdata->base + RNG_SR, sr, + sr & RNG_SR_DRDY, 10000); + return err; } static int stm32_rng_cleanup(struct stm32_rng_plat *pdata) @@ -108,6 +132,8 @@ static int stm32_rng_probe(struct udevice *dev) { struct stm32_rng_plat *pdata = dev_get_plat(dev); + pdata->data = (struct stm32_rng_data *)dev_get_driver_data(dev); + reset_assert(&pdata->rst); udelay(20); reset_deassert(&pdata->rst); @@ -146,10 +172,17 @@ static const struct dm_rng_ops stm32_rng_ops = { .read = stm32_rng_read, }; +static const struct stm32_rng_data stm32mp13_rng_data = { + .has_cond_reset = true, +}; + +static const struct stm32_rng_data stm32_rng_data = { + .has_cond_reset = false, +}; + static const struct udevice_id stm32_rng_match[] = { - { - .compatible = "st,stm32-rng", - }, + {.compatible = "st,stm32mp13-rng", .data = (ulong)&stm32mp13_rng_data}, + {.compatible = "st,stm32-rng", .data = (ulong)&stm32_rng_data}, {}, }; diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 8171b17faf..01387c1119 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -69,7 +69,7 @@ static int serial_check_stdout(const void *blob, struct udevice **devp) * anyway. */ if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node), - devp, false)) { + devp, NULL, false)) { if (!device_probe(*devp)) return 0; } diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index d867b27806..ee30110b56 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -391,8 +391,6 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, } else if (ret) { dev_err(bus, "Invalid chip select %d:%d (err=%d)\n", busnum, cs, ret); return ret; - } else if (dev) { - plat = dev_get_parent_plat(dev); } if (!device_active(dev)) { @@ -418,22 +416,12 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, goto err; } - /* In case bus frequency or mode changed, update it. */ - if ((speed && bus_data->speed && bus_data->speed != speed) || - (plat && plat->mode != mode)) { - ret = spi_set_speed_mode(bus, speed, mode); - if (ret) - goto err_speed_mode; - } - *busp = bus; *devp = slave; log_debug("%s: bus=%p, slave=%p\n", __func__, bus, *devp); return 0; -err_speed_mode: - spi_release_bus(slave); err: log_debug("%s: Error path, created=%d, device '%s'\n", __func__, created, dev->name); diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c index 8f4aabc3d1..ceba413727 100644 --- a/drivers/spi/stm32_qspi.c +++ b/drivers/spi/stm32_qspi.c @@ -150,20 +150,19 @@ static int _stm32_qspi_wait_cmd(struct stm32_qspi_priv *priv, u32 sr; int ret = 0; - if (op->data.nbytes) { - ret = readl_poll_timeout(&priv->regs->sr, sr, - sr & STM32_QSPI_SR_TCF, - STM32_QSPI_CMD_TIMEOUT_US); - if (ret) { - log_err("cmd timeout (stat:%#x)\n", sr); - } else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) { - log_err("transfer error (stat:%#x)\n", sr); - ret = -EIO; - } - /* clear flags */ - writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr); + ret = readl_poll_timeout(&priv->regs->sr, sr, + sr & STM32_QSPI_SR_TCF, + STM32_QSPI_CMD_TIMEOUT_US); + if (ret) { + log_err("cmd timeout (stat:%#x)\n", sr); + } else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) { + log_err("transfer error (stat:%#x)\n", sr); + ret = -EIO; } + /* clear flags */ + writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr); + if (!ret) ret = _stm32_qspi_wait_for_not_busy(priv); @@ -256,10 +255,6 @@ static int stm32_qspi_exec_op(struct spi_slave *slave, op->dummy.buswidth, op->data.buswidth, op->addr.val, op->data.nbytes); - ret = _stm32_qspi_wait_for_not_busy(priv); - if (ret) - return ret; - addr_max = op->addr.val + op->data.nbytes + 1; if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) { diff --git a/drivers/spi/stm32_spi.c b/drivers/spi/stm32_spi.c index bd8514033d..fe5419e851 100644 --- a/drivers/spi/stm32_spi.c +++ b/drivers/spi/stm32_spi.c @@ -97,11 +97,14 @@ #define SPI_SIMPLEX_RX 2 #define SPI_HALF_DUPLEX 3 -struct stm32_spi_priv { +struct stm32_spi_plat { void __iomem *base; struct clk clk; struct reset_ctl rst_ctl; struct gpio_desc cs_gpios[MAX_CS_COUNT]; +}; + +struct stm32_spi_priv { ulong bus_clk_rate; unsigned int fifo_size; unsigned int cur_bpw; @@ -115,28 +118,32 @@ struct stm32_spi_priv { bool cs_high; }; -static void stm32_spi_write_txfifo(struct stm32_spi_priv *priv) +static void stm32_spi_write_txfifo(struct udevice *bus) { + struct stm32_spi_priv *priv = dev_get_priv(bus); + struct stm32_spi_plat *plat = dev_get_plat(bus); + void __iomem *base = plat->base; + while ((priv->tx_len > 0) && - (readl(priv->base + STM32_SPI_SR) & SPI_SR_TXP)) { + (readl(base + STM32_SPI_SR) & SPI_SR_TXP)) { u32 offs = priv->cur_xferlen - priv->tx_len; if (priv->tx_len >= sizeof(u32) && IS_ALIGNED((uintptr_t)(priv->tx_buf + offs), sizeof(u32))) { const u32 *tx_buf32 = (const u32 *)(priv->tx_buf + offs); - writel(*tx_buf32, priv->base + STM32_SPI_TXDR); + writel(*tx_buf32, base + STM32_SPI_TXDR); priv->tx_len -= sizeof(u32); } else if (priv->tx_len >= sizeof(u16) && IS_ALIGNED((uintptr_t)(priv->tx_buf + offs), sizeof(u16))) { const u16 *tx_buf16 = (const u16 *)(priv->tx_buf + offs); - writew(*tx_buf16, priv->base + STM32_SPI_TXDR); + writew(*tx_buf16, base + STM32_SPI_TXDR); priv->tx_len -= sizeof(u16); } else { const u8 *tx_buf8 = (const u8 *)(priv->tx_buf + offs); - writeb(*tx_buf8, priv->base + STM32_SPI_TXDR); + writeb(*tx_buf8, base + STM32_SPI_TXDR); priv->tx_len -= sizeof(u8); } } @@ -144,9 +151,12 @@ static void stm32_spi_write_txfifo(struct stm32_spi_priv *priv) log_debug("%d bytes left\n", priv->tx_len); } -static void stm32_spi_read_rxfifo(struct stm32_spi_priv *priv) +static void stm32_spi_read_rxfifo(struct udevice *bus) { - u32 sr = readl(priv->base + STM32_SPI_SR); + struct stm32_spi_priv *priv = dev_get_priv(bus); + struct stm32_spi_plat *plat = dev_get_plat(bus); + void __iomem *base = plat->base; + u32 sr = readl(base + STM32_SPI_SR); u32 rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT; while ((priv->rx_len > 0) && @@ -158,7 +168,7 @@ static void stm32_spi_read_rxfifo(struct stm32_spi_priv *priv) (priv->rx_len >= sizeof(u32) || (sr & SPI_SR_RXWNE))) { u32 *rx_buf32 = (u32 *)(priv->rx_buf + offs); - *rx_buf32 = readl(priv->base + STM32_SPI_RXDR); + *rx_buf32 = readl(base + STM32_SPI_RXDR); priv->rx_len -= sizeof(u32); } else if (IS_ALIGNED((uintptr_t)(priv->rx_buf + offs), sizeof(u16)) && (priv->rx_len >= sizeof(u16) || @@ -166,38 +176,38 @@ static void stm32_spi_read_rxfifo(struct stm32_spi_priv *priv) (rxplvl >= 2 || priv->cur_bpw > 8)))) { u16 *rx_buf16 = (u16 *)(priv->rx_buf + offs); - *rx_buf16 = readw(priv->base + STM32_SPI_RXDR); + *rx_buf16 = readw(base + STM32_SPI_RXDR); priv->rx_len -= sizeof(u16); } else { u8 *rx_buf8 = (u8 *)(priv->rx_buf + offs); - *rx_buf8 = readb(priv->base + STM32_SPI_RXDR); + *rx_buf8 = readb(base + STM32_SPI_RXDR); priv->rx_len -= sizeof(u8); } - sr = readl(priv->base + STM32_SPI_SR); + sr = readl(base + STM32_SPI_SR); rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT; } log_debug("%d bytes left\n", priv->rx_len); } -static int stm32_spi_enable(struct stm32_spi_priv *priv) +static int stm32_spi_enable(void __iomem *base) { log_debug("\n"); /* Enable the SPI hardware */ - setbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_SPE); + setbits_le32(base + STM32_SPI_CR1, SPI_CR1_SPE); return 0; } -static int stm32_spi_disable(struct stm32_spi_priv *priv) +static int stm32_spi_disable(void __iomem *base) { log_debug("\n"); /* Disable the SPI hardware */ - clrbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_SPE); + clrbits_le32(base + STM32_SPI_CR1, SPI_CR1_SPE); return 0; } @@ -205,45 +215,48 @@ static int stm32_spi_disable(struct stm32_spi_priv *priv) static int stm32_spi_claim_bus(struct udevice *slave) { struct udevice *bus = dev_get_parent(slave); - struct stm32_spi_priv *priv = dev_get_priv(bus); + struct stm32_spi_plat *plat = dev_get_plat(bus); + void __iomem *base = plat->base; dev_dbg(slave, "\n"); /* Enable the SPI hardware */ - return stm32_spi_enable(priv); + return stm32_spi_enable(base); } static int stm32_spi_release_bus(struct udevice *slave) { struct udevice *bus = dev_get_parent(slave); - struct stm32_spi_priv *priv = dev_get_priv(bus); + struct stm32_spi_plat *plat = dev_get_plat(bus); + void __iomem *base = plat->base; dev_dbg(slave, "\n"); /* Disable the SPI hardware */ - return stm32_spi_disable(priv); + return stm32_spi_disable(base); } static void stm32_spi_stopxfer(struct udevice *dev) { - struct stm32_spi_priv *priv = dev_get_priv(dev); + struct stm32_spi_plat *plat = dev_get_plat(dev); + void __iomem *base = plat->base; u32 cr1, sr; int ret; dev_dbg(dev, "\n"); - cr1 = readl(priv->base + STM32_SPI_CR1); + cr1 = readl(base + STM32_SPI_CR1); if (!(cr1 & SPI_CR1_SPE)) return; /* Wait on EOT or suspend the flow */ - ret = readl_poll_timeout(priv->base + STM32_SPI_SR, sr, + ret = readl_poll_timeout(base + STM32_SPI_SR, sr, !(sr & SPI_SR_EOT), 100000); if (ret < 0) { if (cr1 & SPI_CR1_CSTART) { - writel(cr1 | SPI_CR1_CSUSP, priv->base + STM32_SPI_CR1); - if (readl_poll_timeout(priv->base + STM32_SPI_SR, + writel(cr1 | SPI_CR1_CSUSP, base + STM32_SPI_CR1); + if (readl_poll_timeout(base + STM32_SPI_SR, sr, !(sr & SPI_SR_SUSP), 100000) < 0) dev_err(dev, "Suspend request timeout\n"); @@ -251,11 +264,12 @@ static void stm32_spi_stopxfer(struct udevice *dev) } /* clear status flags */ - setbits_le32(priv->base + STM32_SPI_IFCR, SPI_IFCR_ALL); + setbits_le32(base + STM32_SPI_IFCR, SPI_IFCR_ALL); } static int stm32_spi_set_cs(struct udevice *dev, unsigned int cs, bool enable) { + struct stm32_spi_plat *plat = dev_get_plat(dev); struct stm32_spi_priv *priv = dev_get_priv(dev); dev_dbg(dev, "cs=%d enable=%d\n", cs, enable); @@ -263,18 +277,20 @@ static int stm32_spi_set_cs(struct udevice *dev, unsigned int cs, bool enable) if (cs >= MAX_CS_COUNT) return -ENODEV; - if (!dm_gpio_is_valid(&priv->cs_gpios[cs])) + if (!dm_gpio_is_valid(&plat->cs_gpios[cs])) return -EINVAL; if (priv->cs_high) enable = !enable; - return dm_gpio_set_value(&priv->cs_gpios[cs], enable ? 1 : 0); + return dm_gpio_set_value(&plat->cs_gpios[cs], enable ? 1 : 0); } static int stm32_spi_set_mode(struct udevice *bus, uint mode) { struct stm32_spi_priv *priv = dev_get_priv(bus); + struct stm32_spi_plat *plat = dev_get_plat(bus); + void __iomem *base = plat->base; u32 cfg2_clrb = 0, cfg2_setb = 0; dev_dbg(bus, "mode=%d\n", mode); @@ -295,7 +311,7 @@ static int stm32_spi_set_mode(struct udevice *bus, uint mode) cfg2_clrb |= SPI_CFG2_LSBFRST; if (cfg2_clrb || cfg2_setb) - clrsetbits_le32(priv->base + STM32_SPI_CFG2, + clrsetbits_le32(base + STM32_SPI_CFG2, cfg2_clrb, cfg2_setb); if (mode & SPI_CS_HIGH) @@ -308,6 +324,8 @@ static int stm32_spi_set_mode(struct udevice *bus, uint mode) static int stm32_spi_set_fthlv(struct udevice *dev, u32 xfer_len) { struct stm32_spi_priv *priv = dev_get_priv(dev); + struct stm32_spi_plat *plat = dev_get_plat(dev); + void __iomem *base = plat->base; u32 fthlv, half_fifo; /* data packet should not exceed 1/2 of fifo space */ @@ -321,7 +339,7 @@ static int stm32_spi_set_fthlv(struct udevice *dev, u32 xfer_len) if (!fthlv) fthlv = 1; - clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_FTHLV, + clrsetbits_le32(base + STM32_SPI_CFG1, SPI_CFG1_FTHLV, (fthlv - 1) << SPI_CFG1_FTHLV_SHIFT); return 0; @@ -330,6 +348,8 @@ static int stm32_spi_set_fthlv(struct udevice *dev, u32 xfer_len) static int stm32_spi_set_speed(struct udevice *bus, uint hz) { struct stm32_spi_priv *priv = dev_get_priv(bus); + struct stm32_spi_plat *plat = dev_get_plat(bus); + void __iomem *base = plat->base; u32 mbrdiv; long div; @@ -353,7 +373,7 @@ static int stm32_spi_set_speed(struct udevice *bus, uint hz) if (!mbrdiv) return -EINVAL; - clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_MBR, + clrsetbits_le32(base + STM32_SPI_CFG1, SPI_CFG1_MBR, (mbrdiv - 1) << SPI_CFG1_MBR_SHIFT); priv->cur_hz = hz; @@ -367,6 +387,8 @@ static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen, struct udevice *bus = dev_get_parent(slave); struct dm_spi_slave_plat *slave_plat; struct stm32_spi_priv *priv = dev_get_priv(bus); + struct stm32_spi_plat *plat = dev_get_plat(bus); + void __iomem *base = plat->base; u32 sr; u32 ifcr = 0; u32 xferlen; @@ -376,7 +398,7 @@ static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen, xferlen = bitlen / 8; if (xferlen <= SPI_CR2_TSIZE) - writel(xferlen, priv->base + STM32_SPI_CR2); + writel(xferlen, base + STM32_SPI_CR2); else return -EMSGSIZE; @@ -396,15 +418,15 @@ static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen, priv->cur_xferlen = xferlen; /* Disable the SPI hardware to unlock CFG1/CFG2 registers */ - stm32_spi_disable(priv); + stm32_spi_disable(base); - clrsetbits_le32(priv->base + STM32_SPI_CFG2, SPI_CFG2_COMM, + clrsetbits_le32(base + STM32_SPI_CFG2, SPI_CFG2_COMM, mode << SPI_CFG2_COMM_SHIFT); stm32_spi_set_fthlv(bus, xferlen); /* Enable the SPI hardware */ - stm32_spi_enable(priv); + stm32_spi_enable(base); } dev_dbg(bus, "priv->tx_len=%d priv->rx_len=%d\n", @@ -416,12 +438,12 @@ static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen, /* Be sure to have data in fifo before starting data transfer */ if (priv->tx_buf) - stm32_spi_write_txfifo(priv); + stm32_spi_write_txfifo(bus); - setbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_CSTART); + setbits_le32(base + STM32_SPI_CR1, SPI_CR1_CSTART); while (1) { - sr = readl(priv->base + STM32_SPI_SR); + sr = readl(base + STM32_SPI_SR); if (sr & SPI_SR_OVR) { dev_err(bus, "Overrun: RX data lost\n"); @@ -433,7 +455,7 @@ static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen, dev_warn(bus, "System too slow is limiting data throughput\n"); if (priv->rx_buf && priv->rx_len > 0) - stm32_spi_read_rxfifo(priv); + stm32_spi_read_rxfifo(bus); ifcr |= SPI_SR_SUSP; } @@ -443,23 +465,23 @@ static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen, if (sr & SPI_SR_TXP) if (priv->tx_buf && priv->tx_len > 0) - stm32_spi_write_txfifo(priv); + stm32_spi_write_txfifo(bus); if (sr & SPI_SR_RXP) if (priv->rx_buf && priv->rx_len > 0) - stm32_spi_read_rxfifo(priv); + stm32_spi_read_rxfifo(bus); if (sr & SPI_SR_EOT) { if (priv->rx_buf && priv->rx_len > 0) - stm32_spi_read_rxfifo(priv); + stm32_spi_read_rxfifo(bus); break; } - writel(ifcr, priv->base + STM32_SPI_IFCR); + writel(ifcr, base + STM32_SPI_IFCR); } /* clear status flags */ - setbits_le32(priv->base + STM32_SPI_IFCR, SPI_IFCR_ALL); + setbits_le32(base + STM32_SPI_IFCR, SPI_IFCR_ALL); stm32_spi_stopxfer(bus); if (flags & SPI_XFER_END) @@ -470,42 +492,72 @@ static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen, static int stm32_spi_get_fifo_size(struct udevice *dev) { - struct stm32_spi_priv *priv = dev_get_priv(dev); + struct stm32_spi_plat *plat = dev_get_plat(dev); + void __iomem *base = plat->base; u32 count = 0; - stm32_spi_enable(priv); + stm32_spi_enable(base); - while (readl(priv->base + STM32_SPI_SR) & SPI_SR_TXP) - writeb(++count, priv->base + STM32_SPI_TXDR); + while (readl(base + STM32_SPI_SR) & SPI_SR_TXP) + writeb(++count, base + STM32_SPI_TXDR); - stm32_spi_disable(priv); + stm32_spi_disable(base); dev_dbg(dev, "%d x 8-bit fifo size\n", count); return count; } +static int stm32_spi_of_to_plat(struct udevice *dev) +{ + struct stm32_spi_plat *plat = dev_get_plat(dev); + int ret; + + plat->base = dev_read_addr_ptr(dev); + if (!plat->base) { + dev_err(dev, "can't get registers base address\n"); + return -ENOENT; + } + + ret = clk_get_by_index(dev, 0, &plat->clk); + if (ret < 0) + return ret; + + ret = reset_get_by_index(dev, 0, &plat->rst_ctl); + if (ret < 0) + goto clk_err; + + ret = gpio_request_list_by_name(dev, "cs-gpios", plat->cs_gpios, + ARRAY_SIZE(plat->cs_gpios), 0); + if (ret < 0) { + dev_err(dev, "Can't get %s cs gpios: %d", dev->name, ret); + ret = -ENOENT; + goto clk_err; + } + + return 0; + +clk_err: + clk_free(&plat->clk); + + return ret; +} + static int stm32_spi_probe(struct udevice *dev) { + struct stm32_spi_plat *plat = dev_get_plat(dev); struct stm32_spi_priv *priv = dev_get_priv(dev); + void __iomem *base = plat->base; unsigned long clk_rate; int ret; unsigned int i; - priv->base = dev_remap_addr(dev); - if (!priv->base) - return -EINVAL; - /* enable clock */ - ret = clk_get_by_index(dev, 0, &priv->clk); + ret = clk_enable(&plat->clk); if (ret < 0) return ret; - ret = clk_enable(&priv->clk); - if (ret < 0) - return ret; - - clk_rate = clk_get_rate(&priv->clk); + clk_rate = clk_get_rate(&plat->clk); if (!clk_rate) { ret = -EINVAL; goto clk_err; @@ -514,46 +566,34 @@ static int stm32_spi_probe(struct udevice *dev) priv->bus_clk_rate = clk_rate; /* perform reset */ - ret = reset_get_by_index(dev, 0, &priv->rst_ctl); - if (ret < 0) - goto clk_err; - - reset_assert(&priv->rst_ctl); + reset_assert(&plat->rst_ctl); udelay(2); - reset_deassert(&priv->rst_ctl); - - ret = gpio_request_list_by_name(dev, "cs-gpios", priv->cs_gpios, - ARRAY_SIZE(priv->cs_gpios), 0); - if (ret < 0) { - dev_err(dev, "Can't get cs gpios: %d", ret); - goto reset_err; - } + reset_deassert(&plat->rst_ctl); priv->fifo_size = stm32_spi_get_fifo_size(dev); - priv->cur_mode = SPI_FULL_DUPLEX; priv->cur_xferlen = 0; priv->cur_bpw = SPI_DEFAULT_WORDLEN; - clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_DSIZE, + clrsetbits_le32(base + STM32_SPI_CFG1, SPI_CFG1_DSIZE, priv->cur_bpw - 1); - for (i = 0; i < ARRAY_SIZE(priv->cs_gpios); i++) { - if (!dm_gpio_is_valid(&priv->cs_gpios[i])) + for (i = 0; i < ARRAY_SIZE(plat->cs_gpios); i++) { + if (!dm_gpio_is_valid(&plat->cs_gpios[i])) continue; - dm_gpio_set_dir_flags(&priv->cs_gpios[i], + dm_gpio_set_dir_flags(&plat->cs_gpios[i], GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); } /* Ensure I2SMOD bit is kept cleared */ - clrbits_le32(priv->base + STM32_SPI_I2SCFGR, SPI_I2SCFGR_I2SMOD); + clrbits_le32(base + STM32_SPI_I2SCFGR, SPI_I2SCFGR_I2SMOD); /* * - SS input value high * - transmitter half duplex direction * - automatic communication suspend when RX-Fifo is full */ - setbits_le32(priv->base + STM32_SPI_CR1, + setbits_le32(base + STM32_SPI_CR1, SPI_CR1_SSI | SPI_CR1_HDDIR | SPI_CR1_MASRX); /* @@ -562,40 +602,38 @@ static int stm32_spi_probe(struct udevice *dev) * SS input value is determined by the SSI bit * - keep control of all associated GPIOs */ - setbits_le32(priv->base + STM32_SPI_CFG2, + setbits_le32(base + STM32_SPI_CFG2, SPI_CFG2_MASTER | SPI_CFG2_SSM | SPI_CFG2_AFCNTR); return 0; -reset_err: - reset_free(&priv->rst_ctl); - clk_err: - clk_disable(&priv->clk); - clk_free(&priv->clk); + clk_disable(&plat->clk); + clk_free(&plat->clk); return ret; }; static int stm32_spi_remove(struct udevice *dev) { - struct stm32_spi_priv *priv = dev_get_priv(dev); + struct stm32_spi_plat *plat = dev_get_plat(dev); + void __iomem *base = plat->base; int ret; stm32_spi_stopxfer(dev); - stm32_spi_disable(priv); + stm32_spi_disable(base); - ret = reset_assert(&priv->rst_ctl); + ret = reset_assert(&plat->rst_ctl); if (ret < 0) return ret; - reset_free(&priv->rst_ctl); + reset_free(&plat->rst_ctl); - ret = clk_disable(&priv->clk); + ret = clk_disable(&plat->clk); if (ret < 0) return ret; - clk_free(&priv->clk); + clk_free(&plat->clk); return ret; }; @@ -618,7 +656,9 @@ U_BOOT_DRIVER(stm32_spi) = { .id = UCLASS_SPI, .of_match = stm32_spi_ids, .ops = &stm32_spi_ops, - .priv_auto = sizeof(struct stm32_spi_priv), + .of_to_plat = stm32_spi_of_to_plat, + .plat_auto = sizeof(struct stm32_spi_plat), + .priv_auto = sizeof(struct stm32_spi_priv), .probe = stm32_spi_probe, .remove = stm32_spi_remove, }; diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index dad46aa388..a89d62aaf0 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -641,6 +642,8 @@ static int optee_probe(struct udevice *dev) { struct optee_pdata *pdata = dev_get_plat(dev); u32 sec_caps; + struct udevice *child; + int ret; if (!is_optee_api(pdata->invoke_fn)) { dev_err(dev, "OP-TEE api uid mismatch\n"); @@ -665,6 +668,16 @@ static int optee_probe(struct udevice *dev) return -ENOENT; } + /* + * in U-Boot, the discovery of TA on the TEE bus is not supported: + * only bind the drivers associated to the supported OP-TEE TA + */ + if (IS_ENABLED(CONFIG_RNG_OPTEE)) { + ret = device_bind_driver(dev, "optee-rng", "optee-rng", &child); + if (ret) + return ret; + } + return 0; } diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h index 8d40ce60c2..a8ef926a48 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -86,16 +86,6 @@ #define OPTEE_MSG_ATTR_CACHE_MASK GENMASK(2, 0) #define OPTEE_MSG_ATTR_CACHE_PREDEFINED 0 -/* - * Same values as TEE_LOGIN_* from TEE Internal API - */ -#define OPTEE_MSG_LOGIN_PUBLIC 0x00000000 -#define OPTEE_MSG_LOGIN_USER 0x00000001 -#define OPTEE_MSG_LOGIN_GROUP 0x00000002 -#define OPTEE_MSG_LOGIN_APPLICATION 0x00000004 -#define OPTEE_MSG_LOGIN_APPLICATION_USER 0x00000005 -#define OPTEE_MSG_LOGIN_APPLICATION_GROUP 0x00000006 - /* * Page size used in non-contiguous buffer entries */ @@ -279,7 +269,7 @@ struct optee_msg_arg { * parameters to pass the following information: * param[0].u.value.a-b uuid of Trusted Application * param[1].u.value.a-b uuid of Client - * param[1].u.value.c Login class of client OPTEE_MSG_LOGIN_* + * param[1].u.value.c Login class of client TEE_LOGIN_* * * OPTEE_MSG_CMD_INVOKE_COMMAND invokes a command a previously opened * session to a Trusted Application. struct optee_msg_arg::func is Trusted diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c index c8e8419b22..ebea168789 100644 --- a/drivers/timer/timer-uclass.c +++ b/drivers/timer/timer-uclass.c @@ -146,7 +146,7 @@ int notrace dm_timer_init(void) * If the timer is not marked to be bound before * relocation, bind it anyway. */ - if (!lists_bind_fdt(dm_root(), node, &dev, false)) { + if (!lists_bind_fdt(dm_root(), node, &dev, NULL, false)) { ret = device_probe(dev); if (ret) return ret; diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index ab1d061bd0..a362c96811 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -82,6 +82,8 @@ source "drivers/usb/emul/Kconfig" source "drivers/usb/phy/Kconfig" +source "drivers/usb/typec/Kconfig" + source "drivers/usb/ulpi/Kconfig" if USB_HOST diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 2f31814442..c96a3f248c 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -979,6 +980,7 @@ static void dwc2_phy_shutdown(struct udevice *dev, struct phy_bulk *phys) static int dwc2_udc_otg_of_to_plat(struct udevice *dev) { struct dwc2_plat_otg_data *plat = dev_get_plat(dev); + struct udevice *typec; ulong drvdata; void (*set_params)(struct dwc2_plat_otg_data *data); int ret; @@ -1006,11 +1008,20 @@ static int dwc2_udc_otg_of_to_plat(struct udevice *dev) return ret; } - plat->force_b_session_valid = - dev_read_bool(dev, "u-boot,force-b-session-valid"); - - plat->force_vbus_detection = - dev_read_bool(dev, "u-boot,force-vbus-detection"); + /* + * check for High speed port/endpoint subnode presence and retrieve Type-C + * device if exist. HS port subnode is always port number 0 => port@0 + */ + ret = typec_get_device_from_usb(dev, &typec, 0); + if (!ret) { + ret = typec_get_data_role(typec, 0); + plat->force_b_session_valid = (ret == TYPEC_DEVICE); + } else { + plat->force_b_session_valid = + dev_read_bool(dev, "u-boot,force-b-session-valid"); + plat->force_vbus_detection = + dev_read_bool(dev, "u-boot,force-vbus-detection"); + } /* force plat according compatible */ drvdata = dev_get_driver_data(dev); diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index 4bedc7d3a1..e9340ff5cb 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -336,6 +336,8 @@ static int state_dfu_idle(struct f_dfu *f_dfu, f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE; f_dfu->blk_seq_num = 0; value = handle_upload(req, len); + if (value >= 0 && value < len) + f_dfu->dfu_state = DFU_STATE_dfuIDLE; break; case USB_REQ_DFU_ABORT: /* no zlp? */ diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 0cdf47c2dd..06e6a48949 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -167,6 +167,12 @@ #define gadget_is_mtu3(g) 0 #endif +#ifdef CONFIG_USB_GADGET_DWC2_OTG +#define gadget_is_dwc2(g) (!strcmp("dwc2-udc", (g)->name)) +#else +#define gadget_is_dwc2(g) 0 +#endif + /** * usb_gadget_controller_number - support bcdDevice id convention * @gadget: the controller being driven @@ -232,5 +238,7 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x25; else if (gadget_is_mtu3(gadget)) return 0x26; + else if (gadget_is_dwc2(gadget)) + return 0x27; return -ENOENT; } diff --git a/drivers/usb/host/usb-sandbox.c b/drivers/usb/host/usb-sandbox.c index d7cc92aa54..d1103dcb2e 100644 --- a/drivers/usb/host/usb-sandbox.c +++ b/drivers/usb/host/usb-sandbox.c @@ -9,6 +9,13 @@ #include #include #include +#include + +struct sandbox_udc { + struct usb_gadget gadget; +}; + +struct sandbox_udc *this_controller; struct sandbox_usb_ctrl { int rootdev; @@ -117,6 +124,27 @@ static int sandbox_submit_int(struct udevice *bus, struct usb_device *udev, return ret; } +int usb_gadget_handle_interrupts(int index) +{ + return 0; +} + +int usb_gadget_register_driver(struct usb_gadget_driver *driver) +{ + struct sandbox_udc *dev = this_controller; + + return driver->bind(&dev->gadget); +} + +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +{ + struct sandbox_udc *dev = this_controller; + + driver->unbind(&dev->gadget); + + return 0; +} + static int sandbox_alloc_device(struct udevice *dev, struct usb_device *udev) { struct sandbox_usb_ctrl *ctrl = dev_get_priv(dev); diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig new file mode 100644 index 0000000000..c9930320ca --- /dev/null +++ b/drivers/usb/typec/Kconfig @@ -0,0 +1,24 @@ +menuconfig TYPEC + bool "USB Type-C support" + depends on DM + help + Enable this configurations option if you have USB Type-C connectors on + your system and 1) you know your USB Type-C hardware requires OS + control (a driver) to function, or 2) if you need to be able to read + the status of the USB Type-C ports in your system, or 3) if you need + to be able to swap the power role (decide are you supplying or + consuming power over the cable) or data role (host or device) when + both roles are supported. + +if TYPEC + +config TYPEC_STUSB160X + bool "STMicroelectronics STUSB160x Type-C controller driver" + depends on DM && DM_I2C + help + Say Y or M here if your system has STMicroelectronics STUSB160x + Type-C port controller. + +source "drivers/usb/typec/ucsi/Kconfig" + +endif diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile new file mode 100644 index 0000000000..e0b66ae8ef --- /dev/null +++ b/drivers/usb/typec/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-$(CONFIG_TYPEC) += typec-uclass.o +obj-$(CONFIG_TYPEC_STUSB160X) += typec-stusb160x.o +obj-$(CONFIG_TYPEC_UCSI) += ucsi/ diff --git a/drivers/usb/typec/typec-stusb160x.c b/drivers/usb/typec/typec-stusb160x.c new file mode 100644 index 0000000000..28e9bf1c74 --- /dev/null +++ b/drivers/usb/typec/typec-stusb160x.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + */ + +#define LOG_CATEGORY UCLASS_USB_TYPEC + +#include +#include +#include +#include +#include + +#define STUSB160X_ALERT_STATUS 0x0B /* RC */ +#define STUSB160X_CC_CONNECTION BIT(6) + +#define STUSB160X_CC_CONNECTION_STATUS_TRANS 0x0D /* RC */ +#define STUSB160X_CC_ATTACH_TRANS BIT(0) + +#define STUSB160X_CC_CONNECTION_STATUS 0x0E /* RO */ +#define STUSB160X_CC_ATTACH BIT(0) +#define STUSB160X_CC_DATA_ROLE BIT(2) + +#define STUSB160X_CC_POWER_MODE_CTRL 0x28 /* RW */ +#define STUSB160X_DUAL_WITH_ACCESSORY 3 + +struct stusb160x_priv { + enum typec_state attached; + enum typec_data_role data_role; +}; + +static int stusb160x_get_status(struct udevice *dev, bool force) +{ + struct stusb160x_priv *priv = dev_get_priv(dev); + int alert, trans, status; + + alert = dm_i2c_reg_read(dev, STUSB160X_ALERT_STATUS); + if (alert < 0) + return alert; + + /* If no update, exit */ + if ((!(alert & STUSB160X_CC_CONNECTION)) && !force) + goto exit; + + trans = dm_i2c_reg_read(dev, STUSB160X_CC_CONNECTION_STATUS_TRANS); + if (trans < 0) + return trans; + + status = dm_i2c_reg_read(dev, STUSB160X_CC_CONNECTION_STATUS); + if (status < 0) + return status; + + priv->data_role = status & STUSB160X_CC_DATA_ROLE ? TYPEC_HOST : TYPEC_DEVICE; + priv->attached = status & STUSB160X_CC_ATTACH ? TYPEC_ATTACHED : TYPEC_UNATTACHED; +exit: + dev_dbg(dev, "status: %s data role: %s\n", + priv->attached == TYPEC_ATTACHED ? "Attached" : "Unattached", + priv->data_role == TYPEC_HOST ? "Host" : "Device"); + + return 0; +} + +static int stusb160x_get_data_role(struct udevice *dev, u8 con_idx) +{ + struct stusb160x_priv *priv = dev_get_priv(dev); + int ret; + + ret = stusb160x_get_status(dev, false); + if (ret < 0) + return ret; + + return priv->data_role; +} + +static int stusb160x_is_attached(struct udevice *dev, u8 con_idx) +{ + struct stusb160x_priv *priv = dev_get_priv(dev); + int ret; + + ret = stusb160x_get_status(dev, false); + if (ret < 0) + return ret; + + return priv->attached; +} + +static u8 stusb160x_get_nb_connector(struct udevice *dev) +{ + /* only one connector supported */ + return 1; +} + +static int stusb160x_probe(struct udevice *dev) +{ + int power_mode_ctrl; + int ret; + + /* configure STUSB160X_CC_POWER_MODE_CTRL */ + power_mode_ctrl = dm_i2c_reg_read(dev, STUSB160X_CC_POWER_MODE_CTRL); + if (power_mode_ctrl < 0) + return power_mode_ctrl; + + power_mode_ctrl |= STUSB160X_DUAL_WITH_ACCESSORY; + ret = dm_i2c_reg_write(dev, STUSB160X_CC_POWER_MODE_CTRL, power_mode_ctrl); + if (ret < 0) + return ret; + + /* get current status : attached/unattached, device/host */ + return stusb160x_get_status(dev, true); +} + +static const struct typec_ops stusb160x_typec_ops = { + .is_attached = stusb160x_is_attached, + .get_data_role = stusb160x_get_data_role, + .get_nb_connector = stusb160x_get_nb_connector, +}; + +static const struct udevice_id typec_of_match[] = { + { .compatible = "st,stusb1600"}, + {} +}; + +U_BOOT_DRIVER(typec_stusb160x) = { + .id = UCLASS_USB_TYPEC, + .name = "typec_stusb160x", + .of_match = typec_of_match, + .ops = &stusb160x_typec_ops, + .priv_auto = sizeof(struct stusb160x_priv), + .probe = stusb160x_probe, +}; diff --git a/drivers/usb/typec/typec-uclass.c b/drivers/usb/typec/typec-uclass.c new file mode 100644 index 0000000000..6b870c7ff6 --- /dev/null +++ b/drivers/usb/typec/typec-uclass.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + */ + +#define LOG_CATEGORY UCLASS_USB_TYPEC + +#include +#include +#include +#include +#include +#include +#include + +int typec_get_device_from_usb(struct udevice *dev, struct udevice **typec, u8 index) +{ + ofnode node, child; + u32 endpoint_phandle; + u32 reg; + int ret; + + /* 'port' nodes can be grouped under an optional 'ports' node */ + node = dev_read_subnode(dev, "ports"); + if (!ofnode_valid(node)) { + node = dev_read_subnode(dev, "port"); + } else { + /* several 'port' nodes, found the requested port@index one */ + ofnode_for_each_subnode(child, node) { + ofnode_read_u32(child, "reg", ®); + if (index == reg) { + node = child; + break; + } + } + node = child; + } + + if (!ofnode_valid(node)) { + dev_dbg(dev, "connector port or port@%d subnode not found\n", index); + return -ENODEV; + } + + /* get endpoint node */ + node = ofnode_first_subnode(node); + if (!ofnode_valid(node)) + return -EINVAL; + + ret = ofnode_read_u32(node, "remote-endpoint", &endpoint_phandle); + if (ret) + return ret; + + /* retrieve connector endpoint phandle */ + node = ofnode_get_by_phandle(endpoint_phandle); + if (!ofnode_valid(node)) + return -EINVAL; + /* + * Use a while to retrieve an USB Type-C device either at connector + * level or just above (depending if UCSI uclass is used or not) + */ + while (ofnode_valid(node)) { + node = ofnode_get_parent(node); + if (!ofnode_valid(node)) { + dev_err(dev, "No UCLASS_USB_TYPEC for remote-endpoint\n"); + return -EINVAL; + } + + uclass_find_device_by_ofnode(UCLASS_USB_TYPEC, node, typec); + if (*typec) + break; + } + + ret = device_probe(*typec); + if (ret) { + dev_err(dev, "Type-C won't probe (ret=%d)\n", ret); + return ret; + } + + return 0; +} + +int typec_get_data_role(struct udevice *dev, u8 con_idx) +{ + const struct typec_ops *ops = device_get_ops(dev); + int ret; + + if (!ops->get_data_role) + return -ENOSYS; + + ret = ops->get_data_role(dev, con_idx); + dev_dbg(dev, "%s\n", ret == TYPEC_HOST ? "Host" : "Device"); + + return ret; +} + +int typec_is_attached(struct udevice *dev, u8 con_idx) +{ + const struct typec_ops *ops = device_get_ops(dev); + int ret; + + if (!ops->is_attached) + return -ENOSYS; + + ret = ops->is_attached(dev, con_idx); + dev_dbg(dev, "%s\n", ret == TYPEC_ATTACHED ? "Attached" : "Not attached"); + + return ret; +} + +int typec_get_nb_connector(struct udevice *dev) +{ + const struct typec_ops *ops = device_get_ops(dev); + int ret; + + if (!ops->get_nb_connector) + return -ENOSYS; + + ret = ops->get_nb_connector(dev); + dev_dbg(dev, "%d connector(s)\n", ret); + + return ret; +} + +UCLASS_DRIVER(typec) = { + .id = UCLASS_USB_TYPEC, + .name = "typec", +}; diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig new file mode 100644 index 0000000000..928106b1db --- /dev/null +++ b/drivers/usb/typec/ucsi/Kconfig @@ -0,0 +1,26 @@ +menuconfig TYPEC_UCSI + bool "USB Type-C Connector System Software Interface (UCSI)" + depends on DM && TYPEC + help + USB Type-C Connector System Software Interface (UCSI) is a + specification for an interface that allows the operating system to + control the USB Type-C ports. On UCSI system the USB Type-C ports + function autonomously by default, but in order to get the status of + the ports and support basic operations like role swapping, the driver + is required. UCSI is available on most of the new Intel based systems + that are equipped with Embedded Controller and USB Type-C ports. + + UCSI specification does not define the interface method, so depending + on the platform, ACPI, PCI, I2C, etc. may be used. Therefore this + driver only provides the core part, and separate drivers are needed + for every supported interface method. + + The UCSI specification can be downloaded from: + https://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html + +config UCSI_STM32G0 + bool "Support for STM32G0 UCSI controller" + depends on TYPEC_UCSI && DM_I2C + help + This driver enables UCSI support on platforms that expose a STM32G0 + Type-C controller over I2C interface. diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile new file mode 100644 index 0000000000..043000e238 --- /dev/null +++ b/drivers/usb/typec/ucsi/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += ucsi-uclass.o +obj-$(CONFIG_UCSI_STM32G0) += ucsi-stm32g0.o diff --git a/drivers/usb/typec/ucsi/ucsi-stm32g0.c b/drivers/usb/typec/ucsi/ucsi-stm32g0.c new file mode 100644 index 0000000000..e3a1bc4889 --- /dev/null +++ b/drivers/usb/typec/ucsi/ucsi-stm32g0.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + */ + +#define LOG_CATEGORY UCLASS_UCSI + +#include +#include +#include +#include +#include +#include +#include +#include + +static int stm32_ucsi_read(struct udevice *dev, unsigned int offset, void *val, size_t len) +{ + struct dm_i2c_chip *chip = dev_get_parent_plat(dev); + u8 reg = offset; + struct i2c_msg msg[] = { + { + .addr = chip->chip_addr, + .flags = 0, + .len = 1, + .buf = ®, + }, + { + .addr = chip->chip_addr, + .flags = I2C_M_RD, + .len = len, + .buf = val, + }, + }; + int ret; + + ret = dm_i2c_xfer(dev, msg, ARRAY_SIZE(msg)); + if (ret) + dev_err(dev, "i2c read failed @offset 0x%x (%d)\n", offset, ret); + + /* + * Add this delay to ensure that PPM has completed the current command, + * before sending it another one. + */ + udelay(20); + + return ret; +} + +static int stm32_ucsi_write(struct udevice *dev, unsigned int offset, + const void *val, size_t len) +{ + struct dm_i2c_chip *chip = dev_get_parent_plat(dev); + struct i2c_msg msg[] = { + { + .addr = chip->chip_addr, + .flags = 0, + } + }; + unsigned char *buf; + int ret; + + buf = kzalloc(len + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf[0] = offset; + memcpy(&buf[1], val, len); + msg[0].len = len + 1; + msg[0].buf = buf; + + ret = dm_i2c_xfer(dev, msg, ARRAY_SIZE(msg)); + kfree(buf); + if (ret) + dev_err(dev, "i2c write failed @offset 0x%x (%d)\n", offset, ret); + + /* + * Add this delay to ensure that PPM has completed the current command, + * before sending it another one. + */ + mdelay(2); + + return ret; +} + +int stm32_ucsi_probe(struct udevice *dev) +{ + u16 ucsi_version; + int ret; + + ret = stm32_ucsi_read(dev, UCSI_VERSION, &ucsi_version, sizeof(ucsi_version)); + if (ret < 0) + return ret; + + dev_dbg(dev, "STM32G0 version 0x%x\n", ucsi_version); + + return 0; +} + +static const struct ucsi_ops stm32_ucsi_ops = { + .read = stm32_ucsi_read, + .write = stm32_ucsi_write, +}; + +static const struct udevice_id stm32_ucsi_of_match[] = { + { .compatible = "st,stm32g0-typec"}, + {} +}; + +U_BOOT_DRIVER(ucsi_stm32g0) = { + .id = UCLASS_UCSI, + .name = "ucsi-stm32g0", + .of_match = stm32_ucsi_of_match, + .probe = stm32_ucsi_probe, + .ops = &stm32_ucsi_ops, + .bind = dm_scan_fdt_dev, +}; diff --git a/drivers/usb/typec/ucsi/ucsi-uclass.c b/drivers/usb/typec/ucsi/ucsi-uclass.c new file mode 100644 index 0000000000..8744497ebf --- /dev/null +++ b/drivers/usb/typec/ucsi/ucsi-uclass.c @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + * + * Code inspired from kernel drivers/usb/typec/ucsi/ucsi.c + * + */ + +#define LOG_CATEGORY UCLASS_UCSI + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * UCSI_TIMEOUT_US - PPM communication timeout + * + * Ideally we could use MIN_TIME_TO_RESPOND_WITH_BUSY (which is defined in UCSI + * specification) here as reference, but unfortunately we can't. It is very + * difficult to estimate the time it takes for the system to process the command + * before it is actually passed to the PPM. + */ +#define UCSI_TIMEOUT_US 50000000 + +struct connector { + enum typec_state attached; + enum typec_data_role data_role; +}; + +struct ucsi_priv { + struct connector *con; + u8 nb_connector; +}; + +static int ucsi_read(struct udevice *dev, int offset, void *buf, int size) +{ + const struct ucsi_ops *ops = device_get_ops(dev); + + if (!ops->read) + return -ENOSYS; + + return ops->read(dev, offset, buf, size); +} + +static int ucsi_write(struct udevice *dev, int offset, void *buf, int size) +{ + const struct ucsi_ops *ops = device_get_ops(dev); + + if (!ops->write) + return -ENOSYS; + + return ops->write(dev, offset, buf, size); +} + +static int ucsi_acknowledge_command(struct udevice *dev) +{ + u64 ctrl; + + ctrl = UCSI_ACK_CC_CI; + ctrl |= UCSI_ACK_COMMAND_COMPLETE; + + return ucsi_write(dev, UCSI_CONTROL, &ctrl, sizeof(ctrl)); +} + +static int ucsi_acknowledge_connector_change(struct udevice *dev) +{ + u64 ctrl; + + ctrl = UCSI_ACK_CC_CI; + ctrl |= UCSI_ACK_CONNECTOR_CHANGE; + + return ucsi_write(dev, UCSI_CONTROL, &ctrl, sizeof(ctrl)); +} + +static int ucsi_exec_command(struct udevice *dev, u64 command); + +static int ucsi_read_error(struct udevice *dev) +{ + u16 error; + int ret; + + /* Acknowlege the command that failed */ + ret = ucsi_acknowledge_command(dev); + + if (ret) + return ret; + + ret = ucsi_exec_command(dev, UCSI_GET_ERROR_STATUS); + + if (ret < 0) + return ret; + + ret = ucsi_read(dev, UCSI_MESSAGE_IN, &error, sizeof(error)); + if (ret) + return ret; + + switch (error) { + case UCSI_ERROR_INCOMPATIBLE_PARTNER: + return -EOPNOTSUPP; + case UCSI_ERROR_CC_COMMUNICATION_ERR: + return -ECOMM; + case UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL: + return -EPROTO; + case UCSI_ERROR_DEAD_BATTERY: + dev_warn(dev, "Dead battery condition!\n"); + return -EPERM; + case UCSI_ERROR_INVALID_CON_NUM: + case UCSI_ERROR_UNREGONIZED_CMD: + case UCSI_ERROR_INVALID_CMD_ARGUMENT: + dev_err(dev, "possible UCSI driver bug %u\n", error); + return -EINVAL; + case UCSI_ERROR_OVERCURRENT: + dev_warn(dev, "Overcurrent condition\n"); + break; + case UCSI_ERROR_PARTNER_REJECTED_SWAP: + dev_warn(dev, "Partner rejected swap\n"); + break; + case UCSI_ERROR_HARD_RESET: + dev_warn(dev, "Hard reset occurred\n"); + break; + case UCSI_ERROR_PPM_POLICY_CONFLICT: + dev_warn(dev, "PPM Policy conflict\n"); + break; + case UCSI_ERROR_SWAP_REJECTED: + dev_warn(dev, "Swap rejected\n"); + break; + case UCSI_ERROR_UNDEFINED: + default: + dev_err(dev, "unknown error %u\n", error); + break; + } + + return -EIO; +} + +static int ucsi_exec_command(struct udevice *dev, u64 cmd) +{ + u32 cci; + int ret; + + ret = ucsi_write(dev, UCSI_CONTROL, &cmd, sizeof(cmd)); + if (ret) + return ret; + + ret = ucsi_read(dev, UCSI_CCI, &cci, sizeof(cci)); + if (ret) + return ret; + + if (cci & UCSI_CCI_BUSY) + return -EBUSY; + + if (!(cci & UCSI_CCI_COMMAND_COMPLETE)) + return -EIO; + + if (cci & UCSI_CCI_NOT_SUPPORTED) + return -EOPNOTSUPP; + + if (cci & UCSI_CCI_ERROR) { + if (cmd == UCSI_GET_ERROR_STATUS) + return -EIO; + return ucsi_read_error(dev); + } + + return UCSI_CCI_LENGTH(cci); +} + +static int ucsi_send_command(struct udevice *dev, u64 command, + void *data, size_t size) +{ + u8 length; + int ret; + + ret = ucsi_exec_command(dev, command); + if (ret < 0) + goto out; + + length = ret; + + if (data) { + ret = ucsi_read(dev, UCSI_MESSAGE_IN, data, size); + if (ret) + goto out; + } + + ret = ucsi_acknowledge_command(dev); + if (ret) + goto out; + + ret = length; +out: + + return ret; +} + +static int ucsi_reset_ppm(struct udevice *dev) +{ + u64 command = UCSI_PPM_RESET; + unsigned long tmo; + u32 cci; + int ret; + + ret = ucsi_write(dev, UCSI_CONTROL, &command, sizeof(command)); + if (ret < 0) + goto out; + + tmo = timer_get_us() + UCSI_TIMEOUT_US; + + do { + if (time_before(tmo, timer_get_us())) { + ret = -ETIMEDOUT; + goto out; + } + + ret = ucsi_read(dev, UCSI_CCI, &cci, sizeof(cci)); + if (ret) + goto out; + + /* If the PPM is still doing something else, reset it again. */ + if (cci & ~UCSI_CCI_RESET_COMPLETE) { + ret = ucsi_write(dev, UCSI_CONTROL, &command, + sizeof(command)); + if (ret < 0) + goto out; + } + + mdelay(20); + } while (!(cci & UCSI_CCI_RESET_COMPLETE)); + +out: + return ret; +} + +static int ucsi_get_status(struct udevice *child, u8 con_idx, bool force) +{ + struct udevice *parent = dev_get_parent(child); + struct ucsi_priv *priv = dev_get_priv(child); + struct ucsi_connector_status status; + u64 command; + u32 cci; + int ret = 0; + + if (con_idx > (priv->nb_connector - 1)) + return -EINVAL; + + ret = ucsi_read(parent, UCSI_CCI, &cci, sizeof(cci)); + if (ret) + return ret; + + /* is there any change ? */ + if (!UCSI_CCI_CONNECTOR(cci) && !force) + goto exit; + + command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con_idx + 1); + ret = ucsi_send_command(parent, command, &status, sizeof(status)); + if (ret < 0) + return ret; + + priv->con[con_idx].attached = status.flags & UCSI_CONSTAT_CONNECTED ? + TYPEC_ATTACHED : TYPEC_UNATTACHED; + + switch (UCSI_CONSTAT_PARTNER_TYPE(status.flags)) { + case UCSI_CONSTAT_PARTNER_TYPE_UFP: + case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP: + case UCSI_CONSTAT_PARTNER_TYPE_CABLE: + priv->con[con_idx].data_role = TYPEC_HOST; + break; + case UCSI_CONSTAT_PARTNER_TYPE_DFP: + priv->con[con_idx].data_role = TYPEC_DEVICE; + break; + } + + ret = ucsi_acknowledge_connector_change(parent); +exit: + dev_dbg(child, "connector[%d] status: %s data role: %s\n", + con_idx, + priv->con[con_idx].attached == TYPEC_ATTACHED ? "Attached" : "Unattached", + priv->con[con_idx].data_role == TYPEC_HOST ? "Host" : "Device"); + + return ret; +} + +int ucsi_post_probe(struct udevice *dev) +{ + struct connector *con; + struct ucsi_priv *priv; + struct udevice *child; + struct ucsi_capability cap; + u64 command; + int ret; + u8 i; + + /* Reset the PPM */ + ret = ucsi_reset_ppm(dev); + if (ret) { + dev_err(dev, "failed to reset PPM!\n"); + return ret; + } + + /* enable connector change notification */ + command = UCSI_SET_NOTIFICATION_ENABLE | UCSI_ENABLE_NTFY_CONNECTOR_CHANGE; + ret = ucsi_send_command(dev, command, NULL, 0); + if (ret < 0) + return ret; + + /* get current status : attached/unattached, device/host */ + ret = device_get_child(dev, 0, &child); + if (ret < 0) + return ret; + + /* Get PPM capabilities */ + command = UCSI_GET_CAPABILITY; + ret = ucsi_send_command(dev, command, &cap, sizeof(cap)); + if (ret < 0) + return ret; + + if (!cap.num_connectors) + return -ENODEV; + + priv = dev_get_priv(child); + priv->nb_connector = cap.num_connectors; + priv->con = kcalloc(priv->nb_connector, sizeof(*con), GFP_KERNEL); + if (!priv->con) + return -ENOMEM; + + for (i = 0; i < priv->nb_connector; i++) { + ret = ucsi_get_status(child, i, true); + if (ret < 0) + return ret; + } + + return 0; +} + +UCLASS_DRIVER(ucsi) = { + .id = UCLASS_UCSI, + .name = "ucsi", + .post_probe = ucsi_post_probe, +}; + +static int ucsi_is_attached(struct udevice *dev, u8 con_idx) +{ + struct ucsi_priv *priv = dev_get_priv(dev); + int ret; + + ret = ucsi_get_status(dev, con_idx, false); + if (ret < 0) + return ret; + + return priv->con[con_idx].attached; +} + +static int ucsi_get_data_role(struct udevice *dev, u8 con_idx) +{ + struct ucsi_priv *priv = dev_get_priv(dev); + int ret; + + ret = ucsi_get_status(dev, con_idx, false); + if (ret < 0) + return ret; + + return priv->con[con_idx].data_role; +} + +static u8 usci_get_nb_connector(struct udevice *dev) +{ + struct ucsi_priv *priv = dev_get_priv(dev); + + return priv->nb_connector; +} + +static const struct typec_ops ucsi_typec_ops = { + .is_attached = ucsi_is_attached, + .get_data_role = ucsi_get_data_role, + .get_nb_connector = usci_get_nb_connector, +}; + +static const struct udevice_id typec_of_match[] = { + { .compatible = "usb-c-connector"}, + {} +}; + +U_BOOT_DRIVER(typec_ucsi) = { + .id = UCLASS_USB_TYPEC, + .name = "typec_ucsi", + .of_match = typec_of_match, + .ops = &ucsi_typec_ops, + .priv_auto = sizeof(struct ucsi_priv), +}; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8b940d70eb..1dd7d232c4 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -430,6 +430,15 @@ config VIDEO_LCD_RAYDIUM_RM68200 Say Y here if you want to enable support for Raydium RM68200 720x1280 DSI video mode panel. +config VIDEO_LCD_ROCKTECH_HX8394 + bool "ROCKTECH HX8394 DSI LCD panel support" + depends on DM_VIDEO + select VIDEO_MIPI_DSI + default n + help + Say Y here if you want to enable support for Rocktech HX8394 + 720x1280 DSI video mode panel. + config VIDEO_LCD_SSD2828 bool "SSD2828 bridge chip" default n diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 7ae0ab2b35..d4f9323ace 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o +obj-$(CONFIG_VIDEO_LCD_ROCKTECH_HX8394) += rocktech-hx8394.o obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o diff --git a/drivers/video/dw_mipi_dsi.c b/drivers/video/dw_mipi_dsi.c index 9ae09eec12..a5b38acabd 100644 --- a/drivers/video/dw_mipi_dsi.c +++ b/drivers/video/dw_mipi_dsi.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/video/rocktech-hx8394.c b/drivers/video/rocktech-hx8394.c new file mode 100644 index 0000000000..9a2689600b --- /dev/null +++ b/drivers/video/rocktech-hx8394.c @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 STMicroelectronics - All Rights Reserved + * Author: Yannick Fertre for STMicroelectronics. + * + * This hx8394 panel driver is inspired from the Linux Kernel driver + * drivers/gpu/drm/panel/panel-rocktech-hx8394.c. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MCS_SETPOWER 0xB1 +#define MCS_SETDISP 0xB2 +#define MCS_SETCYC 0xB4 +#define MCS_SETVCOM 0xB6 +#define MCS_SETEXTC 0xB9 +#define MCS_SETMIPI 0xBA +#define MCS_SET_BANK 0xBD +#define MCS_NO_DOC1 0xBF +#define MCS_NO_DOC2 0xC0 +#define MCS_NO_DOC3 0xC6 +#define MCS_NO_DOC4 0xD8 +#define MCS_NO_DOC5 0xD4 +#define MCS_SETPANEL 0xCC +#define MCS_SETGIP_0 0xD3 +#define MCS_SETGIP_1 0xD5 +#define MCS_SETGIP_2 0xD6 + +#define MCS_SETGAMMA 0xE0 +#define MCS_READ_ID1 0xDA +#define MCS_READ_ID2 0xDB +#define MCS_READ_ID3 0xDC + +#define MY BIT(7) /* Row Address Order */ +#define MX BIT(6) /* Column Address Order */ +#define MV BIT(5) /* Row/Column Exchange */ +#define ML BIT(4) /* Vertical Refresh Order */ +#define RGB BIT(3) /* RGB-BGR Order */ +#define DDL BIT(2) /* Display Data Latch Order */ +#define FH BIT(1) /* Flip Horizontal */ +#define FV BIT(0) /* Flip Vertical */ + +struct hx8394_panel_priv { + struct udevice *reg; + struct udevice *backlight; + struct gpio_desc reset; +}; + +static const struct display_timing default_timing = { + .pixelclock.typ = 54000000, + .hactive.typ = 720, + .hfront_porch.typ = 48, + .hback_porch.typ = 48, + .hsync_len.typ = 9, + .vactive.typ = 1280, + .vfront_porch.typ = 12, + .vback_porch.typ = 12, + .vsync_len.typ = 5, +}; + +static void hx8394_dcs_write_buf(struct udevice *dev, const void *data, + size_t len) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + struct mipi_dsi_device *device = plat->device; + int err; + + err = mipi_dsi_dcs_write_buffer(device, data, len); + if (err < 0) + dev_err(dev, "MIPI DSI DCS write buffer failed: %d\n", err); +} + +#define dcs_write_seq(dev, seq...) \ +({ \ + static const u8 d[] = { seq }; \ + \ + hx8394_dcs_write_buf(dev, d, ARRAY_SIZE(d)); \ +}) + +#define dcs_write_cmd_seq(dev, cmd, seq...) \ +({ \ + static const u8 d[] = { seq }; \ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); \ + struct mipi_dsi_device *device = plat->device; \ + int err; \ + err = mipi_dsi_dcs_write(device, cmd, d, ARRAY_SIZE(d)); \ + if (err < 0) \ + dev_err(dev, "MIPI DSI DCS write failed: %d\n", err); \ +}) + +static void hx8394_init_sequence(struct udevice *dev) +{ + dcs_write_cmd_seq(dev, MCS_SETEXTC, 0xFF, 0x83, 0x94); + dcs_write_cmd_seq(dev, MCS_SETMIPI, 0x61, 0x03, 0x68, 0x6B, 0xB2, 0xC0); + dcs_write_seq(dev, MCS_SETPOWER, 0x48, 0x12, 0x72, 0x09, 0x32, 0x54, 0x71, 0x71, 0x57, + 0x47); + dcs_write_cmd_seq(dev, MCS_SETDISP, 0x00, 0x80, 0x64, 0x0C, 0x0D, 0x2F); + dcs_write_seq(dev, MCS_SETCYC, 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0C, 0x86, 0x75, + 0x00, 0x3F, 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0C, 0x86); + dcs_write_seq(dev, MCS_SETGIP_0, 0x00, 0x00, 0x07, 0x07, 0x40, 0x07, 0x0C, 0x00, 0x08, 0x10, + 0x08, 0x00, 0x08, 0x54, 0x15, 0x0A, 0x05, 0x0A, 0x02, 0x15, 0x06, 0x05, 0x06, + 0x47, 0x44, 0x0A, 0x0A, 0x4B, 0x10, 0x07, 0x07, 0x0C, 0x40); + dcs_write_seq(dev, MCS_SETGIP_1, 0x1C, 0x1C, 0x1D, 0x1D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x24, 0x25, 0x18, 0x18, 0x26, 0x27, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x20, 0x21, 0x18, 0x18, 0x18, 0x18); + dcs_write_seq(dev, MCS_SETGIP_2, 0x1C, 0x1C, 0x1D, 0x1D, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, + 0x01, 0x00, 0x0B, 0x0A, 0x09, 0x08, 0x21, 0x20, 0x18, 0x18, 0x27, 0x26, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x25, 0x24, 0x18, 0x18, 0x18, 0x18); + dcs_write_cmd_seq(dev, MCS_SETVCOM, 0x92, 0x92); + dcs_write_seq(dev, MCS_SETGAMMA, 0x00, 0x0A, 0x15, 0x1B, 0x1E, 0x21, 0x24, 0x22, 0x47, 0x56, + 0x65, 0x66, 0x6E, 0x82, 0x88, 0x8B, 0x9A, 0x9D, 0x98, 0xA8, 0xB9, 0x5D, 0x5C, + 0x61, 0x66, 0x6A, 0x6F, 0x7F, 0x7F, 0x00, 0x0A, 0x15, 0x1B, 0x1E, 0x21, 0x24, + 0x22, 0x47, 0x56, 0x65, 0x65, 0x6E, 0x81, 0x87, 0x8B, 0x98, 0x9D, 0x99, 0xA8, + 0xBA, 0x5D, 0x5D, 0x62, 0x67, 0x6B, 0x72, 0x7F, 0x7F); + dcs_write_cmd_seq(dev, MCS_NO_DOC2, 0x1F, 0x31); + dcs_write_cmd_seq(dev, MCS_SETPANEL, 0x03); + dcs_write_cmd_seq(dev, MCS_NO_DOC5, 0x02); + dcs_write_cmd_seq(dev, MCS_SET_BANK, 0x02); + dcs_write_seq(dev, MCS_NO_DOC4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF); + dcs_write_cmd_seq(dev, MCS_SET_BANK, 0x00); + dcs_write_cmd_seq(dev, MCS_SET_BANK, 0x01); + dcs_write_cmd_seq(dev, MCS_SETPOWER, 0x00); + dcs_write_cmd_seq(dev, MCS_SET_BANK, 0x00); + dcs_write_cmd_seq(dev, MCS_NO_DOC1, 0x40, 0x81, 0x50, 0x00, 0x1A, 0xFC, 0x01); + dcs_write_cmd_seq(dev, MCS_NO_DOC3, 0xED); + dcs_write_cmd_seq(dev, MIPI_DCS_SET_ADDRESS_MODE, FH); +} + +static int hx8394_panel_enable_backlight(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + struct mipi_dsi_device *device = plat->device; + struct hx8394_panel_priv *priv = dev_get_priv(dev); + int ret; + + ret = mipi_dsi_attach(device); + if (ret < 0) + return ret; + + hx8394_init_sequence(dev); + + ret = mipi_dsi_dcs_exit_sleep_mode(device); + if (ret) + return ret; + + mdelay(120); + + ret = mipi_dsi_dcs_set_display_on(device); + if (ret) + return ret; + + mdelay(50); + + ret = backlight_enable(priv->backlight); + + return ret; +} + +static int hx8394_panel_get_display_timing(struct udevice *dev, + struct display_timing *timings) +{ + memcpy(timings, &default_timing, sizeof(*timings)); + + return 0; +} + +static int hx8394_panel_of_to_plat(struct udevice *dev) +{ + struct hx8394_panel_priv *priv = dev_get_priv(dev); + int ret; + + ret = device_get_supply_regulator(dev, "power-supply", + &priv->reg); + if (ret) { + dev_err(dev, "Warning: cannot get power supply\n"); + return ret; + } + + ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset, + GPIOD_IS_OUT); + if (ret) { + dev_err(dev, "Warning: cannot get reset GPIO\n"); + if (ret != -ENOENT) + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", &priv->backlight); + if (ret) + dev_err(dev, "Cannot get backlight: ret=%d\n", ret); + + return ret; +} + +static int hx8394_panel_probe(struct udevice *dev) +{ + struct hx8394_panel_priv *priv = dev_get_priv(dev); + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + int ret; + + ret = regulator_set_enable(priv->reg, true); + if (ret) + return ret; + + /* reset panel */ + dm_gpio_set_value(&priv->reset, true); + mdelay(1); + dm_gpio_set_value(&priv->reset, false); + mdelay(50); + + /* fill characteristics of DSI data link */ + plat->lanes = 2; + plat->format = MIPI_DSI_FMT_RGB888; + plat->mode_flags = MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM; + + return 0; +} + +static const struct panel_ops hx8394_panel_ops = { + .enable_backlight = hx8394_panel_enable_backlight, + .get_display_timing = hx8394_panel_get_display_timing, +}; + +static const struct udevice_id hx8394_panel_ids[] = { + { .compatible = "rocktech,hx8394" }, + { } +}; + +U_BOOT_DRIVER(hx8394_panel) = { + .name = "hx8394_panel", + .id = UCLASS_PANEL, + .of_match = hx8394_panel_ids, + .ops = &hx8394_panel_ops, + .of_to_plat = hx8394_panel_of_to_plat, + .probe = hx8394_panel_probe, + .plat_auto = sizeof(struct mipi_dsi_panel_plat), + .priv_auto = sizeof(struct hx8394_panel_priv), +}; diff --git a/drivers/video/stm32/stm32_dsi.c b/drivers/video/stm32/stm32_dsi.c index 4027e978c8..134abd93e1 100644 --- a/drivers/video/stm32/stm32_dsi.c +++ b/drivers/video/stm32/stm32_dsi.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c index f55a39498e..58b6434a48 100644 --- a/drivers/video/stm32/stm32_ltdc.c +++ b/drivers/video/stm32/stm32_ltdc.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -26,8 +25,114 @@ struct stm32_ltdc_priv { void __iomem *regs; enum video_log2_bpp l2bpp; u32 bg_col_argb; + const u32 *layer_regs; + const u32 *pix_fmt_hw; u32 crop_x, crop_y, crop_w, crop_h; u32 alpha; + u32 hw_version; +}; + +/* Layer register offsets */ +static const u32 layer_regs_a0[] = { + 0x80, /* L1 configuration 0 */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x84, /* L1 control register */ + 0x88, /* L1 window horizontal position configuration */ + 0x8c, /* L1 window vertical position configuration */ + 0x90, /* L1 color keying configuration */ + 0x94, /* L1 pixel format configuration */ + 0x98, /* L1 constant alpha configuration */ + 0x9c, /* L1 default color configuration */ + 0xa0, /* L1 blending factors configuration */ + 0x00, /* not available */ + 0x00, /* not available */ + 0xac, /* L1 color frame buffer address */ + 0xb0, /* L1 color frame buffer length */ + 0xb4, /* L1 color frame buffer line number */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0xc4, /* L1 CLUT write */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00 /* not available */ +}; + +static const u32 layer_regs_a1[] = { + 0x80, /* L1 configuration 0 */ + 0x84, /* L1 configuration 1 */ + 0x00, /* L1 reload control */ + 0x88, /* L1 control register */ + 0x8c, /* L1 window horizontal position configuration */ + 0x90, /* L1 window vertical position configuration */ + 0x94, /* L1 color keying configuration */ + 0x98, /* L1 pixel format configuration */ + 0x9c, /* L1 constant alpha configuration */ + 0xa0, /* L1 default color configuration */ + 0xa4, /* L1 blending factors configuration */ + 0xa8, /* L1 burst length configuration */ + 0x00, /* not available */ + 0xac, /* L1 color frame buffer address */ + 0xb0, /* L1 color frame buffer length */ + 0xb4, /* L1 color frame buffer line number */ + 0xb8, /* L1 auxiliary frame buffer address 0 */ + 0xbc, /* L1 auxiliary frame buffer address 1 */ + 0xc0, /* L1 auxiliary frame buffer length */ + 0xc4, /* L1 auxiliary frame buffer line number */ + 0xc8, /* L1 CLUT write */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00, /* not available */ + 0x00 /* not available */ +}; + +static const u32 layer_regs_a2[] = { + 0x100, /* L1 configuration 0 */ + 0x104, /* L1 configuration 1 */ + 0x108, /* L1 reload control */ + 0x10c, /* L1 control register */ + 0x110, /* L1 window horizontal position configuration */ + 0x114, /* L1 window vertical position configuration */ + 0x118, /* L1 color keying configuration */ + 0x11c, /* L1 pixel format configuration */ + 0x120, /* L1 constant alpha configuration */ + 0x124, /* L1 default color configuration */ + 0x128, /* L1 blending factors configuration */ + 0x12c, /* L1 burst length configuration */ + 0x130, /* L1 planar configuration */ + 0x134, /* L1 color frame buffer address */ + 0x138, /* L1 color frame buffer length */ + 0x13c, /* L1 color frame buffer line number */ + 0x140, /* L1 auxiliary frame buffer address 0 */ + 0x144, /* L1 auxiliary frame buffer address 1 */ + 0x148, /* L1 auxiliary frame buffer length */ + 0x14c, /* L1 auxiliary frame buffer line number */ + 0x150, /* L1 CLUT write */ + 0x154, /* not available */ + 0x158, /* not available */ + 0x15c, /* not available */ + 0x160, /* not available */ + 0x164, /* not available */ + 0x168, /* not available */ + 0x16c, /* L1 Conversion YCbCr RGB 0 */ + 0x170, /* L1 Conversion YCbCr RGB 1 */ + 0x174, /* L1 Flexible Pixel Format 0 */ + 0x178 /* L1 Flexible Pixel Format 1 */ }; /* LTDC main registers */ @@ -50,26 +155,32 @@ struct stm32_ltdc_priv { #define LTDC_CPSR 0x44 /* Current Position Status */ #define LTDC_CDSR 0x48 /* Current Display Status */ -/* LTDC layer 1 registers */ -#define LTDC_L1LC1R 0x80 /* L1 Layer Configuration 1 */ -#define LTDC_L1LC2R 0x84 /* L1 Layer Configuration 2 */ -#define LTDC_L1CR 0x84 /* L1 Control */ -#define LTDC_L1WHPCR 0x88 /* L1 Window Hor Position Config */ -#define LTDC_L1WVPCR 0x8C /* L1 Window Vert Position Config */ -#define LTDC_L1CKCR 0x90 /* L1 Color Keying Configuration */ -#define LTDC_L1PFCR 0x94 /* L1 Pixel Format Configuration */ -#define LTDC_L1CACR 0x98 /* L1 Constant Alpha Config */ -#define LTDC_L1DCCR 0x9C /* L1 Default Color Configuration */ -#define LTDC_L1BFCR 0xA0 /* L1 Blend Factors Configuration */ -#define LTDC_L1FBBCR 0xA4 /* L1 FrameBuffer Bus Control */ -#define LTDC_L1AFBCR 0xA8 /* L1 AuxFB Control */ -#define LTDC_L1CFBAR 0xAC /* L1 Color FrameBuffer Address */ -#define LTDC_L1CFBLR 0xB0 /* L1 Color FrameBuffer Length */ -#define LTDC_L1CFBLNR 0xB4 /* L1 Color FrameBuffer Line Nb */ -#define LTDC_L1AFBAR 0xB8 /* L1 AuxFB Address */ -#define LTDC_L1AFBLR 0xBC /* L1 AuxFB Length */ -#define LTDC_L1AFBLNR 0xC0 /* L1 AuxFB Line Number */ -#define LTDC_L1CLUTWR 0xC4 /* L1 CLUT Write */ +/* Layer register offsets */ +#define LTDC_L1C0R (priv->layer_regs[0]) /* L1 configuration 0 */ +#define LTDC_L1C1R (priv->layer_regs[1]) /* L1 configuration 1 */ +#define LTDC_L1RCR (priv->layer_regs[2]) /* L1 reload control */ +#define LTDC_L1CR (priv->layer_regs[3]) /* L1 control register */ +#define LTDC_L1WHPCR (priv->layer_regs[4]) /* L1 window horizontal position configuration */ +#define LTDC_L1WVPCR (priv->layer_regs[5]) /* L1 window vertical position configuration */ +#define LTDC_L1CKCR (priv->layer_regs[6]) /* L1 color keying configuration */ +#define LTDC_L1PFCR (priv->layer_regs[7]) /* L1 pixel format configuration */ +#define LTDC_L1CACR (priv->layer_regs[8]) /* L1 constant alpha configuration */ +#define LTDC_L1DCCR (priv->layer_regs[9]) /* L1 default color configuration */ +#define LTDC_L1BFCR (priv->layer_regs[10]) /* L1 blending factors configuration */ +#define LTDC_L1BLCR (priv->layer_regs[11]) /* L1 burst length configuration */ +#define LTDC_L1PCR (priv->layer_regs[12]) /* L1 planar configuration */ +#define LTDC_L1CFBAR (priv->layer_regs[13]) /* L1 color frame buffer address */ +#define LTDC_L1CFBLR (priv->layer_regs[14]) /* L1 color frame buffer length */ +#define LTDC_L1CFBLNR (priv->layer_regs[15]) /* L1 color frame buffer line number */ +#define LTDC_L1AFBA0R (priv->layer_regs[16]) /* L1 auxiliary frame buffer address 0 */ +#define LTDC_L1AFBA1R (priv->layer_regs[17]) /* L1 auxiliary frame buffer address 1 */ +#define LTDC_L1AFBLR (priv->layer_regs[18]) /* L1 auxiliary frame buffer length */ +#define LTDC_L1AFBLNR (priv->layer_regs[19]) /* L1 auxiliary frame buffer line number */ +#define LTDC_L1CLUTWR (priv->layer_regs[20]) /* L1 CLUT write */ +#define LTDC_L1CYR0R (priv->layer_regs[27]) /* L1 Conversion YCbCr RGB 0 */ +#define LTDC_L1CYR1R (priv->layer_regs[28]) /* L1 Conversion YCbCr RGB 1 */ +#define LTDC_L1FPF0R (priv->layer_regs[29]) /* L1 Flexible Pixel Format 0 */ +#define LTDC_L1FPF1R (priv->layer_regs[30]) /* L1 Flexible Pixel Format 1 */ /* Bit definitions */ #define SSCR_VSH GENMASK(10, 0) /* Vertical Synchronization Height */ @@ -145,15 +256,60 @@ struct stm32_ltdc_priv { #define BF2_1PAXCA 0x007 /* 1 - (Pixel Alpha x Constant Alpha) */ #define BF2_1CA 0x005 /* 1 - Constant Alpha */ +#define NB_PF 8 /* Max nb of HW pixel format */ + +#define HWVER_10200 0x010200 +#define HWVER_10300 0x010300 +#define HWVER_20101 0x020101 +#define HWVER_40100 0x040100 + enum stm32_ltdc_pix_fmt { - PF_ARGB8888 = 0, - PF_RGB888, - PF_RGB565, - PF_ARGB1555, - PF_ARGB4444, - PF_L8, - PF_AL44, - PF_AL88 + PF_ARGB8888 = 0, /* ARGB [32 bits] */ + PF_ABGR8888, /* ABGR [32 bits] */ + PF_BGRA8888, /* BGRA [32 bits] */ + PF_RGBA8888, /* RGBA [32 bits] */ + PF_RGB888, /* RGB [24 bits] */ + PF_BGR565, /* RGB [16 bits] */ + PF_RGB565, /* RGB [16 bits] */ + PF_ARGB1555, /* ARGB A:1 bit RGB:15 bits [16 bits] */ + PF_ARGB4444, /* ARGB A:4 bits R/G/B: 4 bits each [16 bits] */ + PF_AL44, /* Alpha:4 bits + indexed 4 bits [8 bits] */ + PF_AL88, /* Alpha:8 bits + indexed 8 bits [16 bits] */ + PF_L8, /* Indexed 8 bits [8 bits] */ + PF_NONE +}; + +static const enum stm32_ltdc_pix_fmt pix_fmt_a0[NB_PF] = { + PF_ARGB8888, /* 0x00 */ + PF_RGB888, /* 0x01 */ + PF_RGB565, /* 0x02 */ + PF_ARGB1555, /* 0x03 */ + PF_ARGB4444, /* 0x04 */ + PF_L8, /* 0x05 */ + PF_AL44, /* 0x06 */ + PF_AL88 /* 0x07 */ +}; + +static const enum stm32_ltdc_pix_fmt pix_fmt_a1[NB_PF] = { + PF_ARGB8888, /* 0x00 */ + PF_RGB888, /* 0x01 */ + PF_RGB565, /* 0x02 */ + PF_RGBA8888, /* 0x03 */ + PF_AL44, /* 0x04 */ + PF_L8, /* 0x05 */ + PF_ARGB1555, /* 0x06 */ + PF_ARGB4444 /* 0x07 */ +}; + +static const enum stm32_ltdc_pix_fmt pix_fmt_a2[NB_PF] = { + PF_ARGB8888, /* 0x00 */ + PF_ABGR8888, /* 0x01 */ + PF_RGBA8888, /* 0x02 */ + PF_BGRA8888, /* 0x03 */ + PF_RGB565, /* 0x04 */ + PF_BGR565, /* 0x05 */ + PF_RGB888, /* 0x06 */ + PF_NONE /* 0x07 (flexible pixel format) */ }; /* TODO add more color format support */ @@ -256,7 +412,7 @@ static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv, val |= GCR_HSPOL; if (timings->flags & DISPLAY_FLAGS_VSYNC_HIGH) val |= GCR_VSPOL; - if (timings->flags & DISPLAY_FLAGS_DE_HIGH) + if (timings->flags & DISPLAY_FLAGS_DE_LOW) val |= GCR_DEPOL; if (timings->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) val |= GCR_PCPOL; @@ -307,7 +463,16 @@ static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr) /* Pixel format */ format = stm32_ltdc_get_pixel_format(priv->l2bpp); - clrsetbits_le32(regs + LTDC_L1PFCR, LXPFCR_PF, format); + for (val = 0; val < NB_PF; val++) + if (priv->pix_fmt_hw[val] == format) + break; + + if (val >= NB_PF) { + log_err("invalid pixel format\n"); + return; + } + + clrsetbits_le32(regs + LTDC_L1PFCR, LXPFCR_PF, val); /* Constant alpha value */ clrsetbits_le32(regs + LTDC_L1CACR, LXCACR_CONSTA, priv->alpha); @@ -339,6 +504,7 @@ static int stm32_ltdc_probe(struct udevice *dev) struct display_timing timings; struct clk pclk; struct reset_ctl rst; + ulong rate; int ret; priv->regs = (void *)dev_read_addr(dev); @@ -359,6 +525,27 @@ static int stm32_ltdc_probe(struct udevice *dev) return ret; } + priv->hw_version = readl(priv->regs + LTDC_IDR); + debug("%s: LTDC hardware 0x%x\n", __func__, priv->hw_version); + + switch (priv->hw_version) { + case HWVER_10200: + case HWVER_10300: + priv->layer_regs = layer_regs_a0; + priv->pix_fmt_hw = pix_fmt_a0; + break; + case HWVER_20101: + priv->layer_regs = layer_regs_a1; + priv->pix_fmt_hw = pix_fmt_a1; + break; + case HWVER_40100: + priv->layer_regs = layer_regs_a2; + priv->pix_fmt_hw = pix_fmt_a2; + break; + default: + return -ENODEV; + } + ret = uclass_first_device_err(UCLASS_PANEL, &panel); if (ret) { if (ret != -ENODEV) @@ -376,13 +563,13 @@ static int stm32_ltdc_probe(struct udevice *dev) } } - ret = clk_set_rate(&pclk, timings.pixelclock.typ); - if (ret) - dev_warn(dev, "fail to set pixel clock %d hz\n", - timings.pixelclock.typ); + rate = clk_set_rate(&pclk, timings.pixelclock.typ); + if (IS_ERR_VALUE(rate)) + dev_warn(dev, "fail to set pixel clock %d hz, ret=%ld\n", + timings.pixelclock.typ, rate); dev_dbg(dev, "Set pixel clock req %d hz get %ld hz\n", - timings.pixelclock.typ, clk_get_rate(&pclk)); + timings.pixelclock.typ, rate); ret = reset_get_by_index(dev, 0, &rst); if (ret) { @@ -460,7 +647,10 @@ static int stm32_ltdc_bind(struct udevice *dev) uc_plat->size = CONFIG_VIDEO_STM32_MAX_XRES * CONFIG_VIDEO_STM32_MAX_YRES * (CONFIG_VIDEO_STM32_MAX_BPP >> 3); - dev_dbg(dev, "frame buffer max size %d bytes\n", uc_plat->size); + /* align framebuffer on kernel MMU_SECTION_SIZE = max 2MB for LPAE */ + uc_plat->align = SZ_2M; + dev_dbg(dev, "frame buffer max size %d bytes align %x\n", + uc_plat->size, uc_plat->align); return 0; } diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 9f8cf6ef2a..43ebb3c565 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -228,6 +228,20 @@ void video_sync_all(void) } } +bool video_is_active(void) +{ + struct udevice *dev; + + for (uclass_find_first_device(UCLASS_VIDEO, &dev); + dev; + uclass_find_next_device(&dev)) { + if (device_active(dev)) + return true; + } + + return false; +} + int video_get_xsize(struct udevice *dev) { struct video_priv *priv = dev_get_uclass_priv(dev); diff --git a/env/mmc.c b/env/mmc.c index 09e94f0bd3..090382d4a3 100644 --- a/env/mmc.c +++ b/env/mmc.c @@ -238,12 +238,15 @@ static inline int erase_env(struct mmc *mmc, unsigned long size, { uint blk_start, blk_cnt, n; struct blk_desc *desc = mmc_get_blk_desc(mmc); + u32 erase_size; - blk_start = ALIGN(offset, mmc->write_bl_len) / mmc->write_bl_len; - blk_cnt = ALIGN(size, mmc->write_bl_len) / mmc->write_bl_len; + erase_size = mmc->erase_grp_size * desc->blksz; + blk_start = ALIGN_DOWN(offset, erase_size) / desc->blksz; + blk_cnt = ALIGN(size, erase_size) / desc->blksz; n = blk_derase(desc, blk_start, blk_cnt); - printf("%d blocks erased: %s\n", n, (n == blk_cnt) ? "OK" : "ERROR"); + printf("%d blocks erased at 0x%x: %s\n", n, blk_start, + (n == blk_cnt) ? "OK" : "ERROR"); return (n == blk_cnt) ? 0 : 1; } @@ -265,6 +268,7 @@ static int env_mmc_erase(void) if (mmc_get_env_addr(mmc, copy, &offset)) return CMD_RET_FAILURE; + printf("\n"); ret = erase_env(mmc, CONFIG_ENV_SIZE, offset); #ifdef CONFIG_ENV_OFFSET_REDUND diff --git a/env/onenand.c b/env/onenand.c index c8da3ff811..1faa2cb62a 100644 --- a/env/onenand.c +++ b/env/onenand.c @@ -73,9 +73,7 @@ static int env_onenand_save(void) #endif loff_t env_addr = CONFIG_ENV_ADDR; size_t retlen; - struct erase_info instr = { - .callback = NULL, - }; + struct erase_info instr = {}; ret = env_export(&env_new); if (ret) diff --git a/fs/yaffs2/yaffs_mtdif.c b/fs/yaffs2/yaffs_mtdif.c index d338f9aa91..50fed2d4b1 100644 --- a/fs/yaffs2/yaffs_mtdif.c +++ b/fs/yaffs2/yaffs_mtdif.c @@ -145,7 +145,6 @@ int nandmtd_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber) ei.len = dev->data_bytes_per_chunk * dev->param.chunks_per_block; ei.time = 1000; ei.retries = 2; - ei.callback = NULL; ei.priv = (u_long) dev; /* Todo finish off the ei if required */ diff --git a/include/configs/dh_imx6.h b/include/configs/dh_imx6.h index d9be1c38c4..0198126de5 100644 --- a/include/configs/dh_imx6.h +++ b/include/configs/dh_imx6.h @@ -58,8 +58,6 @@ /* USB Configs */ #ifdef CONFIG_CMD_USB #define CONFIG_EHCI_HCD_INIT_AFTER_RESET -#define CONFIG_USB_HOST_ETHER -#define CONFIG_USB_ETHER_ASIX #define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW) #define CONFIG_MXC_USB_FLAGS 0 #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 /* Enabled USB controller number */ diff --git a/include/configs/dh_stm32mp1.h b/include/configs/dh_stm32mp1.h deleted file mode 100644 index 89d317ba2b..0000000000 --- a/include/configs/dh_stm32mp1.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ -/* - * Copyright (C) 2020 Marek Vasut - * - * Configuration settings for the DH STM32MP15x SoMs - */ - -#ifndef __CONFIG_DH_STM32MP1_H__ -#define __CONFIG_DH_STM32MP1_H__ - -#include - -#define CONFIG_SPL_TARGET "u-boot.itb" - -#endif diff --git a/include/configs/kp_imx6q_tpc.h b/include/configs/kp_imx6q_tpc.h index 749e880f36..7216939265 100644 --- a/include/configs/kp_imx6q_tpc.h +++ b/include/configs/kp_imx6q_tpc.h @@ -30,8 +30,6 @@ /* USB Configs */ #ifdef CONFIG_CMD_USB #define CONFIG_EHCI_HCD_INIT_AFTER_RESET -#define CONFIG_USB_HOST_ETHER -#define CONFIG_USB_ETHER_ASIX #define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW) #define CONFIG_MXC_USB_FLAGS 0 #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 /* Enabled USB controller number */ diff --git a/include/configs/mx53ppd.h b/include/configs/mx53ppd.h index b1e6a5638b..c9fecc3f9b 100644 --- a/include/configs/mx53ppd.h +++ b/include/configs/mx53ppd.h @@ -23,10 +23,6 @@ #define CONFIG_REVISION_TAG /* USB Configs */ -#define CONFIG_USB_HOST_ETHER -#define CONFIG_USB_ETHER_ASIX -#define CONFIG_USB_ETHER_MCS7830 -#define CONFIG_USB_ETHER_SMSC95XX #define CONFIG_MXC_USB_PORT 1 #define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW) #define CONFIG_MXC_USB_FLAGS 0 diff --git a/include/configs/pm9263.h b/include/configs/pm9263.h index e825270de8..8d11759aa0 100644 --- a/include/configs/pm9263.h +++ b/include/configs/pm9263.h @@ -145,7 +145,6 @@ #define CONFIG_INITRD_TAG 1 #undef CONFIG_SKIP_LOWLEVEL_INIT -#define CONFIG_USER_LOWLEVEL_INIT 1 /* * Hardware drivers diff --git a/include/configs/rpi.h b/include/configs/rpi.h index 522b41c02d..709af64c4b 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -65,7 +65,6 @@ /* GPIO */ #define CONFIG_BCM2835_GPIO /* LCD */ -#define CONFIG_LCD_DT_SIMPLEFB #define CONFIG_VIDEO_BCM2835 /* DFU over USB/UDC */ diff --git a/include/configs/stih410-b2260.h b/include/configs/stih410-b2260.h index 33b34ee0cd..f35d26aa2e 100644 --- a/include/configs/stih410-b2260.h +++ b/include/configs/stih410-b2260.h @@ -65,11 +65,6 @@ #define CONFIG_USB_OHCI_NEW #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 -#define CONFIG_USB_HOST_ETHER -#define CONFIG_USB_ETHER_ASIX -#define CONFIG_USB_ETHER_MCS7830 -#define CONFIG_USB_ETHER_SMSC95XX - /* NET Configs */ #endif /* __CONFIG_H */ diff --git a/include/configs/stm32f429-discovery.h b/include/configs/stm32f429-discovery.h index 9d029fbcc6..d0ef18779f 100644 --- a/include/configs/stm32f429-discovery.h +++ b/include/configs/stm32f429-discovery.h @@ -23,22 +23,12 @@ #define CONFIG_RED_LED 110 #define CONFIG_GREEN_LED 109 -#define CONFIG_STM32_FLASH - #define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ -#define CONFIG_CMDLINE_TAG -#define CONFIG_SETUP_MEMORY_TAGS -#define CONFIG_INITRD_TAG -#define CONFIG_REVISION_TAG - #define CONFIG_SYS_CBSIZE 1024 #define CONFIG_SYS_MALLOC_LEN (2 << 20) -#define CONFIG_BOOTCOMMAND \ - "run bootcmd_romfs" - #define CONFIG_EXTRA_ENV_SETTINGS \ "bootargs_romfs=uclinux.physaddr=0x08180000 root=/dev/mtdblock0\0" \ "bootcmd_romfs=setenv bootargs ${bootargs} ${bootargs_romfs};" \ diff --git a/include/configs/stm32f429-evaluation.h b/include/configs/stm32f429-evaluation.h index fefdb2dd15..3b6223d737 100644 --- a/include/configs/stm32f429-evaluation.h +++ b/include/configs/stm32f429-evaluation.h @@ -25,15 +25,8 @@ #define CONFIG_SYS_MAX_FLASH_SECT 12 #define CONFIG_SYS_MAX_FLASH_BANKS 2 -#define CONFIG_STM32_FLASH - #define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ -#define CONFIG_CMDLINE_TAG -#define CONFIG_SETUP_MEMORY_TAGS -#define CONFIG_INITRD_TAG -#define CONFIG_REVISION_TAG - #define CONFIG_SYS_CBSIZE 1024 #define CONFIG_SYS_MALLOC_LEN (1 * 1024 * 1024) diff --git a/include/configs/stm32f469-discovery.h b/include/configs/stm32f469-discovery.h index ba9f05a61b..6a0fa02451 100644 --- a/include/configs/stm32f469-discovery.h +++ b/include/configs/stm32f469-discovery.h @@ -25,15 +25,8 @@ #define CONFIG_SYS_MAX_FLASH_SECT 12 #define CONFIG_SYS_MAX_FLASH_BANKS 2 -#define CONFIG_STM32_FLASH - #define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ -#define CONFIG_CMDLINE_TAG -#define CONFIG_SETUP_MEMORY_TAGS -#define CONFIG_INITRD_TAG -#define CONFIG_REVISION_TAG - #define CONFIG_SYS_CBSIZE 1024 #define CONFIG_SYS_MALLOC_LEN (1 * 1024 * 1024) diff --git a/include/configs/stm32f746-disco.h b/include/configs/stm32f746-disco.h index 08d050adfa..247191a475 100644 --- a/include/configs/stm32f746-disco.h +++ b/include/configs/stm32f746-disco.h @@ -29,18 +29,11 @@ #define CONFIG_SYS_MAX_FLASH_SECT 8 #define CONFIG_SYS_MAX_FLASH_BANKS 1 -#define CONFIG_STM32_FLASH - #define CONFIG_DW_GMAC_DEFAULT_DMA_PBL (8) #define CONFIG_DW_ALTDESCRIPTOR #define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ -#define CONFIG_CMDLINE_TAG -#define CONFIG_SETUP_MEMORY_TAGS -#define CONFIG_INITRD_TAG -#define CONFIG_REVISION_TAG - #define CONFIG_SYS_CBSIZE 1024 #define CONFIG_SYS_MALLOC_LEN (1 * 1024 * 1024) diff --git a/include/configs/stm32h743-disco.h b/include/configs/stm32h743-disco.h index 6e10dbdfe9..e5bb08eec7 100644 --- a/include/configs/stm32h743-disco.h +++ b/include/configs/stm32h743-disco.h @@ -24,11 +24,6 @@ #define CONFIG_SYS_HZ_CLOCK 1000000 -#define CONFIG_CMDLINE_TAG -#define CONFIG_SETUP_MEMORY_TAGS -#define CONFIG_INITRD_TAG -#define CONFIG_REVISION_TAG - #define CONFIG_SYS_MAXARGS 16 #define CONFIG_SYS_MALLOC_LEN (1 * 1024 * 1024) diff --git a/include/configs/stm32h743-eval.h b/include/configs/stm32h743-eval.h index 268d39c7ad..89169f85d5 100644 --- a/include/configs/stm32h743-eval.h +++ b/include/configs/stm32h743-eval.h @@ -24,11 +24,6 @@ #define CONFIG_SYS_HZ_CLOCK 1000000 -#define CONFIG_CMDLINE_TAG -#define CONFIG_SETUP_MEMORY_TAGS -#define CONFIG_INITRD_TAG -#define CONFIG_REVISION_TAG - #define CONFIG_SYS_MAXARGS 16 #define CONFIG_SYS_MALLOC_LEN (1 * 1024 * 1024) diff --git a/include/configs/stm32h750-art-pi.h b/include/configs/stm32h750-art-pi.h index 3fd5461167..a9006e224a 100644 --- a/include/configs/stm32h750-art-pi.h +++ b/include/configs/stm32h750-art-pi.h @@ -24,11 +24,6 @@ #define CONFIG_SYS_HZ_CLOCK 1000000 -#define CONFIG_CMDLINE_TAG -#define CONFIG_SETUP_MEMORY_TAGS -#define CONFIG_INITRD_TAG -#define CONFIG_REVISION_TAG - #define CONFIG_SYS_MAXARGS 16 #define CONFIG_SYS_MALLOC_LEN (1 * 1024 * 1024) diff --git a/include/configs/stm32mp13_common.h b/include/configs/stm32mp13_common.h new file mode 100644 index 0000000000..a0e90762af --- /dev/null +++ b/include/configs/stm32mp13_common.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + * + * Configuration settings for the STM32MP15x CPU + */ + +#ifndef __CONFIG_STM32MP13_COMMMON_H +#define __CONFIG_STM32MP13_COMMMON_H +#include +#include + +/* + * Configuration of the external SRAM memory used by U-Boot + */ +#define CONFIG_SYS_SDRAM_BASE STM32_DDR_BASE +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + SZ_4M) + +/* + * Console I/O buffer size + */ +#define CONFIG_SYS_CBSIZE SZ_1K + +/* + * default load address used for command tftp, bootm , loadb, ... + */ +#define CONFIG_LOADADDR 0xc2000000 +#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR + +/* + * For booting Linux, use the first 256 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CONFIG_SYS_BOOTMAPSZ SZ_256M + +/* Extend size of kernel image for uncompression */ +#define CONFIG_SYS_BOOTM_LEN SZ_32M + +/*MMC SD*/ +#define CONFIG_SYS_MMC_MAX_DEVICE 2 + +/* NAND support */ +#define CONFIG_SYS_NAND_ONFI_DETECTION +#define CONFIG_SYS_MAX_NAND_DEVICE 1 + +/* Ethernet need */ +#ifdef CONFIG_DWC_ETH_QOS +#define CONFIG_SYS_NONCACHED_MEMORY (1 * SZ_1M) +#define CONFIG_SERVERIP 192.168.1.1 +#define CONFIG_BOOTP_SERVERIP +#define CONFIG_SYS_AUTOLOAD "no" +#endif + +/*****************************************************************************/ +#ifdef CONFIG_DISTRO_DEFAULTS +/*****************************************************************************/ + +#ifdef CONFIG_CMD_MMC +#define BOOT_TARGET_MMC0(func) func(MMC, mmc, 0) +#define BOOT_TARGET_MMC1(func) func(MMC, mmc, 1) +#else +#define BOOT_TARGET_MMC0(func) +#define BOOT_TARGET_MMC1(func) +#endif + +#ifdef CONFIG_NET +#define BOOT_TARGET_PXE(func) func(PXE, pxe, na) +#else +#define BOOT_TARGET_PXE(func) +#endif + +#ifdef CONFIG_CMD_UBIFS +#define BOOT_TARGET_UBIFS(func) func(UBIFS, ubifs, 0) +#else +#define BOOT_TARGET_UBIFS(func) +#endif + +#ifdef CONFIG_CMD_USB +#define BOOT_TARGET_USB(func) func(USB, usb, 0) +#else +#define BOOT_TARGET_USB(func) +#endif + +#define BOOT_TARGET_DEVICES(func) \ + BOOT_TARGET_MMC1(func) \ + BOOT_TARGET_UBIFS(func) \ + BOOT_TARGET_MMC0(func) \ + BOOT_TARGET_USB(func) \ + BOOT_TARGET_PXE(func) + +/* + * default bootcmd for stm32mp13: + * for serial/usb: execute the stm32prog command + * for mmc boot (eMMC, SD card), distro boot on the same mmc device + * for nand or spi-nand boot, distro boot with ubifs on UBI partition + * for nor boot, use the default distro order in ${boot_targets} + */ +#define STM32MP_BOOTCMD "bootcmd_stm32mp=" \ + "echo \"Boot over ${boot_device}${boot_instance}!\";" \ + "if test ${boot_device} = serial || test ${boot_device} = usb;" \ + "then stm32prog ${boot_device} ${boot_instance}; " \ + "else " \ + "run env_check;" \ + "if test ${boot_device} = mmc;" \ + "then env set boot_targets \"mmc${boot_instance}\"; fi;" \ + "if test ${boot_device} = nand ||" \ + " test ${boot_device} = spi-nand ;" \ + "then env set boot_targets ubifs0; fi;" \ + "run distro_bootcmd;" \ + "fi;\0" + +#define STM32MP_EXTRA \ + "env_check=if env info -p -d -q; then env save; fi\0" \ + "boot_net_usb_start=true\0" + +#ifndef STM32MP_BOARD_EXTRA_ENV +#define STM32MP_BOARD_EXTRA_ENV +#endif + +#include + +/* + * memory layout for 32M uncompressed/compressed kernel, + * 1M fdt, 1M script, 1M pxe and 1M for overlay + * and the ramdisk at the end. + */ +#define __KERNEL_ADDR_R __stringify(0xc2000000) +#define __FDT_ADDR_R __stringify(0xc4000000) +#define __SCRIPT_ADDR_R __stringify(0xc4100000) +#define __PXEFILE_ADDR_R __stringify(0xc4200000) +#define __FDTOVERLAY_ADDR_R __stringify(0xc4300000) +#define __RAMDISK_ADDR_R __stringify(0xc4400000) + +#define STM32MP_MEM_LAYOUT \ + "kernel_addr_r=" __KERNEL_ADDR_R "\0" \ + "fdt_addr_r=" __FDT_ADDR_R "\0" \ + "scriptaddr=" __SCRIPT_ADDR_R "\0" \ + "pxefile_addr_r=" __PXEFILE_ADDR_R "\0" \ + "fdtoverlay_addr_r=" __FDTOVERLAY_ADDR_R "\0" \ + "ramdisk_addr_r=" __RAMDISK_ADDR_R "\0" + +#define CONFIG_EXTRA_ENV_SETTINGS \ + STM32MP_MEM_LAYOUT \ + STM32MP_BOOTCMD \ + BOOTENV \ + STM32MP_EXTRA \ + STM32MP_BOARD_EXTRA_ENV + +#endif /* ifdef CONFIG_DISTRO_DEFAULTS*/ + +#endif /* __CONFIG_STM32MP13_COMMMON_H */ diff --git a/include/configs/stm32mp13_st_common.h b/include/configs/stm32mp13_st_common.h new file mode 100644 index 0000000000..41681537a2 --- /dev/null +++ b/include/configs/stm32mp13_st_common.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * Configuration settings for the STMicroelectonics STM32MP15x boards + */ + +#ifndef __CONFIG_STM32MP13_ST_COMMON_H__ +#define __CONFIG_STM32MP13_ST_COMMON_H__ + +#define STM32MP_BOARD_EXTRA_ENV \ + "usb_pgood_delay=1000\0" \ + "console=ttySTM0\0" + +#include + +/* uart with on-board st-link */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, \ + 230400, 460800, 921600, \ + 1000000, 2000000, 4000000} + +#ifdef CONFIG_EXTRA_ENV_SETTINGS +/* + * default bootcmd for stm32mp13 STMicroelectronics boards: + * for serial/usb: execute the stm32prog command + * for mmc boot (eMMC, SD card), distro boot on the same mmc device + * for nand or spi-nand boot, distro boot with ubifs on UBI partition + * for nor boot, distro boot on SD card = mmc0 ONLY ! + */ +#define ST_STM32MP13_BOOTCMD "bootcmd_stm32mp=" \ + "echo \"Boot over ${boot_device}${boot_instance}!\";" \ + "if test ${boot_device} = serial || test ${boot_device} = usb;" \ + "then stm32prog ${boot_device} ${boot_instance}; " \ + "else " \ + "run env_check;" \ + "if test ${boot_device} = mmc;" \ + "then env set boot_targets \"mmc${boot_instance}\"; fi;" \ + "if test ${boot_device} = nand ||" \ + " test ${boot_device} = spi-nand ;" \ + "then env set boot_targets ubifs0; fi;" \ + "if test ${boot_device} = nor;" \ + "then env set boot_targets mmc0; fi;" \ + "run distro_bootcmd;" \ + "fi;\0" + +#undef CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS \ + STM32MP_MEM_LAYOUT \ + ST_STM32MP13_BOOTCMD \ + BOOTENV \ + STM32MP_EXTRA \ + STM32MP_BOARD_EXTRA_ENV + +#endif +#endif diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp15_common.h similarity index 76% rename from include/configs/stm32mp1.h rename to include/configs/stm32mp15_common.h index b372838be8..58971cc656 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp15_common.h @@ -5,12 +5,12 @@ * Configuration settings for the STM32MP15x CPU */ -#ifndef __CONFIG_H -#define __CONFIG_H +#ifndef __CONFIG_STM32MP15_COMMMON_H +#define __CONFIG_STM32MP15_COMMMON_H #include #include -#ifndef CONFIG_TFABOOT +#ifdef CONFIG_ARMV7_PSCI /* PSCI support */ #define CONFIG_ARMV7_SECURE_BASE STM32_SYSRAM_BASE #define CONFIG_ARMV7_SECURE_MAX_SIZE STM32_SYSRAM_SIZE @@ -20,7 +20,7 @@ * Configuration of the external SRAM memory used by U-Boot */ #define CONFIG_SYS_SDRAM_BASE STM32_DDR_BASE -#define CONFIG_SYS_INIT_SP_ADDR CONFIG_SYS_TEXT_BASE +#define CONFIG_SYS_INIT_SP_ADDR CONFIG_SYS_TEXT_BASE /* * Console I/O buffer size @@ -33,11 +33,6 @@ #define CONFIG_LOADADDR 0xc2000000 #define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR -/* ATAGs */ -#define CONFIG_CMDLINE_TAG -#define CONFIG_SETUP_MEMORY_TAGS -#define CONFIG_INITRD_TAG - /* * For booting Linux, use the first 256 MB of memory, since this is * the maximum mapped by the Linux kernel during initialization. @@ -116,11 +111,11 @@ BOOT_TARGET_PXE(func) /* - * bootcmd for stm32mp1: + * default bootcmd for stm32mp15: * for serial/usb: execute the stm32prog command - * for mmc boot (eMMC, SD card), boot only on the same device - * for nand or spi-nand boot, boot with on ubifs partition on UBI partition - * for nor boot, use SD card = mmc0 + * for mmc boot (eMMC, SD card), distro boot on the same mmc device + * for nand or spi-nand boot, distro boot with ubifs on UBI partition + * for nor boot, use the default distro order in ${boot_targets} */ #define STM32MP_BOOTCMD "bootcmd_stm32mp=" \ "echo \"Boot over ${boot_device}${boot_instance}!\";" \ @@ -133,14 +128,12 @@ "if test ${boot_device} = nand ||" \ " test ${boot_device} = spi-nand ;" \ "then env set boot_targets ubifs0; fi;" \ - "if test ${boot_device} = nor;" \ - "then env set boot_targets mmc0; fi;" \ "run distro_bootcmd;" \ "fi;\0" #ifdef CONFIG_FASTBOOT_CMD_OEM_FORMAT /* eMMC default partitions for fastboot command: oem format */ -#define PARTS_DEFAULT \ +#define STM32MP_PARTS_DEFAULT \ "partitions=" \ "name=ssbl,size=2M;" \ "name=bootfs,size=64MB,bootable;" \ @@ -148,7 +141,15 @@ "name=rootfs,size=746M;" \ "name=userfs,size=-\0" #else -#define PARTS_DEFAULT +#define STM32MP_PARTS_DEFAULT +#endif + +#define STM32MP_EXTRA \ + "env_check=if env info -p -d -q; then env save; fi\0" \ + "boot_net_usb_start=true\0" + +#ifndef STM32MP_BOARD_EXTRA_ENV +#define STM32MP_BOARD_EXTRA_ENV #endif #include @@ -158,21 +159,30 @@ * 1M fdt, 1M script, 1M pxe and 1M for overlay * and the ramdisk at the end. */ +#define __KERNEL_ADDR_R __stringify(0xc2000000) +#define __FDT_ADDR_R __stringify(0xc4000000) +#define __SCRIPT_ADDR_R __stringify(0xc4100000) +#define __PXEFILE_ADDR_R __stringify(0xc4200000) +#define __FDTOVERLAY_ADDR_R __stringify(0xc4300000) +#define __RAMDISK_ADDR_R __stringify(0xc4400000) + +#define STM32MP_MEM_LAYOUT \ + "kernel_addr_r=" __KERNEL_ADDR_R "\0" \ + "fdt_addr_r=" __FDT_ADDR_R "\0" \ + "scriptaddr=" __SCRIPT_ADDR_R "\0" \ + "pxefile_addr_r=" __PXEFILE_ADDR_R "\0" \ + "fdtoverlay_addr_r=" __FDTOVERLAY_ADDR_R "\0" \ + "ramdisk_addr_r=" __RAMDISK_ADDR_R "\0" + #define CONFIG_EXTRA_ENV_SETTINGS \ - "kernel_addr_r=0xc2000000\0" \ - "fdt_addr_r=0xc4000000\0" \ - "scriptaddr=0xc4100000\0" \ - "pxefile_addr_r=0xc4200000\0" \ - "fdtoverlay_addr_r=0xc4300000\0" \ - "ramdisk_addr_r=0xc4400000\0" \ - "altbootcmd=run bootcmd\0" \ - "env_check=if env info -p -d -q; then env save; fi\0" \ + STM32MP_MEM_LAYOUT \ STM32MP_BOOTCMD \ - PARTS_DEFAULT \ + STM32MP_PARTS_DEFAULT \ BOOTENV \ - "boot_net_usb_start=true\0" + STM32MP_EXTRA \ + STM32MP_BOARD_EXTRA_ENV #endif /* ifndef CONFIG_SPL_BUILD */ #endif /* ifdef CONFIG_DISTRO_DEFAULTS*/ -#endif /* __CONFIG_H */ +#endif /* __CONFIG_STM32MP15_COMMMON_H */ diff --git a/include/configs/stm32mp15_dh_dhsom.h b/include/configs/stm32mp15_dh_dhsom.h new file mode 100644 index 0000000000..c79f0272cb --- /dev/null +++ b/include/configs/stm32mp15_dh_dhsom.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2020 Marek Vasut + * + * Configuration settings for the DH STM32MP15x SoMs + */ + +#ifndef __CONFIG_STM32MP15_DH_DHSOM_H__ +#define __CONFIG_STM32MP15_DH_DHSOM_H__ + +/* PHY needs a longer autoneg timeout */ +#define PHY_ANEG_TIMEOUT 20000 + +#define STM32MP_BOARD_EXTRA_ENV \ + "usb_pgood_delay=1000\0" \ + "update_sf=" /* Erase SPI NOR and install U-Boot from SD */ \ + "setexpr loadaddr1 ${loadaddr} + 0x1000000 && " \ + "load mmc 0:4 ${loadaddr1} /boot/u-boot-spl.stm32 && " \ + "env set filesize1 ${filesize} && " \ + "load mmc 0:4 ${loadaddr} /boot/u-boot.itb && " \ + "sf probe && sf erase 0 0x200000 && " \ + "sf update ${loadaddr1} 0 ${filesize1} && " \ + "sf update ${loadaddr1} 0x40000 ${filesize1} && " \ + "sf update ${loadaddr} 0x80000 ${filesize} && " \ + "env set filesize1 && env set loadaddr1\0" + +#include + +#define CONFIG_SPL_TARGET "u-boot.itb" + +#endif diff --git a/include/configs/stm32mp15_st_common.h b/include/configs/stm32mp15_st_common.h new file mode 100644 index 0000000000..c395f7f986 --- /dev/null +++ b/include/configs/stm32mp15_st_common.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + * + * Configuration settings for the STMicroelectonics STM32MP15x boards + */ + +#ifndef __CONFIG_STM32MP15_ST_COMMON_H__ +#define __CONFIG_STM32MP15_ST_COMMON_H__ + +#define STM32MP_BOARD_EXTRA_ENV \ + "usb_pgood_delay=1000\0" \ + "console=ttySTM0\0" + +#include + +/* uart with on-board st-link */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, \ + 230400, 460800, 921600, \ + 1000000, 2000000 } + +#ifdef CONFIG_EXTRA_ENV_SETTINGS +/* + * default bootcmd for stm32mp1 STMicroelectronics boards: + * for serial/usb: execute the stm32prog command + * for mmc boot (eMMC, SD card), distro boot on the same mmc device + * for nand or spi-nand boot, distro boot with ubifs on UBI partition + * for nor boot, distro boot on SD card = mmc0 ONLY ! + */ +#define ST_STM32MP1_BOOTCMD "bootcmd_stm32mp=" \ + "echo \"Boot over ${boot_device}${boot_instance}!\";" \ + "if test ${boot_device} = serial || test ${boot_device} = usb;" \ + "then stm32prog ${boot_device} ${boot_instance}; " \ + "else " \ + "run env_check;" \ + "if test ${boot_device} = mmc;" \ + "then env set boot_targets \"mmc${boot_instance}\"; fi;" \ + "if test ${boot_device} = nand ||" \ + " test ${boot_device} = spi-nand ;" \ + "then env set boot_targets ubifs0; fi;" \ + "if test ${boot_device} = nor;" \ + "then env set boot_targets mmc0; fi;" \ + "run distro_bootcmd;" \ + "fi;\0" + +#undef CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS \ + STM32MP_MEM_LAYOUT \ + ST_STM32MP1_BOOTCMD \ + STM32MP_PARTS_DEFAULT \ + BOOTENV \ + STM32MP_EXTRA \ + STM32MP_BOARD_EXTRA_ENV + +#endif +#endif diff --git a/include/dm/lists.h b/include/dm/lists.h index 1a86552546..5896ae3658 100644 --- a/include/dm/lists.h +++ b/include/dm/lists.h @@ -53,13 +53,14 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only); * @parent: parent device (root) * @node: device tree node to bind * @devp: if non-NULL, returns a pointer to the bound device + * @drv: if non-NULL, force this driver to be bound * @pre_reloc_only: If true, bind only nodes with special devicetree properties, * or drivers with the DM_FLAG_PRE_RELOC flag. If false bind all drivers. * @return 0 if device was bound, -EINVAL if the device tree is invalid, * other -ve value on error */ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, - bool pre_reloc_only); + struct driver *drv, bool pre_reloc_only); /** * device_bind_driver() - bind a device to a driver diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index 695e78ad0d..137533cebc 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -6,7 +6,7 @@ #ifndef __PINCTRL_H #define __PINCTRL_H -#define PINNAME_SIZE 10 +#define PINNAME_SIZE 16 #define PINMUX_SIZE 40 /** diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index e7edd409f3..62ad7a5300 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -118,10 +118,12 @@ enum uclass_id { UCLASS_TIMER, /* Timer device */ UCLASS_TPM, /* Trusted Platform Module TIS interface */ UCLASS_UFS, /* Universal Flash Storage */ + UCLASS_UCSI, /* USB Type-C Connector System Software Interface */ UCLASS_USB, /* USB bus */ UCLASS_USB_DEV_GENERIC, /* USB generic device */ UCLASS_USB_HUB, /* USB hub */ UCLASS_USB_GADGET_GENERIC, /* USB generic device */ + UCLASS_USB_TYPEC, /* USB Type-C */ UCLASS_VIDEO, /* Video or LCD device */ UCLASS_VIDEO_BRIDGE, /* Video bridge, e.g. DisplayPort to LVDS */ UCLASS_VIDEO_CONSOLE, /* Text console driver for video device */ diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h index 4cdaf13582..2e23e0384b 100644 --- a/include/dt-bindings/clock/stm32mp1-clks.h +++ b/include/dt-bindings/clock/stm32mp1-clks.h @@ -179,6 +179,12 @@ #define DAC12_K 168 #define ETHPTP_K 169 +#define PCLK1 170 +#define PCLK2 171 +#define PCLK3 172 +#define PCLK4 173 +#define PCLK5 174 + /* PLL */ #define PLL1 176 #define PLL2 177 @@ -248,4 +254,27 @@ #define STM32MP1_LAST_CLK 232 +/* SCMI clock identifiers */ +#define CK_SCMI_HSE 0 +#define CK_SCMI_HSI 1 +#define CK_SCMI_CSI 2 +#define CK_SCMI_LSE 3 +#define CK_SCMI_LSI 4 +#define CK_SCMI_PLL2_Q 5 +#define CK_SCMI_PLL2_R 6 +#define CK_SCMI_MPU 7 +#define CK_SCMI_AXI 8 +#define CK_SCMI_BSEC 9 +#define CK_SCMI_CRYP1 10 +#define CK_SCMI_GPIOZ 11 +#define CK_SCMI_HASH1 12 +#define CK_SCMI_I2C4 13 +#define CK_SCMI_I2C6 14 +#define CK_SCMI_IWDG1 15 +#define CK_SCMI_RNG1 16 +#define CK_SCMI_RTC 17 +#define CK_SCMI_RTCAPB 18 +#define CK_SCMI_SPI6 19 +#define CK_SCMI_USART1 20 + #endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ diff --git a/include/dt-bindings/clock/stm32mp13-clks.h b/include/dt-bindings/clock/stm32mp13-clks.h new file mode 100644 index 0000000000..02befd25ed --- /dev/null +++ b/include/dt-bindings/clock/stm32mp13-clks.h @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2020 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP13_CLKS_H_ +#define _DT_BINDINGS_STM32MP13_CLKS_H_ + +/* OSCILLATOR clocks */ +#define CK_HSE 0 +#define CK_CSI 1 +#define CK_LSI 2 +#define CK_LSE 3 +#define CK_HSI 4 +#define CK_HSE_DIV2 5 + +/* PLL */ +#define PLL1 6 +#define PLL2 7 +#define PLL3 8 +#define PLL4 9 + +/* ODF */ +#define PLL1_P 10 +#define PLL1_Q 11 +#define PLL1_R 12 +#define PLL2_P 13 +#define PLL2_Q 14 +#define PLL2_R 15 +#define PLL3_P 16 +#define PLL3_Q 17 +#define PLL3_R 18 +#define PLL4_P 19 +#define PLL4_Q 20 +#define PLL4_R 21 + +#define PCLK1 22 +#define PCLK2 23 +#define PCLK3 24 +#define PCLK4 25 +#define PCLK5 26 +#define PCLK6 27 + +/* SYSTEM CLOCK */ +#define CK_PER 28 +#define CK_MPU 29 +#define CK_AXI 30 +#define CK_MLAHB 31 + +/* BASE TIMER */ +#define CK_TIMG1 32 +#define CK_TIMG2 33 +#define CK_TIMG3 34 + +/* AUX */ +#define RTC 35 + +/* TRACE & DEBUG clocks */ +#define CK_DBG 36 +#define CK_TRACE 37 + +/* MCO clocks */ +#define CK_MCO1 38 +#define CK_MCO2 39 + +/* IP clocks */ +#define SYSCFG 40 +#define VREF 41 +#define DTS 42 +#define PMBCTRL 43 +#define HDP 44 +#define IWDG2 45 +#define STGENRO 46 +#define USART1 47 +#define RTCAPB 48 +#define TZC 49 +#define TZPC 50 +#define IWDG1 51 +#define BSEC 52 +#define DMA1 53 +#define DMA2 54 +#define DMAMUX1 55 +#define DMAMUX2 56 +#define GPIOA 57 +#define GPIOB 58 +#define GPIOC 59 +#define GPIOD 60 +#define GPIOE 61 +#define GPIOF 62 +#define GPIOG 63 +#define GPIOH 64 +#define GPIOI 65 +#define CRYP1 66 +#define HASH1 67 +#define BKPSRAM 68 +#define MDMA 69 +#define CRC1 70 +#define USBH 71 +#define DMA3 72 +#define TSC 73 +#define PKA 74 +#define AXIMC 75 +#define MCE 76 +#define ETH1TX 77 +#define ETH2TX 78 +#define ETH1RX 79 +#define ETH2RX 80 +#define ETH1MAC 81 +#define ETH2MAC 82 +#define ETH1STP 83 +#define ETH2STP 84 + +/* IP clocks with parents */ +#define SDMMC1_K 85 +#define SDMMC2_K 86 +#define ADC1_K 87 +#define ADC2_K 88 +#define FMC_K 89 +#define QSPI_K 90 +#define RNG1_K 91 +#define USBPHY_K 92 +#define STGEN_K 93 +#define SPDIF_K 94 +#define SPI1_K 95 +#define SPI2_K 96 +#define SPI3_K 97 +#define SPI4_K 98 +#define SPI5_K 99 +#define I2C1_K 100 +#define I2C2_K 101 +#define I2C3_K 102 +#define I2C4_K 103 +#define I2C5_K 104 +#define TIM2_K 105 +#define TIM3_K 106 +#define TIM4_K 107 +#define TIM5_K 108 +#define TIM6_K 109 +#define TIM7_K 110 +#define TIM12_K 111 +#define TIM13_K 112 +#define TIM14_K 113 +#define TIM1_K 114 +#define TIM8_K 115 +#define TIM15_K 116 +#define TIM16_K 117 +#define TIM17_K 118 +#define LPTIM1_K 119 +#define LPTIM2_K 120 +#define LPTIM3_K 121 +#define LPTIM4_K 122 +#define LPTIM5_K 123 +#define USART1_K 124 +#define USART2_K 125 +#define USART3_K 126 +#define UART4_K 127 +#define UART5_K 128 +#define USART6_K 129 +#define UART7_K 130 +#define UART8_K 131 +#define DFSDM_K 132 +#define FDCAN_K 133 +#define SAI1_K 134 +#define SAI2_K 135 +#define ADFSDM_K 136 +#define USBO_K 137 +#define LTDC_PX 138 +#define ETH1CK_K 139 +#define ETH1PTP_K 140 +#define ETH2CK_K 141 +#define ETH2PTP_K 142 +#define DCMIPP_K 143 +#define SAES_K 144 +#define DTS_K 145 + +/* DDR */ +#define DDRC1 146 +#define DDRC1LP 147 +#define DDRC2 148 +#define DDRC2LP 149 +#define DDRPHYC 150 +#define DDRPHYCLP 151 +#define DDRCAPB 152 +#define DDRCAPBLP 153 +#define AXIDCG 154 +#define DDRPHYCAPB 155 +#define DDRPHYCAPBLP 156 +#define DDRPERFM 157 + +#define ADC1 158 +#define ADC2 159 +#define SAI1 160 +#define SAI2 161 + +#define STM32MP1_LAST_CLK 162 + +/* SCMI clock identifiers */ +#define CK_SCMI_HSE 0 +#define CK_SCMI_HSI 1 +#define CK_SCMI_CSI 2 +#define CK_SCMI_LSE 3 +#define CK_SCMI_LSI 4 +#define CK_SCMI_HSE_DIV2 5 +#define CK_SCMI_PLL2_Q 6 +#define CK_SCMI_PLL2_R 7 +#define CK_SCMI_PLL3_P 8 +#define CK_SCMI_PLL3_Q 9 +#define CK_SCMI_PLL3_R 10 +#define CK_SCMI_PLL4_P 11 +#define CK_SCMI_PLL4_Q 12 +#define CK_SCMI_PLL4_R 13 +#define CK_SCMI_MPU 14 +#define CK_SCMI_AXI 15 +#define CK_SCMI_MLAHB 16 +#define CK_SCMI_CKPER 17 +#define CK_SCMI_PCLK1 18 +#define CK_SCMI_PCLK2 19 +#define CK_SCMI_PCLK3 20 +#define CK_SCMI_PCLK4 21 +#define CK_SCMI_PCLK5 22 +#define CK_SCMI_PCLK6 23 +#define CK_SCMI_CKTIMG1 24 +#define CK_SCMI_CKTIMG2 25 +#define CK_SCMI_CKTIMG3 26 +#define CK_SCMI_RTC 27 +#define CK_SCMI_RTCAPB 28 + +#endif /* _DT_BINDINGS_STM32MP13_CLKS_H_ */ diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h index e6fb8ada3f..370a25a936 100644 --- a/include/dt-bindings/pinctrl/stm32-pinfunc.h +++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h @@ -26,6 +26,7 @@ #define AF14 0xf #define AF15 0x10 #define ANALOG 0x11 +#define RSVD 0x12 /* define Pins number*/ #define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h index 702da37a2e..bdbf9e2530 100644 --- a/include/dt-bindings/reset/stm32mp1-resets.h +++ b/include/dt-bindings/reset/stm32mp1-resets.h @@ -106,4 +106,18 @@ #define GPIOJ_R 19785 #define GPIOK_R 19786 +/* SCMI reset domain identifiers */ +#define RST_SCMI_SPI6 0 +#define RST_SCMI_I2C4 1 +#define RST_SCMI_I2C6 2 +#define RST_SCMI_USART1 3 +#define RST_SCMI_STGEN 4 +#define RST_SCMI_GPIOZ 5 +#define RST_SCMI_CRYP1 6 +#define RST_SCMI_HASH1 7 +#define RST_SCMI_RNG1 8 +#define RST_SCMI_MDMA 9 +#define RST_SCMI_MCU 10 +#define RST_SCMI_MCU_HOLD_BOOT 11 + #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ diff --git a/include/dt-bindings/reset/stm32mp13-resets.h b/include/dt-bindings/reset/stm32mp13-resets.h new file mode 100644 index 0000000000..934864e90d --- /dev/null +++ b/include/dt-bindings/reset/stm32mp13-resets.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP13_RESET_H_ +#define _DT_BINDINGS_STM32MP13_RESET_H_ + +#define TIM2_R 13568 +#define TIM3_R 13569 +#define TIM4_R 13570 +#define TIM5_R 13571 +#define TIM6_R 13572 +#define TIM7_R 13573 +#define LPTIM1_R 13577 +#define SPI2_R 13579 +#define SPI3_R 13580 +#define USART3_R 13583 +#define UART4_R 13584 +#define UART5_R 13585 +#define UART7_R 13586 +#define UART8_R 13587 +#define I2C1_R 13589 +#define I2C2_R 13590 +#define SPDIF_R 13594 +#define TIM1_R 13632 +#define TIM8_R 13633 +#define SPI1_R 13640 +#define USART6_R 13645 +#define SAI1_R 13648 +#define SAI2_R 13649 +#define DFSDM_R 13652 +#define FDCAN_R 13656 +#define LPTIM2_R 13696 +#define LPTIM3_R 13697 +#define LPTIM4_R 13698 +#define LPTIM5_R 13699 +#define SYSCFG_R 13707 +#define VREF_R 13709 +#define DTS_R 13712 +#define PMBCTRL_R 13713 +#define LTDC_R 13760 +#define DCMIPP_R 13761 +#define DDRPERFM_R 13768 +#define USBPHY_R 13776 +#define STGEN_R 13844 +#define USART1_R 13888 +#define USART2_R 13889 +#define SPI4_R 13890 +#define SPI5_R 13891 +#define I2C3_R 13892 +#define I2C4_R 13893 +#define I2C5_R 13894 +#define TIM12_R 13895 +#define TIM13_R 13896 +#define TIM14_R 13897 +#define TIM15_R 13898 +#define TIM16_R 13899 +#define TIM17_R 13900 +#define DMA1_R 13952 +#define DMA2_R 13953 +#define DMAMUX1_R 13954 +#define DMA3_R 13955 +#define DMAMUX2_R 13956 +#define ADC1_R 13957 +#define ADC2_R 13958 +#define USBO_R 13960 +#define GPIOA_R 14080 +#define GPIOB_R 14081 +#define GPIOC_R 14082 +#define GPIOD_R 14083 +#define GPIOE_R 14084 +#define GPIOF_R 14085 +#define GPIOG_R 14086 +#define GPIOH_R 14087 +#define GPIOI_R 14088 +#define TSC_R 14095 +#define PKA_R 14146 +#define SAES_R 14147 +#define CRYP1_R 14148 +#define HASH1_R 14149 +#define RNG1_R 14150 +#define AXIMC_R 14160 +#define MDMA_R 14208 +#define MCE_R 14209 +#define ETH1MAC_R 14218 +#define FMC_R 14220 +#define QSPI_R 14222 +#define SDMMC1_R 14224 +#define SDMMC2_R 14225 +#define CRC1_R 14228 +#define USBH_R 14232 +#define ETH2MAC_R 14238 + +/* SCMI reset domain identifiers */ +#define RST_SCMI_LTDC 0 +#define RST_SCMI_MDMA 1 + +#endif /* _DT_BINDINGS_STM32MP13_RESET_H_ */ diff --git a/include/dt-bindings/rtc/rtc-stm32.h b/include/dt-bindings/rtc/rtc-stm32.h new file mode 100644 index 0000000000..2fd78c2e62 --- /dev/null +++ b/include/dt-bindings/rtc/rtc-stm32.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides constants for STM32_RTC bindings. + */ + +#ifndef _DT_BINDINGS_RTC_RTC_STM32_H +#define _DT_BINDINGS_RTC_RTC_STM32_H + +#define RTC_NO_OUT 0 +#define RTC_OUT1 1 +#define RTC_OUT2 2 +#define RTC_OUT2_RMP 3 + +#endif diff --git a/include/dt-bindings/soc/stm32-hdp.h b/include/dt-bindings/soc/stm32-hdp.h new file mode 100644 index 0000000000..d986653272 --- /dev/null +++ b/include/dt-bindings/soc/stm32-hdp.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Roullier Christophe + * for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32_HDP_H +#define _DT_BINDINGS_STM32_HDP_H + +#define STM32_HDP(port, value) ((value) << ((port) * 4)) + +/* define HDP Pins number*/ +#define HDP0_PWR_PWRWAKE_SYS 0 +#define HDP0_CM4_SLEEPDEEP 1 +#define HDP0_PWR_STDBY_WKUP 2 +#define HDP0_PWR_ENCOMP_VDDCORE 3 +#define HDP0_BSEC_OUT_SEC_NIDEN 4 +#define HDP0_RCC_CM4_SLEEPDEEP 6 +#define HDP0_GPU_DBG7 7 +#define HDP0_DDRCTRL_LP_REQ 8 +#define HDP0_PWR_DDR_RET_ENABLE_N 9 +#define HDP0_GPOVAL_0 15 + +#define HDP1_PWR_PWRWAKE_MCU 0 +#define HDP1_CM4_HALTED 1 +#define HDP1_CA7_NAXIERRIRQ 2 +#define HDP1_PWR_OKIN_MR 3 +#define HDP1_BSEC_OUT_SEC_DBGEN 4 +#define HDP1_EXTI_SYS_WAKEUP 5 +#define HDP1_RCC_PWRDS_MPU 6 +#define HDP1_GPU_DBG6 7 +#define HDP1_DDRCTRL_DFI_CTRLUPD_REQ 8 +#define HDP1_DDRCTRL_CACTIVE_DDRC_ASR 9 +#define HDP1_GPOVAL_1 15 + +#define HDP2_PWR_PWRWAKE_MPU 0 +#define HDP2_CM4_RXEV 1 +#define HDP2_CA7_NPMUIRQ1 2 +#define HDP2_CA7_NFIQOUT1 3 +#define HDP2_BSEC_IN_RSTCORE_N 4 +#define HDP2_EXTI_C2_WAKEUP 5 +#define HDP2_RCC_PWRDS_MCU 6 +#define HDP2_GPU_DBG5 7 +#define HDP2_DDRCTRL_DFI_INIT_COMPLETE 8 +#define HDP2_DDRCTRL_PERF_OP_IS_REFRESH 9 +#define HDP2_DDRCTRL_GSKP_DFI_LP_REQ 10 +#define HDP2_GPOVAL_2 15 + +#define HDP3_PWR_SEL_VTH_VDD_CORE 0 +#define HDP3_CM4_TXEV 1 +#define HDP3_CA7_NPMUIRQ0 2 +#define HDP3_CA7_NFIQOUT0 3 +#define HDP3_BSEC_OUT_SEC_DFTLOCK 4 +#define HDP3_EXTI_C1_WAKEUP 5 +#define HDP3_RCC_PWRDS_SYS 6 +#define HDP3_GPU_DBG4 7 +#define HDP3_DDRCTRL_STAT_DDRC_REG_SELREF_TYPE0 8 +#define HDP3_DDRCTRL_CACTIVE_1 9 +#define HDP3_GPOVAL_3 15 + +#define HDP4_PWR_PDDS 0 +#define HDP4_CM4_SLEEPING 1 +#define HDP4_CA7_NRESET1 2 +#define HDP4_CA7_NIRQOUT1 3 +#define HDP4_BSEC_OUT_SEC_DFTEN 4 +#define HDP4_BSEC_OUT_SEC_DBGSWENABLE 5 +#define HDP4_ETH_OUT_PMT_INTR_O 6 +#define HDP4_GPU_DBG3 7 +#define HDP4_DDRCTRL_STAT_DDRC_REG_SELREF_TYPE1 8 +#define HDP4_DDRCTRL_CACTIVE_0 9 +#define HDP4_GPOVAL_4 15 + +#define HDP5_CA7_STANDBYWFIL2 0 +#define HDP5_PWR_VTH_VDDCORE_ACK 1 +#define HDP5_CA7_NRESET0 2 +#define HDP5_CA7_NIRQOUT0 3 +#define HDP5_BSEC_IN_PWROK 4 +#define HDP5_BSEC_OUT_SEC_DEVICEEN 5 +#define HDP5_ETH_OUT_LPI_INTR_O 6 +#define HDP5_GPU_DBG2 7 +#define HDP5_DDRCTRL_CACTIVE_DDRC 8 +#define HDP5_DDRCTRL_WR_CREDIT_CNT 9 +#define HDP5_GPOVAL_5 15 + +#define HDP6_CA7_STANDBYWFI1 0 +#define HDP6_CA7_STANDBYWFE1 1 +#define HDP6_CA7_EVENT0 2 +#define HDP6_CA7_DBGACK1 3 +#define HDP6_BSEC_OUT_SEC_SPNIDEN 5 +#define HDP6_ETH_OUT_MAC_SPEED_O1 6 +#define HDP6_GPU_DBG1 7 +#define HDP6_DDRCTRL_CSYSACK_DDRC 8 +#define HDP6_DDRCTRL_LPR_CREDIT_CNT 9 +#define HDP6_GPOVAL_6 15 + +#define HDP7_CA7_STANDBYWFI0 0 +#define HDP7_CA7_STANDBYWFE0 1 +#define HDP7_CA7_DBGACK0 3 +#define HDP7_BSEC_OUT_FUSE_OK 4 +#define HDP7_BSEC_OUT_SEC_SPIDEN 5 +#define HDP7_ETH_OUT_MAC_SPEED_O0 6 +#define HDP7_GPU_DBG0 7 +#define HDP7_DDRCTRL_CSYSREQ_DDRC 8 +#define HDP7_DDRCTRL_HPR_CREDIT_CNT 9 +#define HDP7_GPOVAL_7 15 + +#endif /* _DT_BINDINGS_STM32_HDP_H */ diff --git a/include/dt-bindings/soc/stm32mp13-hdp.h b/include/dt-bindings/soc/stm32mp13-hdp.h new file mode 100644 index 0000000000..091c1c8358 --- /dev/null +++ b/include/dt-bindings/soc/stm32mp13-hdp.h @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Roullier Christophe + * for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32_HDP_H +#define _DT_BINDINGS_STM32_HDP_H + +#define STM32_HDP(port, value) ((value) << ((port) * 4)) + +/* define HDP Pins number*/ +#define HDP0_PWR_PWRWAKE_SYS 0 +#define HDP0_PWR_STOP_FORBIDDEN 1 +#define HDP0_PWR_STDBY_WKUP 2 +#define HDP0_PWR_ENCOMP_VDDCORE 3 +#define HDP0_BSEC_OUT_SEC_NIDEN 4 +#define HDP0_AIEC_SYS_WAKEUP 5 +#define HDP0_DDRCTRL_LP_REQ 8 +#define HDP0_PWR_DDR_RET_ENABLE_N 9 +#define HDP0_DTS_CLK_PTAT 10 +#define HDP0_SRAM3CTRL_TAMP_ERASE_ACT 12 +#define HDP0_GPOVAL_0 15 + +#define HDP1_PWR_SEL_VTH_VDDCPU 0 +#define HDP1_PWR_MPU_RAM_LOWSPEED 1 +#define HDP1_CA7_NAXIERRIRQ 2 +#define HDP1_PWR_OKIN_MR 3 +#define HDP1_BSEC_OUT_SEC_DBGEN 4 +#define HDP1_AIEC_C1_WAKEUP 5 +#define HDP1_RCC_PWRDS_MPU 6 +#define HDP1_DDRCTRL_DFI_CTRLUPD_REQ 8 +#define HDP1_DDRCTRL_CACTIVE_DDRC_ASR 9 +#define HDP1_SRAM3CTRL_HW_ERASE_ACT 12 +#define HDP1_NIC400_S0_BREADY 13 +#define HDP1_GPOVAL_1 15 + +#define HDP2_PWR_PWRWAKE_MPU 0 +#define HDP2_PWR_MPU_CLOCK_DISABLE_ACK 1 +#define HDP2_CA7_NDGBRESET_I 2 +#define HDP2_BSEC_IN_RSTCORE_N 4 +#define HDP2_BSEC_OUT_SEC_BSC_DIS 5 +#define HDP2_DDRCTRL_DFI_INIT_COMPLETE 8 +#define HDP2_DDRCTRL_PERF_OP_IS_REFRESH 9 +#define HDP2_DDRCTRL_GSKP_DFI_LP_REQ 10 +#define HDP2_SRAM3CTRL_SW_ERASE_ACT 12 +#define HDP2_NIC400_S0_BVALID 13 +#define HDP2_GPOVAL_2 15 + +#define HDP3_PWR_SEL_VTH_VDD_CORE 0 +#define HDP3_PWR_MPU_CLOCK_DISABLE_REQ 1 +#define HDP3_CA7_NPMUIRQ0 2 +#define HDP3_CA7_NFIQOUT0 3 +#define HDP3_BSEC_OUT_SEC_DFTLOCK 4 +#define HDP3_BSEC_OUT_SEC_JTAG_DIS 5 +#define HDP3_RCC_PWRDS_SYS 6 +#define HDP3_SRAM3CTRL_TAMP_ERASE_REQ 7 +#define HDP3_DDRCTRL_STAT_DDRC_REG_SELREF_TYPE0 8 +#define HDP3_DTS_VALOBUS1_0 10 +#define HDP3_DTS_VALOBUS2_0 11 +#define HDP3_TAMP_POTENTIAL_TAMP_ERFCFG 12 +#define HDP3_NIC400_S0_WREADY 13 +#define HDP3_NIC400_S0_RREADY 14 +#define HDP3_GPOVAL_3 15 + +#define HDP4_PWR_STOP2_ACTIVE 1 +#define HDP4_CA7_NL2RESET1 2 +#define HDP4_CA7_NPORESET_VARM_I 3 +#define HDP4_BSEC_OUT_SEC_DFTEN 4 +#define HDP4_BSEC_OUT_SEC_DBGSWENABLE 5 +#define HDP4_ETH1_OUT_PMT_INTR_O 6 +#define HDP4_ETH2_OUT_PMT_INTR_O 7 +#define HDP4_DDRCTRL_STAT_DDRC_REG_SELREF_TYPE1 8 +#define HDP4_DDRCTRL_CACTIVE_0 9 +#define HDP4_DTS_VALOBUS1_1 10 +#define HDP4_DTS_VALOBUS2_1 11 +#define HDP4_TAMP_NRESET_SRAM_ERCFG 12 +#define HDP4_NIC400_S0_WLAST 13 +#define HDP4_NIC400_S0_RLAST 14 +#define HDP4_GPOVAL_4 15 + +#define HDP5_CA7_STANDBYWFIL2 0 +#define HDP5_PWR_VTH_VDDCORE_ACK 1 +#define HDP5_CA7_NCORERESET_I 2 +#define HDP5_CA7_NIRQOUT0 3 +#define HDP5_BSEC_IN_PWROK 4 +#define HDP5_BSEC_OUT_SEC_DEVICEEN 5 +#define HDP5_ETH1_OUT_LPI_INTR_O 6 +#define HDP5_ETH2_OUT_LPI_INTR_O 7 +#define HDP5_DDRCTRL_CACTIVE_DDRC 8 +#define HDP5_DDRCTRL_WR_CREDIT_CNT 9 +#define HDP5_DTS_VALOBUS1_2 10 +#define HDP5_DTS_VALOBUS2_2 11 +#define HDP5_PKA_PKA_ITAMP_OUT 12 +#define HDP5_NIC400_S0_WVALID 13 +#define HDP5_NIC400_S0_RVALID 14 +#define HDP5_GPOVAL_5 15 + +#define HDP6_CA7_STANDBYWFE0 0 +#define HDP6_PWR_VTH_VDDCPU_ACK 1 +#define HDP6_CA7_EVENT0 2 +#define HDP6_BSEC_IN_TAMPER_DET 4 +#define HDP6_BSEC_OUT_SEC_SPNIDEN 5 +#define HDP6_ETH1_OUT_MAC_SPEED_O1 6 +#define HDP6_ETH2_OUT_MAC_SPEED_O1 7 +#define HDP6_DDRCTRL_CSYSACK_DDRC 8 +#define HDP6_DDRCTRL_LPR_CREDIT_CNT 9 +#define HDP6_DTS_VALOBUS1_3 10 +#define HDP6_DTS_VALOBUS2_3 11 +#define HDP6_SAES_TAMPER_OUT 12 +#define HDP6_NIC400_S0_AWREADY 13 +#define HDP6_NIC400_S0_ARREADY 14 +#define HDP6_GPOVAL_6 15 + +#define HDP7_CA7_STANDBYWFI0 0 +#define HDP7_PWR_RCC_VCPU_RDY 1 +#define HDP7_CA7_EVENTI 2 +#define HDP7_CA7_DBGACK0 3 +#define HDP7_BSEC_OUT_FUSE_OK 4 +#define HDP7_BSEC_OUT_SEC_SPIDEN 5 +#define HDP7_ETH1_OUT_MAC_SPEED_O0 6 +#define HDP7_ETH2_OUT_MAC_SPEED_O0 7 +#define HDP7_DDRCTRL_CSYSREQ_DDRC 8 +#define HDP7_DDRCTRL_HPR_CREDIT_CNT 9 +#define HDP7_DTS_VALOBUS1_4 10 +#define HDP7_DTS_VALOBUS2_4 11 +#define HDP7_RNG_TAMPER_OUT 12 +#define HDP7_NIC400_S0_AWVALID 13 +#define HDP7_NIC400_S0_ARVALID 14 +#define HDP7_GPOVAL_7 15 + +#endif /* _DT_BINDINGS_STM32_HDP_H */ diff --git a/include/fdt_simplefb.h b/include/fdt_simplefb.h index 7cc305e1fd..41cd740ac0 100644 --- a/include/fdt_simplefb.h +++ b/include/fdt_simplefb.h @@ -8,6 +8,7 @@ #ifndef _FDT_SIMPLEFB_H_ #define _FDT_SIMPLEFB_H_ -int lcd_dt_simplefb_add_node(void *blob); -int lcd_dt_simplefb_enable_existing_node(void *blob); +int fdt_simplefb_add_node(void *blob); +int fdt_simplefb_enable_existing_node(void *blob); +int fdt_simplefb_enable_and_mem_rsv(void *blob); #endif diff --git a/include/fdtdec.h b/include/fdtdec.h index 8ac20c9a64..ecbdac2760 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -24,16 +24,19 @@ typedef phys_addr_t fdt_addr_t; typedef phys_size_t fdt_size_t; -#define FDT_ADDR_T_NONE (-1U) #define FDT_SIZE_T_NONE (-1U) #ifdef CONFIG_PHYS_64BIT +#define FDT_ADDR_T_NONE ((ulong)(-1)) + #define fdt_addr_to_cpu(reg) be64_to_cpu(reg) #define fdt_size_to_cpu(reg) be64_to_cpu(reg) #define cpu_to_fdt_addr(reg) cpu_to_be64(reg) #define cpu_to_fdt_size(reg) cpu_to_be64(reg) typedef fdt64_t fdt_val_t; #else +#define FDT_ADDR_T_NONE (-1U) + #define fdt_addr_to_cpu(reg) be32_to_cpu(reg) #define fdt_size_to_cpu(reg) be32_to_cpu(reg) #define cpu_to_fdt_addr(reg) cpu_to_be32(reg) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 3b302fb8c3..7455400981 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -51,7 +51,6 @@ struct erase_info { u_long retries; unsigned dev; unsigned cell; - void (*callback) (struct erase_info *self); u_long priv; u_char state; struct erase_info *next; @@ -535,16 +534,6 @@ extern int unregister_mtd_user (struct mtd_notifier *old); #endif void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size); -#ifdef CONFIG_MTD_PARTITIONS -void mtd_erase_callback(struct erase_info *instr); -#else -static inline void mtd_erase_callback(struct erase_info *instr) -{ - if (instr->callback) - instr->callback(instr); -} -#endif - static inline int mtd_is_bitflip(int err) { return err == -EUCLEAN; } diff --git a/include/nand.h b/include/nand.h index 80dd6469bc..efe193078b 100644 --- a/include/nand.h +++ b/include/nand.h @@ -68,7 +68,6 @@ static inline int nand_erase(struct mtd_info *info, loff_t off, size_t size) instr.mtd = info; instr.addr = off; instr.len = size; - instr.callback = 0; return mtd_erase(info, &instr); } diff --git a/include/netdev.h b/include/netdev.h index 00a0993a83..24ff243567 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -25,7 +25,7 @@ struct udevice; int board_eth_init(struct bd_info *bis); int board_interface_eth_init(struct udevice *dev, - phy_interface_t interface_type); + phy_interface_t interface_type, ulong rate); int cpu_eth_init(struct bd_info *bis); /* Driver initialization prototypes */ diff --git a/include/rproc_optee.h b/include/rproc_optee.h new file mode 100644 index 0000000000..13193bbe77 --- /dev/null +++ b/include/rproc_optee.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) STMicroelectronics 2020 - All Rights Reserved + */ + +#ifndef _RPROC_OPTEE_H_ +#define _RPROC_OPTEE_H_ + +/** + * struct rproc_optee - TEE remoteproc structure + * @tee: TEE device + * @fw_id: Identifier of the target firmware + * @session: TEE session identifier + */ +struct rproc_optee { + struct udevice *tee; + u32 fw_id; + u32 session; +}; + +#if IS_ENABLED(CONFIG_REMOTEPROC_OPTEE) + +/** + * rproc_optee_open() - open a rproc tee session + * + * Open a session towards the trusted application in charge of the remote + * processor. + * + * @trproc: OPTEE remoteproc context structure + * + * @return 0 if the session is opened, or an appropriate error value. + */ +int rproc_optee_open(struct rproc_optee *trproc); + +/** + * rproc_optee_close() - close a rproc tee session + * + * Close the trusted application session in charge of the remote processor. + * + * @trproc: OPTEE remoteproc context structure + * + * @return 0 on success, or an appropriate error value. + */ +int rproc_optee_close(struct rproc_optee *trproc); + +/** + * rproc_optee_start() - Request OP-TEE to start a remote processor + * + * @trproc: OPTEE remoteproc context structure + * + * @return 0 on success, or an appropriate error value. + */ +int rproc_optee_start(struct rproc_optee *trproc); + +/** + * rproc_optee_stop() - Request OP-TEE to stop a remote processor + * + * @trproc: OPTEE remoteproc context structure + * + * @return 0 on success, or an appropriate error value. + */ +int rproc_optee_stop(struct rproc_optee *trproc); + +/** + * rproc_optee_get_rsc_table() - Request OP-TEE the resource table + * + * Get the address and the size of the resource table. If no resource table is + * found, the size and address are null. + * + * @trproc: OPTEE remoteproc context structure + * @rsc_addr: out the physical address of the resource table returned + * @rsc_size: out the size of the resource table + * + * @return 0 on success, or an appropriate error value. + */ +int rproc_optee_get_rsc_table(struct rproc_optee *trproc, phys_addr_t *rsc_addr, + phys_size_t *rsc_size); + +/** + * rproc_optee_load() - load an signed ELF image + * + * @trproc: OPTEE remoteproc context structure + * @addr: valid ELF image address + * @size: size of the image + * + * @return 0 if the image is successfully loaded, else appropriate error value. + */ +int rproc_optee_load(struct rproc_optee *trproc, ulong addr, ulong size); + +#else + +static inline int rproc_optee_open(struct rproc_optee *trproc) +{ + return -ENOSYS; +} + +static inline int rproc_optee_close(struct rproc_optee *trproc) +{ + return -ENOSYS; +} + +static inline int rproc_optee_start(struct rproc_optee *trproc) +{ + return -ENOSYS; +} + +static inline int rproc_optee_stop(struct rproc_optee *trproc) +{ + return -ENOSYS; +} + +static inline int rproc_optee_get_rsc_table(struct rproc_optee *trproc, + phys_addr_t *rsc_addr, + phys_size_t *rsc_size) +{ + return -ENOSYS; +} + +static inline int rproc_optee_load(struct rproc_optee *trproc, ulong addr, + ulong size) +{ + return -ENOSYS; +} + +#endif + +#endif /* _RPROC_OPTEE_H_ */ diff --git a/include/scmi_agent.h b/include/scmi_agent.h index f1be9ff209..83af4c7809 100644 --- a/include/scmi_agent.h +++ b/include/scmi_agent.h @@ -45,13 +45,13 @@ struct scmi_msg { } /** - * scmi_send_and_process_msg() - send and process a SCMI message + * devm_scmi_process_msg() - Send and process an SCMI message * - * Send a message to a SCMI server through a target SCMI agent device. + * Send a message to an SCMI server through a target SCMI agent device. * Caller sets scmi_msg::out_msg_sz to the output message buffer size. * On return, scmi_msg::out_msg_sz stores the response payload size. * - * @dev: SCMI agent device + * @dev: SCMI device * @msg: Message structure reference * @return 0 on success and a negative errno on failure */ diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h index 2db71697e8..d4843f3619 100644 --- a/include/scmi_protocols.h +++ b/include/scmi_protocols.h @@ -40,22 +40,65 @@ enum scmi_status_code { SCMI_PROTOCOL_ERROR = -10, }; +/* + * Generic message IDs + */ +enum scmi_discovery_id { + SCMI_PROTOCOL_VERSION = 0x0, + SCMI_PROTOCOL_ATTRIBUTES = 0x1, + SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2, +}; + /* * SCMI Clock Protocol */ enum scmi_clock_message_id { + SCMI_CLOCK_ATTRIBUTES = 0x3, SCMI_CLOCK_RATE_SET = 0x5, SCMI_CLOCK_RATE_GET = 0x6, SCMI_CLOCK_CONFIG_SET = 0x7, }; +#define SCMI_CLK_PROTO_ATTR_COUNT_MASK GENMASK(15, 0) #define SCMI_CLK_RATE_ASYNC_NOTIFY BIT(0) #define SCMI_CLK_RATE_ASYNC_NORESP (BIT(0) | BIT(1)) #define SCMI_CLK_RATE_ROUND_DOWN 0 #define SCMI_CLK_RATE_ROUND_UP BIT(2) #define SCMI_CLK_RATE_ROUND_CLOSEST BIT(3) +#define SCMI_CLOCK_NAME_LENGTH_MAX 16 + +/** + * struct scmi_clk_get_nb_out - Response for SCMI_PROTOCOL_ATTRIBUTES command + * @status: SCMI command status + * @attributes: Attributes of the clock protocol, mainly number of clocks exposed + */ +struct scmi_clk_protocol_attr_out { + s32 status; + u32 attributes; +}; + +/** + * struct scmi_clk_attribute_in - Message payload for SCMI_CLOCK_ATTRIBUTES command + * @clock_id: SCMI clock ID + */ +struct scmi_clk_attribute_in { + u32 clock_id; +}; + +/** + * struct scmi_clk_get_nb_out - Response payload for SCMI_CLOCK_ATTRIBUTES command + * @status: SCMI command status + * @attributes: clock attributes + * @clock_name: name of the clock + */ +struct scmi_clk_attribute_out { + s32 status; + u32 attributes; + char clock_name[SCMI_CLOCK_NAME_LENGTH_MAX]; +}; + /** * struct scmi_clk_state_in - Message payload for CLOCK_CONFIG_SET command * @clock_id: SCMI clock ID @@ -97,14 +140,14 @@ struct scmi_clk_rate_get_out { /** * struct scmi_clk_state_in - Message payload for CLOCK_RATE_SET command - * @clock_id: SCMI clock ID * @flags: Flags for the clock rate set request + * @clock_id: SCMI clock ID * @rate_lsb: 32bit LSB of the clock rate in Hertz * @rate_msb: 32bit MSB of the clock rate in Hertz */ struct scmi_clk_rate_set_in { - u32 clock_id; u32 flags; + u32 clock_id; u32 rate_lsb; u32 rate_msb; }; @@ -195,6 +238,16 @@ enum scmi_voltage_domain_message_id { #define SCMI_VOLTD_CONFIG_OFF 0 #define SCMI_VOLTD_CONFIG_ON 0x7 +/** + * struct scmi_clk_state_in - Message payload for CLOCK_CONFIG_SET command + * @status: SCMI command status + * @attributes: Attributes of the voltage domain protocol + */ +struct scmi_voltd_protocol_attr_out { + s32 status; + u32 attributes; +}; + /** * struct scmi_voltd_attr_in - Payload for VOLTAGE_DOMAIN_ATTRIBUTES message * @domain_id: SCMI voltage domain ID diff --git a/include/spi_flash.h b/include/spi_flash.h index 3d747c925b..4d4ae89c19 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -165,6 +165,9 @@ static inline int spi_flash_read(struct spi_flash *flash, u32 offset, struct mtd_info *mtd = &flash->mtd; size_t retlen; + if (!len) + return 0; + return mtd->_read(mtd, offset, len, &retlen, buf); } @@ -174,6 +177,9 @@ static inline int spi_flash_write(struct spi_flash *flash, u32 offset, struct mtd_info *mtd = &flash->mtd; size_t retlen; + if (!len) + return 0; + return mtd->_write(mtd, offset, len, &retlen, buf); } @@ -188,6 +194,9 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, return -EINVAL; } + if (!len) + return 0; + memset(&instr, 0, sizeof(instr)); instr.addr = offset; instr.len = len; diff --git a/include/tee.h b/include/tee.h index 2ef29bfc8f..3d76ae66cd 100644 --- a/include/tee.h +++ b/include/tee.h @@ -31,6 +31,25 @@ #define TEE_PARAM_ATTR_MASK (TEE_PARAM_ATTR_TYPE_MASK | \ TEE_PARAM_ATTR_META) +/* + * Global Platform login identifiers for tee_open_session_arg::clnt_login + */ +#define TEE_LOGIN_PUBLIC 0x00000000 +#define TEE_LOGIN_USER 0x00000001 +#define TEE_LOGIN_GROUP 0x00000002 +#define TEE_LOGIN_APPLICATION 0x00000004 +#define TEE_LOGIN_APPLICATION_USER 0x00000005 +#define TEE_LOGIN_APPLICATION_GROUP 0x00000006 +/* + * Reserve use of GP implementation specific login method range + * (0x80000000 - 0xBFFFFFFF). This range is rather being used + * for REE kernel clients or TEE implementation. + */ +#define TEE_LOGIN_REE_KERNEL_MIN 0x80000000 +#define TEE_LOGIN_REE_KERNEL_MAX 0xBFFFFFFF +/* Private login method for REE kernel/privileged clients */ +#define TEE_LOGIN_REE_KERNEL 0x80000000 + /* * Some Global Platform error codes which has a meaning if the * TEE_GEN_CAP_GP bit is returned by the driver in @@ -45,6 +64,7 @@ #define TEE_ERROR_NOT_SUPPORTED 0xffff000a #define TEE_ERROR_COMMUNICATION 0xffff000e #define TEE_ERROR_SECURITY 0xffff000f +#define TEE_ERROR_SHORT_BUFFER 0xffff0010 #define TEE_ERROR_OUT_OF_MEMORY 0xffff000c #define TEE_ERROR_OVERFLOW 0xffff300f #define TEE_ERROR_TARGET_DEAD 0xffff3024 @@ -135,8 +155,8 @@ struct tee_param { /** * struct tee_open_session_arg - extra arguments for tee_open_session() * @uuid: [in] UUID of the Trusted Application - * @clnt_uuid: [in] Normally zeroes - * @clnt_login: [in] Normally 0 + * @clnt_uuid: [in] UUID of client, zeroes for PUBLIC/REE_KERNEL + * @clnt_login: [in] Class of client TEE_LOGIN_* * @session: [out] Session id * @ret: [out] return value * @ret_origin: [out] origin of the return value diff --git a/include/typec.h b/include/typec.h new file mode 100644 index 0000000000..9241da4614 --- /dev/null +++ b/include/typec.h @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + */ + +enum typec_state { + TYPEC_UNATTACHED, + TYPEC_ATTACHED, +}; + +enum typec_data_role { + TYPEC_DEVICE, + TYPEC_HOST, +}; + +/** + * struct typec_ops - driver I/O operations for TYPEC uclass + * + * Drivers should support 2 operations. These operations is intended + * to be used by uclass code, not directly from other code. + */ +struct typec_ops { + /** + * is_attached() - Return if cable is attached + * + * @dev: TYPEC device to read from + * @con_idx: connector index (0 is the first one) + * @return TYPEC_UNATTACHED if not attached, TYPEC_ATTACHED if attached, -ve on error + */ + int (*is_attached)(struct udevice *dev, u8 con_idx); + + /** + * get_data_role() - Return data role (HOST or DEVICE) + * + * @dev: TYPEC device to read from + * @con_idx: connector index (0 is the first one) + * @return: TYPEC_DEVICE if device role, TYPEC_HOST if host role, -ve on error + */ + int (*get_data_role)(struct udevice *dev, u8 con_idx); + + /** + * get_nb_connector() - Return connector number managed by TypeC controller. + * + * @dev: TYPEC device to read from + * @return: number of connector managed by TypeC controller, -ve on error + */ + u8 (*get_nb_connector)(struct udevice *dev); +}; + +#ifdef CONFIG_TYPEC +/** + * typec_is_attached() - Test if Type-C connector is attached + * + * @return TYPEC_ATTACHED if attached, TYPEC_UNATTACHED is not attached, + * or -ve on error. + */ +int typec_is_attached(struct udevice *dev, u8 con_idx); + +/** + * typec_get_data_role() - Return current Type-C data role + * + * @return TYPEC_DEVICE if attached to a host, TYPEC_HOST is attached to a + * device or -ve on error. + */ +int typec_get_data_role(struct udevice *dev, u8 con_idx); + +/** + * typec_get_nb_connector() - Return Type-C connector supported by controller + * + * @return Type-C connector number or -ve on error. + */ +int typec_get_nb_connector(struct udevice *dev); + +/** + * typec_get_device_from_usb() - Allows to retrieve a Type-C device from + * an USB device. typec_get_driver_from_usb() checks in USB device node + * for port and endpoint sub-node, if exist, retrieve the connector node, + * probe the associated Type-C device and return it (see DT example below). + * See Documentation/devicetree/bindings/connector/usb-connector.yaml for more + * details + * + * @dev: USB device + * @typec: Type-C device + * @index: USB controller port number + * @return -ve on error. + * + * usb_dwc3_0: usb@10000000 { + * ... + * port@0 { + * reg = <0>; + * typec_hs: endpoint { + * remote-endpoint = <&usb_con_hs>; + * }; + * }; + * + * port@1 { + * reg = <1>; + * typec_ss: endpoint { + * remote-endpoint = <&usb_con_ss>; + * }; + * }; + * }; + * + * usb-typec@1 { + * ... + * connector { + * compatible = "usb-c-connector"; + * label = "USB-C"; + * + * ports { + * #address-cells = <1>; + * #size-cells = <0>; + * + * port@0 { + * reg = <0>; + * usb_con_hs: endpoint { + * remote-endpoint = <&typec_hs>; + * }; + * }; + * + * port@1 { + * reg = <1>; + * usb_con_ss: endpoint { + * remote-endpoint = <&typec_ss>; + * }; + * }; + * }; + * }; + * }; + */ +int typec_get_device_from_usb(struct udevice *dev, struct udevice **typec, u8 + index); +#else +static inline int typec_is_attached(struct udevice *dev, u8 con_idx) +{ + return -ENODEV; +} + +static inline int typec_get_data_role(struct udevice *dev, u8 con_idx) +{ + return -EINVAL; +} + +static inline int typec_get_nb_connector(struct udevice *dev) +{ + return -EINVAL; +} + +static inline int typec_get_device_from_usb(struct udevice *dev, struct udevice **typec, + u8 index) +{ + return -ENODEV; +} +#endif diff --git a/include/ucsi.h b/include/ucsi.h new file mode 100644 index 0000000000..1c46e05481 --- /dev/null +++ b/include/ucsi.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _UCSI_H_ +#define _UCSI_H_ + +/* UCSI offsets (Bytes) */ +#define UCSI_VERSION 0 +#define UCSI_CCI 4 +#define UCSI_CONTROL 8 +#define UCSI_MESSAGE_IN 16 + +/* Commands */ +#define UCSI_PPM_RESET 0x01 +#define UCSI_ACK_CC_CI 0x04 +#define UCSI_SET_NOTIFICATION_ENABLE 0x05 +#define UCSI_GET_CAPABILITY 0x06 +#define UCSI_GET_ALTERNATE_MODES 0x0c +#define UCSI_GET_CONNECTOR_STATUS 0x12 +#define UCSI_GET_ERROR_STATUS 0x13 + +#define UCSI_CONNECTOR_NUMBER(_num_) ((u64)(_num_) << 16) + +/* ACK_CC_CI bits */ +#define UCSI_ACK_CONNECTOR_CHANGE BIT(16) +#define UCSI_ACK_COMMAND_COMPLETE BIT(17) + +/* SET_NOTIFICATION_ENABLE command bits */ +#define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE BIT(30) + +/* Command Status and Connector Change Indication (CCI) bits */ +#define UCSI_CCI_CONNECTOR(_c_) (((_c_) & GENMASK(7, 1)) >> 1) +#define UCSI_CCI_LENGTH(_c_) (((_c_) & GENMASK(15, 8)) >> 8) +#define UCSI_CCI_NOT_SUPPORTED BIT(25) +#define UCSI_CCI_RESET_COMPLETE BIT(27) +#define UCSI_CCI_BUSY BIT(28) +#define UCSI_CCI_ERROR BIT(30) +#define UCSI_CCI_COMMAND_COMPLETE BIT(31) + +/* Error information returned by PPM in response to GET_ERROR_STATUS command. */ +#define UCSI_ERROR_UNREGONIZED_CMD BIT(0) +#define UCSI_ERROR_INVALID_CON_NUM BIT(1) +#define UCSI_ERROR_INVALID_CMD_ARGUMENT BIT(2) +#define UCSI_ERROR_INCOMPATIBLE_PARTNER BIT(3) +#define UCSI_ERROR_CC_COMMUNICATION_ERR BIT(4) +#define UCSI_ERROR_DEAD_BATTERY BIT(5) +#define UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL BIT(6) +#define UCSI_ERROR_OVERCURRENT BIT(7) +#define UCSI_ERROR_UNDEFINED BIT(8) +#define UCSI_ERROR_PARTNER_REJECTED_SWAP BIT(9) +#define UCSI_ERROR_HARD_RESET BIT(10) +#define UCSI_ERROR_PPM_POLICY_CONFLICT BIT(11) +#define UCSI_ERROR_SWAP_REJECTED BIT(12) + +/* Data structure filled by PPM in response to GET_CAPABILITY command. */ +struct ucsi_capability { + u32 attributes; + u8 num_connectors; + u8 features; + u16 reserved_1; + u8 num_alt_modes; + u8 reserved_2; + u16 bc_version; + u16 pd_version; + u16 typec_version; +} __packed; + +/* Data structure filled by PPM in response to GET_CONNECTOR_STATUS command. */ +struct ucsi_connector_status { + u16 change; + u16 flags; +#define UCSI_CONSTAT_CONNECTED BIT(3) +#define UCSI_CONSTAT_PARTNER_TYPE(_f_) (((_f_) & GENMASK(15, 13)) >> 13) +#define UCSI_CONSTAT_PARTNER_TYPE_DFP 1 +#define UCSI_CONSTAT_PARTNER_TYPE_UFP 2 +#define UCSI_CONSTAT_PARTNER_TYPE_CABLE 3 /* Powered Cable */ +#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP 4 /* Powered Cable */ +#define UCSI_CONSTAT_PARTNER_TYPE_DEBUG 5 +#define UCSI_CONSTAT_PARTNER_TYPE_AUDIO 6 + u32 request_data_obj; + u8 pwr_status; +} __packed; + +/** + * struct ucsi_ops - driver I/O operations for UCSI uclass + * + * Drivers should support 2 operations. These operations are intended to be used + * by uclass code, not directly from other code. + */ +struct ucsi_ops { + /** + * read() - Read operation + * + * @ucsi: UCSI device to read from + * @offset: UCSI data structure offset + * @buf: Buffer to receive the data + * @len Number of bytes to read + * @return 0 on success, -ve on failure + */ + int (*read)(struct udevice *ucsi, unsigned int offset, void *val, size_t len); + + /** + * write() - Write operation + * + * @ucsi: UCSI device to write to + * @offset: UCSI data structure offset + * @buf: Buffer data to write + * @len Number of bytes to write + * @return 0 on success, -ve on failure + */ + int (*write)(struct udevice *ucsi, unsigned int offset, const void *val, size_t len); +}; +#endif /* _UCSI_H_ */ diff --git a/include/video.h b/include/video.h index 827733305e..82da364a30 100644 --- a/include/video.h +++ b/include/video.h @@ -267,6 +267,13 @@ static inline int video_sync_copy_all(struct udevice *dev) #endif +/** + * video_is_active() - Test if one video device it active + * + * @return true if at least one video device is active, else false. + */ +bool video_is_active(void); + #ifndef CONFIG_DM_VIDEO /* Video functions */ diff --git a/lib/uuid.c b/lib/uuid.c index 67267c66a3..e4703dce2b 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -257,7 +257,7 @@ void gen_rand_uuid(unsigned char *uuid_bin) if (IS_ENABLED(CONFIG_DM_RNG)) { ret = uclass_get_device(UCLASS_RNG, 0, &devp); - if (ret) { + if (!ret) { ret = dm_rng_read(devp, &randv, sizeof(randv)); if (ret < 0) randv = 0; diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index a9c2380d17..a466bf1e00 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -847,7 +847,6 @@ CONFIG_LBA48 CONFIG_LBDAF CONFIG_LCD_ALIGNMENT CONFIG_LCD_BMP_RLE8 -CONFIG_LCD_DT_SIMPLEFB CONFIG_LCD_INFO CONFIG_LCD_INFO_BELOW_LOGO CONFIG_LCD_IN_PSRAM @@ -1423,10 +1422,6 @@ CONFIG_STACKBASE CONFIG_STANDALONE_LOAD_ADDR CONFIG_STATIC_BOARD_REV CONFIG_STD_DEVICES_SETTINGS -CONFIG_STM32_FLASH -CONFIG_STV0991 -CONFIG_STV0991_HZ -CONFIG_STV0991_HZ_CLOCK CONFIG_SXNI855T CONFIG_SYSFS CONFIG_SYSMGR_ISWGRP_HANDOFF @@ -3414,7 +3409,6 @@ CONFIG_USB_TUSB_OMAP_DMA CONFIG_USB_ULPI_TIMEOUT CONFIG_USB_XHCI_EXYNOS CONFIG_USB_XHCI_OMAP -CONFIG_USER_LOWLEVEL_INIT CONFIG_USE_INTERRUPT CONFIG_USE_ONENAND_BOARD_INIT CONFIG_UTBIPAR_INIT_TBIPA diff --git a/test/cmd/pinmux.c b/test/cmd/pinmux.c index 8ae807b537..64392af506 100644 --- a/test/cmd/pinmux.c +++ b/test/cmd/pinmux.c @@ -16,12 +16,12 @@ static int dm_test_cmd_pinmux_status_pinname(struct unit_test_state *uts) /* Test that 'pinmux status ' displays the selected pin. */ console_record_reset(); run_command("pinmux status a5", 0); - ut_assert_nextline("a5 : gpio input . "); + ut_assert_nextline("a5 : gpio input . "); ut_assert_console_end(); console_record_reset(); run_command("pinmux status P7", 0); - ut_assert_nextline("P7 : GPIO2 bias-pull-down input-enable. "); + ut_assert_nextline("P7 : GPIO2 bias-pull-down input-enable. "); ut_assert_console_end(); console_record_reset(); diff --git a/test/dm/nop.c b/test/dm/nop.c index 2cd92c5240..75b9e7b6cc 100644 --- a/test/dm/nop.c +++ b/test/dm/nop.c @@ -25,7 +25,7 @@ static int noptest_bind(struct udevice *parent) const char *bind_flag = ofnode_read_string(ofnode, "bind"); if (bind_flag && (strcmp(bind_flag, "True") == 0)) - lists_bind_fdt(parent, ofnode, &dev, false); + lists_bind_fdt(parent, ofnode, &dev, NULL, false); ofnode = dev_read_next_subnode(ofnode); } diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 44e51de085..421459835d 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -286,7 +286,7 @@ static int dm_test_ofnode_get_reg(struct unit_test_state *uts) ut_assert(ofnode_valid(node)); addr = ofnode_get_addr(node); size = ofnode_get_size(node); - ut_asserteq(FDT_ADDR_T_NONE, addr); + ut_asserteq_64(FDT_ADDR_T_NONE, addr); ut_asserteq(FDT_SIZE_T_NONE, size); node = ofnode_path("/translation-test@8000/noxlatebus@3,300/dev@42"); diff --git a/test/dm/pci.c b/test/dm/pci.c index fa2e4a8559..00e4440a9d 100644 --- a/test/dm/pci.c +++ b/test/dm/pci.c @@ -331,10 +331,10 @@ static int dm_test_pci_addr_live(struct unit_test_state *uts) struct udevice *swap1f, *swap1; ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f)); - ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f)); + ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f)); ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1)); - ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1)); + ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1)); return 0; } diff --git a/test/dm/scmi.c b/test/dm/scmi.c index c938e6d4fc..2149904585 100644 --- a/test/dm/scmi.c +++ b/test/dm/scmi.c @@ -5,7 +5,7 @@ * Tests scmi_agent uclass and the SCMI drivers implemented in other * uclass devices probe when a SCMI server exposes resources. * - * Note in test.dts the protocol@10 node in agent 1. Protocol 0x10 is not + * Note in test.dts the protocol@10 node in scmi node. Protocol 0x10 is not * implemented in U-Boot SCMI components but the implementation is exepected * to not complain on unknown protocol IDs, as long as it is not used. Note * in test.dts tests that SCMI drivers probing does not fail for such an @@ -28,8 +28,7 @@ static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts) struct sandbox_scmi_service *scmi_ctx = sandbox_scmi_service_ctx(); ut_assertnonnull(scmi_ctx); - if (scmi_ctx->agent_count) - ut_asserteq(2, scmi_ctx->agent_count); + ut_assertnull(scmi_ctx->agent); return 0; } @@ -39,35 +38,28 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, { struct sandbox_scmi_devices *scmi_devices; struct sandbox_scmi_service *scmi_ctx; - struct sandbox_scmi_agent *agent0; - struct sandbox_scmi_agent *agent1; + struct sandbox_scmi_agent *agent; /* Device references to check context against test sequence */ scmi_devices = sandbox_scmi_devices_ctx(dev); - ut_assertnonnull(scmi_devices); - ut_asserteq(3, scmi_devices->clk_count); + + ut_asserteq(2, scmi_devices->clk_count); ut_asserteq(1, scmi_devices->reset_count); ut_asserteq(2, scmi_devices->regul_count); /* State of the simulated SCMI server exposed */ scmi_ctx = sandbox_scmi_service_ctx(); - agent0 = scmi_ctx->agent[0]; - agent1 = scmi_ctx->agent[1]; - - ut_asserteq(2, scmi_ctx->agent_count); - - ut_assertnonnull(agent0); - ut_asserteq(2, agent0->clk_count); - ut_assertnonnull(agent0->clk); - ut_asserteq(1, agent0->reset_count); - ut_assertnonnull(agent0->reset); - ut_asserteq(2, agent0->voltd_count); - ut_assertnonnull(agent0->voltd); + ut_assertnonnull(scmi_ctx); + agent = scmi_ctx->agent; + ut_assertnonnull(agent); - ut_assertnonnull(agent1); - ut_assertnonnull(agent1->clk); - ut_asserteq(1, agent1->clk_count); + ut_asserteq(3, agent->clk_count); + ut_assertnonnull(agent->clk); + ut_asserteq(1, agent->reset_count); + ut_assertnonnull(agent->reset); + ut_asserteq(7, agent->voltd_count); + ut_assertnonnull(agent->voltd); return 0; } @@ -118,9 +110,8 @@ static int dm_test_scmi_clocks(struct unit_test_state *uts) { struct sandbox_scmi_devices *scmi_devices; struct sandbox_scmi_service *scmi_ctx; - struct sandbox_scmi_agent *agent0; - struct sandbox_scmi_agent *agent1; - struct udevice *dev = NULL; + struct sandbox_scmi_agent *agent; + struct udevice *dev; int ret_dev; int ret; @@ -129,48 +120,51 @@ static int dm_test_scmi_clocks(struct unit_test_state *uts) return ret; scmi_devices = sandbox_scmi_devices_ctx(dev); + ut_assertnonnull(scmi_devices); + scmi_ctx = sandbox_scmi_service_ctx(); - agent0 = scmi_ctx->agent[0]; - agent1 = scmi_ctx->agent[1]; + ut_assertnonnull(scmi_ctx); + agent = scmi_ctx->agent; + ut_assertnonnull(agent); /* Test SCMI clocks rate manipulation */ + ut_asserteq(333, agent->clk[0].rate); + ut_asserteq(200, agent->clk[1].rate); + ut_asserteq(1000, agent->clk[2].rate); + ut_asserteq(1000, clk_get_rate(&scmi_devices->clk[0])); ut_asserteq(333, clk_get_rate(&scmi_devices->clk[1])); - ut_asserteq(44, clk_get_rate(&scmi_devices->clk[2])); ret_dev = clk_set_rate(&scmi_devices->clk[1], 1088); ut_assert(!ret_dev || ret_dev == 1088); - ut_asserteq(1000, agent0->clk[0].rate); - ut_asserteq(1088, agent0->clk[1].rate); - ut_asserteq(44, agent1->clk[0].rate); + ut_asserteq(1088, agent->clk[0].rate); + ut_asserteq(200, agent->clk[1].rate); + ut_asserteq(1000, agent->clk[2].rate); ut_asserteq(1000, clk_get_rate(&scmi_devices->clk[0])); ut_asserteq(1088, clk_get_rate(&scmi_devices->clk[1])); - ut_asserteq(44, clk_get_rate(&scmi_devices->clk[2])); /* restore original rate for further tests */ ret_dev = clk_set_rate(&scmi_devices->clk[1], 333); ut_assert(!ret_dev || ret_dev == 333); /* Test SCMI clocks gating manipulation */ - ut_assert(!agent0->clk[0].enabled); - ut_assert(!agent0->clk[1].enabled); - ut_assert(!agent1->clk[0].enabled); + ut_assert(!agent->clk[0].enabled); + ut_assert(!agent->clk[1].enabled); + ut_assert(!agent->clk[2].enabled); ut_asserteq(0, clk_enable(&scmi_devices->clk[1])); - ut_asserteq(0, clk_enable(&scmi_devices->clk[2])); - ut_assert(!agent0->clk[0].enabled); - ut_assert(agent0->clk[1].enabled); - ut_assert(agent1->clk[0].enabled); + ut_assert(agent->clk[0].enabled); + ut_assert(!agent->clk[1].enabled); + ut_assert(!agent->clk[2].enabled); ut_assertok(clk_disable(&scmi_devices->clk[1])); - ut_assertok(clk_disable(&scmi_devices->clk[2])); - ut_assert(!agent0->clk[0].enabled); - ut_assert(!agent0->clk[1].enabled); - ut_assert(!agent1->clk[0].enabled); + ut_assert(!agent->clk[0].enabled); + ut_assert(!agent->clk[1].enabled); + ut_assert(!agent->clk[2].enabled); return release_sandbox_scmi_test_devices(uts, dev); } @@ -180,7 +174,7 @@ static int dm_test_scmi_resets(struct unit_test_state *uts) { struct sandbox_scmi_devices *scmi_devices; struct sandbox_scmi_service *scmi_ctx; - struct sandbox_scmi_agent *agent0; + struct sandbox_scmi_agent *agent; struct udevice *dev = NULL; int ret; @@ -189,17 +183,21 @@ static int dm_test_scmi_resets(struct unit_test_state *uts) return ret; scmi_devices = sandbox_scmi_devices_ctx(dev); + ut_assertnonnull(scmi_devices); + scmi_ctx = sandbox_scmi_service_ctx(); - agent0 = scmi_ctx->agent[0]; + ut_assertnonnull(scmi_ctx); + agent = scmi_ctx->agent; + ut_assertnonnull(agent); /* Test SCMI resect controller manipulation */ - ut_assert(!agent0->reset[0].asserted) + ut_assert(!agent->reset[0].asserted) ut_assertok(reset_assert(&scmi_devices->reset[0])); - ut_assert(agent0->reset[0].asserted) + ut_assert(agent->reset[0].asserted) ut_assertok(reset_deassert(&scmi_devices->reset[0])); - ut_assert(!agent0->reset[0].asserted); + ut_assert(!agent->reset[0].asserted); return release_sandbox_scmi_test_devices(uts, dev); } @@ -209,7 +207,7 @@ static int dm_test_scmi_voltage_domains(struct unit_test_state *uts) { struct sandbox_scmi_devices *scmi_devices; struct sandbox_scmi_service *scmi_ctx; - struct sandbox_scmi_agent *agent0; + struct sandbox_scmi_agent *agent; struct dm_regulator_uclass_plat *uc_pdata; struct udevice *dev; struct udevice *regul0_dev; @@ -217,8 +215,12 @@ static int dm_test_scmi_voltage_domains(struct unit_test_state *uts) ut_assertok(load_sandbox_scmi_test_devices(uts, &dev)); scmi_devices = sandbox_scmi_devices_ctx(dev); + ut_assertnonnull(scmi_devices); + scmi_ctx = sandbox_scmi_service_ctx(); - agent0 = scmi_ctx->agent[0]; + ut_assertnonnull(scmi_ctx); + agent = scmi_ctx->agent; + ut_assertnonnull(agent); /* Set/Get an SCMI voltage domain level */ regul0_dev = scmi_devices->regul[0]; @@ -228,32 +230,38 @@ static int dm_test_scmi_voltage_domains(struct unit_test_state *uts) ut_assert(uc_pdata); ut_assertok(regulator_set_value(regul0_dev, uc_pdata->min_uV)); - ut_asserteq(agent0->voltd[0].voltage_uv, uc_pdata->min_uV); + ut_asserteq(agent->voltd[0].voltage_uv, uc_pdata->min_uV); ut_assert(regulator_get_value(regul0_dev) == uc_pdata->min_uV); ut_assertok(regulator_set_value(regul0_dev, uc_pdata->max_uV)); - ut_asserteq(agent0->voltd[0].voltage_uv, uc_pdata->max_uV); + ut_asserteq(agent->voltd[0].voltage_uv, uc_pdata->max_uV); ut_assert(regulator_get_value(regul0_dev) == uc_pdata->max_uV); /* Enable/disable SCMI voltage domains */ + /* + * Note: regul[0] supplies regul[1], as defined in the DT. Supply + * is considered only on regulator enable requests since U-Boot + * does not make any reference count on enable/disable requests + * from consumers. + */ ut_assertok(regulator_set_enable(scmi_devices->regul[0], false)); ut_assertok(regulator_set_enable(scmi_devices->regul[1], false)); - ut_assert(!agent0->voltd[0].enabled); - ut_assert(!agent0->voltd[1].enabled); - - ut_assertok(regulator_set_enable(scmi_devices->regul[0], true)); - ut_assert(agent0->voltd[0].enabled); - ut_assert(!agent0->voltd[1].enabled); + ut_assert(!agent->voltd[0].enabled); + ut_assert(!agent->voltd[1].enabled); ut_assertok(regulator_set_enable(scmi_devices->regul[1], true)); - ut_assert(agent0->voltd[0].enabled); - ut_assert(agent0->voltd[1].enabled); + ut_assert(agent->voltd[0].enabled); + ut_assert(agent->voltd[1].enabled); + + ut_assertok(regulator_set_enable(scmi_devices->regul[1], false)); + ut_assert(agent->voltd[0].enabled); + ut_assert(!agent->voltd[1].enabled); ut_assertok(regulator_set_enable(scmi_devices->regul[0], false)); - ut_assert(!agent0->voltd[0].enabled); - ut_assert(agent0->voltd[1].enabled); + ut_assert(!agent->voltd[0].enabled); + ut_assert(!agent->voltd[1].enabled); return release_sandbox_scmi_test_devices(uts, dev); } diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 8866d4d959..e1de066226 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -768,7 +768,7 @@ static int dm_test_fdt_livetree_writing(struct unit_test_state *uts) /* Test setting generic properties */ /* Non-existent in DTB */ - ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr(dev)); + ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr(dev)); /* reg = 0x42, size = 0x100 */ ut_assertok(ofnode_write_prop(node, "reg", 8, "\x00\x00\x00\x42\x00\x00\x01\x00")); diff --git a/test/py/tests/test_bind.py b/test/py/tests/test_bind.py index 6703325c0b..9f234fb635 100644 --- a/test/py/tests/test_bind.py +++ b/test/py/tests/test_bind.py @@ -33,6 +33,13 @@ def test_bind_unbind_with_node(u_boot_console): assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, False) assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'simple_bus', 1, True) + #bind usb_ether driver (which has no compatible) to usb@1 node. + ##New entry usb_ether should appear in the dm tree + response = u_boot_console.run_command('bind /usb@1 usb_ether') + assert response == '' + tree = u_boot_console.run_command('dm tree') + assert in_tree(tree, 'usb@1', 'ethernet', 'usb_ether', 1, True) + #Unbind child #1. No error expected and all devices should be there except for bind-test-child1 response = u_boot_console.run_command('unbind /bind-test/bind-test-child1') assert response == '' diff --git a/test/py/tests/test_log.py b/test/py/tests/test_log.py index 140dcb9aa2..20a3e56301 100644 --- a/test/py/tests/test_log.py +++ b/test/py/tests/test_log.py @@ -27,13 +27,13 @@ def test_log_format(u_boot_console): cons = u_boot_console with cons.log.section('format'): - run_with_format('all', 'NOTICE.arch,file.c:123-func() msg') + run_with_format('all', 'NOTICE.arch,file.c:123- func() msg') output = cons.run_command('log format') assert output == 'Log format: clFLfm' - run_with_format('fm', 'func() msg') - run_with_format('clfm', 'NOTICE.arch,func() msg') - run_with_format('FLfm', 'file.c:123-func() msg') + run_with_format('fm', ' func() msg') + run_with_format('clfm', 'NOTICE.arch, func() msg') + run_with_format('FLfm', 'file.c:123- func() msg') run_with_format('lm', 'NOTICE. msg') run_with_format('m', 'msg') diff --git a/test/py/tests/test_pinmux.py b/test/py/tests/test_pinmux.py index b3ae2ab024..2411937773 100644 --- a/test/py/tests/test_pinmux.py +++ b/test/py/tests/test_pinmux.py @@ -24,19 +24,19 @@ def test_pinmux_status_all(u_boot_console): output = u_boot_console.run_command('pinmux status -a') assert ('pinctrl-gpio:' in output) - assert ('a5 : gpio output .' in output) - assert ('a6 : gpio output .' in output) + assert ('a5 : gpio output .' in output) + assert ('a6 : gpio output .' in output) assert ('pinctrl:' in output) - assert ('P0 : UART TX.' in output) - assert ('P1 : UART RX.' in output) - assert ('P2 : I2S SCK.' in output) - assert ('P3 : I2S SD.' in output) - assert ('P4 : I2S WS.' in output) - assert ('P5 : GPIO0 bias-pull-up input-disable.' in output) - assert ('P6 : GPIO1 drive-open-drain.' in output) - assert ('P7 : GPIO2 bias-pull-down input-enable.' in output) - assert ('P8 : GPIO3 bias-disable.' in output) + assert ('P0 : UART TX.' in output) + assert ('P1 : UART RX.' in output) + assert ('P2 : I2S SCK.' in output) + assert ('P3 : I2S SD.' in output) + assert ('P4 : I2S WS.' in output) + assert ('P5 : GPIO0 bias-pull-up input-disable.' in output) + assert ('P6 : GPIO1 drive-open-drain.' in output) + assert ('P7 : GPIO2 bias-pull-down input-enable.' in output) + assert ('P8 : GPIO3 bias-disable.' in output) @pytest.mark.buildconfigspec('cmd_pinmux') @pytest.mark.boardspec('sandbox') @@ -73,12 +73,12 @@ def test_pinmux_status(u_boot_console): assert (not 'pinctrl-gpio:' in output) assert (not 'pinctrl:' in output) - assert ('P0 : UART TX.' in output) - assert ('P1 : UART RX.' in output) - assert ('P2 : I2S SCK.' in output) - assert ('P3 : I2S SD.' in output) - assert ('P4 : I2S WS.' in output) - assert ('P5 : GPIO0 bias-pull-up input-disable.' in output) - assert ('P6 : GPIO1 drive-open-drain.' in output) - assert ('P7 : GPIO2 bias-pull-down input-enable.' in output) - assert ('P8 : GPIO3 bias-disable.' in output) + assert ('P0 : UART TX.' in output) + assert ('P1 : UART RX.' in output) + assert ('P2 : I2S SCK.' in output) + assert ('P3 : I2S SD.' in output) + assert ('P4 : I2S WS.' in output) + assert ('P5 : GPIO0 bias-pull-up input-disable.' in output) + assert ('P6 : GPIO1 drive-open-drain.' in output) + assert ('P7 : GPIO2 bias-pull-down input-enable.' in output) + assert ('P8 : GPIO3 bias-disable.' in output) -- 2.25.1