diff --git a/boards/st/nucleo_n657x0_q/Kconfig.nucleo_n657x0_q b/boards/st/nucleo_n657x0_q/Kconfig.nucleo_n657x0_q new file mode 100644 index 0000000000000..a1c2528a4709e --- /dev/null +++ b/boards/st/nucleo_n657x0_q/Kconfig.nucleo_n657x0_q @@ -0,0 +1,7 @@ +# STM32N657X0_Q Nucleo board configuration + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NUCLEO_N657X0_Q + select SOC_STM32N657XX diff --git a/boards/st/nucleo_n657x0_q/board.cmake b/boards/st/nucleo_n657x0_q/board.cmake new file mode 100644 index 0000000000000..a285b0deabd18 --- /dev/null +++ b/boards/st/nucleo_n657x0_q/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 STMicroelectronics + +board_runner_args(stm32cubeprogrammer "--port=swd") +board_runner_args(stm32cubeprogrammer "--tool-opt= mode=HOTPLUG ap=1") +board_runner_args(stm32cubeprogrammer "--extload=MX25UM51245G_STM32N6570-NUCLEO.stldr") +board_runner_args(stm32cubeprogrammer "--download-address=0x70000000") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) diff --git a/boards/st/nucleo_n657x0_q/board.yml b/boards/st/nucleo_n657x0_q/board.yml new file mode 100644 index 0000000000000..57f19a7e1fabb --- /dev/null +++ b/boards/st/nucleo_n657x0_q/board.yml @@ -0,0 +1,6 @@ +board: + name: nucleo_n657x0_q + full_name: Nucleo N657x0-Q + vendor: st + socs: + - name: stm32n657xx diff --git a/boards/st/nucleo_n657x0_q/doc/img/nucleo_n657x0_q.webp b/boards/st/nucleo_n657x0_q/doc/img/nucleo_n657x0_q.webp new file mode 100644 index 0000000000000..c6d918de66d9c Binary files /dev/null and b/boards/st/nucleo_n657x0_q/doc/img/nucleo_n657x0_q.webp differ diff --git a/boards/st/nucleo_n657x0_q/doc/index.rst b/boards/st/nucleo_n657x0_q/doc/index.rst new file mode 100644 index 0000000000000..3ea57ffadd382 --- /dev/null +++ b/boards/st/nucleo_n657x0_q/doc/index.rst @@ -0,0 +1,182 @@ +.. zephyr:board:: nucleo_n657x0_q + +Overview +******** + +The STM32 Nucleo-144 board provides an affordable and flexible way for users to try out +new concepts and build prototypes by choosing from the various combinations of performance +and power consumption features, provided by the STM32 microcontroller. For the compatible boards, +the internal or external SMPS significantly reduces power consumption in Run mode. + +The ST Zio connector, which extends the ARDUINO® Uno V3 connectivity, and the ST morpho headers +provide an easy means of expanding the functionality of the Nucleo open development platform with +a wide choice of specialized shields. + +The STM32 Nucleo-144 board does not require any separate probe as it integrates the ST-LINK +debugger/programmer. + +The STM32 Nucleo-144 board comes with the STM32 comprehensive free software libraries and +examples available with the STM32Cube MCU Package. + +Hardware +******** + +- Common features: + + - STM32 microcontroller in an LQFP144, TFBGA225, or VFBGA264 package + - 3 user LEDs + - 1 user push-button and 1 reset push-button + - 32.768 kHz crystal oscillator + - Board connectors: + + - SWD + - ST morpho expansion connector + + - Flexible power-supply options: ST-LINK USB VBUS, USB connector, or external sources + +- Features specific to some of the boards (refer to the ordering information section + of the data brief for details); + + - External or internal SMPS to generate Vcore logic supply + - Ethernet compliant with IEEE-802.3-2002 + - USB Device only, USB OTG full speed, or SNK/UFP (full-speed or high-speed mode) + - Board connectors: + + - ARDUINO® Uno V3 connector or ST Zio expansion connector including ARDUINO® Uno V3 + - Camera module FPC + - MIPI20 compatible connector with trace signals + - USB with Micro-AB or USB Type-C® + - Ethernet RJ45 + + - On-board ST-LINK (STLINK/V2-1, STLINK-V3E, or STLINK-V3EC) debugger/programmer with + USB re-enumeration capability: mass storage, Virtual COM port, and debug port + +Supported Features +================== + +The Zephyr ``nucleo_n657x0_q`` board supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration can be found in the defconfig file: +:zephyr_file:`boards/st/nucleo_n657x0_q/nucleo_n657x0_q_defconfig` + + +Connections and IOs +=================== + +NUCLEO_N657X0_Q Board has 12 GPIO controllers. These controllers are responsible +for pin muxing, input/output, pull-up, etc. + +For more details please refer to `NUCLEO_N657X0_Q User Manual`_. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- LD1 : PO1 +- LD2 : PG10 +- USART_1_TX : PE5 +- USART_1_RX : PE6 + +System Clock +------------ + +NUCLEO_N657X0_Q System Clock could be driven by internal or external oscillator, +as well as main PLL clock. By default System clock is driven by PLL clock at +400MHz, driven by 64MHz high speed internal oscillator. + +Serial Port +----------- + +NUCLEO_N657X0_Q board has 10 U(S)ARTs. The Zephyr console output is assigned to +USART1. Default settings are 115200 8N1. + +Programming and Debugging +************************* + +NUCLEO_N657X0_Q board includes an ST-LINK/V3 embedded debug tool interface. +This probe allows to flash the board using various tools. + +Flashing +======== + +The board is configured to be flashed using west `STM32CubeProgrammer`_ runner, +so its :ref:`installation ` is required. +Version 2.18.0 or later of `STM32CubeProgrammer`_ is required. + +Flashing an application to NUCLEO_N657X0_Q +------------------------------------------ + +Connect the NUCLEO_N657X0_Q to your host computer using the USB port. +Then build and flash an application. + +.. note:: + For flashing, BOOT0 pin should be set to 0 and BOOT1 to 1 before powering on + the board. + + To run the application after flashing, BOOT1 should be set to 0 and the board + should be powered off and on again. + +Here is an example for the :zephyr:code-sample:`hello_world` application. + +Run a serial host program to connect with your Nucleo board: + +.. code-block:: console + + $ minicom -D /dev/ttyACM0 + +Then build and flash the application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: nucleo_n657x0_q + :goals: build flash + +You should see the following message on the console: + +.. code-block:: console + + Hello World! nucleo_n657x0_q/stm32n657xx + +Debugging +========= + +For now debugging is only available through STM32CubeIDE: +* Go to File > Import and select C/C++ > STM32 Cortex-M Executable +* In Executable field, browse to your /build/zephyr/zephyr.elf +* In MCU field, select STM32N657X0HxQ. +* Click on Finish +* Then click on Debug to start the debugging session + +.. note:: + For debugging, BOOT0 pin should be set to 0 and BOOT1 to 1 before powering on the + board. + +.. _NUCLEO_N657X0_Q website: + https://www.st.com/en/evaluation-tools/nucleo-n657x0-q.html + +.. _NUCLEO_N657X0_Q User Manual: + https://www.st.com/resource/en/user_manual/um3417-stm32n6-nucleo144-board-mb1940-stmicroelectronics.pdf + +.. _STM32N657X0 on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32n657x0.html + +.. _STM32N657 reference manual: + https://www.st.com/resource/en/reference_manual/rm0486-stm32n647657xx-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.dts b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.dts new file mode 100644 index 0000000000000..92943cbfd52fa --- /dev/null +++ b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.dts @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include + +/ { + model = "STMicroelectronics STM32N657X0-Q-NUCLEO board"; + compatible = "st,stm32n657x0-q-nucleo"; + + chosen { + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &axisram2; + }; + + leds: leds { + compatible = "gpio-leds"; + + green_led: led_1 { + gpios = <&gpiog 0 GPIO_ACTIVE_HIGH>; + label = "User LD6"; + }; + + blue_led: led_2 { + gpios = <&gpiog 8 GPIO_ACTIVE_HIGH>; + label = "User LD7"; + }; + + red_led: led_3 { + gpios = <&gpiog 10 GPIO_ACTIVE_HIGH>; + label = "User LD5"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + user_button: button_0 { + gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + label = "User SB1"; + zephyr,code = ; + }; + }; + + aliases { + led0 = &green_led; + sw0 = &user_button; + }; +}; + +&clk_hsi { + hsi-div = <1>; + status = "okay"; +}; + +&pll1 { + clocks = <&clk_hsi>; + div-m = <4>; + mul-n = <75>; + div-p1 = <1>; + div-p2 = <1>; + status = "okay"; +}; + +&ic1 { + pll-src = <1>; + ic-div = <2>; + status = "okay"; +}; + +&ic2 { + pll-src = <1>; + ic-div = <3>; + status = "okay"; +}; + +&ic6 { + pll-src = <1>; + ic-div = <2>; + status = "okay"; +}; + +&ic11 { + pll-src = <1>; + ic-div = <3>; + status = "okay"; +}; + +&perck { + clocks = <&rcc STM32_SRC_HSI PER_SEL(0)>; + status = "okay"; +}; + +&cpusw { + clocks = <&rcc STM32_SRC_IC1 CPU_SEL(3)>; + clock-frequency = ; + status = "okay"; +}; + +&rcc { + /* ic2, ic6 & ic11 must all be enabled to set ic2 as SYSCLK */ + clocks = <&ic2>; + clock-frequency = ; + ahb-prescaler = <2>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb4-prescaler = <1>; + apb5-prescaler = <1>; +}; + +&usart1 { + clocks = <&rcc STM32_CLOCK(APB2, 4)>, + <&rcc STM32_SRC_CKPER USART1_SEL(1)>; + pinctrl-0 = <&usart1_tx_pe5 &usart1_rx_pe6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; diff --git a/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.yaml b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.yaml new file mode 100644 index 0000000000000..7e398f0d7fe91 --- /dev/null +++ b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q.yaml @@ -0,0 +1,14 @@ +identifier: nucleo_n657x0_q +name: ST Nucleo N657X0-Q +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 1024 +flash: 0 +supported: + - gpio + - uart +vendor: st diff --git a/boards/st/nucleo_n657x0_q/nucleo_n657x0_q_defconfig b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q_defconfig new file mode 100644 index 0000000000000..5dfa1d198f0ab --- /dev/null +++ b/boards/st/nucleo_n657x0_q/nucleo_n657x0_q_defconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 STMicroelectronics + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# No internal Flash +CONFIG_XIP=n diff --git a/boards/st/stm32n6570_dk/Kconfig.stm32n6570_dk b/boards/st/stm32n6570_dk/Kconfig.stm32n6570_dk new file mode 100644 index 0000000000000..667266938964b --- /dev/null +++ b/boards/st/stm32n6570_dk/Kconfig.stm32n6570_dk @@ -0,0 +1,5 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_STM32N6570_DK + select SOC_STM32N657XX diff --git a/boards/st/stm32n6570_dk/board.cmake b/boards/st/stm32n6570_dk/board.cmake new file mode 100644 index 0000000000000..fbbb050642a77 --- /dev/null +++ b/boards/st/stm32n6570_dk/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 STMicroelectronics + +board_runner_args(stm32cubeprogrammer "--port=swd") +board_runner_args(stm32cubeprogrammer "--tool-opt= mode=HOTPLUG ap=1") +board_runner_args(stm32cubeprogrammer "--extload=MX66UW1G45G_STM32N6570-DK.stldr") +board_runner_args(stm32cubeprogrammer "--download-address=0x70000000") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) diff --git a/boards/st/stm32n6570_dk/board.yml b/boards/st/stm32n6570_dk/board.yml new file mode 100644 index 0000000000000..04d7a92c5b05b --- /dev/null +++ b/boards/st/stm32n6570_dk/board.yml @@ -0,0 +1,6 @@ +board: + name: stm32n6570_dk + full_name: STM32N6570-DK + vendor: st + socs: + - name: stm32n657xx diff --git a/boards/st/stm32n6570_dk/doc/img/stm32n6570_dk.webp b/boards/st/stm32n6570_dk/doc/img/stm32n6570_dk.webp new file mode 100644 index 0000000000000..a6788dc33283e Binary files /dev/null and b/boards/st/stm32n6570_dk/doc/img/stm32n6570_dk.webp differ diff --git a/boards/st/stm32n6570_dk/doc/index.rst b/boards/st/stm32n6570_dk/doc/index.rst new file mode 100644 index 0000000000000..7b4218d2c8f03 --- /dev/null +++ b/boards/st/stm32n6570_dk/doc/index.rst @@ -0,0 +1,188 @@ +.. zephyr:board:: stm32n6570_dk + +Overview +******** + +The STM32N6570_DK Discovery kit is a complete demonstration and development platform +for the Arm® Cortex®‑M55 core‑based STM32N657X0H3Q microcontroller. + +The STM32N6570_DK Discovery kit includes a full range of hardware features that help +the user evaluate many peripherals, such as USB Type-C®, Octo‑SPI flash memory and +Hexadeca‑SPI PSRAM devices, Ethernet, camera module, LCD, microSD™, audio codec, +digital microphones, ADC, flexible extension connectors, and user button. +The four flexible extension connectors feature easy and unlimited expansion capabilities +for specific applications such as wireless connectivity, analog applications, and sensors. + +The STM32N657X0H3Q microcontroller features one USB 2.0 high‑speed/full‑speed +Device/Host/OTG controller, one USB 2.0 high‑speed/full‑speed Device/Host/OTG controller +with UCPD (USB Type-C® Power Delivery), one Ethernet with TSN (time-sensitive networking), +four I2Cs, two I3Cs, six SPIs (of which four I2S‑capable), two SAIs, with four DMIC support, +five USARTs, five UARTs (ISO78916 interface, LIN, IrDA, up to 12.5 Mbit/s), one LPUART, +two SDMMCs (MMC version 4.0, CE-ATA version 1.0, and SD version 1.0.1), three CAN FD +with TTCAN capability, JTAG and SWD debugging support, and Embedded Trace Macrocell™ (ETM). + +The STM32N6570_DK Discovery kit integrates an STLINK-V3EC embedded in-circuit debugger and +programmer for the STM32 MCU, with a USB Virtual COM port bridge and the comprehensive MCU Package. + +Hardware +******** + +- STM32N657X0H3Q Arm® Cortex®‑M55‑based microcontroller featuring ST Neural-ART Accelerator, + H264 encoder, NeoChrom 2.5D GPU, and 4.2 Mbytes of contiguous SRAM, in a VFBGA264 package +- 5" LCD module with capacitive touch panel +- USB Type-C® with USB 2.0 HS interface, dual‑role‑power (DRP) +- USB Type-A with USB 2.0 HS interface, host, 0.5 A max +- 1‑Gbit Ethernet with TSN (time-sensitive networking) compliant with IEEE‑802.3‑2002 +- SAI audio codec +- One MEMS digital microphone +- 1‑Gbit Octo‑SPI flash memory +- 256-Mbit Hexadeca‑SPI PSRAM +- Two user LEDs +- User, tamper, and reset push-buttons +- Board connectors: + + - USB Type-C® + - USB Type-A + - Ethernet RJ45 + - Camera module + - microSD™ card + - LCD + - Stereo headset jack including analog microphone input + - Audio MEMS daughterboard expansion connector + - ARDUINO® Uno R3 expansion connector + - STMod+ expansion connector + +- On-board STLINK-V3EC debugger/programmer with USB re-enumeration capability: + Virtual COM port, and debug port + + +Supported Features +================== + +The Zephyr ``stm32n6570_dk`` board supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration can be found in the defconfig file: +:zephyr_file:`boards/st/stm32n6570_dk/stm32n6570_dk_defconfig` + + +Connections and IOs +=================== + +STM32N6570_DK Board has 12 GPIO controllers. These controllers are responsible +for pin muxing, input/output, pull-up, etc. + +For more details please refer to `STM32N6570_DK User Manual`_. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- LD1 : PO1 +- LD2 : PG10 +- USART_1_TX : PE5 +- USART_1_RX : PE6 + +System Clock +------------ + +STM32N6570_DK System Clock could be driven by internal or external oscillator, +as well as main PLL clock. By default System clock is driven by PLL clock at +400MHz, driven by 64MHz high speed internal oscillator. + +Serial Port +----------- + +STM32N6570_DK board has 10 U(S)ARTs. The Zephyr console output is assigned to +USART1. Default settings are 115200 8N1. + +Programming and Debugging +************************* + +STM32N6570_DK board includes an ST-LINK/V3 embedded debug tool interface. +This probe allows to flash the board using various tools. + +Flashing +======== + +The board is configured to be flashed using west `STM32CubeProgrammer`_ runner, +so its :ref:`installation ` is required. +Version 2.18.0 or later of `STM32CubeProgrammer`_ is required. + +Flashing an application to STM32N6570_DK +------------------------------------------ + +Connect the STM32N6570_DK to your host computer using the USB port. +Then build and flash an application. + +.. note:: + For flashing, BOOT0 pin should be set to 0 and BOOT1 to 1 before powering on + the board. + + To run the application after flashing, BOOT1 should be set to 0 and the board + should be powered off and on again. + +Here is an example for the :zephyr:code-sample:`hello_world` application. + +Run a serial host program to connect with your Disco board: + +.. code-block:: console + + $ minicom -D /dev/ttyACM0 + +Then build and flash the application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: stm32n6570_dk + :goals: build flash + +You should see the following message on the console: + +.. code-block:: console + + Hello World! stm32n6570_dk/stm32n657xx + + +Debugging +========= + +For now debugging is only available through STM32CubeIDE: +* Go to File > Import and select C/C++ > STM32 Cortex-M Executable +* In Executable field, browse to your /build/zephyr/zephyr.elf +* In MCU field, select STM32N657X0HxQ. +* Click on Finish +* Then click on Debug to start the debugging session + +.. note:: + For debugging, BOOT0 pin should be set to 0 and BOOT1 to 1 before powering on the + board. + +.. _STM32N6570_DK website: + https://www.st.com/en/evaluation-tools/stm32n6570-dk.html + +.. _STM32N6570_DK User Manual: + https://www.st.com/resource/en/user_manual/um3300-discovery-kit-with-stm32n657x0-mcu-stmicroelectronics.pdf + +.. _STM32N657X0 on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32n657x0.html + +.. _STM32N657 reference manual: + https://www.st.com/resource/en/reference_manual/rm0486-stm32n647657xx-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/st/stm32n6570_dk/stm32n6570_dk.dts b/boards/st/stm32n6570_dk/stm32n6570_dk.dts new file mode 100644 index 0000000000000..94cd6ac702b02 --- /dev/null +++ b/boards/st/stm32n6570_dk/stm32n6570_dk.dts @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include + +/ { + model = "STMicroelectronics STM32N6570 Discovery Kit board"; + compatible = "st,stm32n6570-dk"; + + chosen { + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &axisram2; + }; + + aliases { + led0 = &green_led_1; + }; + + leds: leds { + compatible = "gpio-leds"; + + green_led_1: led_1 { + gpios = <&gpioo 1 GPIO_ACTIVE_HIGH>; + label = "User LD1"; + }; + + red_led_1: led_2 { + gpios = <&gpiog 10 GPIO_ACTIVE_HIGH>; + label = "User LD2"; + }; + }; +}; + +&clk_hsi { + hsi-div = <1>; + status = "okay"; +}; + +&pll1 { + clocks = <&clk_hsi>; + div-m = <4>; + mul-n = <75>; + div-p1 = <1>; + div-p2 = <1>; + status = "okay"; +}; + +&ic1 { + pll-src = <1>; + ic-div = <2>; + status = "okay"; +}; + +&ic2 { + pll-src = <1>; + ic-div = <3>; + status = "okay"; +}; + +&ic6 { + pll-src = <1>; + ic-div = <2>; + status = "okay"; +}; + +&ic11 { + pll-src = <1>; + ic-div = <3>; + status = "okay"; +}; + +&perck { + clocks = <&rcc STM32_SRC_HSI PER_SEL(0)>; + status = "okay"; +}; + +&cpusw { + clocks = <&rcc STM32_SRC_IC1 CPU_SEL(3)>; + clock-frequency = ; + status = "okay"; +}; + +&rcc { + /* ic2, ic6 & ic11 must all be enabled to set ic2 as SYSCLK */ + clocks = <&ic2>; + clock-frequency = ; + ahb-prescaler = <2>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb4-prescaler = <1>; + apb5-prescaler = <1>; +}; + +&usart1 { + clocks = <&rcc STM32_CLOCK(APB2, 4)>, + <&rcc STM32_SRC_CKPER USART1_SEL(1)>; + pinctrl-0 = <&usart1_tx_pe5 &usart1_rx_pe6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; diff --git a/boards/st/stm32n6570_dk/stm32n6570_dk.yaml b/boards/st/stm32n6570_dk/stm32n6570_dk.yaml new file mode 100644 index 0000000000000..390fd67caa937 --- /dev/null +++ b/boards/st/stm32n6570_dk/stm32n6570_dk.yaml @@ -0,0 +1,14 @@ +identifier: stm32n6570_dk +name: STM32N6570 Discovery Kit +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 1024 +flash: 0 +supported: + - gpio + - uart +vendor: st diff --git a/boards/st/stm32n6570_dk/stm32n6570_dk_defconfig b/boards/st/stm32n6570_dk/stm32n6570_dk_defconfig new file mode 100644 index 0000000000000..5dfa1d198f0ab --- /dev/null +++ b/boards/st/stm32n6570_dk/stm32n6570_dk_defconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 STMicroelectronics + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# No internal Flash +CONFIG_XIP=n diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 8c451149a584f..9d7a87e03e671 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -59,6 +59,8 @@ elseif(CONFIG_SOC_SERIES_STM32H7RSX) zephyr_library_sources(clock_stm32_ll_h7.c) elseif(CONFIG_SOC_SERIES_STM32H5X) zephyr_library_sources(clock_stm32_ll_h5.c) +elseif(CONFIG_SOC_SERIES_STM32N6X) + zephyr_library_sources(clock_stm32_ll_n6.c) elseif(CONFIG_SOC_SERIES_STM32U5X) zephyr_library_sources(clock_stm32_ll_u5.c) elseif(CONFIG_SOC_SERIES_STM32WB0X) diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index 47a1b790a7b0d..d99fa3b62eb29 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -10,7 +10,8 @@ menuconfig CLOCK_CONTROL_STM32_CUBE default y select USE_STM32_LL_UTILS select USE_STM32_LL_RCC if (SOC_SERIES_STM32MP1X || SOC_SERIES_STM32H7X || \ - SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X) + SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || \ + SOC_SERIES_STM32N6X) select RUNTIME_NMI if ($(dt_nodelabel_enabled,clk_hse) && \ $(dt_nodelabel_has_prop,clk_hse,css-enabled)) help diff --git a/drivers/clock_control/clock_stm32_ll_n6.c b/drivers/clock_control/clock_stm32_ll_n6.c new file mode 100644 index 0000000000000..e69faf6823d5b --- /dev/null +++ b/drivers/clock_control/clock_stm32_ll_n6.c @@ -0,0 +1,950 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Macros to fill up prescaler values */ +#define z_ic_src_pll(v) LL_RCC_ICCLKSOURCE_PLL ## v +#define ic_src_pll(v) z_ic_src_pll(v) + +#define z_hsi_divider(v) LL_RCC_HSI_DIV_ ## v +#define hsi_divider(v) z_hsi_divider(v) + +#define z_ahb_prescaler(v) LL_RCC_AHB_DIV_ ## v +#define ahb_prescaler(v) z_ahb_prescaler(v) + +#define z_apb1_prescaler(v) LL_RCC_APB1_DIV_ ## v +#define apb1_prescaler(v) z_apb1_prescaler(v) + +#define z_apb2_prescaler(v) LL_RCC_APB2_DIV_ ## v +#define apb2_prescaler(v) z_apb2_prescaler(v) + +#define z_apb4_prescaler(v) LL_RCC_APB4_DIV_ ## v +#define apb4_prescaler(v) z_apb4_prescaler(v) + +#define z_apb5_prescaler(v) LL_RCC_APB5_DIV_ ## v +#define apb5_prescaler(v) z_apb5_prescaler(v) + +#define PLL1_ID 1 +#define PLL2_ID 2 +#define PLL3_ID 3 +#define PLL4_ID 4 + + +static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler) +{ + return clock / prescaler; +} + +__unused +/** @brief returns the pll source frequency of given pll_id */ +static uint32_t get_pllsrc_frequency(int pll_id) +{ + if ((IS_ENABLED(STM32_PLL_SRC_HSI) && pll_id == PLL1_ID) || + (IS_ENABLED(STM32_PLL2_SRC_HSI) && pll_id == PLL2_ID) || + (IS_ENABLED(STM32_PLL3_SRC_HSI) && pll_id == PLL3_ID) || + (IS_ENABLED(STM32_PLL4_SRC_HSI) && pll_id == PLL4_ID)) { + return STM32_HSI_FREQ; + } else if ((IS_ENABLED(STM32_PLL_SRC_HSE) && pll_id == PLL1_ID) || + (IS_ENABLED(STM32_PLL2_SRC_HSE) && pll_id == PLL2_ID) || + (IS_ENABLED(STM32_PLL3_SRC_HSE) && pll_id == PLL3_ID) || + (IS_ENABLED(STM32_PLL4_SRC_HSE) && pll_id == PLL4_ID)) { + return STM32_HSE_FREQ; + } + + __ASSERT(0, "No PLL Source configured"); + return 0; +} + +static uint32_t get_pllout_frequency(int pll_id) +{ + uint32_t pllsrc_freq = get_pllsrc_frequency(pll_id); + int pllm_div; + int plln_mul; + int pllout_div1; + int pllout_div2; + + switch (pll_id) { +#if defined(STM32_PLL1_ENABLED) + case PLL1_ID: + pllm_div = STM32_PLL1_M_DIVISOR; + plln_mul = STM32_PLL1_N_MULTIPLIER; + pllout_div1 = STM32_PLL1_P1_DIVISOR; + pllout_div2 = STM32_PLL1_P2_DIVISOR; + break; +#endif /* STM32_PLL1_ENABLED */ +#if defined(STM32_PLL2_ENABLED) + case PLL2_ID: + pllm_div = STM32_PLL2_M_DIVISOR; + plln_mul = STM32_PLL2_N_MULTIPLIER; + pllout_div1 = STM32_PLL2_P1_DIVISOR; + pllout_div2 = STM32_PLL2_P2_DIVISOR; + break; +#endif /* STM32_PLL2_ENABLED */ +#if defined(STM32_PLL3_ENABLED) + case PLL3_ID: + pllm_div = STM32_PLL3_M_DIVISOR; + plln_mul = STM32_PLL3_N_MULTIPLIER; + pllout_div1 = STM32_PLL3_P1_DIVISOR; + pllout_div2 = STM32_PLL3_P2_DIVISOR; + break; +#endif /* STM32_PLL3_ENABLED */ +#if defined(STM32_PLL4_ENABLED) + case PLL4_ID: + pllm_div = STM32_PLL4_M_DIVISOR; + plln_mul = STM32_PLL4_N_MULTIPLIER; + pllout_div1 = STM32_PLL4_P1_DIVISOR; + pllout_div2 = STM32_PLL4_P2_DIVISOR; + break; +#endif /* STM32_PLL4_ENABLED */ + default: + __ASSERT(0, "No PLL configured"); + return 0; + } + + __ASSERT_NO_MSG(pllm_div && pllout_div1 && pllout_div2); + + return (pllsrc_freq / pllm_div) * plln_mul / (pllout_div1 * pllout_div2); +} + +__unused uint32_t get_icout_frequency(uint32_t icsrc, int div) +{ + if (icsrc == LL_RCC_ICCLKSOURCE_PLL1) { + return get_pllout_frequency(PLL1_ID) / div; + } else if (icsrc == LL_RCC_ICCLKSOURCE_PLL2) { + return get_pllout_frequency(PLL2_ID) / div; + } else if (icsrc == LL_RCC_ICCLKSOURCE_PLL3) { + return get_pllout_frequency(PLL3_ID) / div; + } else if (icsrc == LL_RCC_ICCLKSOURCE_PLL4) { + return get_pllout_frequency(PLL4_ID) / div; + } + + __ASSERT(0, "No IC Source configured"); + return 0; +} + +static uint32_t get_sysclk_frequency(void) +{ +#if defined(STM32_SYSCLK_SRC_HSE) + return STM32_HSE_FREQ; +#elif defined(STM32_SYSCLK_SRC_HSI) + return STM32_HSI_FREQ; +#elif defined(STM32_SYSCLK_SRC_IC2) + return get_icout_frequency(LL_RCC_IC2_GetSource(), STM32_IC2_DIV); +#else + __ASSERT(0, "No SYSCLK Source configured"); + return 0; +#endif + +} + + +/** @brief Verifies clock is part of active clock configuration */ +static int enabled_clock(uint32_t src_clk) +{ + if ((src_clk == STM32_SRC_SYSCLK) || + ((src_clk == STM32_SRC_LSE) && IS_ENABLED(STM32_LSE_ENABLED)) || + ((src_clk == STM32_SRC_LSI) && IS_ENABLED(STM32_LSI_ENABLED)) || + ((src_clk == STM32_SRC_HSE) && IS_ENABLED(STM32_HSE_ENABLED)) || + ((src_clk == STM32_SRC_HSI) && IS_ENABLED(STM32_HSI_ENABLED)) || + ((src_clk == STM32_SRC_PLL1) && IS_ENABLED(STM32_PLL1_ENABLED)) || + ((src_clk == STM32_SRC_PLL2) && IS_ENABLED(STM32_PLL2_ENABLED)) || + ((src_clk == STM32_SRC_PLL3) && IS_ENABLED(STM32_PLL3_ENABLED)) || + ((src_clk == STM32_SRC_PLL4) && IS_ENABLED(STM32_PLL4_ENABLED)) || + ((src_clk == STM32_SRC_CKPER) && IS_ENABLED(STM32_CKPER_ENABLED)) || + ((src_clk == STM32_SRC_IC1) && IS_ENABLED(STM32_IC1_ENABLED)) || + ((src_clk == STM32_SRC_IC2) && IS_ENABLED(STM32_IC2_ENABLED)) || + ((src_clk == STM32_SRC_IC3) && IS_ENABLED(STM32_IC3_ENABLED)) || + ((src_clk == STM32_SRC_IC4) && IS_ENABLED(STM32_IC4_ENABLED)) || + ((src_clk == STM32_SRC_IC5) && IS_ENABLED(STM32_IC5_ENABLED)) || + ((src_clk == STM32_SRC_IC6) && IS_ENABLED(STM32_IC6_ENABLED)) || + ((src_clk == STM32_SRC_IC7) && IS_ENABLED(STM32_IC7_ENABLED)) || + ((src_clk == STM32_SRC_IC8) && IS_ENABLED(STM32_IC8_ENABLED)) || + ((src_clk == STM32_SRC_IC9) && IS_ENABLED(STM32_IC9_ENABLED)) || + ((src_clk == STM32_SRC_IC10) && IS_ENABLED(STM32_IC10_ENABLED)) || + ((src_clk == STM32_SRC_IC11) && IS_ENABLED(STM32_IC11_ENABLED)) || + ((src_clk == STM32_SRC_IC12) && IS_ENABLED(STM32_IC12_ENABLED)) || + ((src_clk == STM32_SRC_IC13) && IS_ENABLED(STM32_IC13_ENABLED)) || + ((src_clk == STM32_SRC_IC14) && IS_ENABLED(STM32_IC14_ENABLED)) || + ((src_clk == STM32_SRC_IC15) && IS_ENABLED(STM32_IC15_ENABLED)) || + ((src_clk == STM32_SRC_IC16) && IS_ENABLED(STM32_IC16_ENABLED)) || + ((src_clk == STM32_SRC_IC17) && IS_ENABLED(STM32_IC17_ENABLED)) || + ((src_clk == STM32_SRC_IC18) && IS_ENABLED(STM32_IC18_ENABLED)) || + ((src_clk == STM32_SRC_IC19) && IS_ENABLED(STM32_IC19_ENABLED)) || + ((src_clk == STM32_SRC_IC20) && IS_ENABLED(STM32_IC20_ENABLED))) { + return 0; + } + + return -ENOTSUP; +} + +static inline int stm32_clock_control_on(const struct device *dev, + clock_control_subsys_t sub_system) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + + ARG_UNUSED(dev); + + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attempt to toggle a wrong periph clock bit */ + return -ENOTSUP; + } + + /* Set Run clock */ + sys_set_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus, + pclken->enr); + + /* Set Low Power clock */ + sys_set_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus + STM32_CLOCK_LP_BUS_SHIFT, + pclken->enr); + + return 0; +} + +static inline int stm32_clock_control_off(const struct device *dev, + clock_control_subsys_t sub_system) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + + ARG_UNUSED(dev); + + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attempt to toggle a wrong periph clock bit */ + return -ENOTSUP; + } + + /* Clear Run clock */ + sys_clear_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus, + pclken->enr); + + /* Clear Low Power clock */ + sys_clear_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus + STM32_CLOCK_LP_BUS_SHIFT, + pclken->enr); + + return 0; +} + +static inline int stm32_clock_control_configure(const struct device *dev, + clock_control_subsys_t sub_system, + void *data) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + int err; + + ARG_UNUSED(dev); + ARG_UNUSED(data); + + err = enabled_clock(pclken->bus); + if (err < 0) { + /* Attempt to configure a src clock not available or not valid */ + return err; + } + + sys_clear_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_CLOCK_REG_GET(pclken->enr), + STM32_CLOCK_MASK_GET(pclken->enr) << STM32_CLOCK_SHIFT_GET(pclken->enr)); + sys_set_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_CLOCK_REG_GET(pclken->enr), + STM32_CLOCK_VAL_GET(pclken->enr) << STM32_CLOCK_SHIFT_GET(pclken->enr)); + + return 0; +} + +static int stm32_clock_control_get_subsys_rate(const struct device *dev, + clock_control_subsys_t sys, + uint32_t *rate) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sys); + + uint32_t sys_clock = get_sysclk_frequency(); + uint32_t ahb_clock = get_bus_clock(sys_clock, STM32_AHB_PRESCALER); + + ARG_UNUSED(dev); + + switch (pclken->bus) { + case STM32_SRC_SYSCLK: + *rate = get_sysclk_frequency(); + break; + case STM32_CLOCK_BUS_AHB1: + case STM32_CLOCK_BUS_AHB2: + case STM32_CLOCK_BUS_AHB3: + case STM32_CLOCK_BUS_AHB4: + case STM32_CLOCK_BUS_AHB5: + *rate = ahb_clock; + break; + case STM32_CLOCK_BUS_APB1: + case STM32_CLOCK_BUS_APB1_2: + *rate = get_bus_clock(ahb_clock, STM32_APB1_PRESCALER); + break; + case STM32_CLOCK_BUS_APB2: + *rate = get_bus_clock(ahb_clock, STM32_APB2_PRESCALER); + break; + case STM32_CLOCK_BUS_APB4: + case STM32_CLOCK_BUS_APB4_2: + *rate = get_bus_clock(ahb_clock, STM32_APB4_PRESCALER); + break; + case STM32_CLOCK_BUS_APB5: + *rate = get_bus_clock(ahb_clock, STM32_APB5_PRESCALER); + break; +#if defined(STM32_LSE_ENABLED) + case STM32_SRC_LSE: + *rate = STM32_LSE_FREQ; + break; +#endif /* STM32_LSE_ENABLED */ +#if defined(STM32_LSI_ENABLED) + case STM32_SRC_LSI: + *rate = STM32_LSI_FREQ; + break; +#endif /* STM32_LSI_ENABLED */ +#if defined(STM32_HSE_ENABLED) + case STM32_SRC_HSE: + *rate = STM32_HSE_FREQ; + break; +#endif /* STM32_HSE_ENABLED */ +#if defined(STM32_HSI_ENABLED) + case STM32_SRC_HSI: + *rate = STM32_HSI_FREQ; + break; +#endif /* STM32_HSI_ENABLED */ + case STM32_SRC_PLL1: + *rate = get_pllout_frequency(PLL1_ID); + break; + case STM32_SRC_PLL2: + *rate = get_pllout_frequency(PLL2_ID); + break; + case STM32_SRC_PLL3: + *rate = get_pllout_frequency(PLL3_ID); + break; + case STM32_SRC_PLL4: + *rate = get_pllout_frequency(PLL4_ID); + break; +#if defined(STM32_CKPER_ENABLED) + case STM32_SRC_CKPER: + *rate = LL_RCC_GetCLKPClockFreq(LL_RCC_CLKP_CLKSOURCE); + break; +#endif /* STM32_CKPER_ENABLED */ +#if defined(STM32_IC1_ENABLED) + case STM32_SRC_IC1: + *rate = get_icout_frequency(LL_RCC_IC1_GetSource(), STM32_IC1_DIV); + break; +#endif /* STM32_IC1_ENABLED */ +#if defined(STM32_IC2_ENABLED) + case STM32_SRC_IC2: + *rate = get_icout_frequency(LL_RCC_IC2_GetSource(), STM32_IC2_DIV); + break; +#endif /* STM32_IC2_ENABLED */ +#if defined(STM32_IC3_ENABLED) + case STM32_SRC_IC3: + *rate = get_icout_frequency(LL_RCC_IC3_GetSource(), STM32_IC3_DIV); + break; +#endif /* STM32_IC3_ENABLED */ +#if defined(STM32_IC4_ENABLED) + case STM32_SRC_IC4: + *rate = get_icout_frequency(LL_RCC_IC4_GetSource(), STM32_IC4_DIV); + break; +#endif /* STM32_IC4_ENABLED */ +#if defined(STM32_IC5_ENABLED) + case STM32_SRC_IC5: + *rate = get_icout_frequency(LL_RCC_IC5_GetSource(), STM32_IC5_DIV); + break; +#endif /* STM32_IC5_ENABLED */ +#if defined(STM32_IC6_ENABLED) + case STM32_SRC_IC6: + *rate = get_icout_frequency(LL_RCC_IC6_GetSource(), STM32_IC6_DIV); + break; +#endif /* STM32_IC6_ENABLED */ +#if defined(STM32_IC7_ENABLED) + case STM32_SRC_IC7: + *rate = get_icout_frequency(LL_RCC_IC7_GetSource(), STM32_IC7_DIV); + break; +#endif /* STM32_IC7_ENABLED */ +#if defined(STM32_IC8_ENABLED) + case STM32_SRC_IC8: + *rate = get_icout_frequency(LL_RCC_IC8_GetSource(), STM32_IC8_DIV); + break; +#endif /* STM32_IC8_ENABLED */ +#if defined(STM32_IC9_ENABLED) + case STM32_SRC_IC9: + *rate = get_icout_frequency(LL_RCC_IC9_GetSource(), STM32_IC9_DIV); + break; +#endif /* STM32_IC9_ENABLED */ +#if defined(STM32_IC10_ENABLED) + case STM32_SRC_IC10: + *rate = get_icout_frequency(LL_RCC_IC10_GetSource(), STM32_IC10_DIV); + break; +#endif /* STM32_IC10_ENABLED */ +#if defined(STM32_IC11_ENABLED) + case STM32_SRC_IC11: + *rate = get_icout_frequency(LL_RCC_IC11_GetSource(), STM32_IC11_DIV); + break; +#endif /* STM32_IC11_ENABLED */ +#if defined(STM32_IC12_ENABLED) + case STM32_SRC_IC12: + *rate = get_icout_frequency(LL_RCC_IC12_GetSource(), STM32_IC12_DIV); + break; +#endif /* STM32_IC12_ENABLED */ +#if defined(STM32_IC13_ENABLED) + case STM32_SRC_IC13: + *rate = get_icout_frequency(LL_RCC_IC13_GetSource(), STM32_IC13_DIV); + break; +#endif /* STM32_IC13_ENABLED */ +#if defined(STM32_IC14_ENABLED) + case STM32_SRC_IC14: + *rate = get_icout_frequency(LL_RCC_IC14_GetSource(), STM32_IC14_DIV); + break; +#endif /* STM32_IC14_ENABLED */ +#if defined(STM32_IC15_ENABLED) + case STM32_SRC_IC15: + *rate = get_icout_frequency(LL_RCC_IC15_GetSource(), STM32_IC15_DIV); + break; +#endif /* STM32_IC15_ENABLED */ +#if defined(STM32_IC16_ENABLED) + case STM32_SRC_IC16: + *rate = get_icout_frequency(LL_RCC_IC16_GetSource(), STM32_IC16_DIV); + break; +#endif /* STM32_IC16_ENABLED */ +#if defined(STM32_IC17_ENABLED) + case STM32_SRC_IC17: + *rate = get_icout_frequency(LL_RCC_IC17_GetSource(), STM32_IC17_DIV); + break; +#endif /* STM32_IC17_ENABLED */ +#if defined(STM32_IC18_ENABLED) + case STM32_SRC_IC18: + *rate = get_icout_frequency(LL_RCC_IC18_GetSource(), STM32_IC18_DIV); + break; +#endif /* STM32_IC18_ENABLED */ +#if defined(STM32_IC19_ENABLED) + case STM32_SRC_IC19: + *rate = get_icout_frequency(LL_RCC_IC19_GetSource(), STM32_IC19_DIV); + break; +#endif /* STM32_IC19_ENABLED */ +#if defined(STM32_IC20_ENABLED) + case STM32_SRC_IC20: + *rate = get_icout_frequency(LL_RCC_IC20_GetSource(), STM32_IC20_DIV); + break; +#endif /* STM32_IC20_ENABLED */ + default: + return -ENOTSUP; + } + + if (pclken->div) { + *rate /= (pclken->div + 1); + } + + return 0; +} + +static DEVICE_API(clock_control, stm32_clock_control_api) = { + .on = stm32_clock_control_on, + .off = stm32_clock_control_off, + .get_rate = stm32_clock_control_get_subsys_rate, + .configure = stm32_clock_control_configure, +}; + +/* + * Unconditionally switch the system clock source to HSI. + */ +__unused +static void stm32_clock_switch_to_hsi(void) +{ + /* Enable HSI if not enabled */ + if (LL_RCC_HSI_IsReady() != 1) { + /* Enable HSI */ + LL_RCC_HSI_Enable(); + while (LL_RCC_HSI_IsReady() != 1) { + /* Wait for HSI ready */ + } + } + + /* Set HSI as SYSCLCK source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) { + } + + LL_RCC_SetCpuClkSource(LL_RCC_CPU_CLKSOURCE_HSI); + while (LL_RCC_GetCpuClkSource() != LL_RCC_CPU_CLKSOURCE_STATUS_HSI) { + } +} + +static int set_up_ics(void) +{ +#if defined(STM32_IC1_ENABLED) + LL_RCC_IC1_SetSource(ic_src_pll(STM32_IC1_PLL_SRC)); + LL_RCC_IC1_SetDivider(STM32_IC1_DIV); + LL_RCC_IC1_Enable(); +#endif + +#if defined(STM32_IC2_ENABLED) + LL_RCC_IC2_SetSource(ic_src_pll(STM32_IC2_PLL_SRC)); + LL_RCC_IC2_SetDivider(STM32_IC2_DIV); + LL_RCC_IC2_Enable(); +#endif + +#if defined(STM32_IC3_ENABLED) + LL_RCC_IC3_SetSource(ic_src_pll(STM32_IC3_PLL_SRC)); + LL_RCC_IC3_SetDivider(STM32_IC3_DIV); + LL_RCC_IC3_Enable(); +#endif + +#if defined(STM32_IC4_ENABLED) + LL_RCC_IC4_SetSource(ic_src_pll(STM32_IC4_PLL_SRC)); + LL_RCC_IC4_SetDivider(STM32_IC4_DIV); + LL_RCC_IC4_Enable(); +#endif + +#if defined(STM32_IC5_ENABLED) + LL_RCC_IC5_SetSource(ic_src_pll(STM32_IC5_PLL_SRC)); + LL_RCC_IC5_SetDivider(STM32_IC5_DIV); + LL_RCC_IC5_Enable(); +#endif + +#if defined(STM32_IC6_ENABLED) + LL_RCC_IC6_SetSource(ic_src_pll(STM32_IC6_PLL_SRC)); + LL_RCC_IC6_SetDivider(STM32_IC6_DIV); + LL_RCC_IC6_Enable(); +#endif + +#if defined(STM32_IC7_ENABLED) + LL_RCC_IC7_SetSource(ic_src_pll(STM32_IC7_PLL_SRC)); + LL_RCC_IC7_SetDivider(STM32_IC7_DIV); + LL_RCC_IC7_Enable(); +#endif + +#if defined(STM32_IC8_ENABLED) + LL_RCC_IC8_SetSource(ic_src_pll(STM32_IC8_PLL_SRC)); + LL_RCC_IC8_SetDivider(STM32_IC8_DIV); + LL_RCC_IC8_Enable(); +#endif + +#if defined(STM32_IC9_ENABLED) + LL_RCC_IC9_SetSource(ic_src_pll(STM32_IC9_PLL_SRC)); + LL_RCC_IC9_SetDivider(STM32_IC9_DIV); + LL_RCC_IC9_Enable(); +#endif + +#if defined(STM32_IC10_ENABLED) + LL_RCC_IC10_SetSource(ic_src_pll(STM32_IC10_PLL_SRC)); + LL_RCC_IC10_SetDivider(STM32_IC10_DIV); + LL_RCC_IC10_Enable(); +#endif + +#if defined(STM32_IC11_ENABLED) + LL_RCC_IC11_SetSource(ic_src_pll(STM32_IC11_PLL_SRC)); + LL_RCC_IC11_SetDivider(STM32_IC11_DIV); + LL_RCC_IC11_Enable(); +#endif + +#if defined(STM32_IC12_ENABLED) + LL_RCC_IC12_SetSource(ic_src_pll(STM32_IC12_PLL_SRC)); + LL_RCC_IC12_SetDivider(STM32_IC12_DIV); + LL_RCC_IC12_Enable(); +#endif + +#if defined(STM32_IC13_ENABLED) + LL_RCC_IC13_SetSource(ic_src_pll(STM32_IC13_PLL_SRC)); + LL_RCC_IC13_SetDivider(STM32_IC13_DIV); + LL_RCC_IC13_Enable(); +#endif + +#if defined(STM32_IC14_ENABLED) + LL_RCC_IC14_SetSource(ic_src_pll(STM32_IC14_PLL_SRC)); + LL_RCC_IC14_SetDivider(STM32_IC14_DIV); + LL_RCC_IC14_Enable(); +#endif + +#if defined(STM32_IC15_ENABLED) + LL_RCC_IC15_SetSource(ic_src_pll(STM32_IC15_PLL_SRC)); + LL_RCC_IC15_SetDivider(STM32_IC15_DIV); + LL_RCC_IC15_Enable(); +#endif + +#if defined(STM32_IC16_ENABLED) + LL_RCC_IC16_SetSource(ic_src_pll(STM32_IC16_PLL_SRC)); + LL_RCC_IC16_SetDivider(STM32_IC16_DIV); + LL_RCC_IC16_Enable(); +#endif + +#if defined(STM32_IC17_ENABLED) + LL_RCC_IC17_SetSource(ic_src_pll(STM32_IC17_PLL_SRC)); + LL_RCC_IC17_SetDivider(STM32_IC17_DIV); + LL_RCC_IC17_Enable(); +#endif + +#if defined(STM32_IC18_ENABLED) + LL_RCC_IC18_SetSource(ic_src_pll(STM32_IC18_PLL_SRC)); + LL_RCC_IC18_SetDivider(STM32_IC18_DIV); + LL_RCC_IC18_Enable(); +#endif + +#if defined(STM32_IC19_ENABLED) + LL_RCC_IC19_SetSource(ic_src_pll(STM32_IC19_PLL_SRC)); + LL_RCC_IC19_SetDivider(STM32_IC19_DIV); + LL_RCC_IC19_Enable(); +#endif + +#if defined(STM32_IC20_ENABLED) + LL_RCC_IC20_SetSource(ic_src_pll(STM32_IC20_PLL_SRC)); + LL_RCC_IC20_SetDivider(STM32_IC20_DIV); + LL_RCC_IC20_Enable(); +#endif + + return 0; +} + +static int set_up_plls(void) +{ +#if defined(STM32_PLL1_ENABLED) + /* TODO: Do not switch systematically on HSI if not needed */ + stm32_clock_switch_to_hsi(); + + LL_RCC_PLL1_Disable(); + + /* Configure PLL source : Can be HSE, HSI, MSI */ + if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetSource(LL_RCC_PLLSOURCE_HSE); + } else if (IS_ENABLED(STM32_PLL_SRC_MSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetSource(LL_RCC_PLLSOURCE_MSI); + } else if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetSource(LL_RCC_PLLSOURCE_HSI); + } else { + return -ENOTSUP; + } + + /* Disable PLL1 modulation spread-spectrum */ + LL_RCC_PLL1_DisableModulationSpreadSpectrum(); + + /* Disable bypass to use the PLL VCO */ + if (LL_RCC_PLL1_IsEnabledBypass()) { + LL_RCC_PLL1_DisableBypass(); + } + + /* Configure PLL */ + LL_RCC_PLL1_SetM(STM32_PLL1_M_DIVISOR); + LL_RCC_PLL1_SetN(STM32_PLL1_N_MULTIPLIER); + LL_RCC_PLL1_SetP1(STM32_PLL1_P1_DIVISOR); + LL_RCC_PLL1_SetP2(STM32_PLL1_P2_DIVISOR); + + /* Disable fractional mode */ + LL_RCC_PLL1_SetFRACN(0); + LL_RCC_PLL1_DisableFractionalModulationSpreadSpectrum(); + + LL_RCC_PLL1_AssertModulationSpreadSpectrumReset(); + + /* Enable post division */ + if (!LL_RCC_PLL1P_IsEnabled()) { + LL_RCC_PLL1P_Enable(); + } + + LL_RCC_PLL1_Enable(); + while (LL_RCC_PLL1_IsReady() != 1U) { + } +#endif /* STM32_PLL1_ENABLED */ + +#if defined(STM32_PLL2_ENABLED) + LL_RCC_PLL2_Disable(); + + /* Configure PLL source : Can be HSE, HSI, MSI */ + if (IS_ENABLED(STM32_PLL2_SRC_HSE)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL2_SetSource(LL_RCC_PLLSOURCE_HSE); + } else if (IS_ENABLED(STM32_PLL2_SRC_MSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL2_SetSource(LL_RCC_PLLSOURCE_MSI); + } else if (IS_ENABLED(STM32_PLL2_SRC_HSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL2_SetSource(LL_RCC_PLLSOURCE_HSI); + } else { + return -ENOTSUP; + } + + /* Disable PLL2 modulation spread-spectrum */ + LL_RCC_PLL2_DisableModulationSpreadSpectrum(); + + /* Disable bypass to use the PLL VCO */ + if (LL_RCC_PLL2_IsEnabledBypass()) { + LL_RCC_PLL2_DisableBypass(); + } + + /* Configure PLL */ + LL_RCC_PLL2_SetM(STM32_PLL2_M_DIVISOR); + LL_RCC_PLL2_SetN(STM32_PLL2_N_MULTIPLIER); + LL_RCC_PLL2_SetP1(STM32_PLL2_P1_DIVISOR); + LL_RCC_PLL2_SetP2(STM32_PLL2_P2_DIVISOR); + + /* Disable fractional mode */ + LL_RCC_PLL2_SetFRACN(0); + LL_RCC_PLL2_DisableFractionalModulationSpreadSpectrum(); + + LL_RCC_PLL2_AssertModulationSpreadSpectrumReset(); + + /* Enable post division */ + if (!LL_RCC_PLL2P_IsEnabled()) { + LL_RCC_PLL2P_Enable(); + } + + LL_RCC_PLL2_Enable(); + while (LL_RCC_PLL2_IsReady() != 1U) { + } +#endif + +#if defined(STM32_PLL3_ENABLED) + LL_RCC_PLL3_Disable(); + + /* Configure PLL source : Can be HSE, HSI, MSIS */ + if (IS_ENABLED(STM32_PLL3_SRC_HSE)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL3_SetSource(LL_RCC_PLLSOURCE_HSE); + } else if (IS_ENABLED(STM32_PLL3_SRC_MSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL3_SetSource(LL_RCC_PLLSOURCE_MSI); + } else if (IS_ENABLED(STM32_PLL3_SRC_HSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL3_SetSource(LL_RCC_PLLSOURCE_HSI); + } else { + return -ENOTSUP; + } + + /* Disable PLL3 modulation spread-spectrum */ + LL_RCC_PLL3_DisableModulationSpreadSpectrum(); + + /* Disable bypass to use the PLL VCO */ + if (LL_RCC_PLL3_IsEnabledBypass()) { + LL_RCC_PLL3_DisableBypass(); + } + + /* Configure PLL */ + LL_RCC_PLL3_SetM(STM32_PLL3_M_DIVISOR); + LL_RCC_PLL3_SetN(STM32_PLL3_N_MULTIPLIER); + LL_RCC_PLL3_SetP1(STM32_PLL3_P1_DIVISOR); + LL_RCC_PLL3_SetP2(STM32_PLL3_P2_DIVISOR); + + /* Disable fractional mode */ + LL_RCC_PLL3_SetFRACN(0); + LL_RCC_PLL3_DisableFractionalModulationSpreadSpectrum(); + + LL_RCC_PLL3_AssertModulationSpreadSpectrumReset(); + + /* Enable post division */ + if (!LL_RCC_PLL3P_IsEnabled()) { + LL_RCC_PLL3P_Enable(); + } + + LL_RCC_PLL3_Enable(); + while (LL_RCC_PLL3_IsReady() != 1U) { + } +#endif + +#if defined(STM32_PLL4_ENABLED) + LL_RCC_PLL4_Disable(); + + /* Configure PLL source : Can be HSE, HSI, MSIS */ + if (IS_ENABLED(STM32_PLL4_SRC_HSE)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL4_SetSource(LL_RCC_PLLSOURCE_HSE); + } else if (IS_ENABLED(STM32_PLL4_SRC_MSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL4_SetSource(LL_RCC_PLLSOURCE_MSI); + } else if (IS_ENABLED(STM32_PLL4_SRC_HSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL4_SetSource(LL_RCC_PLLSOURCE_HSI); + } else { + return -ENOTSUP; + } + + /* Disable PLL4 modulation spread-spectrum */ + LL_RCC_PLL4_DisableModulationSpreadSpectrum(); + + /* Disable bypass to use the PLL VCO */ + if (LL_RCC_PLL4_IsEnabledBypass()) { + LL_RCC_PLL4_DisableBypass(); + } + + /* Configure PLL */ + LL_RCC_PLL4_SetM(STM32_PLL4_M_DIVISOR); + LL_RCC_PLL4_SetN(STM32_PLL4_N_MULTIPLIER); + LL_RCC_PLL4_SetP1(STM32_PLL4_P1_DIVISOR); + LL_RCC_PLL4_SetP2(STM32_PLL4_P2_DIVISOR); + + /* Disable fractional mode */ + LL_RCC_PLL4_SetFRACN(0); + LL_RCC_PLL4_DisableFractionalModulationSpreadSpectrum(); + + LL_RCC_PLL4_AssertModulationSpreadSpectrumReset(); + + /* Enable post division */ + if (!LL_RCC_PLL4P_IsEnabled()) { + LL_RCC_PLL4P_Enable(); + } + + LL_RCC_PLL4_Enable(); + while (LL_RCC_PLL4_IsReady() != 1U) { + } +#endif + + return 0; +} + +static void set_up_fixed_clock_sources(void) +{ + if (IS_ENABLED(STM32_HSE_ENABLED)) { + /* Check if need to enable HSE bypass feature or not */ + if (IS_ENABLED(STM32_HSE_BYPASS)) { + LL_RCC_HSE_EnableBypass(); + } else { + LL_RCC_HSE_DisableBypass(); + } + + if (IS_ENABLED(STM32_HSE_DIV2)) { + LL_RCC_HSE_SelectHSEDiv2AsDiv2Clock(); + } else { + LL_RCC_HSE_SelectHSEAsDiv2Clock(); + } + + /* Enable HSE */ + LL_RCC_HSE_Enable(); + while (LL_RCC_HSE_IsReady() != 1) { + /* Wait for HSE ready */ + } + } + + if (IS_ENABLED(STM32_HSI_ENABLED)) { + /* Enable HSI oscillator */ + LL_RCC_HSI_Enable(); + while (LL_RCC_HSI_IsReady() != 1) { + } + /* HSI divider configuration */ + LL_RCC_HSI_SetDivider(hsi_divider(STM32_HSI_DIVISOR)); + } + + if (IS_ENABLED(STM32_LSE_ENABLED)) { + /* Enable the power interface clock */ + LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_PWR); + + if (!LL_PWR_IsEnabledBkUpAccess()) { + /* Enable write access to Backup domain */ + LL_PWR_EnableBkUpAccess(); + while (!LL_PWR_IsEnabledBkUpAccess()) { + /* Wait for Backup domain access */ + } + } + + /* Configure driving capability */ + LL_RCC_LSE_SetDriveCapability(STM32_LSE_DRIVING << RCC_LSECFGR_LSEDRV_Pos); + + if (IS_ENABLED(STM32_LSE_BYPASS)) { + /* Configure LSE bypass */ + LL_RCC_LSE_EnableBypass(); + } + + /* Enable LSE Oscillator */ + LL_RCC_LSE_Enable(); + /* Wait for LSE ready */ + while (!LL_RCC_LSE_IsReady()) { + } + + LL_PWR_DisableBkUpAccess(); + } + + if (IS_ENABLED(STM32_LSI_ENABLED)) { + /* Enable LSI oscillator */ + LL_RCC_LSI_Enable(); + while (LL_RCC_LSI_IsReady() != 1) { + } + } +} + +int stm32_clock_control_init(const struct device *dev) +{ + int r = 0; + + ARG_UNUSED(dev); + + /* For now, enable clocks (including low_power ones) of all RAM */ + uint32_t all_ram = LL_MEM_AXISRAM1 | LL_MEM_AXISRAM2 | LL_MEM_AXISRAM3 | LL_MEM_AXISRAM4 | + LL_MEM_AXISRAM5 | LL_MEM_AXISRAM6 | LL_MEM_AHBSRAM1 | LL_MEM_AHBSRAM2 | + LL_MEM_BKPSRAM | LL_MEM_FLEXRAM | LL_MEM_CACHEAXIRAM | LL_MEM_VENCRAM; + LL_MEM_EnableClock(all_ram); + LL_MEM_EnableClockLowPower(all_ram); + + /* Set up individual enabled clocks */ + set_up_fixed_clock_sources(); + + /* Set up PLLs */ + r = set_up_plls(); + if (r < 0) { + return r; + } + + /* Preset the prescalers prior to chosing SYSCLK */ + /* Prevents APB clock to go over limits */ + /* Set buses (AHB, APB1, APB2, APB4 & APB5) prescalers */ + LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_AHB_PRESCALER)); + LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_APB1_PRESCALER)); + LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_APB2_PRESCALER)); + LL_RCC_SetAPB4Prescaler(apb4_prescaler(STM32_APB4_PRESCALER)); + LL_RCC_SetAPB5Prescaler(apb5_prescaler(STM32_APB5_PRESCALER)); + + if (IS_ENABLED(STM32_CKPER_ENABLED)) { + LL_MISC_EnableClock(LL_PER); + LL_MISC_EnableClockLowPower(LL_PER); + while (LL_MISC_IsEnabledClock(LL_PER) != 1) { + } + } + + /* Set up ICs */ + r = set_up_ics(); + if (r < 0) { + return r; + } + + /* Set up sys clock */ + if (IS_ENABLED(STM32_SYSCLK_SRC_HSE)) { + /* Set sysclk source to HSE */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE); + while (LL_RCC_GetSysClkSource() != + LL_RCC_SYS_CLKSOURCE_STATUS_HSE) { + } + } else if (IS_ENABLED(STM32_SYSCLK_SRC_HSI)) { + /* Set sysclk source to HSI */ + stm32_clock_switch_to_hsi(); + } else if (IS_ENABLED(STM32_SYSCLK_SRC_IC2)) { + /* Set sysclk source to IC2 */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_IC2_IC6_IC11); + while (LL_RCC_GetSysClkSource() != + LL_RCC_SYS_CLKSOURCE_STATUS_IC2_IC6_IC11) { + } + } else { + return -ENOTSUP; + } + + /* Update CMSIS variable */ + SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + + return r; +} + +/** + * @brief RCC device, note that priority is intentionally set to 1 so + * that the device init runs just after SOC init + */ +DEVICE_DT_DEFINE(DT_NODELABEL(rcc), + &stm32_clock_control_init, + NULL, + NULL, NULL, + PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, + &stm32_clock_control_api); diff --git a/drivers/gpio/gpio_stm32.c b/drivers/gpio/gpio_stm32.c index 29b243b3d0616..79a09dd1238fe 100644 --- a/drivers/gpio/gpio_stm32.c +++ b/drivers/gpio/gpio_stm32.c @@ -772,3 +772,4 @@ GPIO_DEVICE_INIT_STM32_IF_OKAY(m, M); GPIO_DEVICE_INIT_STM32_IF_OKAY(n, N); GPIO_DEVICE_INIT_STM32_IF_OKAY(o, O); GPIO_DEVICE_INIT_STM32_IF_OKAY(p, P); +GPIO_DEVICE_INIT_STM32_IF_OKAY(q, Q); diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c index 9dc3e26f37cca..73668b0b284c5 100644 --- a/drivers/pinctrl/pinctrl_stm32.c +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -63,6 +63,7 @@ static const struct device *const gpio_ports[] = { DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpion)), DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioo)), DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiop)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioq)), }; /** Number of GPIO ports. */ diff --git a/dts/arm/st/n6/stm32n6.dtsi b/dts/arm/st/n6/stm32n6.dtsi new file mode 100644 index 0000000000000..f2e7dc8f47fd8 --- /dev/null +++ b/dts/arm/st/n6/stm32n6.dtsi @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m55"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + mpu: mpu@e000ed90 { + compatible = "arm,armv8.1m-mpu"; + reg = <0xe000ed90 0x40>; + }; + }; + }; + + axisram1: memory@34000000 { + compatible = "mmio-sram"; + }; + + axisram2: memory@34180400 { + compatible = "mmio-sram"; + }; + + clocks { + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "st,stm32n6-hse-clock"; + status = "disabled"; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "st,stm32h7-hsi-clock"; + clock-frequency = ; + status = "disabled"; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "st,stm32-lse-clock"; + clock-frequency = <32768>; + driving-capability = <2>; + status = "disabled"; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + + pll1: pll: pll { + #clock-cells = <0>; + compatible = "st,stm32n6-pll-clock"; + status = "disabled"; + }; + + pll2: pll2 { + #clock-cells = <0>; + compatible = "st,stm32n6-pll-clock"; + status = "disabled"; + }; + + pll3: pll3 { + #clock-cells = <0>; + compatible = "st,stm32n6-pll-clock"; + status = "disabled"; + }; + + pll4: pll4 { + #clock-cells = <0>; + compatible = "st,stm32n6-pll-clock"; + status = "disabled"; + }; + + cpusw: cpusw { + #clock-cells = <0>; + compatible = "st,stm32n6-cpu-clock-mux", "st,stm32-clock-mux"; + status = "disabled"; + }; + + perck: perck { + #clock-cells = <0>; + compatible = "st,stm32-clock-mux"; + status = "disabled"; + }; + + ic1: ic1 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic2: ic2 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic3: ic3 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic4: ic4 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic5: ic5 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic6: ic6 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic7: ic7 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic8: ic8 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic9: ic9 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic10: ic10 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic11: ic11 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic12: ic12 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic13: ic13 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic14: ic14 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic15: ic15 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic16: ic16 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic17: ic17 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic18: ic18 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic19: ic19 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + + ic20: ic20 { + #clock-cells = <0>; + compatible = "st,stm32n6-ic-clock-mux"; + status = "disabled"; + }; + }; + + soc { + rcc: rcc@56028000 { + compatible = "st,stm32n6-rcc"; + clocks-controller; + #clock-cells = <2>; + reg = <0x56028000 0x2000>; + + rctl: reset-controller { + compatible = "st,stm32-rcc-rctl"; + #reset-cells = <1>; + }; + }; + + exti: interrupt-controller@56025000 { + compatible = "st,stm32g0-exti", "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + reg = <0x56025000 0x400>; + num-lines = <16>; + interrupts = <20 0>, <21 0>, <22 0>, <23 0>, + <24 0>, <25 0>, <26 0>, <27 0>, + <28 0>, <29 0>, <30 0>, <31 0>, + <32 0>, <33 0>, <34 0>, <35 0>; + interrupt-names = "line0", "line1", "line2", "line3", + "line4", "line5", "line6", "line7", + "line8", "line9", "line10", "line11", + "line12", "line13", "line14", "line15"; + line-ranges = <0 1>, <1 1>, <2 1>, <3 1>, + <4 1>, <5 1>, <6 1>, <7 1>, + <8 1>, <9 1>, <10 1>, <11 1>, + <12 1>, <13 1>, <14 1>, <15 1>; + }; + + pinctrl: pin-controller@56020000 { + compatible = "st,stm32-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x56020000 0x2000>; + + gpioa: gpio@56020000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56020000 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 0)>; + }; + + gpiob: gpio@56020400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56020400 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 1)>; + }; + + gpioc: gpio@56020800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56020800 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 2)>; + }; + + gpiod: gpio@56020c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56020c00 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 3)>; + }; + + gpioe: gpio@56021000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56021000 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 4)>; + }; + + gpiof: gpio@56021400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56021400 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 5)>; + }; + + gpiog: gpio@56021800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56021800 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 6)>; + }; + + gpioh: gpio@56021c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56021c00 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 7)>; + }; + + gpion: gpio@56023400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56023400 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 13)>; + }; + + gpioo: gpio@56023800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56023800 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 14)>; + }; + + gpiop: gpio@56023c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56023C00 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 15)>; + }; + + gpioq: gpio@56024000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x56024000 0x400>; + clocks = <&rcc STM32_CLOCK(AHB4, 16)>; + }; + }; + + usart1: serial@52001000 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x52001000 0x400>; + clocks = <&rcc STM32_CLOCK(APB2, 4)>; + resets = <&rctl STM32_RESET(APB2, 4)>; + interrupts = <159 0>; + status = "disabled"; + }; + + usart2: serial@50004400 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50004400 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 17)>; + resets = <&rctl STM32_RESET(APB1L, 17)>; + interrupts = <160 0>; + status = "disabled"; + }; + + usart3: serial@50004800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50004800 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 18)>; + resets = <&rctl STM32_RESET(APB1L, 18)>; + interrupts = <161 0>; + status = "disabled"; + }; + + uart4: serial@50004c00 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50004C00 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 19)>; + resets = <&rctl STM32_RESET(APB1L, 19)>; + interrupts = <162 0>; + status = "disabled"; + }; + + uart5: serial@50005000 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50005000 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 20)>; + resets = <&rctl STM32_RESET(APB1L, 20)>; + interrupts = <163 0>; + status = "disabled"; + }; + + usart6: serial@52001400 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x52001400 0x400>; + clocks = <&rcc STM32_CLOCK(APB2, 5)>; + resets = <&rctl STM32_RESET(APB2, 5)>; + interrupts = <164 0>; + status = "disabled"; + }; + + uart7: serial@50007800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50007800 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 30)>; + resets = <&rctl STM32_RESET(APB1L, 30)>; + interrupts = <165 0>; + status = "disabled"; + }; + + uart8: serial@50007c00 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x50007C00 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 31)>; + resets = <&rctl STM32_RESET(APB1L, 31)>; + interrupts = <166 0>; + status = "disabled"; + }; + + uart9: serial@52001800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x52001800 0x400>; + clocks = <&rcc STM32_CLOCK(APB2, 6)>; + resets = <&rctl STM32_RESET(APB2, 6)>; + interrupts = <167 0>; + status = "disabled"; + }; + + usart10: serial@52001c00 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x52001C00 0x400>; + clocks = <&rcc STM32_CLOCK(APB2, 7)>; + resets = <&rctl STM32_RESET(APB2, 7)>; + interrupts = <168 0>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; diff --git a/dts/arm/st/n6/stm32n657.dtsi b/dts/arm/st/n6/stm32n657.dtsi new file mode 100644 index 0000000000000..7cc6f02b17081 --- /dev/null +++ b/dts/arm/st/n6/stm32n657.dtsi @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +/ { + soc { + compatible = "st,stm32n657", "st,stm32n6", "simple-bus"; + }; +}; diff --git a/dts/arm/st/n6/stm32n657X0.dtsi b/dts/arm/st/n6/stm32n657X0.dtsi new file mode 100644 index 0000000000000..613c3ee443eb1 --- /dev/null +++ b/dts/arm/st/n6/stm32n657X0.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +/ { + axisram1: memory@34000000 { + reg = <0x34000000 DT_SIZE_K(624)>; + }; + + axisram2: memory@34180400 { + reg = <0x34180400 DT_SIZE_K(511)>; + }; +}; diff --git a/dts/bindings/clock/st,stm32n6-cpu-clock-mux.yaml b/dts/bindings/clock/st,stm32n6-cpu-clock-mux.yaml new file mode 100644 index 0000000000000..653a0b0a15a5b --- /dev/null +++ b/dts/bindings/clock/st,stm32n6-cpu-clock-mux.yaml @@ -0,0 +1,29 @@ +# Copyright (c) 2025, STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32N6 CPU Clock + Describes the STM32N6 CPU clock multiplexer. On STM32N6, this is the CPU + clock that feeds the SysTick. + For instance: + &cpusw { + clocks = <&rcc STM32_SRC_IC1 CPU_SEL(3)>; + clock-frequency = ; + status = "okay"; + }; + +compatible: "st,stm32n6-cpu-clock-mux" + +include: + - name: base.yaml + property-allowlist: + - status + - compatible + - clocks + +properties: + clock-frequency: + required: true + type: int + description: | + default frequency in Hz for CPU clock (sysa_ck/sys_cpu_ck) diff --git a/dts/bindings/clock/st,stm32n6-hse-clock.yaml b/dts/bindings/clock/st,stm32n6-hse-clock.yaml new file mode 100644 index 0000000000000..36234050230f7 --- /dev/null +++ b/dts/bindings/clock/st,stm32n6-hse-clock.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: STM32N6 HSE Clock + +compatible: "st,stm32n6-hse-clock" + +include: [fixed-clock.yaml] + +properties: + hse-bypass: + type: boolean + description: | + HSE crystal oscillator bypass + Set to the property to by-pass the oscillator with an external clock. + + hse-div2: + type: boolean + description: | + When set HSE output clock is divided by 2. + Otherwise, no prescaler is used. diff --git a/dts/bindings/clock/st,stm32n6-ic-clock-mux.yaml b/dts/bindings/clock/st,stm32n6-ic-clock-mux.yaml new file mode 100644 index 0000000000000..2462d3166b751 --- /dev/null +++ b/dts/bindings/clock/st,stm32n6-ic-clock-mux.yaml @@ -0,0 +1,33 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32N6 Divider IC multiplexer + This node select a clock input and a divider. + For instance: + &ic6 { + pll-src = <2>; + div = <16>; + status = "okay"; + }; + +compatible: "st,stm32n6-ic-clock-mux" + +properties: + pll-src: + type: int + required: true + description: | + PLL clock source + enum: + - 1 + - 2 + - 3 + - 4 + + ic-div: + type: int + description: | + ICx integer division factor + The input ICx frequency is divided by the specified value + Valid range: 1 - 256 diff --git a/dts/bindings/clock/st,stm32n6-pll-clock.yaml b/dts/bindings/clock/st,stm32n6-pll-clock.yaml new file mode 100644 index 0000000000000..b445304aa7d79 --- /dev/null +++ b/dts/bindings/clock/st,stm32n6-pll-clock.yaml @@ -0,0 +1,62 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + PLL node binding for STM32N6 devices + + It can be used to describe 4 different PLLs: PLL1, PLL2, PLL3 and PLL4. + + These PLLs can take one of clk_hse, clk_hsi or clk_msi as input clock, with + an input frequency from 5 to 50 MHz. PLLM factor is used to set the input + clock in this acceptable range. + + Each PLL has one output clock whose frequency can be computed with the + following formula: + + f(PLL_P) = f(VCO clock) / (PLLP1 × PLLP2) + + with f(VCO clock) = f(PLL clock input) × (PLLN / PLLM) + + Note: To reduce the power consumption, it is recommended to configure the VCOx + clock output to the lowest frequency. + + The PLL output frequency must not exceed 3200 MHz. + +compatible: "st,stm32n6-pll-clock" + +include: [clock-controller.yaml, base.yaml] + +properties: + + "#clock-cells": + const: 0 + + clocks: + required: true + + div-m: + type: int + required: true + description: | + Prescaler for PLLx + input clock + Valid range: 1 - 63 + + mul-n: + type: int + required: true + description: | + PLLx multiplication factor for VCO + Valid range: 16 - 2500 + + div-p1: + type: int + description: | + PLLx DIVP1 division factor + Valid range: 1 - 7 + + div-p2: + type: int + description: | + PLLx DIVP2 division factor + Valid range: 1 - 7 diff --git a/dts/bindings/clock/st,stm32n6-rcc.yaml b/dts/bindings/clock/st,stm32n6-rcc.yaml new file mode 100644 index 0000000000000..b3e1750e42a83 --- /dev/null +++ b/dts/bindings/clock/st,stm32n6-rcc.yaml @@ -0,0 +1,125 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 Reset and Clock controller node for STM32N6 devices + This node is in charge of system clock ('SYSCLK') source selection and + System Clock Generation. + + Configuring STM32 Reset and Clock controller node: + + System clock source should be selected amongst the clock nodes available in "clocks" + node (typically 'clk_hse, clk_csi', 'pll', ...). + As part of this node configuration, SYSCLK frequency should also be defined, using + "clock-frequency" property. + Last, bus clocks (typically HCLK, PCLK1, PCLK2) should be configured using matching + prescaler properties. + Here is an example of correctly configured rcc node: + &rcc { + clocks = <&ic2>; + clock-frequency = ; + ahb-prescaler = <2>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb4-prescaler = <1>; + apb5-prescaler = <1>; + } + + Confere st,stm32-rcc binding for information about domain clocks configuration. + +compatible: "st,stm32n6-rcc" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#clock-cells": + const: 2 + + clock-frequency: + required: true + type: int + description: | + default frequency in Hz for clock output + + ahb-prescaler: + type: int + required: true + description: | + AHB clock prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + apb1-prescaler: + type: int + required: true + description: | + CPU domain APB1 prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + apb2-prescaler: + type: int + required: true + description: | + CPU domain APB2 prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + apb4-prescaler: + type: int + required: true + description: | + CPU domain APB4 prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + apb5-prescaler: + type: int + required: true + description: | + CPU domain APB5 prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + +clock-cells: + - bus + - bits diff --git a/include/zephyr/drivers/clock_control/stm32_clock_control.h b/include/zephyr/drivers/clock_control/stm32_clock_control.h index a7974467d2e59..3ba8fe3449208 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -53,6 +53,8 @@ #include #elif defined(CONFIG_SOC_SERIES_STM32H7RSX) #include +#elif defined(CONFIG_SOC_SERIES_STM32N6X) +#include #elif defined(CONFIG_SOC_SERIES_STM32U0X) #include #elif defined(CONFIG_SOC_SERIES_STM32U5X) @@ -72,6 +74,7 @@ #define STM32_APB1_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb1_prescaler) #define STM32_APB2_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb2_prescaler) #define STM32_APB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb3_prescaler) +#define STM32_APB4_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb4_prescaler) #define STM32_APB5_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb5_prescaler) #define STM32_APB7_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb7_prescaler) #define STM32_AHB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), ahb3_prescaler) @@ -141,6 +144,9 @@ #if DT_SAME_NODE(DT_RCC_CLOCKS_CTRL, DT_NODELABEL(clk_csi)) #define STM32_SYSCLK_SRC_CSI 1 #endif +#if DT_SAME_NODE(DT_RCC_CLOCKS_CTRL, DT_NODELABEL(ic2)) +#define STM32_SYSCLK_SRC_IC2 1 +#endif /** PLL node related symbols */ @@ -252,6 +258,38 @@ #define STM32_PLL2_PREDIV DT_PROP(DT_NODELABEL(pll2), prediv) #endif +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll1), st_stm32n6_pll_clock, okay) +#define STM32_PLL1_ENABLED 1 +#define STM32_PLL1_M_DIVISOR DT_PROP(DT_NODELABEL(pll1), div_m) +#define STM32_PLL1_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll1), mul_n) +#define STM32_PLL1_P1_DIVISOR DT_PROP(DT_NODELABEL(pll1), div_p1) +#define STM32_PLL1_P2_DIVISOR DT_PROP(DT_NODELABEL(pll1), div_p2) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32n6_pll_clock, okay) +#define STM32_PLL2_ENABLED 1 +#define STM32_PLL2_M_DIVISOR DT_PROP(DT_NODELABEL(pll2), div_m) +#define STM32_PLL2_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll2), mul_n) +#define STM32_PLL2_P1_DIVISOR DT_PROP(DT_NODELABEL(pll2), div_p1) +#define STM32_PLL2_P2_DIVISOR DT_PROP(DT_NODELABEL(pll2), div_p2) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32n6_pll_clock, okay) +#define STM32_PLL3_ENABLED 1 +#define STM32_PLL3_M_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_m) +#define STM32_PLL3_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll3), mul_n) +#define STM32_PLL3_P1_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_p1) +#define STM32_PLL3_P2_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_p2) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll4), st_stm32n6_pll_clock, okay) +#define STM32_PLL4_ENABLED 1 +#define STM32_PLL4_M_DIVISOR DT_PROP(DT_NODELABEL(pll4), div_m) +#define STM32_PLL4_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll4), mul_n) +#define STM32_PLL4_P1_DIVISOR DT_PROP(DT_NODELABEL(pll4), div_p1) +#define STM32_PLL4_P2_DIVISOR DT_PROP(DT_NODELABEL(pll4), div_p2) +#endif + /** PLL/PLL1 clock source */ #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pll)) && \ DT_NODE_HAS_PROP(DT_NODELABEL(pll), clocks) @@ -281,6 +319,9 @@ #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pll2)) && \ DT_NODE_HAS_PROP(DT_NODELABEL(pll2), clocks) #define DT_PLL2_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(pll2)) +#if DT_SAME_NODE(DT_PLL2_CLOCKS_CTRL, DT_NODELABEL(clk_msi)) +#define STM32_PLL2_SRC_MSI 1 +#endif #if DT_SAME_NODE(DT_PLL2_CLOCKS_CTRL, DT_NODELABEL(clk_msis)) #define STM32_PLL2_SRC_MSIS 1 #endif @@ -297,6 +338,9 @@ #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pll3)) && \ DT_NODE_HAS_PROP(DT_NODELABEL(pll3), clocks) #define DT_PLL3_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(pll3)) +#if DT_SAME_NODE(DT_PLL3_CLOCKS_CTRL, DT_NODELABEL(clk_msi)) +#define STM32_PLL3_SRC_MSI 1 +#endif #if DT_SAME_NODE(DT_PLL3_CLOCKS_CTRL, DT_NODELABEL(clk_msis)) #define STM32_PLL3_SRC_MSIS 1 #endif @@ -309,6 +353,22 @@ #endif +/** PLL4 clock source */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(pll4), okay) && \ + DT_NODE_HAS_PROP(DT_NODELABEL(pll4), clocks) +#define DT_PLL4_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(pll4)) +#if DT_SAME_NODE(DT_PLL4_CLOCKS_CTRL, DT_NODELABEL(clk_msi)) +#define STM32_PLL4_SRC_MSI 1 +#endif +#if DT_SAME_NODE(DT_PLL4_CLOCKS_CTRL, DT_NODELABEL(clk_hsi)) +#define STM32_PLL4_SRC_HSI 1 +#endif +#if DT_SAME_NODE(DT_PLL4_CLOCKS_CTRL, DT_NODELABEL(clk_hse)) +#define STM32_PLL4_SRC_HSE 1 +#endif + +#endif + /** Fixed clocks related symbols */ @@ -414,6 +474,11 @@ #define STM32_HSE_ENABLED 1 #define STM32_HSE_DIV2 DT_PROP(DT_NODELABEL(clk_hse), hse_div2) #define STM32_HSE_FREQ DT_PROP(DT_NODELABEL(clk_hse), clock_frequency) +#elif DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hse), st_stm32n6_hse_clock, okay) +#define STM32_HSE_ENABLED 1 +#define STM32_HSE_BYPASS DT_PROP(DT_NODELABEL(clk_hse), hse_bypass) +#define STM32_HSE_DIV2 DT_PROP(DT_NODELABEL(clk_hse), hse_div2) +#define STM32_HSE_FREQ DT_PROP(DT_NODELABEL(clk_hse), clock_frequency) #else #define STM32_HSE_FREQ 0 #endif @@ -431,6 +496,130 @@ #define STM32_CKPER_ENABLED 1 #endif +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(cpusw), st_stm32_clock_mux, okay) +#define STM32_CPUSW_ENABLED 1 +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic1), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC1_ENABLED 1 +#define STM32_IC1_PLL_SRC DT_PROP(DT_NODELABEL(ic1), pll_src) +#define STM32_IC1_DIV DT_PROP(DT_NODELABEL(ic1), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic2), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC2_ENABLED 1 +#define STM32_IC2_PLL_SRC DT_PROP(DT_NODELABEL(ic2), pll_src) +#define STM32_IC2_DIV DT_PROP(DT_NODELABEL(ic2), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic3), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC3_ENABLED 1 +#define STM32_IC3_PLL_SRC DT_PROP(DT_NODELABEL(ic3), pll_src) +#define STM32_IC3_DIV DT_PROP(DT_NODELABEL(ic3), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic4), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC4_ENABLED 1 +#define STM32_IC4_PLL_SRC DT_PROP(DT_NODELABEL(ic4), pll_src) +#define STM32_IC4_DIV DT_PROP(DT_NODELABEL(ic4), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic5), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC5_ENABLED 1 +#define STM32_IC5_PLL_SRC DT_PROP(DT_NODELABEL(ic5), pll_src) +#define STM32_IC5_DIV DT_PROP(DT_NODELABEL(ic5), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic6), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC6_ENABLED 1 +#define STM32_IC6_PLL_SRC DT_PROP(DT_NODELABEL(ic6), pll_src) +#define STM32_IC6_DIV DT_PROP(DT_NODELABEL(ic6), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic7), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC7_ENABLED 1 +#define STM32_IC7_PLL_SRC DT_PROP(DT_NODELABEL(ic7), pll_src) +#define STM32_IC7_DIV DT_PROP(DT_NODELABEL(ic7), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic8), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC8_ENABLED 1 +#define STM32_IC8_PLL_SRC DT_PROP(DT_NODELABEL(ic8), pll_src) +#define STM32_IC8_DIV DT_PROP(DT_NODELABEL(ic8), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic9), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC9_ENABLED 1 +#define STM32_IC9_PLL_SRC DT_PROP(DT_NODELABEL(ic9), pll_src) +#define STM32_IC9_DIV DT_PROP(DT_NODELABEL(ic9), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic10), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC10_ENABLED 1 +#define STM32_IC10_PLL_SRC DT_PROP(DT_NODELABEL(ic10), pll_src) +#define STM32_IC10_DIV DT_PROP(DT_NODELABEL(ic10), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic11), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC11_ENABLED 1 +#define STM32_IC11_PLL_SRC DT_PROP(DT_NODELABEL(ic11), pll_src) +#define STM32_IC11_DIV DT_PROP(DT_NODELABEL(ic11), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic12), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC12_ENABLED 1 +#define STM32_IC12_PLL_SRC DT_PROP(DT_NODELABEL(ic12), pll_src) +#define STM32_IC12_DIV DT_PROP(DT_NODELABEL(ic12), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic13), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC13_ENABLED 1 +#define STM32_IC13_PLL_SRC DT_PROP(DT_NODELABEL(ic13), pll_src) +#define STM32_IC13_DIV DT_PROP(DT_NODELABEL(ic13), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic14), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC14_ENABLED 1 +#define STM32_IC14_PLL_SRC DT_PROP(DT_NODELABEL(ic14), pll_src) +#define STM32_IC14_DIV DT_PROP(DT_NODELABEL(ic14), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic15), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC15_ENABLED 1 +#define STM32_IC15_PLL_SRC DT_PROP(DT_NODELABEL(ic15), pll_src) +#define STM32_IC15_DIV DT_PROP(DT_NODELABEL(ic15), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic16), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC16_ENABLED 1 +#define STM32_IC16_PLL_SRC DT_PROP(DT_NODELABEL(ic16), pll_src) +#define STM32_IC16_DIV DT_PROP(DT_NODELABEL(ic16), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic17), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC17_ENABLED 1 +#define STM32_IC17_PLL_SRC DT_PROP(DT_NODELABEL(ic17), pll_src) +#define STM32_IC17_DIV DT_PROP(DT_NODELABEL(ic17), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic18), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC18_ENABLED 1 +#define STM32_IC18_PLL_SRC DT_PROP(DT_NODELABEL(ic18), pll_src) +#define STM32_IC18_DIV DT_PROP(DT_NODELABEL(ic18), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic19), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC19_ENABLED 1 +#define STM32_IC19_PLL_SRC DT_PROP(DT_NODELABEL(ic19), pll_src) +#define STM32_IC19_DIV DT_PROP(DT_NODELABEL(ic19), ic_div) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ic20), st_stm32n6_ic_clock_mux, okay) +#define STM32_IC20_ENABLED 1 +#define STM32_IC20_PLL_SRC DT_PROP(DT_NODELABEL(ic20), pll_src) +#define STM32_IC20_DIV DT_PROP(DT_NODELABEL(ic20), ic_div) +#endif + /** Driver structure definition */ struct stm32_pclken { diff --git a/include/zephyr/dt-bindings/clock/stm32_clock.h b/include/zephyr/dt-bindings/clock/stm32_clock.h index 37241a26c46dd..0564c3084b155 100644 --- a/include/zephyr/dt-bindings/clock/stm32_clock.h +++ b/include/zephyr/dt-bindings/clock/stm32_clock.h @@ -22,6 +22,7 @@ #define STM32_CLOCK_BUS_APB5 12 #define STM32_CLOCK_BUS_AXI 13 #define STM32_CLOCK_BUS_MLAHB 14 +#define STM32_CLOCK_BUS_APB4_2 15 #define STM32_CLOCK_DIV_SHIFT 12 diff --git a/include/zephyr/dt-bindings/clock/stm32n6_clock.h b/include/zephyr/dt-bindings/clock/stm32n6_clock.h new file mode 100644 index 0000000000000..156ca1f27abe5 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/stm32n6_clock.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32N6_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32N6_CLOCK_H_ + +#include "stm32_common_clocks.h" + +/** Domain clocks */ + +/* RM0468, Table 56 Kernel clock distribution summary */ + +/** System clock */ +/* defined in stm32_common_clocks.h */ +/** Fixed clocks */ +#define STM32_SRC_HSE (STM32_SRC_LSI + 1) +#define STM32_SRC_HSI (STM32_SRC_HSE + 1) +#define STM32_SRC_MSI (STM32_SRC_HSI + 1) +/** PLL outputs */ +#define STM32_SRC_PLL1 (STM32_SRC_MSI + 1) +#define STM32_SRC_PLL2 (STM32_SRC_PLL1 + 1) +#define STM32_SRC_PLL3 (STM32_SRC_PLL2 + 1) +#define STM32_SRC_PLL4 (STM32_SRC_PLL3 + 1) +/** Clock muxes */ +#define STM32_SRC_CKPER (STM32_SRC_PLL4 + 1) +#define STM32_SRC_IC1 (STM32_SRC_CKPER + 1) +#define STM32_SRC_IC2 (STM32_SRC_IC1 + 1) +#define STM32_SRC_IC3 (STM32_SRC_IC2 + 1) +#define STM32_SRC_IC4 (STM32_SRC_IC3 + 1) +#define STM32_SRC_IC5 (STM32_SRC_IC4 + 1) +#define STM32_SRC_IC6 (STM32_SRC_IC5 + 1) +#define STM32_SRC_IC7 (STM32_SRC_IC6 + 1) +#define STM32_SRC_IC8 (STM32_SRC_IC7 + 1) +#define STM32_SRC_IC9 (STM32_SRC_IC8 + 1) +#define STM32_SRC_IC10 (STM32_SRC_IC9 + 1) +#define STM32_SRC_IC11 (STM32_SRC_IC10 + 1) +#define STM32_SRC_IC12 (STM32_SRC_IC11 + 1) +#define STM32_SRC_IC13 (STM32_SRC_IC12 + 1) +#define STM32_SRC_IC14 (STM32_SRC_IC13 + 1) +#define STM32_SRC_IC15 (STM32_SRC_IC14 + 1) +#define STM32_SRC_IC16 (STM32_SRC_IC15 + 1) +#define STM32_SRC_IC17 (STM32_SRC_IC16 + 1) +#define STM32_SRC_IC18 (STM32_SRC_IC17 + 1) +#define STM32_SRC_IC19 (STM32_SRC_IC18 + 1) +#define STM32_SRC_IC20 (STM32_SRC_IC19 + 1) + +/** Bus clocks */ +#define STM32_CLOCK_BUS_AHB1 0x250 +#define STM32_CLOCK_BUS_AHB2 0x254 +#define STM32_CLOCK_BUS_AHB3 0x258 +#define STM32_CLOCK_BUS_AHB4 0x25C +#define STM32_CLOCK_BUS_AHB5 0x260 +#define STM32_CLOCK_BUS_APB1 0x264 +#define STM32_CLOCK_BUS_APB1_2 0x268 +#define STM32_CLOCK_BUS_APB2 0x26C +#define STM32_CLOCK_BUS_APB3 0x270 +#define STM32_CLOCK_BUS_APB4 0x274 +#define STM32_CLOCK_BUS_APB4_2 0x278 +#define STM32_CLOCK_BUS_APB5 0x27C + +#define STM32_CLOCK_LP_BUS_SHIFT 0x40 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB5 + +#define STM32_CLOCK_REG_MASK 0xFFFU +#define STM32_CLOCK_REG_SHIFT 0U +#define STM32_CLOCK_SHIFT_MASK 0x1FU +#define STM32_CLOCK_SHIFT_SHIFT 12U +#define STM32_CLOCK_MASK_MASK 0x7U +#define STM32_CLOCK_MASK_SHIFT 17U +#define STM32_CLOCK_VAL_MASK 0x7U +#define STM32_CLOCK_VAL_SHIFT 20U + +/** + * @brief STM32U5 clock configuration bit field. + * + * - reg (1/2/3) [ 0 : 11 ] + * - shift (0..31) [ 12 : 16 ] + * - mask (0x1, 0x3, 0x7) [ 17 : 19 ] + * - val (0..7) [ 20 : 22 ] + * + * @param reg RCC_CCIPRx register offset + * @param shift Position within RCC_CCIPRx. + * @param mask Mask for the RCC_CCIPRx field. + * @param val Clock value (0, 1, ... 7). + */ +#define STM32_DOMAIN_CLOCK(val, mask, shift, reg) \ + ((((reg) & STM32_CLOCK_REG_MASK) << STM32_CLOCK_REG_SHIFT) | \ + (((shift) & STM32_CLOCK_SHIFT_MASK) << STM32_CLOCK_SHIFT_SHIFT) | \ + (((mask) & STM32_CLOCK_MASK_MASK) << STM32_CLOCK_MASK_SHIFT) | \ + (((val) & STM32_CLOCK_VAL_MASK) << STM32_CLOCK_VAL_SHIFT)) + +/** @brief RCC_CCIPRx register offset (RM0468.pdf) */ +#define CCIPR1_REG 0x144 +#define CCIPR2_REG 0x148 +#define CCIPR3_REG 0x14C +#define CCIPR4_REG 0x150 +#define CCIPR5_REG 0x154 +#define CCIPR6_REG 0x158 +#define CCIPR7_REG 0x15C +#define CCIPR8_REG 0x160 +#define CCIPR9_REG 0x164 +#define CCIPR12_REG 0x170 +#define CCIPR13_REG 0x174 +#define CCIPR14_REG 0x178 + +/** @brief Device domain clocks selection helpers */ +/** CCIPR1 devices */ +#define ADF1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR1_REG) +#define ADC12_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 4, CCIPR1_REG) +#define DCMIPP_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 20, CCIPR1_REG) +/** CCIPR2 devices */ +#define ETH1PTP_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 0, CCIPR2_REG) +#define ETH1CLK_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 12, CCIPR2_REG) +#define ETH1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR2_REG) +#define ETH1REFCLK_SEL(val) STM32_DOMAIN_CLOCK((val), 1, 20, CCIPR2_REG) +#define ETH1GTXCLK_SEL(val) STM32_DOMAIN_CLOCK((val), 1, 24, CCIPR2_REG) +/** CCIPR3 devices */ +#define FDCAN_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 0, CCIPR3_REG) +#define FMC_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 4, CCIPR3_REG) +/** CCIPR4 devices */ +#define I2C1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR4_REG) +#define I2C2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 4, CCIPR4_REG) +#define I2C3_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR4_REG) +#define I2C4_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 12, CCIPR4_REG) +#define I3C1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR4_REG) +#define I3C2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 20, CCIPR4_REG) +#define LTDC_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 24, CCIPR4_REG) +/** CCIPR5 devices */ +#define MCO1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR5_REG) +#define MCO2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR5_REG) +#define MDF1SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR5_REG) +/** CCIPR6 devices */ +#define XSPI1_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 0, CCIPR6_REG) +#define XSPI2_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 4, CCIPR6_REG) +#define XSPI3_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 8, CCIPR6_REG) +#define OTGPHY1_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 12, CCIPR6_REG) +#define OTGPHY1CKREF_SEL(val) STM32_DOMAIN_CLOCK((val), 1, 16, CCIPR6_REG) +#define OTGPHY2_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 20, CCIPR6_REG) +#define OTGPHY2CKREF_SEL(val) STM32_DOMAIN_CLOCK((val), 1, 24, CCIPR6_REG) +/** CCIPR7 devices */ +#define PER_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR7_REG) +#define PSSI_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 4, CCIPR7_REG) +#define RTC_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 8, CCIPR7_REG) +#define SAI1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 20, CCIPR7_REG) +#define SAI2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 24, CCIPR7_REG) +/** CCIPR8 devices */ +#define SDMMC1_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 0, CCIPR8_REG) +#define SDMMC2_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 4, CCIPR8_REG) +/** CCIPR9 devices */ +#define SPDIFRX1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR9_REG) +#define SPI1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 4, CCIPR9_REG) +#define SPI2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR9_REG) +#define SPI3_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 12, CCIPR9_REG) +#define SPI4_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR9_REG) +#define SPI5_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 20, CCIPR9_REG) +#define SPI6_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 24, CCIPR9_REG) +/** CCIPR12 devices */ +#define LPTIM1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR12_REG) +#define LPTIM2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 12, CCIPR12_REG) +#define LPTIM3_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR12_REG) +#define LPTIM4_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 20, CCIPR12_REG) +#define LPTIM5_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 24, CCIPR12_REG) +/** CCIPR13 devices */ +#define USART1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR13_REG) +#define USART2_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 4, CCIPR13_REG) +#define USART3_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR13_REG) +#define UART4_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 12, CCIPR13_REG) +#define UART5_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 16, CCIPR13_REG) +#define USART6_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 20, CCIPR13_REG) +#define UART7_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 24, CCIPR13_REG) +#define UART8_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 28, CCIPR13_REG) +/** CCIPR14 devices */ +#define UART9_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 0, CCIPR14_REG) +#define USART10_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 4, CCIPR14_REG) +#define LPUART1_SEL(val) STM32_DOMAIN_CLOCK((val), 7, 8, CCIPR14_REG) + +/** @brief RCC_ICxCFGR register offset (RM0468.pdf) */ +#define ICxCFGR_REG(ic) (0xC4 + ((ic) - 1) * 4) + +/** @brief Divider ICx source selection */ +#define ICx_PLLy_SEL(ic, pll) STM32_DOMAIN_CLOCK((pll) - 1, 3, 28, ICxCFGR_REG(ic)) + +/** @brief RCC_CFGR1 register offset (RM0468.pdf) */ +#define CFGR1_REG 0x20 + +/** @brief CPU clock switch selection */ +#define CPU_SEL(val) STM32_DOMAIN_CLOCK((val), 3, 16, CFGR1_REG) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32N6_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h index 0c5933c580e50..25b76bb2dd570 100644 --- a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h +++ b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h @@ -26,9 +26,10 @@ #define STM32_PORTN 13 #define STM32_PORTO 14 #define STM32_PORTP 15 /* IO port P (0xF) */ +#define STM32_PORTQ 16 /* IO port Q (0x10) */ #ifndef STM32_PORTS_MAX -#define STM32_PORTS_MAX (STM32_PORTP + 1) +#define STM32_PORTS_MAX (STM32_PORTQ + 1) #endif /** diff --git a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h index 52612f6948d51..aa055a5c3f73b 100644 --- a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h @@ -55,7 +55,7 @@ * - line [ 5 : 8 ] * - port [ 9 : 13 ] * - * @param port Port ('A'..'P') + * @param port Port ('A'..'Q') * @param line Pin (0..15) * @param mode Mode (ANALOG, GPIO_IN, ALTERNATE). */ diff --git a/include/zephyr/dt-bindings/reset/stm32n6_reset.h b/include/zephyr/dt-bindings/reset/stm32n6_reset.h new file mode 100644 index 0000000000000..0b645598f0862 --- /dev/null +++ b/include/zephyr/dt-bindings/reset/stm32n6_reset.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32N6_RESET_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32N6_RESET_H_ + +#include "stm32-common.h" + +/* RCC bus reset register offset */ +#define STM32_RESET_BUS_AHB1 0x210 +#define STM32_RESET_BUS_AHB2 0x214 +#define STM32_RESET_BUS_AHB3 0x218 +#define STM32_RESET_BUS_AHB4 0x21C +#define STM32_RESET_BUS_AHB5 0x220 +#define STM32_RESET_BUS_APB1L 0x224 +#define STM32_RESET_BUS_APB1H 0x228 +#define STM32_RESET_BUS_APB2 0x22C +#define STM32_RESET_BUS_APB4L 0x234 +#define STM32_RESET_BUS_APB4H 0x238 +#define STM32_RESET_BUS_APB5 0x23C + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32N6_RESET_H_ */ diff --git a/modules/Kconfig.stm32 b/modules/Kconfig.stm32 index c586a51fcf752..c7d4437fd1316 100644 --- a/modules/Kconfig.stm32 +++ b/modules/Kconfig.stm32 @@ -30,6 +30,16 @@ config USE_STM32_HAL_ADC_EX Enable STM32Cube Extended Analog-to-Digital Converter (ADC) HAL module driver +config USE_STM32_HAL_BSEC + bool + help + Enable STM32Cube Boot and Security Control (BSEC) HAL module driver + +config USE_STM32_HAL_CACHEAXI + bool + help + Enable STM32Cube AXI Cache (CACHEAXI) HAL module driver + config USE_STM32_HAL_CAN bool help @@ -213,6 +223,11 @@ config USE_STM32_HAL_GFXMMU help Enable STM32Cube Chrom-GRCTM (GFXMMU) HAL module driver +config USE_STM32_HAL_GFXTIM + bool + help + Enable STM32Cube Graphic Timer (GFXTIM) HAL module driver + config USE_STM32_HAL_GPIO bool help @@ -335,6 +350,11 @@ config USE_STM32_HAL_LTDC_EX help Enable STM32Cube Extended LCD-TFT controller (LTDC) HAL module driver +config USE_STM32_HAL_MCE + bool + help + Enable STM32Cube Memory Cipher Engine (MCE) HAL module driver + config USE_STM32_HAL_MDF bool help @@ -463,11 +483,21 @@ config USE_STM32_HAL_RAMECC help Enable STM32Cube RAM ECC monitoring (RAMECC) HAL module driver +config USE_STM32_HAL_RIF + bool + help + Enable STM32Cube Resource Isolation Framework (RIF) HAL module driver + config USE_STM32_HAL_RNG bool help Enable STM32Cube True random number generator (RNG) HAL module driver +config USE_STM32_HAL_RNG_EX + bool + help + Enable STM32Cube Extended True random number generator (RNG) HAL module driver + config USE_STM32_HAL_RTC bool help @@ -533,6 +563,11 @@ config USE_STM32_HAL_SMBUS help Enable STM32Cube System Management Bus (SMBus) HAL module driver +config USE_STM32_HAL_SMBUS_EX + bool + help + Enable STM32Cube Extended System Management Bus (SMBus) HAL module driver + config USE_STM32_HAL_SPDIFRX bool help @@ -656,7 +691,7 @@ config USE_STM32_LL_DELAYBLOCK config USE_STM32_LL_DLYB bool help - Enable STM32Cube DelayBlock (DELAYBLOCK) LL module driver (stm32U5) + Enable STM32Cube DelayBlock (DELAYBLOCK) LL module driver (stm32U5 or STM32N6) config USE_STM32_LL_DMA bool @@ -823,4 +858,14 @@ config USE_STM32_LL_UTILS help Enable STM32Cube Utility functions (UTILS) LL module driver +config USE_STM32_LL_VENC + bool + help + Enable STM32Cube Video Encoder (VENC) LL module driver + +config USE_STM32_UTIL_I3C + bool + help + Enable STM32Cube I3C Timing Utility functions (UTILS) module driver + endif # HAS_STM32CUBE diff --git a/scripts/west_commands/runners/stm32cubeprogrammer.py b/scripts/west_commands/runners/stm32cubeprogrammer.py index 432d7431b76a2..a124e32d168f9 100644 --- a/scripts/west_commands/runners/stm32cubeprogrammer.py +++ b/scripts/west_commands/runners/stm32cubeprogrammer.py @@ -34,6 +34,7 @@ def __init__( port: str, frequency: int | None, reset_mode: str | None, + download_address: int | None, start_address: int | None, conn_modifiers: str | None, cli: Path | None, @@ -46,6 +47,7 @@ def __init__( self._port = port self._frequency = frequency + self._download_address = download_address self._start_address = start_address self._reset_mode = reset_mode self._conn_modifiers = conn_modifiers @@ -149,6 +151,15 @@ def do_add_parser(cls, parser): choices=["sw", "hw", "core"], help="Reset mode", ) + parser.add_argument( + "--download-address", + # To accept arguments in hex format, a wrapper lambda around int() must be used. + # Wrapping the lambda with functools.wraps() makes it so that 'invalid int value' + # is displayed when an invalid value is provided for this argument. + type=functools.wraps(int)(lambda s: int(s, base=0)), + required=False, + help="Address where flashing should be done" + ) parser.add_argument( "--start-address", # To accept arguments in hex format, a wrapper lambda around int() must be used. @@ -194,6 +205,7 @@ def do_create( port=args.port, frequency=args.frequency, reset_mode=args.reset_mode, + download_address=args.download_address, start_address=args.start_address, conn_modifiers=args.conn_modifiers, cli=args.cli, @@ -233,13 +245,22 @@ def flash(self, **kwargs) -> None: self.check_call(cmd + ["--erase", "all"]) # flash image and run application - dl_file = self.cfg.elf_file if self._use_elf else self.cfg.hex_file + if self._use_elf: + dl_file = self.cfg.elf_file + elif self.cfg.bin_file is not None and os.path.isfile(self.cfg.bin_file) and \ + "zephyr.signed" in self.cfg.bin_file: + dl_file = self.cfg.bin_file + elif self.cfg.hex_file is not None and os.path.isfile(self.cfg.hex_file): + # --user-elf not used and no bin file given, default to hex + dl_file = self.cfg.hex_file if dl_file is None: raise RuntimeError('cannot flash; no download file was specified') elif not os.path.isfile(dl_file): raise RuntimeError(f'download file {dl_file} does not exist') flash_and_run_args = ["--download", dl_file] + if self._download_address is not None: + flash_and_run_args.append(f"0x{self._download_address:X}") # '--start' is needed to start execution after flash. # The default start address is the beggining of the flash, diff --git a/scripts/west_commands/tests/test_stm32cubeprogrammer.py b/scripts/west_commands/tests/test_stm32cubeprogrammer.py index e574fd5327620..216e9233b55af 100644 --- a/scripts/west_commands/tests/test_stm32cubeprogrammer.py +++ b/scripts/west_commands/tests/test_stm32cubeprogrammer.py @@ -64,6 +64,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -88,6 +89,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": 0x8001000, "conn_modifiers": None, "cli": CLI_PATH, @@ -113,6 +115,7 @@ "port": "swd", "frequency": "4000", "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -137,6 +140,7 @@ "port": "swd", "frequency": None, "reset_mode": "hw", + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -161,6 +165,7 @@ "port": "swd", "frequency": None, "reset_mode": "sw", + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -185,6 +190,7 @@ "port": "swd", "frequency": None, "reset_mode": "core", + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -209,6 +215,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": "br=115200 sn=TEST", "cli": CLI_PATH, @@ -233,6 +240,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -257,6 +265,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -282,6 +291,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": CLI_PATH, @@ -307,6 +317,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": None, @@ -331,6 +342,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": None, @@ -355,6 +367,7 @@ "port": "swd", "frequency": None, "reset_mode": None, + "download_address": None, "start_address": None, "conn_modifiers": None, "cli": None, @@ -375,6 +388,32 @@ ], ], }, + { + "port": "swd", + "frequency": None, + "reset_mode": None, + "download_address": 0x80000000, + "start_address": None, + "conn_modifiers": None, + "cli": CLI_PATH, + "use_elf": False, + "erase": False, + "extload": None, + "tool_opt": [], + "system": "", + "cli_path": str(CLI_PATH), + "calls": [ + [ + str(CLI_PATH), + "--connect", + "port=swd", + "--download", + RC_KERNEL_HEX, + "0x80000000", + "--start", + ], + ], + }, ) """Test cases.""" @@ -400,6 +439,7 @@ def test_stm32cubeprogrammer_init( port=tc["port"], frequency=tc["frequency"], reset_mode=tc["reset_mode"], + download_address=tc["download_address"], start_address=tc["start_address"], conn_modifiers=tc["conn_modifiers"], cli=tc["cli"], @@ -436,6 +476,8 @@ def test_stm32cubeprogrammer_create( args.extend(["--frequency", tc["frequency"]]) if tc["reset_mode"]: args.extend(["--reset-mode", tc["reset_mode"]]) + if tc["download_address"]: + args.extend(["--download-address", str(tc["download_address"])]) if tc["start_address"]: args.extend(["--start-address", str(tc["start_address"])]) if tc["conn_modifiers"]: diff --git a/soc/st/stm32/Kconfig.defconfig b/soc/st/stm32/Kconfig.defconfig index 0741439de6c79..67879e6cf6285 100644 --- a/soc/st/stm32/Kconfig.defconfig +++ b/soc/st/stm32/Kconfig.defconfig @@ -7,6 +7,8 @@ if SOC_FAMILY_STM32 +# Source series Kconfig files first, so SoCs +# can override the defaults given here rsource "*/Kconfig.defconfig" config CLOCK_CONTROL diff --git a/soc/st/stm32/soc.yml b/soc/st/stm32/soc.yml index ba24bcf143ec6..4e5d659573395 100644 --- a/soc/st/stm32/soc.yml +++ b/soc/st/stm32/soc.yml @@ -186,6 +186,9 @@ family: - name: stm32mp1x socs: - name: stm32mp157cxx + - name: stm32n6x + socs: + - name: stm32n657xx - name: stm32u0x socs: - name: stm32u031xx diff --git a/soc/st/stm32/stm32n6x/CMakeLists.txt b/soc/st/stm32/stm32n6x/CMakeLists.txt new file mode 100644 index 0000000000000..008bb9440cd2a --- /dev/null +++ b/soc/st/stm32/stm32n6x/CMakeLists.txt @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(${ZEPHYR_BASE}/drivers) +zephyr_sources( + soc.c + ) + +zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") + +if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows) + set(SIGNING_TOOL STM32_SigningTool_CLI.exe) +else() + set(SIGNING_TOOL STM32_SigningTool_CLI) +endif() + +set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${SIGNING_TOOL} + -in ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.bin + -nk -t fsbl -hv 2.3 + -o ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.signed.bin + -dump ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.signed.bin + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} +) + +set_property(TARGET runners_yaml_props_target PROPERTY bin_file ${CONFIG_KERNEL_BIN_NAME}.signed.bin) diff --git a/soc/st/stm32/stm32n6x/Kconfig b/soc/st/stm32/stm32n6x/Kconfig new file mode 100644 index 0000000000000..e8711ce26fd08 --- /dev/null +++ b/soc/st/stm32/stm32n6x/Kconfig @@ -0,0 +1,19 @@ +# ST Microelectronics STM32N6 MCU series + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_STM32N6X + select ARM + select CPU_CORTEX_M55 + select ARM_TRUSTZONE_M + select CPU_HAS_ARM_SAU + select CPU_HAS_ARM_MPU + select CPU_HAS_FPU + select ARMV8_M_DSP + select CPU_CORTEX_M_HAS_DWT + select HAS_STM32CUBE + select INIT_ARCH_HW_AT_BOOT + select SOC_RESET_HOOK + select TRUSTED_EXECUTION_SECURE + select BUILD_OUTPUT_BIN diff --git a/soc/st/stm32/stm32n6x/Kconfig.defconfig b/soc/st/stm32/stm32n6x/Kconfig.defconfig new file mode 100644 index 0000000000000..2e9856e8b02a2 --- /dev/null +++ b/soc/st/stm32/stm32n6x/Kconfig.defconfig @@ -0,0 +1,17 @@ +# ST Microelectronics STM32N6 MCU series + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_STM32N6X + +rsource "Kconfig.defconfig.stm32n6*" + +DT_STM32_CPU_CLOCK_PATH := $(dt_nodelabel_path,cpusw) +DT_STM32_CPU_CLOCK_FREQ := $(dt_node_int_prop_int,$(DT_STM32_CPU_CLOCK_PATH),clock-frequency) + +# For STM32N6, override the value defined in STM32 Kconfig to use CPU clock frequency +config SYS_CLOCK_HW_CYCLES_PER_SEC + default "$(DT_STM32_CPU_CLOCK_FREQ)" if "$(dt_nodelabel_enabled,cpusw)" + +endif # SOC_SERIES_STM32N6X diff --git a/soc/st/stm32/stm32n6x/Kconfig.defconfig.stm32n657xx b/soc/st/stm32/stm32n6x/Kconfig.defconfig.stm32n657xx new file mode 100644 index 0000000000000..910e642669077 --- /dev/null +++ b/soc/st/stm32/stm32n6x/Kconfig.defconfig.stm32n657xx @@ -0,0 +1,11 @@ +# ST Microelectronics STM32N6 MCU series + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32N657XX + +config NUM_IRQS + default 194 + +endif # SOC_STM32N657XX diff --git a/soc/st/stm32/stm32n6x/Kconfig.soc b/soc/st/stm32/stm32n6x/Kconfig.soc new file mode 100644 index 0000000000000..71879c0848a38 --- /dev/null +++ b/soc/st/stm32/stm32n6x/Kconfig.soc @@ -0,0 +1,18 @@ +# ST Microelectronics STM32N6 MCU series + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_STM32N6X + bool + select SOC_FAMILY_STM32 + +config SOC_SERIES + default "stm32n6x" if SOC_SERIES_STM32N6X + +config SOC_STM32N657XX + bool + select SOC_SERIES_STM32N6X + +config SOC + default "stm32n657xx" if SOC_STM32N657XX diff --git a/soc/st/stm32/stm32n6x/soc.c b/soc/st/stm32/stm32n6x/soc.c new file mode 100644 index 0000000000000..c967404862c17 --- /dev/null +++ b/soc/st/stm32/stm32n6x/soc.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief System/hardware module for STM32N6 processor + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL +LOG_MODULE_REGISTER(soc); + +extern char _vector_start[]; +void *g_pfnVectors = (void *)_vector_start; + +#if defined(CONFIG_SOC_RESET_HOOK) +void soc_reset_hook(void) +{ + /* This is provided by STM32Cube HAL */ + SystemInit(); +} +#endif + +/** + * @brief Perform basic hardware initialization at boot. + * + * This needs to be run from the very beginning. + * + * @return 0 + */ +void soc_early_init_hook(void) +{ + /* Enable caches */ + sys_cache_instr_enable(); + sys_cache_data_enable(); + + /* Update CMSIS SystemCoreClock variable (HCLK) */ + /* At reset, system core clock is set to 64 MHz from HSI */ + SystemCoreClock = 64000000; + + /* Enable PWR */ + LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_PWR); + + /* Enable IOs */ + LL_PWR_EnableVddIO2(); + LL_PWR_EnableVddIO3(); + LL_PWR_EnableVddIO4(); + LL_PWR_EnableVddIO5(); +} diff --git a/soc/st/stm32/stm32n6x/soc.h b/soc/st/stm32/stm32n6x/soc.h new file mode 100644 index 0000000000000..9274a7db70b71 --- /dev/null +++ b/soc/st/stm32/stm32n6x/soc.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file SoC configuration macros for the STM32N6 family processors. + * + */ + + +#ifndef _STM32N6_SOC_H_ +#define _STM32N6_SOC_H_ + +#ifndef _ASMLANGUAGE + +#include + +#endif /* !_ASMLANGUAGE */ + +#endif /* _STM32N6_SOC_H_ */ diff --git a/west.yml b/west.yml index eb8ac3785d30f..49a4eb111c1c4 100644 --- a/west.yml +++ b/west.yml @@ -238,7 +238,7 @@ manifest: groups: - hal - name: hal_stm32 - revision: 37842371f5ef0078ad32f16e5059c1df58b51892 + revision: 1d1f81866ccbaa6e84e9960ed763e005d1e45560 path: modules/hal/stm32 groups: - hal