diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 8c271dba2e4ee..a3272c770cc83 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -5813,6 +5813,7 @@ West: collaborators: - nashif - inteljiangwe1 + - dkalowsk files: [] labels: - "area: MCTP" diff --git a/boards/adi/max32666fthr/max32666fthr_max32666_cpu0.dts b/boards/adi/max32666fthr/max32666fthr_max32666_cpu0.dts index 55e74f44a952a..0a4f8bde0773c 100644 --- a/boards/adi/max32666fthr/max32666fthr_max32666_cpu0.dts +++ b/boards/adi/max32666fthr/max32666fthr_max32666_cpu0.dts @@ -184,11 +184,3 @@ power-source = ; drive-strength = <1>; }; - -&sdhc0 { - status = "okay"; - - mmc { - status = "okay"; - }; -}; diff --git a/boards/adi/max32666fthr/max32666fthr_max32666_cpu0.yaml b/boards/adi/max32666fthr/max32666fthr_max32666_cpu0.yaml index ad9094dc41524..cc040cb718c6a 100644 --- a/boards/adi/max32666fthr/max32666fthr_max32666_cpu0.yaml +++ b/boards/adi/max32666fthr/max32666fthr_max32666_cpu0.yaml @@ -20,6 +20,5 @@ supported: - pwm - w1 - flash - - sdhc ram: 128 flash: 1024 diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts index fd5ad106117b3..d5fea020431fa 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts @@ -130,7 +130,7 @@ zephyr_udc0: &usbhs { /* cache control functions - must be executed from RAM */ pm_ramfunc: cpurad_s2ram@2302ff40 { compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x2302ff80 192>; + reg = <0x2302ff40 192>; zephyr,memory-region = "PMLocalRamfunc"; }; }; diff --git a/boards/oct/osd32mp1_brk/Kconfig.defconfig b/boards/oct/osd32mp1_brk/Kconfig.defconfig index 7ca8f045d0a44..aa485652f7ee9 100644 --- a/boards/oct/osd32mp1_brk/Kconfig.defconfig +++ b/boards/oct/osd32mp1_brk/Kconfig.defconfig @@ -7,7 +7,4 @@ config SPI_STM32_INTERRUPT default y depends on SPI -config CLOCK_STM32_HSE_CLOCK - default 24000000 - endif # BOARD_OSD32MP1_BRK diff --git a/boards/oct/osd32mp1_brk/osd32mp1_brk.dts b/boards/oct/osd32mp1_brk/osd32mp1_brk.dts index 84c14691094f0..bf31940c76cdb 100644 --- a/boards/oct/osd32mp1_brk/osd32mp1_brk.dts +++ b/boards/oct/osd32mp1_brk/osd32mp1_brk.dts @@ -52,6 +52,11 @@ }; }; +&clk_hse { + clock-frequency = ; + status = "okay"; +}; + &spi4_miso_pe13 { slew-rate = "very-high-speed"; }; diff --git a/boards/others/stm32f030_demo/stm32f030_demo_defconfig b/boards/others/stm32f030_demo/stm32f030_demo_defconfig index 8c2017d2bcc6a..dde4ff07a7177 100644 --- a/boards/others/stm32f030_demo/stm32f030_demo_defconfig +++ b/boards/others/stm32f030_demo/stm32f030_demo_defconfig @@ -1,9 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Kernel Options due to Low Memory (4k) -CONFIG_MAIN_STACK_SIZE=640 -CONFIG_IDLE_STACK_SIZE=200 -CONFIG_ISR_STACK_SIZE=512 # Prevent Interrupt Vector Table in RAM CONFIG_SRAM_VECTOR_TABLE=n diff --git a/boards/shields/adafruit_sht4x/Kconfig.shield b/boards/shields/adafruit_sht4x/Kconfig.shield new file mode 100644 index 0000000000000..b5dcc09c3d7c6 --- /dev/null +++ b/boards/shields/adafruit_sht4x/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2025 Jonas Berg +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_ADAFRUIT_SHT4X + def_bool $(shields_list_contains,adafruit_sht4x) diff --git a/boards/shields/adafruit_sht4x/adafruit_sht4x.overlay b/boards/shields/adafruit_sht4x/adafruit_sht4x.overlay new file mode 100644 index 0000000000000..91e6d70fd3e9a --- /dev/null +++ b/boards/shields/adafruit_sht4x/adafruit_sht4x.overlay @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Jonas Berg + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + dht0 = &adafruit_sht4x; + }; +}; + +&zephyr_i2c { + status = "okay"; + + adafruit_sht4x: sht4x@44 { + status = "okay"; + compatible = "sensirion,sht4x"; + repeatability = <2>; /* High repeatability */ + reg = <0x44>; + }; +}; diff --git a/boards/shields/adafruit_sht4x/doc/adafruit_sht40.webp b/boards/shields/adafruit_sht4x/doc/adafruit_sht40.webp new file mode 100644 index 0000000000000..289cfbc385ed2 Binary files /dev/null and b/boards/shields/adafruit_sht4x/doc/adafruit_sht40.webp differ diff --git a/boards/shields/adafruit_sht4x/doc/index.rst b/boards/shields/adafruit_sht4x/doc/index.rst new file mode 100644 index 0000000000000..c22a97c1ca48c --- /dev/null +++ b/boards/shields/adafruit_sht4x/doc/index.rst @@ -0,0 +1,62 @@ +.. _adafruit_sht4x: + +Adafruit SHT40 SHT41 and SHT45 Shields +###################################### + +Overview +******** + +The `Adafruit SHT40 SHT41 and SHT45 Shields`_ feature +a Sensirion SHT4x Humidity and Temperature Sensor and two STEMMA QT connectors. +It measures temperature and humidity. See for example the `SHT40 sensor`_. + +.. figure:: adafruit_sht40.webp + :align: center + :alt: Adafruit SHT40 Shield + + Adafruit SHT40 Shield (Credit: Adafruit) + + +Requirements +************ + +This shield can be used with boards which provide an I2C connector, for +example STEMMA QT or Qwiic connectors. +The target board must define a ``zephyr_i2c`` node label. +See :ref:`shields` for more details. + + +Pin Assignments +=============== + ++--------------+-------------------+ +| Shield Pin | Function | ++==============+===================+ +| SDA | Sensor I2C SDA | ++--------------+-------------------+ +| SCL | Sensor I2C SCL | ++--------------+-------------------+ + +See :dtcompatible:`sensirion,sht4x` for details on possible devicetree settings, +for example regarding the trade-off between speed and repeatability. + +This shield definition assumes an I2C address of 0x44. + + +Programming +*********** + +Set ``--shield adafruit_sht4x`` when you invoke ``west build``. For example +when running the :zephyr:code-sample:`dht_polling` sample: + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/dht_polling + :board: adafruit_feather_rp2040 + :shield: adafruit_sht4x + :goals: build flash + +.. _Adafruit SHT40 SHT41 and SHT45 Shields: + https://learn.adafruit.com/adafruit-sht40-temperature-humidity-sensor + +.. _SHT40 sensor: + https://sensirion.com/products/catalog/SHT40 diff --git a/boards/shields/adafruit_sht4x/shield.yml b/boards/shields/adafruit_sht4x/shield.yml new file mode 100644 index 0000000000000..6ca05f5ed9965 --- /dev/null +++ b/boards/shields/adafruit_sht4x/shield.yml @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2025, Jonas Berg + +shield: + name: adafruit_sht4x + full_name: Adafruit SHT40 SHT41 SHT45 Temperature and Humidity Sensor Shield + vendor: adafruit + supported_features: + - sensor diff --git a/boards/st/nucleo_f030r8/nucleo_f030r8_defconfig b/boards/st/nucleo_f030r8/nucleo_f030r8_defconfig index bc6f05a7777b3..dde4ff07a7177 100644 --- a/boards/st/nucleo_f030r8/nucleo_f030r8_defconfig +++ b/boards/st/nucleo_f030r8/nucleo_f030r8_defconfig @@ -1,9 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Kernel Options due to Low Memory (8k) -CONFIG_MAIN_STACK_SIZE=640 -CONFIG_IDLE_STACK_SIZE=200 -CONFIG_ISR_STACK_SIZE=512 # Prevent Interrupt Vector Table in RAM CONFIG_SRAM_VECTOR_TABLE=n diff --git a/boards/st/nucleo_f031k6/nucleo_f031k6_defconfig b/boards/st/nucleo_f031k6/nucleo_f031k6_defconfig index fdc64d65e1adc..c98d7ba651b3c 100644 --- a/boards/st/nucleo_f031k6/nucleo_f031k6_defconfig +++ b/boards/st/nucleo_f031k6/nucleo_f031k6_defconfig @@ -1,9 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Kernel Options due to Low Memory (4k) -CONFIG_MAIN_STACK_SIZE=512 -CONFIG_IDLE_STACK_SIZE=150 -CONFIG_ISR_STACK_SIZE=512 CONFIG_LOG_BUFFER_SIZE=256 # Prevent Interrupt Vector Table in RAM CONFIG_SRAM_VECTOR_TABLE=n diff --git a/boards/st/nucleo_g031k8/nucleo_g031k8_defconfig b/boards/st/nucleo_g031k8/nucleo_g031k8_defconfig index e91ac02cdda07..e3d8f7bb3d266 100644 --- a/boards/st/nucleo_g031k8/nucleo_g031k8_defconfig +++ b/boards/st/nucleo_g031k8/nucleo_g031k8_defconfig @@ -1,10 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Kernel Options due to Low Memory (8k) -CONFIG_MAIN_STACK_SIZE=640 -CONFIG_IDLE_STACK_SIZE=200 -CONFIG_ISR_STACK_SIZE=512 - # Serial Drivers CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/st/nucleo_h7s3l8/doc/index.rst b/boards/st/nucleo_h7s3l8/doc/index.rst index 27a777e34d78a..84562d6c77b5e 100644 --- a/boards/st/nucleo_h7s3l8/doc/index.rst +++ b/boards/st/nucleo_h7s3l8/doc/index.rst @@ -162,6 +162,7 @@ and a ST morpho connector. Board is configured as follows: - I2C : PB8, PB9 - SPI1 NSS/SCK/MISO/MOSI : PD14PA5/PA6/PB5 (Arduino SPI) - FDCAN1 RX/TX : PD0, PD1 +- ETH : A2, A7, B6, G4, G5, G6, G11, G12, G13 System Clock ------------ @@ -183,7 +184,7 @@ In order to test backup SRAM you may want to disconnect VBAT from VDD. You can do it by removing ``SB13`` jumper on the back side of the board. FDCAN -===== +----- The Nucleo H7S3L8 board does not have any onboard CAN transceiver. In order to use the FDCAN bus on this board, an external CAN bus transceiver must be diff --git a/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.dts b/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.dts index 9e2324fbe9540..a7b3bb2ade792 100644 --- a/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.dts +++ b/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.dts @@ -175,6 +175,31 @@ status = "okay"; }; +&mac { + pinctrl-0 = <ð_rmii_rxd0_pg4 + ð_rmii_rxd1_pg5 + ð_rmii_ref_clk_pb6 + ð_rmii_crs_dv_pa7 + ð_rmii_tx_en_pg11 + ð_rmii_txd0_pg13 + ð_rmii_txd1_pg12>; + pinctrl-names = "default"; + phy-connection-type = "rmii"; + phy-handle = <ð_phy>; + status = "okay"; +}; + +&mdio { + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pg6>; + pinctrl-names = "default"; + status = "okay"; + + eth_phy: ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + }; +}; + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.yaml b/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.yaml index 5b7624bc06f9c..7b20c79ebf399 100644 --- a/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.yaml +++ b/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.yaml @@ -15,4 +15,5 @@ supported: - octospi - can - canfd + - netif:eth vendor: st diff --git a/boards/st/nucleo_l011k4/nucleo_l011k4_defconfig b/boards/st/nucleo_l011k4/nucleo_l011k4_defconfig index 026b05cc7f84e..e3d8f7bb3d266 100644 --- a/boards/st/nucleo_l011k4/nucleo_l011k4_defconfig +++ b/boards/st/nucleo_l011k4/nucleo_l011k4_defconfig @@ -1,10 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Kernel Options due to Low Memory (2k) -CONFIG_MAIN_STACK_SIZE=320 -CONFIG_IDLE_STACK_SIZE=100 -CONFIG_ISR_STACK_SIZE=256 - # Serial Drivers CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/st/nucleo_l031k6/nucleo_l031k6_defconfig b/boards/st/nucleo_l031k6/nucleo_l031k6_defconfig index e91ac02cdda07..e3d8f7bb3d266 100644 --- a/boards/st/nucleo_l031k6/nucleo_l031k6_defconfig +++ b/boards/st/nucleo_l031k6/nucleo_l031k6_defconfig @@ -1,10 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Kernel Options due to Low Memory (8k) -CONFIG_MAIN_STACK_SIZE=640 -CONFIG_IDLE_STACK_SIZE=200 -CONFIG_ISR_STACK_SIZE=512 - # Serial Drivers CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/st/nucleo_l053r8/nucleo_l053r8_defconfig b/boards/st/nucleo_l053r8/nucleo_l053r8_defconfig index 634c2f45edfa4..f23dd0a9d8373 100644 --- a/boards/st/nucleo_l053r8/nucleo_l053r8_defconfig +++ b/boards/st/nucleo_l053r8/nucleo_l053r8_defconfig @@ -3,11 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Kernel Options due to Low Memory (8k) -CONFIG_MAIN_STACK_SIZE=640 -CONFIG_IDLE_STACK_SIZE=200 -CONFIG_ISR_STACK_SIZE=512 - # Serial Drivers CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/st/stm32f0_disco/stm32f0_disco_defconfig b/boards/st/stm32f0_disco/stm32f0_disco_defconfig index bc6f05a7777b3..dde4ff07a7177 100644 --- a/boards/st/stm32f0_disco/stm32f0_disco_defconfig +++ b/boards/st/stm32f0_disco/stm32f0_disco_defconfig @@ -1,9 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Kernel Options due to Low Memory (8k) -CONFIG_MAIN_STACK_SIZE=640 -CONFIG_IDLE_STACK_SIZE=200 -CONFIG_ISR_STACK_SIZE=512 # Prevent Interrupt Vector Table in RAM CONFIG_SRAM_VECTOR_TABLE=n diff --git a/boards/st/stm32g0316_disco/stm32g0316_disco_defconfig b/boards/st/stm32g0316_disco/stm32g0316_disco_defconfig index b9dc13649c8fe..adb1ec61c8f31 100644 --- a/boards/st/stm32g0316_disco/stm32g0316_disco_defconfig +++ b/boards/st/stm32g0316_disco/stm32g0316_disco_defconfig @@ -1,8 +1,3 @@ -# Kernel Options due to Low Memory (8k) -CONFIG_MAIN_STACK_SIZE=640 -CONFIG_IDLE_STACK_SIZE=200 -CONFIG_ISR_STACK_SIZE=512 - # Serial Drivers CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/st/stm32mp157c_dk2/Kconfig.defconfig b/boards/st/stm32mp157c_dk2/Kconfig.defconfig index 40490cb49c3f9..1f58590c079d5 100644 --- a/boards/st/stm32mp157c_dk2/Kconfig.defconfig +++ b/boards/st/stm32mp157c_dk2/Kconfig.defconfig @@ -9,7 +9,4 @@ config SPI_STM32_INTERRUPT default y depends on SPI -config CLOCK_STM32_HSE_CLOCK - default 24000000 - endif # BOARD_STM32MP157_Dk2 diff --git a/boards/st/stm32mp157c_dk2/stm32mp157c_dk2.dts b/boards/st/stm32mp157c_dk2/stm32mp157c_dk2.dts index b5057ebbfd2d1..a9f39c28520ac 100644 --- a/boards/st/stm32mp157c_dk2/stm32mp157c_dk2.dts +++ b/boards/st/stm32mp157c_dk2/stm32mp157c_dk2.dts @@ -57,6 +57,11 @@ clock-frequency = ; }; +&clk_hse { + clock-frequency = ; + status = "okay"; +}; + &spi4_miso_pe13 { slew-rate = "very-high-speed"; }; diff --git a/boards/st/stm32n6570_dk/stm32n6570_dk_common.dtsi b/boards/st/stm32n6570_dk/stm32n6570_dk_common.dtsi index e6721599454df..0f1096116a1bd 100644 --- a/boards/st/stm32n6570_dk/stm32n6570_dk_common.dtsi +++ b/boards/st/stm32n6570_dk/stm32n6570_dk_common.dtsi @@ -521,3 +521,7 @@ csi_interface: &dcmipp { &venc { status = "okay"; }; + +&jpeg { + status = "okay"; +}; diff --git a/boards/st/stm32u083c_dk/stm32u083c_dk.dts b/boards/st/stm32u083c_dk/stm32u083c_dk.dts index 315a1826fcbb3..4506778fd18af 100644 --- a/boards/st/stm32u083c_dk/stm32u083c_dk.dts +++ b/boards/st/stm32u083c_dk/stm32u083c_dk.dts @@ -175,3 +175,19 @@ stm32_lp_tick_source: &lptim2 { }; }; }; + +zephyr_udc0: &usb { + pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; +}; + +&clk_hsi48 { + crs-usb-sof; + status = "okay"; +}; + +&clk48 { + clocks = <&rcc STM32_SRC_HSI48 CLK48_SEL(3)>; + status = "okay"; +}; diff --git a/doc/_extensions/zephyr/domain/static/css/board.css b/doc/_extensions/zephyr/domain/static/css/board.css index d2d90b9fe5c34..96ee894808bd6 100644 --- a/doc/_extensions/zephyr/domain/static/css/board.css +++ b/doc/_extensions/zephyr/domain/static/css/board.css @@ -4,69 +4,6 @@ */ /* Board overview "card" on board documentation pages */ -.sidebar.board-overview { - border-radius: 12px; - padding: 0px; - background: var(--admonition-note-background-color); - color: var(--admonition-note-title-color); - border-color: var(--admonition-note-title-background-color); -} - -@media screen and (max-width: 480px) { - .sidebar.board-overview { - float: none; - margin-left: 0; - } -} - -.sidebar.board-overview { - color: var(--admonition-note-color); -} - -.sidebar.board-overview .sidebar-title { - font-family: var(--header-font-family); - background: var(--admonition-note-title-background-color); - color: var(--admonition-note-title-color); - border-radius: 12px 12px 0px 0px; - margin: 0px; - text-align: center; -} - -.sidebar.board-overview figure { - padding: 1rem; - margin-bottom: -1rem; -} - -.sidebar.board-overview figure img { - height: auto !important; -} - -.sidebar.board-overview figure figcaption p { - margin-bottom: 0px; -} - -.sidebar.board-overview dl.field-list { - align-items: center; - margin-top: 12px !important; - margin-bottom: 12px !important; - grid-template-columns: auto 1fr !important; - padding-right: 1em; -} - -.sidebar.board-overview dl.field-list>dt { - background: transparent !important; -} - -.sidebar.board-overview dl.field-list>dd { - margin-left: 1em; - text-overflow: ellipsis; - overflow: hidden; -} - -.sidebar.board-overview dl.field-list>dd code { - font-size: 0.9em; -} - .sidebar.board-overview #board-github-link { text-align: center; margin-bottom: 1em; diff --git a/doc/_scripts/gen_devicetree_rest.py b/doc/_scripts/gen_devicetree_rest.py index 908cfb0278b9f..9287411b72528 100644 --- a/doc/_scripts/gen_devicetree_rest.py +++ b/doc/_scripts/gen_devicetree_rest.py @@ -499,6 +499,17 @@ def write_orphans(bindings, base_binding, vnd_lookup, driver_sources, out_dir): logging.info('done writing :orphan: files; %d files needed updates', num_written) +def make_sidebar(compatible, vendor_name, vendor_ref_target, driver_path=None): + lines = [ + ".. sidebar:: Overview", + "", + f" :Name: ``{compatible}``", + f" :Vendor: :ref:`{vendor_name} <{vendor_ref_target}>`", + ] + if driver_path: + lines.append(f" :Driver: :zephyr_file:`{driver_path}`") + return "\n".join(lines) + "\n" + def print_binding_page(binding, base_names, vnd_lookup, driver_sources,dup_compats, string_io): # Print the rst content for 'binding' to 'string_io'. The @@ -550,24 +561,18 @@ def print_binding_page(binding, base_names, vnd_lookup, driver_sources,dup_compa {underline} ''', string_io) - # Vendor: vnd = compatible_vnd(compatible) - print('Vendor: ' - f':ref:`{vnd_lookup.vendor(vnd)} <{vnd_lookup.target(vnd)}>`\n', - file=string_io) - - # Link to driver implementation (if it exists). - compatible = re.sub("[-,.@/+]", "_", compatible.lower()) - if compatible in driver_sources: - print_block( - f"""\ - .. note:: - - An implementation of a driver matching this compatible is available in - :zephyr_file:`{driver_sources[compatible]}`. - """, - string_io, - ) + vendor_name = vnd_lookup.vendor(vnd) + vendor_target = vnd_lookup.target(vnd) + driver_path = driver_sources.get(re.sub("[-,.@/+]", "_", compatible.lower())) + + sidebar_content = make_sidebar( + compatible=compatible, + vendor_name=vendor_name, + vendor_ref_target=vendor_target, + driver_path=driver_path, + ) + print_block(sidebar_content, string_io) # Binding description. if binding.bus: diff --git a/doc/_static/css/custom.css b/doc/_static/css/custom.css index 2d365419c38a2..e6c0853b1c48c 100644 --- a/doc/_static/css/custom.css +++ b/doc/_static/css/custom.css @@ -927,6 +927,70 @@ div.graphviz > object { filter: var(--graphviz-filter); } +/* Sidebar */ +.rst-content .sidebar { + border-radius: 12px; + padding: 0px; + background: var(--admonition-note-background-color); + color: var(--admonition-note-title-color); + border-color: var(--admonition-note-title-background-color); +} + +@media screen and (max-width: 480px) { + .rst-content .sidebar { + float: none; + margin-left: 0; + } +} + +.rst-content .sidebar { + color: var(--admonition-note-color); +} + +.rst-content .sidebar .sidebar-title { + font-family: var(--header-font-family); + background: var(--admonition-note-title-background-color); + color: var(--admonition-note-title-color); + border-radius: 12px 12px 0px 0px; + margin: 0px; + text-align: center; +} + +.rst-content .sidebar figure { + padding: 1rem; + margin-bottom: -1rem; +} + +.rst-content .sidebar figure img { + height: auto !important; +} + +.rst-content .sidebar figure figcaption p { + margin-bottom: 0px; +} + +.rst-content .sidebar dl.field-list { + align-items: center; + margin-top: 12px !important; + margin-bottom: 12px !important; + grid-template-columns: auto 1fr !important; + padding-right: 1em; +} + +.rst-content .sidebar dl.field-list>dt { + background: transparent !important; +} + +.rst-content .sidebar dl.field-list>dd { + margin-left: 1em; + text-overflow: ellipsis; + overflow: hidden; +} + +.rst-content .sidebar dl.field-list>dd code { + font-size: 0.9em; +} + /* Home page grid display */ .grid { list-style-type: none !important; diff --git a/doc/contribute/style/naming.rst b/doc/contribute/style/naming.rst index 384ece51ffd1a..c8db8d1c8513c 100644 --- a/doc/contribute/style/naming.rst +++ b/doc/contribute/style/naming.rst @@ -15,7 +15,7 @@ as stated in each individual sub-section. Public symbol prefixes ====================== -All :term:`public APIs ` in Zephyr must be prefixed according +All :term:`public APIs ` introduced to Zephyr must be prefixed according to the area or subsystem they belong to. Examples of area or subsystem prefixes are provided below for reference. diff --git a/doc/releases/migration-guide-4.3.rst b/doc/releases/migration-guide-4.3.rst index 135f02d3a033f..d829a56c6de31 100644 --- a/doc/releases/migration-guide-4.3.rst +++ b/doc/releases/migration-guide-4.3.rst @@ -67,6 +67,14 @@ ADC * ``iadc_gecko.c`` driver is replaced by ``adc_silabs_iadc.c``. :dtcompatible:`silabs,gecko-iadc` is replaced by :dtcompatible:`silabs,iadc`. +Clock Control +============= + +* :kconfig:option:`CONFIG_CLOCK_STM32_HSE_CLOCK` is no longer user-configurable. Its value is now + always taken from the ``clock-frequency`` property of ``&clk_hse`` DT node, but only if the node + is enabled (otherwise, the symbol is not defined). This change should only affect STM32 MPU-based + platforms and aligns them with existing practice from STM32 MCU platforms. + Comparator ========== diff --git a/doc/releases/release-notes-4.3.rst b/doc/releases/release-notes-4.3.rst index 5644568846b44..30a2c025ba6e9 100644 --- a/doc/releases/release-notes-4.3.rst +++ b/doc/releases/release-notes-4.3.rst @@ -146,6 +146,10 @@ New APIs and options * :kconfig:option:`CONFIG_CPU_FREQ` +* Crypto + + * :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS` + * Display * :c:enumerator:`PIXEL_FORMAT_AL_88` diff --git a/doc/zephyr.doxyfile.in b/doc/zephyr.doxyfile.in index d0d56dc970bd0..f172606e48c3f 100644 --- a/doc/zephyr.doxyfile.in +++ b/doc/zephyr.doxyfile.in @@ -527,7 +527,7 @@ LOOKUP_CACHE_SIZE = 9 # DOT_NUM_THREADS setting. # Minimum value: 0, maximum value: 32, default value: 1. -NUM_PROC_THREADS = 1 +NUM_PROC_THREADS = 0 # If the TIMESTAMP tag is set different from NO then each generated page will # contain the date or date and time when the page was generated. Setting this to diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index 9d76ae2bf2ded..3683b04855bf4 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -22,23 +22,30 @@ menuconfig CLOCK_CONTROL_STM32_CUBE if CLOCK_CONTROL_STM32_CUBE -DT_STM32_HSE_CLOCK := $(dt_nodelabel_path,clk_hse) -DT_STM32_HSE_CLOCK_FREQ := $(dt_node_int_prop_int,$(DT_STM32_HSE_CLOCK),clock-frequency) - config CLOCK_STM32_HSE_CLOCK - int "HSE clock value" - default "$(DT_STM32_HSE_CLOCK_FREQ)" if "$(dt_nodelabel_enabled,clk_hse)" - default 8000000 + int + default $(dt_nodelabel_int_prop,clk_hse,clock-frequency) + depends on $(dt_nodelabel_enabled,clk_hse) help - Value of external high-speed clock (HSE). This symbol could be optionally - configured using device tree by setting "clock-frequency" value of clk_hse - node. For instance: - &clk_hse{ - status = "okay"; - clock-frequency = ; - }; - Note: Device tree configuration is overridden when current symbol is set: - CONFIG_CLOCK_STM32_HSE_CLOCK=32000000 + Frequency of external high-speed clock (HSE). + + The value of this symbol is used to set the preprocessor + definition "HSE_VALUE" notably consumed by the HAL. + + This symbol cannot be set externally: its value is directly + taken from the "clock-frequency" property of the "clk_hse" + Device Tree node when it is enabled. + + This node would usually looks similar to: + + &clk_hse { + clock-frequency = ; + status = "okay"; + }; + + If the "clk_hse" node does not exist or is not enabled + (status != "okay"), this symbol is not defined and the + HSE_VALUE preprocessor definition does not exist. config CLOCK_STM32_MUX bool "STM32 clock mux driver" diff --git a/drivers/clock_control/clock_stm32_ll_u5.c b/drivers/clock_control/clock_stm32_ll_u5.c index 35611555e4c98..db9d63bbb0779 100644 --- a/drivers/clock_control/clock_stm32_ll_u5.c +++ b/drivers/clock_control/clock_stm32_ll_u5.c @@ -145,7 +145,8 @@ int enabled_clock(uint32_t src_clk) ((src_clk == STM32_SRC_PLL2_R) && IS_ENABLED(STM32_PLL2_R_ENABLED)) || ((src_clk == STM32_SRC_PLL3_P) && IS_ENABLED(STM32_PLL3_P_ENABLED)) || ((src_clk == STM32_SRC_PLL3_Q) && IS_ENABLED(STM32_PLL3_Q_ENABLED)) || - ((src_clk == STM32_SRC_PLL3_R) && IS_ENABLED(STM32_PLL3_R_ENABLED))) { + ((src_clk == STM32_SRC_PLL3_R) && IS_ENABLED(STM32_PLL3_R_ENABLED)) || + (src_clk == STM32_SRC_DSIPHY)) { return 0; } diff --git a/drivers/clock_control/clock_stm32g0_u0.c b/drivers/clock_control/clock_stm32g0_u0.c index 5f7a3bfb1ad4d..f337ad739ae13 100644 --- a/drivers/clock_control/clock_stm32g0_u0.c +++ b/drivers/clock_control/clock_stm32g0_u0.c @@ -68,6 +68,41 @@ void config_pll_sysclock(void) #endif /* defined(STM32_PLL_ENABLED) */ +#if defined(STM32_CK48_ENABLED) +/** + * @brief calculate the CK48 frequency depending on its clock source + */ +__unused +uint32_t get_ck48_frequency(void) +{ + switch (LL_RCC_GetRNGClockSource(LL_RCC_RNG_CLKSOURCE)) { + case LL_RCC_RNG_CLKSOURCE_PLLQ: + /* Get the PLL48CK source : HSE or HSI */ + uint32_t pll_source = (LL_RCC_PLL_GetMainSource() == LL_RCC_PLLSOURCE_HSE) + ? HSE_VALUE + : HSI_VALUE; + + /* Get the PLL48CK Q freq. No HAL macro for that */ + return __LL_RCC_CALC_PLLCLK_Q_FREQ(pll_source, LL_RCC_PLL_GetM(), LL_RCC_PLL_GetN(), + LL_RCC_PLL_GetQ()); + case LL_RCC_RNG_CLKSOURCE_MSI: + return __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGESEL_RUN, LL_RCC_MSI_GetRange()); +#if defined(USB_DRD_FS) + case LL_RCC_RNG_CLKSOURCE_HSI48: + return MHZ(48); +#endif + case LL_RCC_RNG_CLKSOURCE_NONE: + /* Clock source not configured */ + return 0; + default: + __ASSERT(0, "Invalid source"); + break; + } + + return 0; +} +#endif + /** * @brief Activate default clocks */ diff --git a/drivers/eeprom/CMakeLists.txt b/drivers/eeprom/CMakeLists.txt index dced9ecb29afa..5f667fa2434ac 100644 --- a/drivers/eeprom/CMakeLists.txt +++ b/drivers/eeprom/CMakeLists.txt @@ -26,3 +26,5 @@ zephyr_library_sources_ifdef(CONFIG_EEPROM_AT2X_EMUL eeprom_at2x_emul.c) zephyr_library_sources_ifdef(CONFIG_EEPROM_MB85RCXX eeprom_mb85rcxx.c) zephyr_library_sources_ifdef(CONFIG_EEPROM_MB85RSXX eeprom_mb85rsxx.c) + +zephyr_library_sources_ifdef(CONFIG_EEPROM_FM25XXX eeprom_fm25xxx.c) diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig index ca8d3c4e4726e..ec90b1e731011 100644 --- a/drivers/eeprom/Kconfig +++ b/drivers/eeprom/Kconfig @@ -100,6 +100,7 @@ source "drivers/eeprom/Kconfig.tmp11x" source "drivers/eeprom/Kconfig.xec" source "drivers/eeprom/Kconfig.mb85rcxx" source "drivers/eeprom/Kconfig.mb85rsxx" +source "drivers/eeprom/Kconfig.fm25xxx" config EEPROM_SIMULATOR bool "Simulated EEPROM driver" diff --git a/drivers/eeprom/Kconfig.fm25xxx b/drivers/eeprom/Kconfig.fm25xxx new file mode 100644 index 0000000000000..db0b7ff62394d --- /dev/null +++ b/drivers/eeprom/Kconfig.fm25xxx @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Luna Pes +# SPDX-License-Identifier: Apache-2.0 + +config EEPROM_FM25XXX + bool "Infineon FM25XXX SPI FRAM" + default y + depends on DT_HAS_INFINEON_FM25XXX_ENABLED + select SPI + help + Enable Infineon FM25XXX SPI FRAM diff --git a/drivers/eeprom/eeprom_fm25xxx.c b/drivers/eeprom/eeprom_fm25xxx.c new file mode 100644 index 0000000000000..f0061c84265c1 --- /dev/null +++ b/drivers/eeprom/eeprom_fm25xxx.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2025 Luna Pes + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file implements the Infineon AN304 SPI Guide for F-RAM */ + +#include "zephyr/devicetree.h" +#include "zephyr/kernel.h" +#include "zephyr/sys/byteorder.h" +#include "zephyr/sys/util.h" +#include +#include +#include +#include + +#define DT_DRV_COMPAT infineon_fm25xxx + +LOG_MODULE_REGISTER(fm25xxx, CONFIG_EEPROM_LOG_LEVEL); + +/* Registers */ +#define FM25XXX_WREN 0x06 +#define FM25XXX_WRDI 0x04 +#define FM25XXX_RDSR 0x05 +#define FM25XXX_WRSR 0x01 +#define FM25XXX_READ 0x03 +#define FM25XXX_WRITE 0x02 + +struct fm25xxx_config { + struct spi_dt_spec spi; + size_t size; + bool readonly; +}; + +struct fm25xxx_data { + struct k_sem lock; +}; + +static uint8_t eeprom_fm25xxx_size_to_addr_bytes(size_t size) +{ + if (size <= 500) { + return 1; + } else if (size <= 64000) { + return 2; + } else { + return 3; + } +} + +static int eeprom_fm25xxx_set_enable_write(const struct device *dev, bool enable_writes) +{ + const struct fm25xxx_config *config = dev->config; + uint8_t op = enable_writes ? FM25XXX_WREN : FM25XXX_WRDI; + + const struct spi_buf tx_bufs[] = {{ + .buf = &op, + .len = sizeof(op), + }}; + const struct spi_buf_set tx_buf_set = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs), + }; + + int ret = spi_write_dt(&config->spi, &tx_buf_set); + + if (ret != 0) { + LOG_ERR("Failed to %s writes", enable_writes ? "enable" : "disable"); + return ret; + } + + return 0; +} + +int eeprom_fm25xxx_read(const struct device *dev, off_t offset, void *data, size_t len) +{ + int ret; + const struct fm25xxx_config *config = dev->config; + + if (offset + len > config->size) { + LOG_ERR("Can not read more data than the device size"); + return -EINVAL; + } + + if (len == 0) { + return 0; + } + + uint8_t read_op[4] = {FM25XXX_READ}; + off_t last_offset_bit = (offset >> 8) & 0x01; + + size_t addr_bytes = eeprom_fm25xxx_size_to_addr_bytes(config->size); + size_t op_len = 1 + addr_bytes; + + switch (addr_bytes) { + case 1: + read_op[0] |= (last_offset_bit << 3); + read_op[1] = offset & 0xff; + break; + case 2: + sys_put_be16(offset, &read_op[1]); + break; + case 3: + sys_put_be24(offset, &read_op[1]); + break; + default: + LOG_ERR("Invalid number of address bytes %u", addr_bytes); + return -EINVAL; + } + + LOG_HEXDUMP_DBG(read_op, 4, "Read op"); + + const struct spi_buf tx_bufs[] = {{ + .buf = &read_op, + .len = op_len, + }}; + const struct spi_buf_set tx_buf_set = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs), + }; + + const struct spi_buf rx_bufs[2] = { + { + .buf = NULL, + .len = op_len, + }, + { + .buf = data, + .len = len, + }, + }; + const struct spi_buf_set rx_buf_set = { + .buffers = rx_bufs, + .count = ARRAY_SIZE(rx_bufs), + }; + + ret = spi_transceive_dt(&config->spi, &tx_buf_set, &rx_buf_set); + + if (ret != 0) { + LOG_ERR("Failed to read from FRAM"); + return ret; + } + + return 0; +} + +int eeprom_fm25xxx_write(const struct device *dev, off_t offset, const void *data, size_t len) +{ + int ret; + const struct fm25xxx_config *config = dev->config; + struct fm25xxx_data *dev_data = dev->data; + + if (config->readonly) { + LOG_ERR("Can not write to a readonly device"); + return -EACCES; + } + + if (offset + len > config->size) { + LOG_ERR("Can not write more data than the device size"); + return -EINVAL; + } + + if (len == 0) { + return 0; + } + + uint8_t write_op[4] = {FM25XXX_WRITE}; + off_t last_offset_bit = (offset >> 8) & 0x01; + + size_t addr_bytes = eeprom_fm25xxx_size_to_addr_bytes(config->size); + size_t op_len = 1 + addr_bytes; + + switch (addr_bytes) { + case 1: + write_op[0] |= (last_offset_bit << 3); + write_op[1] = offset & 0xff; + break; + case 2: + sys_put_be16(offset, &write_op[1]); + break; + case 3: + sys_put_be24(offset, &write_op[1]); + break; + default: + LOG_ERR("Invalid number of address bytes %u", addr_bytes); + return -EINVAL; + } + + LOG_HEXDUMP_DBG(write_op, 4, "Write op"); + + const struct spi_buf tx_bufs[] = { + { + .buf = &write_op, + .len = op_len, + }, + { + .buf = (void *)data, + .len = len, + }, + }; + const struct spi_buf_set tx_buf_set = { + .buffers = tx_bufs, + .count = ARRAY_SIZE(tx_bufs), + }; + + k_sem_take(&dev_data->lock, K_FOREVER); + + ret = eeprom_fm25xxx_set_enable_write(dev, true); + if (ret != 0) { + k_sem_give(&dev_data->lock); + LOG_ERR("Could not enable writes"); + return ret; + } + + ret = spi_write_dt(&config->spi, &tx_buf_set); + if (ret != 0) { + k_sem_give(&dev_data->lock); + LOG_ERR("Failed to write to FRAM"); + return ret; + } + + ret = eeprom_fm25xxx_set_enable_write(dev, false); + if (ret != 0) { + k_sem_give(&dev_data->lock); + LOG_ERR("Could not disable writes"); + return ret; + } + + k_sem_give(&dev_data->lock); + + return 0; +} + +size_t eeprom_fm25xxx_get_size(const struct device *dev) +{ + const struct fm25xxx_config *config = dev->config; + + return config->size; +} + +static int eeprom_fm25xxx_init(const struct device *dev) +{ + const struct fm25xxx_config *config = dev->config; + struct fm25xxx_data *data = dev->data; + + k_sem_init(&data->lock, 1, 1); + + if (!spi_is_ready_dt(&config->spi)) { + LOG_ERR("SPI bus not ready"); + return -ENODEV; + } + + return 0; +} + +static DEVICE_API(eeprom, eeprom_fm25xxx_api) = { + .read = &eeprom_fm25xxx_read, + .write = &eeprom_fm25xxx_write, + .size = &eeprom_fm25xxx_get_size, +}; + +#define FM25XXX_INIT(inst) \ + static struct fm25xxx_data fm25xxx_data_##inst; \ + static const struct fm25xxx_config fm25xxx_config_##inst = { \ + .spi = SPI_DT_SPEC_INST_GET(inst, SPI_OP_MODE_MASTER | SPI_WORD_SET(8)), \ + .size = DT_INST_PROP(inst, size), \ + .readonly = DT_INST_PROP(inst, read_only), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, eeprom_fm25xxx_init, NULL, &fm25xxx_data_##inst, \ + &fm25xxx_config_##inst, POST_KERNEL, CONFIG_EEPROM_INIT_PRIORITY, \ + &eeprom_fm25xxx_api); + +DT_INST_FOREACH_STATUS_OKAY(FM25XXX_INIT) diff --git a/drivers/ethernet/Kconfig.stm32_hal b/drivers/ethernet/Kconfig.stm32_hal index 3fd26ab4adde0..5c7d260a84c24 100644 --- a/drivers/ethernet/Kconfig.stm32_hal +++ b/drivers/ethernet/Kconfig.stm32_hal @@ -26,7 +26,12 @@ choice ETH_STM32_HAL_API_VERSION config ETH_STM32_HAL_API_V2 bool "Use official STM32Cube HAL driver" - depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || SOC_SERIES_STM32N6X + depends on SOC_SERIES_STM32F4X \ + || SOC_SERIES_STM32F7X \ + || SOC_SERIES_STM32H5X \ + || SOC_SERIES_STM32H7X \ + || SOC_SERIES_STM32H7RSX \ + || SOC_SERIES_STM32N6X select USE_STM32_HAL_ETH_EX if SOC_SERIES_STM32N6X help Use the official STM32Cube HAL driver instead of the legacy one. @@ -86,7 +91,10 @@ menuconfig PTP_CLOCK_STM32_HAL default y depends on PTP_CLOCK || NET_L2_PTP depends on ETH_STM32_HAL_API_V2 - depends on SOC_SERIES_STM32F7X || SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X + depends on SOC_SERIES_STM32F7X \ + || SOC_SERIES_STM32H5X \ + || SOC_SERIES_STM32H7X \ + || SOC_SERIES_STM32H7RSX help Enable STM32 PTP clock support. diff --git a/drivers/ethernet/eth_esp32.c b/drivers/ethernet/eth_esp32.c index 166064db2d53d..eb51cf35f41b0 100644 --- a/drivers/ethernet/eth_esp32.c +++ b/drivers/ethernet/eth_esp32.c @@ -202,35 +202,6 @@ static void phy_link_state_changed(const struct device *phy_dev, } } -#if DT_INST_NODE_HAS_PROP(0, ref_clk_output_gpios) -static int emac_config_apll_clock(void) -{ - uint32_t expt_freq = MHZ(50); - uint32_t real_freq = 0; - esp_err_t ret = periph_rtc_apll_freq_set(expt_freq, &real_freq); - - if (ret == ESP_ERR_INVALID_ARG) { - LOG_ERR("Set APLL clock coefficients failed"); - return -EIO; - } - - if (ret == ESP_ERR_INVALID_STATE) { - LOG_INF("APLL is occupied already, it is working at %d Hz", real_freq); - } - - /* If the difference of real APLL frequency - * is not within 50 ppm, i.e. 2500 Hz, - * the APLL is unavailable - */ - if (abs((int)real_freq - (int)expt_freq) > 2500) { - LOG_ERR("The APLL is working at an unusable frequency"); - return -EIO; - } - - return 0; -} -#endif /* DT_INST_NODE_HAS_PROP(0, ref_clk_output_gpios) */ - int eth_esp32_initialize(const struct device *dev) { struct eth_esp32_dev_data *const dev_data = dev->data; @@ -281,21 +252,7 @@ int eth_esp32_initialize(const struct device *dev) if (strcmp(phy_connection_type, "rmii") == 0) { emac_hal_iomux_init_rmii(); -#if DT_INST_NODE_HAS_PROP(0, ref_clk_output_gpios) - BUILD_ASSERT(DT_INST_GPIO_PIN(0, ref_clk_output_gpios) == 0 || - DT_INST_GPIO_PIN(0, ref_clk_output_gpios) == 16 || - DT_INST_GPIO_PIN(0, ref_clk_output_gpios) == 17, - "Only GPIO0/16/17 are allowed as a GPIO REF_CLK source!"); - int ref_clk_gpio = DT_INST_GPIO_PIN(0, ref_clk_output_gpios); - emac_hal_iomux_rmii_clk_output(ref_clk_gpio); - emac_ll_clock_enable_rmii_output(dev_data->hal.ext_regs); - periph_rtc_apll_acquire(); - res = emac_config_apll_clock(); - if (res != 0) { - goto err; - } - rtc_clk_apll_enable(true); -#else +#if !DT_INST_NODE_HAS_PROP(0, ref_clk_output_gpios) emac_hal_iomux_rmii_clk_input(); emac_ll_clock_enable_rmii_input(dev_data->hal.ext_regs); #endif diff --git a/drivers/ethernet/eth_stm32_hal_priv.h b/drivers/ethernet/eth_stm32_hal_priv.h index 3ee7f16d71519..80c52fc04db5b 100644 --- a/drivers/ethernet/eth_stm32_hal_priv.h +++ b/drivers/ethernet/eth_stm32_hal_priv.h @@ -33,7 +33,7 @@ extern const struct device *eth_stm32_phy_dev; DT_NODE_HAS_STATUS_OKAY(DT_CHOSEN(zephyr_dtcm)) #define __eth_stm32_desc __dtcm_noinit_section #define __eth_stm32_buf __dtcm_noinit_section -#elif defined(CONFIG_SOC_SERIES_STM32H7X) +#elif defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H7RSX) #define __eth_stm32_desc __attribute__((section(".eth_stm32_desc"))) #define __eth_stm32_buf __attribute__((section(".eth_stm32_buf"))) #elif defined(CONFIG_NOCACHE_MEMORY) diff --git a/drivers/ethernet/phy/phy_microchip_ksz8081.c b/drivers/ethernet/phy/phy_microchip_ksz8081.c index a671dbf57abb7..f723b63efd1fe 100644 --- a/drivers/ethernet/phy/phy_microchip_ksz8081.c +++ b/drivers/ethernet/phy/phy_microchip_ksz8081.c @@ -61,6 +61,7 @@ struct mc_ksz8081_config { #define KSZ8081_DO_AUTONEG_FLAG BIT(0) #define KSZ8081_SILENCE_DEBUG_LOGS BIT(1) #define KSZ8081_LINK_STATE_VALID BIT(2) +#define KSZ8081_INITIALIZED BIT(3) #define USING_INTERRUPT_GPIO \ UTIL_OR(DT_ALL_INST_HAS_PROP_STATUS_OKAY(int_gpios), \ @@ -183,7 +184,11 @@ static void phy_mc_ksz8081_interrupt_handler(const struct device *port, struct g gpio_port_pins_t pins) { struct mc_ksz8081_data *data = CONTAINER_OF(cb, struct mc_ksz8081_data, gpio_callback); - int ret = k_work_reschedule(&data->phy_monitor_work, K_NO_WAIT); + int ret = -ESRCH; + + if (data->flags & KSZ8081_INITIALIZED) { + ret = k_work_reschedule(&data->phy_monitor_work, K_NO_WAIT); + } if (ret < 0) { LOG_ERR("Failed to schedule monitor_work from ISR"); @@ -671,21 +676,17 @@ static int phy_mc_ksz8081_init(const struct device *dev) data->dev = dev; - k_busy_wait(100000); - ret = k_mutex_init(&data->mutex); if (ret) { return ret; } mdio_bus_enable(config->mdio_dev); - k_busy_wait(100000); ret = ksz8081_init_reset_gpios(dev); if (ret) { return ret; } - k_busy_wait(100000); /* Reset PHY */ ret = phy_mc_ksz8081_reset(dev); @@ -693,19 +694,19 @@ static int phy_mc_ksz8081_init(const struct device *dev) return ret; } - ret = ksz8081_init_int_gpios(dev); - if (ret < 0) { - return ret; - } - - k_busy_wait(100000); k_work_init_delayable(&data->phy_monitor_work, phy_mc_ksz8081_monitor_work_handler); /* Advertise default speeds */ - k_busy_wait(100000); phy_mc_ksz8081_cfg_link(dev, config->default_speeds, 0); + ret = ksz8081_init_int_gpios(dev); + if (ret < 0) { + return ret; + } + + data->flags |= KSZ8081_INITIALIZED; + return 0; } diff --git a/drivers/mdio/mdio_esp32.c b/drivers/mdio/mdio_esp32.c index 7dd8995b65456..c422c78c85a58 100644 --- a/drivers/mdio/mdio_esp32.c +++ b/drivers/mdio/mdio_esp32.c @@ -17,6 +17,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(mdio_esp32, CONFIG_MDIO_LOG_LEVEL); @@ -152,15 +153,19 @@ static int mdio_esp32_initialize(const struct device *dev) DT_INST_GPIO_PIN(0, ref_clk_output_gpios) == 17, "Only GPIO0/16/17 are allowed as a GPIO REF_CLK source!"); int ref_clk_gpio = DT_INST_GPIO_PIN(0, ref_clk_output_gpios); - emac_hal_iomux_rmii_clk_output(ref_clk_gpio); + + /* Configure REF_CLK output when GPIO0 is used */ + if (ref_clk_gpio == 0) { + REG_SET_FIELD(PIN_CTRL, CLK_OUT1, 6); + } + emac_ll_clock_enable_rmii_output(dev_data->hal.ext_regs); periph_rtc_apll_acquire(); res = emac_config_apll_clock(); if (res != 0) { goto err; } - rtc_clk_apll_enable(true); #endif /* Init MDIO clock */ diff --git a/drivers/mipi_dsi/dsi_stm32.c b/drivers/mipi_dsi/dsi_stm32.c index 181226df760fb..6d972e7cf8b79 100644 --- a/drivers/mipi_dsi/dsi_stm32.c +++ b/drivers/mipi_dsi/dsi_stm32.c @@ -38,6 +38,7 @@ struct mipi_dsi_stm32_config { const struct device *rcc; const struct reset_dt_spec reset; struct stm32_pclken dsi_clk; + struct stm32_pclken dsisrc_clk; struct stm32_pclken ref_clk; struct stm32_pclken pix_clk; uint32_t data_lanes; @@ -56,6 +57,27 @@ struct mipi_dsi_stm32_data { uint32_t pixel_clk_khz; }; +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32u5_mipi_dsi) +/* Configures DSI PHY as DSI clock source (STM32U5 specific) */ +static int stm32_dsi_clock_source_config(const struct device *dev) +{ + const struct mipi_dsi_stm32_config *config = dev->config; + int ret; + + ret = clock_control_configure(config->rcc, (clock_control_subsys_t)&config->dsisrc_clk, + NULL); + if (ret < 0) { + LOG_ERR("Failed to configure DSI clock source (%d)", ret); + return ret; + } + + LOG_DBG("DSI kernel clock source selection, RCC_CCIPR2_DSIHOSTSEL: %u", + __HAL_RCC_GET_DSI_SOURCE() == RCC_DSICLKSOURCE_DSIPHY); + + return 0; +} +#endif + static void mipi_dsi_stm32_log_config(const struct device *dev) { const struct mipi_dsi_stm32_config *config = dev->config; @@ -66,9 +88,20 @@ static void mipi_dsi_stm32_log_config(const struct device *dev) LOG_DBG(" AutomaticClockLaneControl 0x%x", data->hdsi.Init.AutomaticClockLaneControl); LOG_DBG(" TXEscapeCkdiv %u", data->hdsi.Init.TXEscapeCkdiv); LOG_DBG(" NumberOfLanes %u", data->hdsi.Init.NumberOfLanes); +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32u5_mipi_dsi) + LOG_DBG(" PHYFrequencyRange 0x%x", data->hdsi.Init.PHYFrequencyRange); + LOG_DBG(" PHYLowPowerOffset 0x%x", data->hdsi.Init.PHYLowPowerOffset); +#endif + + LOG_DBG("PLLInit configuration:"); LOG_DBG(" PLLNDIV %u", data->pll_init.PLLNDIV); LOG_DBG(" PLLIDF %u", data->pll_init.PLLIDF); LOG_DBG(" PLLODF %u", data->pll_init.PLLODF); +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32u5_mipi_dsi) + LOG_DBG(" PLLVCORange 0x%x", data->pll_init.PLLVCORange); + LOG_DBG(" PLLChargePump 0x%x", data->pll_init.PLLChargePump); + LOG_DBG(" PLLTuning 0x%x", data->pll_init.PLLTuning); +#endif LOG_DBG("HAL_DSI_ConfigVideoMode setup:"); LOG_DBG(" VirtualChannelID %u", data->vid_cfg.VirtualChannelID); @@ -168,9 +201,15 @@ static int mipi_dsi_stm32_host_init(const struct device *dev) return ret; } +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32u5_mipi_dsi) + /* LANE_BYTE_CLOCK = CLK_IN / PLLIDF * 2 * PLLNDIV / PLLODF / 8 */ + data->lane_clk_khz = hse_clock / data->pll_init.PLLIDF * 2 * data->pll_init.PLLNDIV / + data->pll_init.PLLODF / 8 / 1000; +#else /* LANE_BYTE_CLOCK = CLK_IN / PLLIDF * 2 * PLLNDIV / 2 / PLLODF / 8 */ data->lane_clk_khz = hse_clock / data->pll_init.PLLIDF * 2 * data->pll_init.PLLNDIV / 2 / (1UL << data->pll_init.PLLODF) / 8 / 1000; +#endif /* stm32x_hal_dsi: The values 0 and 1 stop the TX_ESC clock generation */ data->hdsi.Init.TXEscapeCkdiv = 0; @@ -213,6 +252,8 @@ static int mipi_dsi_stm32_host_init(const struct device *dev) return -EIO; } +#ifndef CONFIG_SOC_SERIES_STM32U5X + if (config->lp_rx_filter_freq) { hal_ret = HAL_DSI_SetLowPowerRXFilter(&data->hdsi, config->lp_rx_filter_freq); if (hal_ret != HAL_OK) { @@ -220,6 +261,7 @@ static int mipi_dsi_stm32_host_init(const struct device *dev) return -EIO; } } +#endif hal_ret = HAL_DSI_ConfigErrorMonitor(&data->hdsi, config->active_errors); if (hal_ret != HAL_OK) { @@ -290,6 +332,14 @@ static int mipi_dsi_stm32_attach(const struct device *dev, uint8_t channel, return -EIO; } +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32u5_mipi_dsi) + ret = stm32_dsi_clock_source_config(dev); + if (ret < 0) { + LOG_ERR("Failed to configure DSI clock source"); + return ret; + } +#endif + if (IS_ENABLED(CONFIG_MIPI_DSI_LOG_LEVEL_DBG)) { mipi_dsi_stm32_log_config(dev); } @@ -458,6 +508,12 @@ static int mipi_dsi_stm32_init(const struct device *dev) .enr = DT_INST_CLOCKS_CELL_BY_NAME(inst, dsiclk, bits), \ .bus = DT_INST_CLOCKS_CELL_BY_NAME(inst, dsiclk, bus), \ }, \ + COND_CODE_1(DT_INST_CLOCKS_HAS_NAME(inst, dsisrc), \ + (.dsisrc_clk = { \ + .enr = DT_INST_CLOCKS_CELL_BY_NAME(inst, dsisrc, bits), \ + .bus = DT_INST_CLOCKS_CELL_BY_NAME(inst, dsisrc, bus), \ + },), \ + (.dsisrc_clk = {0},)) \ .ref_clk = { \ .enr = DT_INST_CLOCKS_CELL_BY_NAME(inst, refclk, bits), \ .bus = DT_INST_CLOCKS_CELL_BY_NAME(inst, refclk, bus), \ @@ -480,6 +536,13 @@ static int mipi_dsi_stm32_init(const struct device *dev) DT_INST_PROP(inst, non_continuous) ? \ DSI_AUTO_CLK_LANE_CTRL_ENABLE : \ DSI_AUTO_CLK_LANE_CTRL_DISABLE, \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, phy_freq_range), \ + (.PHYFrequencyRange = DT_INST_PROP(inst, phy_freq_range),),\ + ()) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, phy_low_power_offset), \ + (.PHYLowPowerOffset = \ + DT_INST_PROP(inst, phy_low_power_offset),), \ + ()) \ }, \ }, \ .host_timeouts = COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, host_timeouts), \ @@ -495,15 +558,25 @@ static int mipi_dsi_stm32_init(const struct device *dev) DSI_DATA_ENABLE_ACTIVE_HIGH : DSI_DATA_ENABLE_ACTIVE_LOW, \ .LooselyPacked = DT_INST_PROP(inst, loosely_packed) ? \ DSI_LOOSELY_PACKED_ENABLE : DSI_LOOSELY_PACKED_DISABLE, \ - .LPLargestPacketSize = DT_INST_PROP_OR(inst, largest_packet_size, 4), \ + .LPLargestPacketSize = DT_INST_PROP_OR(inst, largest_packet_size, 4), \ .LPVACTLargestPacketSize = DT_INST_PROP_OR(inst, largest_packet_size, 4), \ .FrameBTAAcknowledgeEnable = DT_INST_PROP(inst, bta_ack_disable) ? \ - DSI_FBTAA_DISABLE : DSI_FBTAA_ENABLE, \ + DSI_FBTAA_DISABLE : DSI_FBTAA_ENABLE, \ }, \ .pll_init = { \ .PLLNDIV = DT_INST_PROP(inst, pll_ndiv), \ .PLLIDF = DT_INST_PROP(inst, pll_idf), \ .PLLODF = DT_INST_PROP(inst, pll_odf), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, pll_vco_range), \ + (.PLLVCORange = DT_INST_PROP(inst, pll_vco_range),), \ + ()) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, pll_charge_pump), \ + (.PLLChargePump = \ + DT_INST_PROP(inst, pll_charge_pump),), \ + ()) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, pll_tuning), \ + (.PLLTuning = DT_INST_PROP(inst, pll_tuning),), \ + ()) \ }, \ }; \ DEVICE_DT_INST_DEFINE(inst, &mipi_dsi_stm32_init, NULL, \ diff --git a/drivers/retained_mem/CMakeLists.txt b/drivers/retained_mem/CMakeLists.txt index 2724c12a7af1f..867833d8fe033 100644 --- a/drivers/retained_mem/CMakeLists.txt +++ b/drivers/retained_mem/CMakeLists.txt @@ -6,5 +6,6 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE retained_mem_handlers.c) zephyr_library_sources_ifdef(CONFIG_RETAINED_MEM_NRF_GPREGRET retained_mem_nrf_gpregret.c) zephyr_library_sources_ifdef(CONFIG_RETAINED_MEM_NRF_RAM_CTRL retained_mem_nrf_ram_ctrl.c) +zephyr_library_sources_ifdef(CONFIG_RETAINED_MEM_SILABS_BURAM retained_mem_silabs_buram.c) zephyr_library_sources_ifdef(CONFIG_RETAINED_MEM_ZEPHYR_RAM retained_mem_zephyr_ram.c) zephyr_library_sources_ifdef(CONFIG_RETAINED_MEM_ZEPHYR_REG retained_mem_zephyr_reg.c) diff --git a/drivers/retained_mem/Kconfig b/drivers/retained_mem/Kconfig index 4ea7dcd894928..c53367466dec5 100644 --- a/drivers/retained_mem/Kconfig +++ b/drivers/retained_mem/Kconfig @@ -35,6 +35,8 @@ source "subsys/logging/Kconfig.template.log_config" source "drivers/retained_mem/Kconfig.nrf" +source "drivers/retained_mem/Kconfig.silabs" + source "drivers/retained_mem/Kconfig.zephyr" endif # RETAINED_MEM diff --git a/drivers/retained_mem/Kconfig.silabs b/drivers/retained_mem/Kconfig.silabs new file mode 100644 index 0000000000000..bd2fc835bd352 --- /dev/null +++ b/drivers/retained_mem/Kconfig.silabs @@ -0,0 +1,9 @@ +# Copyright (c) 2025 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +config RETAINED_MEM_SILABS_BURAM + bool "Silicon Labs BURAM driver" + default y + depends on DT_HAS_SILABS_BURAM_ENABLED + help + Enable driver for Silicon Labs BURAM-based retained memory register support. diff --git a/drivers/retained_mem/retained_mem_silabs_buram.c b/drivers/retained_mem/retained_mem_silabs_buram.c new file mode 100644 index 0000000000000..9f9b4ed4662b4 --- /dev/null +++ b/drivers/retained_mem/retained_mem_silabs_buram.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2023, Nordic Semiconductor ASA + * Copyright (c) 2023, Bjarki Arge Andreasen + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT silabs_buram + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(retained_mem_silabs_buram, CONFIG_RETAINED_MEM_LOG_LEVEL); + +struct silabs_buram_data { +#ifdef CONFIG_RETAINED_MEM_MUTEXES + struct k_mutex lock; +#endif +}; + +struct silabs_buram_config { + uint8_t *address; + size_t size; + const struct device *clock_dev; + const struct silabs_clock_control_cmu_config clock_cfg; +}; + +static inline void silabs_buram_lock_take(const struct device *dev) +{ +#ifdef CONFIG_RETAINED_MEM_MUTEXES + struct silabs_buram_data *data = dev->data; + + k_mutex_lock(&data->lock, K_FOREVER); +#else + ARG_UNUSED(dev); +#endif +} + +static inline void silabs_buram_lock_release(const struct device *dev) +{ +#ifdef CONFIG_RETAINED_MEM_MUTEXES + struct silabs_buram_data *data = dev->data; + + k_mutex_unlock(&data->lock); +#else + ARG_UNUSED(dev); +#endif +} + +static int silabs_buram_init(const struct device *dev) +{ + const struct silabs_buram_config *config = dev->config; + int err; + +#ifdef CONFIG_RETAINED_MEM_MUTEXES + struct silabs_buram_data *data = dev->data; + + k_mutex_init(&data->lock); +#endif + + if (!config->clock_dev) { + /* BURAM is automatically clocked */ + return 0; + } + + err = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->clock_cfg); + if (err < 0 && err != -EALREADY) { + return err; + } + + return 0; +} + +static ssize_t silabs_buram_size(const struct device *dev) +{ + const struct silabs_buram_config *config = dev->config; + + return (ssize_t)config->size; +} + +static int silabs_buram_read(const struct device *dev, off_t offset, uint8_t *buffer, size_t size) +{ + const struct silabs_buram_config *config = dev->config; + + silabs_buram_lock_take(dev); + + memcpy(buffer, (config->address + offset), size); + + silabs_buram_lock_release(dev); + + return 0; +} + +static int silabs_buram_write(const struct device *dev, off_t offset, const uint8_t *buffer, + size_t size) +{ + const struct silabs_buram_config *config = dev->config; + + silabs_buram_lock_take(dev); + + memcpy((config->address + offset), buffer, size); + + silabs_buram_lock_release(dev); + + return 0; +} + +static int silabs_buram_clear(const struct device *dev) +{ + const struct silabs_buram_config *config = dev->config; + + silabs_buram_lock_take(dev); + + memset(config->address, 0, config->size); + + silabs_buram_lock_release(dev); + + return 0; +} + +static DEVICE_API(retained_mem, silabs_buram_api) = { + .size = silabs_buram_size, + .read = silabs_buram_read, + .write = silabs_buram_write, + .clear = silabs_buram_clear, +}; + +#define SILABS_BURAM_DEVICE(inst) \ + static struct silabs_buram_data silabs_buram_data_##inst; \ + static const struct silabs_buram_config silabs_buram_config_##inst = { \ + .address = (uint8_t *)DT_INST_REG_ADDR(inst), \ + .size = DT_INST_REG_SIZE(inst), \ + .clock_dev = COND_CODE_1(DT_INST_CLOCKS_HAS_IDX(inst, 0), \ + (DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst))), \ + (NULL)), \ + .clock_cfg = COND_CODE_1(DT_INST_CLOCKS_HAS_IDX(inst, 0), \ + (SILABS_DT_INST_CLOCK_CFG(inst)), \ + ({0})), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, &silabs_buram_init, NULL, &silabs_buram_data_##inst, \ + &silabs_buram_config_##inst, POST_KERNEL, \ + CONFIG_RETAINED_MEM_INIT_PRIORITY, &silabs_buram_api); + +DT_INST_FOREACH_STATUS_OKAY(SILABS_BURAM_DEVICE) diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 45d74897cfd1e..7ec22bb4cf29d 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -39,6 +39,7 @@ add_subdirectory(wsen) # zephyr-keep-sorted-stop add_subdirectory_ifdef(CONFIG_A01NYUB a01nyub) +add_subdirectory_ifdef(CONFIG_ALS31300 als31300) add_subdirectory_ifdef(CONFIG_AMD_SB_TSI amd_sb_tsi) add_subdirectory_ifdef(CONFIG_AMG88XX amg88xx) add_subdirectory_ifdef(CONFIG_APDS9253 apds9253) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index c3e56e29f981a..0db1debff4d16 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -88,6 +88,7 @@ comment "Device Drivers" # zephyr-keep-sorted-start source "drivers/sensor/adi/Kconfig" +source "drivers/sensor/als31300/Kconfig" source "drivers/sensor/ams/Kconfig" source "drivers/sensor/aosong/Kconfig" source "drivers/sensor/asahi_kasei/Kconfig" diff --git a/drivers/sensor/als31300/CMakeLists.txt b/drivers/sensor/als31300/CMakeLists.txt new file mode 100644 index 0000000000000..a87e1a88cef6a --- /dev/null +++ b/drivers/sensor/als31300/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2025 Croxel +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(als31300.c) +zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API als31300_async.c als31300_decoder.c) diff --git a/drivers/sensor/als31300/Kconfig b/drivers/sensor/als31300/Kconfig new file mode 100644 index 0000000000000..7475fcf64348d --- /dev/null +++ b/drivers/sensor/als31300/Kconfig @@ -0,0 +1,14 @@ +# Copyright (c) 2025 Croxel +# SPDX-License-Identifier: Apache-2.0 + +# ALS31300 3D Linear Hall-Effect Sensor configuration options + +config ALS31300 + bool "ALS31300 3D Linear Hall-Effect Sensor" + default y + depends on DT_HAS_ALLEGRO_ALS31300_ENABLED + select I2C + help + Enable driver for ALS31300 3D Linear Hall-Effect Sensor. + This sensor provides 12-bit magnetic field measurements + on X, Y, and Z axes via I2C interface. diff --git a/drivers/sensor/als31300/als31300.c b/drivers/sensor/als31300/als31300.c new file mode 100644 index 0000000000000..47dbeafa10250 --- /dev/null +++ b/drivers/sensor/als31300/als31300.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2025 Croxel + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT allegro_als31300 + +#include "als31300.h" + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(als31300, CONFIG_SENSOR_LOG_LEVEL); + +/** + * @brief Convert 12-bit two's complement value to signed 16-bit + * @param value 12-bit value to convert (bits 11:0) + * @return Signed 16-bit value + */ +int16_t als31300_convert_12bit_to_signed(uint16_t value) +{ + return (int16_t)sign_extend(value, ALS31300_12BIT_SIGN_BIT_INDEX); +} + +/** + * @brief Parse raw register data from 8-byte buffer + * @param buf 8-byte buffer containing register 0x28 and 0x29 data + * @param readings Pointer to readings structure to store parsed data + */ +void als31300_parse_registers(const uint8_t *buf, struct als31300_readings *readings) +{ + uint32_t reg28_data, reg29_data; + uint16_t x_msb, y_msb, z_msb; + uint8_t x_lsb, y_lsb, z_lsb; + uint8_t temp_msb, temp_lsb; + + /* Convert 8 bytes to two 32-bit values (MSB first) */ + reg28_data = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | + ((uint32_t)buf[3]); + reg29_data = ((uint32_t)buf[4] << 24) | ((uint32_t)buf[5] << 16) | ((uint32_t)buf[6] << 8) | + ((uint32_t)buf[7]); + + /* Extract fields from register 0x28 */ + temp_msb = (reg28_data & ALS31300_REG28_TEMP_MSB_MASK) >> ALS31300_REG28_TEMP_MSB_SHIFT; + z_msb = (reg28_data & ALS31300_REG28_Z_AXIS_MSB_MASK) >> ALS31300_REG28_Z_AXIS_MSB_SHIFT; + y_msb = (reg28_data & ALS31300_REG28_Y_AXIS_MSB_MASK) >> ALS31300_REG28_Y_AXIS_MSB_SHIFT; + x_msb = (reg28_data & ALS31300_REG28_X_AXIS_MSB_MASK) >> ALS31300_REG28_X_AXIS_MSB_SHIFT; + + /* Extract fields from register 0x29 */ + temp_lsb = (reg29_data & ALS31300_REG29_TEMP_LSB_MASK) >> ALS31300_REG29_TEMP_LSB_SHIFT; + z_lsb = (reg29_data & ALS31300_REG29_Z_AXIS_LSB_MASK) >> ALS31300_REG29_Z_AXIS_LSB_SHIFT; + y_lsb = (reg29_data & ALS31300_REG29_Y_AXIS_LSB_MASK) >> ALS31300_REG29_Y_AXIS_LSB_SHIFT; + x_lsb = (reg29_data & ALS31300_REG29_X_AXIS_LSB_MASK) >> ALS31300_REG29_X_AXIS_LSB_SHIFT; + + /* Combine MSB and LSB to form 12-bit values */ + const uint16_t x_raw = (x_msb << 4) | x_lsb; + const uint16_t y_raw = (y_msb << 4) | y_lsb; + const uint16_t z_raw = (z_msb << 4) | z_lsb; + const uint16_t temp_raw = (temp_msb << 6) | temp_lsb; + + /* Convert to signed values (proper 12-bit two's complement) */ + readings->x = als31300_convert_12bit_to_signed(x_raw); + readings->y = als31300_convert_12bit_to_signed(y_raw); + readings->z = als31300_convert_12bit_to_signed(z_raw); + readings->temp = temp_raw; +} + +/** + * @brief Convert raw magnetic field value to microgauss + * This function converts the 12-bit signed raw magnetic field value to + * microgauss units + * Formula: microgauss = (raw_value * 500 * 1000000) / 4096 + * @param raw_value Signed 12-bit magnetic field value + * @return Magnetic field in microgauss + */ +int32_t als31300_convert_to_gauss(int16_t raw_value) +{ + /* Convert to microgauss + * For 500G full scale: (raw_value * 500 * 1000000) / 4096 + * This gives us the fractional part in microgauss + */ + return ((int64_t)raw_value * ALS31300_FULL_SCALE_RANGE_GAUSS * 1000000) / + ALS31300_12BIT_RESOLUTION; +} + +/** + * @brief Convert raw temperature value to celsius + * Based on datasheet formula: T(°C) = 302 * (raw_temp - 1708) / 4096 + * @param raw_temp 12-bit raw temperature value + * @return Temperature in microcelsius + */ +int32_t als31300_convert_temperature(uint16_t raw_temp) +{ + /* Convert to microcelsius + * Formula: microcelsius = (302 * (raw_temp - 1708) * 1000000) / 4096 + */ + return ((int64_t)ALS31300_TEMP_SCALE_FACTOR * ((int32_t)raw_temp - ALS31300_TEMP_OFFSET) * + 1000000) / + ALS31300_TEMP_DIVISOR; +} + +/** + * @brief Read and parse sensor data from ALS31300 + * This function performs an 8-byte I2C burst read from registers 0x28 and 0x29 + * to get magnetic field and temperature data. The data is parsed according to + * the datasheet bit field layout and stored in the provided readings structure. + * @param dev Pointer to the device structure + * @param readings Pointer to readings structure to store data + * @return 0 on success, negative error code on failure + */ +static int als31300_read_sensor_data(const struct device *dev, enum sensor_channel chan, + struct als31300_readings *readings) +{ + const struct als31300_config *cfg = dev->config; + struct als31300_data *data = dev->data; + uint8_t buf[8]; + int ret; + + /* Read both data registers in a single 8-byte transaction for consistency */ + ret = i2c_burst_read_dt(&cfg->i2c, ALS31300_REG_DATA_28, buf, sizeof(buf)); + if (ret < 0) { + LOG_ERR("Failed to read sensor data: %d", ret); + return ret; + } + + /* Parse the register data using common helper */ + als31300_parse_registers(buf, readings); + + /* Also update local data structure for compatibility */ + data->x_raw = readings->x; + data->y_raw = readings->y; + data->z_raw = readings->z; + data->temp_raw = readings->temp; + + return 0; +} + +static int als31300_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct als31300_readings readings; + + return als31300_read_sensor_data(dev, chan, &readings); +} + +static int als31300_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct als31300_data *data = dev->data; + int32_t raw_val; + int32_t converted_val; + + switch (chan) { + case SENSOR_CHAN_MAGN_X: + raw_val = data->x_raw; + break; + case SENSOR_CHAN_MAGN_Y: + raw_val = data->y_raw; + break; + case SENSOR_CHAN_MAGN_Z: + raw_val = data->z_raw; + break; + case SENSOR_CHAN_AMBIENT_TEMP: + /* Temperature conversion */ + converted_val = als31300_convert_temperature(data->temp_raw); + sensor_value_from_micro(val, converted_val); + return 0; + default: + return -ENOTSUP; + } + + /* Convert raw magnetic data to gauss */ + converted_val = als31300_convert_to_gauss(raw_val); + sensor_value_from_micro(val, converted_val); + + return 0; +} + +static DEVICE_API(sensor, als31300_api) = { + .sample_fetch = als31300_sample_fetch, + .channel_get = als31300_channel_get, +#ifdef CONFIG_SENSOR_ASYNC_API + .submit = als31300_submit, + .get_decoder = als31300_get_decoder, +#endif +}; + +/** + * @brief Configure ALS31300 to Active Mode + * This function sets the device to Active Mode by writing to the volatile + * register 0x27. This register can be written without customer access mode. + * @param dev Pointer to the device structure + * @return 0 on success, negative error code on failure + */ +static int als31300_configure_device(const struct device *dev) +{ + const struct als31300_config *cfg = dev->config; + uint32_t reg27_value = 0x00000000; /* All bits to 0 = Active Mode */ + int ret; + + LOG_INF("Configuring ALS31300 to Active Mode..."); + + /* Write 0x00000000 to register 0x27 to set Active Mode + * Bits [1:0] = 0 → Active Mode + * Bits [3:2] = 0 → Single read mode (default I2C mode) + * Bits [6:4] = 0 → Low-power count = 0.5ms (doesn't matter in Active Mode) + * Bits [31:7] = 0 → Reserved (should be 0) + */ + ret = i2c_burst_write_dt(&cfg->i2c, ALS31300_REG_VOLATILE_27, (uint8_t *)®27_value, + sizeof(reg27_value)); + if (ret < 0) { + LOG_ERR("Failed to write to register 0x27: %d", ret); + return ret; + } + + return 0; +} + +/** + * @brief Initialize ALS31300 device + */ +static int als31300_init(const struct device *dev) +{ + const struct als31300_config *cfg = dev->config; + int ret; + + if (!i2c_is_ready_dt(&cfg->i2c)) { + LOG_ERR("I2C device not ready"); + return -ENODEV; + } + + /* Wait for power-on delay as specified in datasheet */ + k_usleep(ALS31300_POWER_ON_DELAY_US); + + /* Test communication by reading a register (can be done without customer access) */ + uint8_t test_val; + + ret = i2c_reg_read_byte_dt(&cfg->i2c, ALS31300_REG_VOLATILE_27, &test_val); + if (ret < 0) { + LOG_ERR("Failed to communicate with sensor: %d", ret); + return ret; + } + + /* Configure device to Active Mode */ + ret = als31300_configure_device(dev); + if (ret < 0) { + LOG_ERR("Failed to configure device: %d", ret); + return ret; + } + + /* Wait a bit more for the sensor to be fully ready in Active Mode */ + k_msleep(ALS31300_REG_WRITE_DELAY_MS); + + return 0; +} + +#define ALS31300_INIT(inst) \ + RTIO_DEFINE(als31300_rtio_ctx_##inst, 16, 16); \ + I2C_DT_IODEV_DEFINE(als31300_bus_##inst, DT_DRV_INST(inst)); \ + \ + static struct als31300_data als31300_data_##inst; \ + \ + static const struct als31300_config als31300_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + .bus = \ + { \ + .ctx = &als31300_rtio_ctx_##inst, \ + .iodev = &als31300_bus_##inst, \ + }, \ + }; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, als31300_init, NULL, &als31300_data_##inst, \ + &als31300_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &als31300_api) + +DT_INST_FOREACH_STATUS_OKAY(ALS31300_INIT); diff --git a/drivers/sensor/als31300/als31300.h b/drivers/sensor/als31300/als31300.h new file mode 100644 index 0000000000000..cca8d5ae05240 --- /dev/null +++ b/drivers/sensor/als31300/als31300.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2025 Croxel + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_ALS31300_H_ +#define ZEPHYR_DRIVERS_SENSOR_ALS31300_H_ + +#include +#include +#include +#include + +/* ALS31300 Register Definitions */ +#define ALS31300_REG_EEPROM_02 0x02 +#define ALS31300_REG_EEPROM_03 0x03 +#define ALS31300_REG_VOLATILE_27 0x27 +#define ALS31300_REG_DATA_28 0x28 +#define ALS31300_REG_DATA_29 0x29 + +/* Customer Access Code */ +#define ALS31300_ACCESS_ADDR 0x35 +#define ALS31300_ACCESS_CODE 0x2C413534 + +/* Register 0x02 bit definitions */ +#define ALS31300_BW_SELECT_MASK GENMASK(23, 21) +#define ALS31300_BW_SELECT_SHIFT 21 +#define ALS31300_HALL_MODE_MASK GENMASK(20, 19) +#define ALS31300_HALL_MODE_SHIFT 19 +#define ALS31300_CHAN_Z_EN BIT(8) +#define ALS31300_CHAN_Y_EN BIT(7) +#define ALS31300_CHAN_X_EN BIT(6) + +/* Register 0x27 bit definitions */ +#define ALS31300_SLEEP_MASK GENMASK(1, 0) +#define ALS31300_SLEEP_ACTIVE 0 +#define ALS31300_SLEEP_MODE 1 +#define ALS31300_SLEEP_LPDCM 2 + +/* Register 0x28 bit fields */ +#define ALS31300_REG28_TEMP_MSB_MASK GENMASK(5, 0) /* Bits 5:0 */ +#define ALS31300_REG28_TEMP_MSB_SHIFT 0 + +#define ALS31300_REG28_INTERRUPT_MASK GENMASK(6, 6) /* Bit 6 */ +#define ALS31300_REG28_INTERRUPT_SHIFT 6 + +#define ALS31300_REG28_NEW_DATA_MASK GENMASK(7, 7) /* Bit 7 */ +#define ALS31300_REG28_NEW_DATA_SHIFT 7 + +#define ALS31300_REG28_Z_AXIS_MSB_MASK GENMASK(15, 8) /* Bits 15:8 */ +#define ALS31300_REG28_Z_AXIS_MSB_SHIFT 8 + +#define ALS31300_REG28_Y_AXIS_MSB_MASK GENMASK(23, 16) /* Bits 23:16 */ +#define ALS31300_REG28_Y_AXIS_MSB_SHIFT 16 + +#define ALS31300_REG28_X_AXIS_MSB_MASK GENMASK(31, 24) /* Bits 31:24 */ +#define ALS31300_REG28_X_AXIS_MSB_SHIFT 24 + +/* Register 0x29 bit fields */ +#define ALS31300_REG29_TEMP_LSB_MASK GENMASK(5, 0) /* Bits 5:0 */ +#define ALS31300_REG29_TEMP_LSB_SHIFT 0 + +#define ALS31300_REG29_HALL_MODE_STATUS_MASK GENMASK(7, 6) /* Bits 7:6 */ +#define ALS31300_REG29_HALL_MODE_STATUS_SHIFT 6 + +#define ALS31300_REG29_Z_AXIS_LSB_MASK GENMASK(11, 8) /* Bits 11:8 */ +#define ALS31300_REG29_Z_AXIS_LSB_SHIFT 8 + +#define ALS31300_REG29_Y_AXIS_LSB_MASK GENMASK(15, 12) /* Bits 15:12 */ +#define ALS31300_REG29_Y_AXIS_LSB_SHIFT 12 + +#define ALS31300_REG29_X_AXIS_LSB_MASK GENMASK(19, 16) /* Bits 19:16 */ +#define ALS31300_REG29_X_AXIS_LSB_SHIFT 16 + +#define ALS31300_REG29_INTERRUPT_WRITE_MASK GENMASK(20, 20) /* Bit 20 */ +#define ALS31300_REG29_INTERRUPT_WRITE_SHIFT 20 + +#define ALS31300_REG29_RESERVED_MASK GENMASK(31, 21) /* Bits 31:21 */ +#define ALS31300_REG29_RESERVED_SHIFT 21 + +/* ALS31300 sensitivity and conversion constants */ +#define ALS31300_FULL_SCALE_RANGE_GAUSS 500 /* 500 gauss full scale */ +#define ALS31300_12BIT_RESOLUTION 4096 /* 2^12 for 12-bit resolution */ +#define ALS31300_12BIT_SIGN_BIT_INDEX 11 /* Sign bit position for 12-bit values (0-based) */ + +/* ALS31300 EEPROM Register 0x02 bit field definitions */ +#define ALS31300_EEPROM_CUSTOMER_EE_MASK GENMASK(4, 0) /* Bits 4:0 */ +#define ALS31300_EEPROM_CUSTOMER_EE_SHIFT 0 + +#define ALS31300_EEPROM_INT_LATCH_EN_MASK BIT(5) /* Bit 5 */ +#define ALS31300_EEPROM_INT_LATCH_EN_SHIFT 5 + +#define ALS31300_EEPROM_CHANNEL_X_EN_MASK BIT(6) /* Bit 6 */ +#define ALS31300_EEPROM_CHANNEL_X_EN_SHIFT 6 + +#define ALS31300_EEPROM_CHANNEL_Y_EN_MASK BIT(7) /* Bit 7 */ +#define ALS31300_EEPROM_CHANNEL_Y_EN_SHIFT 7 + +#define ALS31300_EEPROM_CHANNEL_Z_EN_MASK BIT(8) /* Bit 8 */ +#define ALS31300_EEPROM_CHANNEL_Z_EN_SHIFT 8 + +#define ALS31300_EEPROM_I2C_THRESHOLD_MASK BIT(9) /* Bit 9 */ +#define ALS31300_EEPROM_I2C_THRESHOLD_SHIFT 9 + +#define ALS31300_EEPROM_SLAVE_ADDR_MASK GENMASK(16, 10) /* Bits 16:10 */ +#define ALS31300_EEPROM_SLAVE_ADDR_SHIFT 10 + +#define ALS31300_EEPROM_DISABLE_SLAVE_ADC_MASK BIT(17) /* Bit 17 */ +#define ALS31300_EEPROM_DISABLE_SLAVE_ADC_SHIFT 17 + +#define ALS31300_EEPROM_I2C_CRC_EN_MASK BIT(18) /* Bit 18 */ +#define ALS31300_EEPROM_I2C_CRC_EN_SHIFT 18 + +#define ALS31300_EEPROM_HALL_MODE_MASK GENMASK(20, 19) /* Bits 20:19 */ +#define ALS31300_EEPROM_HALL_MODE_SHIFT 19 + +#define ALS31300_EEPROM_BW_SELECT_MASK GENMASK(23, 21) /* Bits 23:21 */ +#define ALS31300_EEPROM_BW_SELECT_SHIFT 21 + +#define ALS31300_EEPROM_RESERVED_MASK GENMASK(31, 24) /* Bits 31:24 */ +#define ALS31300_EEPROM_RESERVED_SHIFT 24 + +/* Timing constants */ +#define ALS31300_POWER_ON_DELAY_US 600 +#define ALS31300_REG_WRITE_DELAY_MS 50 + +/* Fixed-point conversion constants */ +#define ALS31300_TEMP_SCALE_FACTOR 302 /* Temperature scale factor */ +#define ALS31300_TEMP_OFFSET 1708 /* Temperature offset */ +#define ALS31300_TEMP_DIVISOR 4096 /* Temperature divisor */ + +/* RTIO-specific constants */ +#define ALS31300_MAGN_SHIFT 16 /* Q31 shift for magnetic field values */ +#define ALS31300_TEMP_SHIFT 16 /* Q31 shift for temperature values */ + +/* Sensor readings structure */ +struct als31300_readings { + int16_t x; + int16_t y; + int16_t z; + uint16_t temp; +}; + +/* Bus abstraction structure */ +struct als31300_bus { + struct rtio *ctx; + struct rtio_iodev *iodev; +}; + +/* RTIO encoded data structures */ +struct als31300_encoded_header { + uint8_t channels; + uint8_t reserved[3]; + uint64_t timestamp; +} __attribute__((__packed__)); + +struct als31300_encoded_data { + struct als31300_encoded_header header; + uint8_t payload[8]; /* Raw I2C data from registers 0x28-0x29 */ +} __attribute__((__packed__)); + +/* Forward declarations for structures used in multiple files */ +struct als31300_data { + int16_t x_raw; + int16_t y_raw; + int16_t z_raw; + int16_t temp_raw; +}; + +struct als31300_config { + struct i2c_dt_spec i2c; + struct als31300_bus bus; +}; + +/* Common helper functions shared between sync and async implementations */ +int16_t als31300_convert_12bit_to_signed(uint16_t value); +void als31300_parse_registers(const uint8_t *buf, struct als31300_readings *readings); +int32_t als31300_convert_to_gauss(int16_t raw_value); +int32_t als31300_convert_temperature(uint16_t raw_temp); + +#ifdef CONFIG_SENSOR_ASYNC_API +#include + +struct rtio_sqe; +struct rtio_iodev_sqe; +struct sensor_read_config; +struct sensor_decoder_api; + +/* Async I2C helper function */ +int als31300_prep_i2c_read_async(const struct als31300_config *cfg, uint8_t reg, uint8_t *buf, + size_t size, struct rtio_sqe **out); + +/* Encode function for async API */ +int als31300_encode(const struct device *dev, const struct sensor_read_config *read_config, + uint8_t trigger_status, uint8_t *buf); + +/* Async API functions */ +void als31300_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); +int als31300_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder); +#endif + +#endif /* ZEPHYR_DRIVERS_SENSOR_ALS31300_H_ */ diff --git a/drivers/sensor/als31300/als31300_async.c b/drivers/sensor/als31300/als31300_async.c new file mode 100644 index 0000000000000..0e6285f0098d7 --- /dev/null +++ b/drivers/sensor/als31300/als31300_async.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2025 Croxel + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "als31300.h" + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(als31300, CONFIG_SENSOR_LOG_LEVEL); + +/** + * @brief Encode channel flags for the given sensor channel + */ +static uint8_t als31300_encode_channel(enum sensor_channel chan) +{ + uint8_t encode_bmask = 0; + + switch (chan) { + case SENSOR_CHAN_MAGN_X: + encode_bmask |= BIT(0); + break; + case SENSOR_CHAN_MAGN_Y: + encode_bmask |= BIT(1); + break; + case SENSOR_CHAN_MAGN_Z: + encode_bmask |= BIT(2); + break; + case SENSOR_CHAN_MAGN_XYZ: + encode_bmask |= BIT(0) | BIT(1) | BIT(2); + break; + case SENSOR_CHAN_AMBIENT_TEMP: + encode_bmask |= BIT(3); + break; + case SENSOR_CHAN_ALL: + encode_bmask |= BIT(0) | BIT(1) | BIT(2) | BIT(3); + break; + default: + break; + } + + return encode_bmask; +} + +/** + * @brief Prepare async I2C read operation + */ +int als31300_prep_i2c_read_async(const struct als31300_config *cfg, uint8_t reg, uint8_t *buf, + size_t size, struct rtio_sqe **out) +{ + struct rtio *ctx = cfg->bus.ctx; + struct rtio_iodev *iodev = cfg->bus.iodev; + struct rtio_sqe *write_reg_sqe = rtio_sqe_acquire(ctx); + struct rtio_sqe *read_buf_sqe = rtio_sqe_acquire(ctx); + + if (!write_reg_sqe || !read_buf_sqe) { + rtio_sqe_drop_all(ctx); + return -ENOMEM; + } + + rtio_sqe_prep_tiny_write(write_reg_sqe, iodev, RTIO_PRIO_NORM, ®, 1, NULL); + write_reg_sqe->flags |= RTIO_SQE_TRANSACTION; + + rtio_sqe_prep_read(read_buf_sqe, iodev, RTIO_PRIO_NORM, buf, size, NULL); + read_buf_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; + + if (out) { + *out = read_buf_sqe; + } + + return 0; +} + +/** + * @brief Completion callback for async operations + */ +static void als31300_complete_result(struct rtio *ctx, const struct rtio_sqe *sqe, int result, + void *arg) +{ + ARG_UNUSED(result); + struct rtio_iodev_sqe *iodev_sqe = (struct rtio_iodev_sqe *)sqe->userdata; + struct rtio_cqe *cqe; + int err = 0; + + do { + cqe = rtio_cqe_consume(ctx); + if (cqe != NULL) { + err = cqe->result; + rtio_cqe_release(ctx, cqe); + } + } while (cqe != NULL); + + if (err != 0) { + rtio_iodev_sqe_err(iodev_sqe, err); + } else { + rtio_iodev_sqe_ok(iodev_sqe, 0); + } +} + +/** + * @brief Encode sensor metadata for async API + */ +int als31300_encode(const struct device *dev, const struct sensor_read_config *read_config, + uint8_t trigger_status, uint8_t *buf) +{ + struct als31300_encoded_data *edata = (struct als31300_encoded_data *)buf; + uint64_t cycles; + int err; + + ARG_UNUSED(dev); + + edata->header.channels = 0; + + if (trigger_status) { + /* For triggers, encode all channels */ + edata->header.channels |= als31300_encode_channel(SENSOR_CHAN_ALL); + } else { + /* For normal reads, encode requested channels */ + const struct sensor_chan_spec *const channels = read_config->channels; + size_t num_channels = read_config->count; + + for (size_t i = 0; i < num_channels; i++) { + edata->header.channels |= als31300_encode_channel(channels[i].chan_type); + } + } + + /* Get timestamp */ + err = sensor_clock_get_cycles(&cycles); + if (err != 0) { + return err; + } + + edata->header.timestamp = sensor_clock_cycles_to_ns(cycles); + + return 0; +} + +/** + * @brief RTIO submit function using chained SQE approach + */ +static void als31300_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +{ + const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; + uint32_t min_buf_len = sizeof(struct als31300_encoded_data); + int err; + uint8_t *buf; + uint32_t buf_len; + struct als31300_encoded_data *edata; + const struct als31300_config *conf = dev->config; + + err = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len); + if (err < 0 || buf_len < min_buf_len || !buf) { + LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); + rtio_iodev_sqe_err(iodev_sqe, err); + return; + } + + edata = (struct als31300_encoded_data *)buf; + + err = als31300_encode(dev, cfg, 0, buf); + if (err != 0) { + LOG_ERR("Failed to encode sensor data"); + rtio_iodev_sqe_err(iodev_sqe, err); + return; + } + + struct rtio_sqe *read_sqe; + + err = als31300_prep_i2c_read_async(conf, ALS31300_REG_DATA_28, edata->payload, + sizeof(edata->payload), &read_sqe); + if (err < 0) { + LOG_ERR("Failed to prepare async read operation"); + rtio_iodev_sqe_err(iodev_sqe, err); + return; + } + read_sqe->flags |= RTIO_SQE_CHAINED; + + struct rtio_sqe *complete_sqe = rtio_sqe_acquire(conf->bus.ctx); + + if (!complete_sqe) { + LOG_ERR("Failed to acquire completion SQE"); + rtio_iodev_sqe_err(iodev_sqe, -ENOMEM); + rtio_sqe_drop_all(conf->bus.ctx); + return; + } + + rtio_sqe_prep_callback_no_cqe(complete_sqe, &als31300_complete_result, (void *)dev, + iodev_sqe); + + rtio_submit(conf->bus.ctx, 0); +} + +/** + * @brief RTIO submit function + */ +void als31300_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +{ + als31300_submit_one_shot(dev, iodev_sqe); +} diff --git a/drivers/sensor/als31300/als31300_decoder.c b/drivers/sensor/als31300/als31300_decoder.c new file mode 100644 index 0000000000000..1ac18fa0ac14a --- /dev/null +++ b/drivers/sensor/als31300/als31300_decoder.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2025 Croxel + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "als31300.h" + +#include +#include +#include +#include + +LOG_MODULE_DECLARE(als31300, CONFIG_SENSOR_LOG_LEVEL); + +/** + * @brief Encode channel flags for the given sensor channel + */ +static uint8_t als31300_encode_channel(enum sensor_channel chan) +{ + uint8_t encode_bmask = 0; + + switch (chan) { + case SENSOR_CHAN_MAGN_X: + encode_bmask |= BIT(0); + break; + case SENSOR_CHAN_MAGN_Y: + encode_bmask |= BIT(1); + break; + case SENSOR_CHAN_MAGN_Z: + encode_bmask |= BIT(2); + break; + case SENSOR_CHAN_MAGN_XYZ: + encode_bmask |= BIT(0) | BIT(1) | BIT(2); + break; + case SENSOR_CHAN_AMBIENT_TEMP: + encode_bmask |= BIT(3); + break; + case SENSOR_CHAN_ALL: + encode_bmask |= BIT(0) | BIT(1) | BIT(2) | BIT(3); + break; + default: + break; + } + + return encode_bmask; +} + +/** + * @brief Convert raw magnetic field value to Q31 format + * @param raw_value Signed 12-bit magnetic field value + * @param q31_out Pointer to store Q31 value + */ +static void als31300_convert_raw_to_q31_magn(int16_t raw_value, q31_t *q31_out) +{ + /* Convert to microgauss using integer arithmetic */ + int32_t microgauss = als31300_convert_to_gauss(raw_value); + + /* Convert to Q31 format: Q31 = (value * 2^shift) / 1000000 + * For magnetic field, we use shift=16, so the full scale is ±2^(31-16) = ±32768 gauss + * This gives us good resolution for the ±500G range of the ALS31300 + * microgauss * 2^16 / 1000000 = microgauss * 65536 / 1000000 + */ + *q31_out = (q31_t)(((int64_t)microgauss << ALS31300_MAGN_SHIFT) / 1000000); +} + +/** + * @brief Convert raw temperature value to Q31 format + * @param raw_temp 12-bit raw temperature value + * @param q31_out Pointer to store Q31 value + */ +static void als31300_convert_temp_to_q31(uint16_t raw_temp, q31_t *q31_out) +{ + /* Convert to microcelsius using integer arithmetic */ + int32_t microcelsius = als31300_convert_temperature(raw_temp); + + /* Convert to Q31 format: Q31 = (value * 2^shift) / 1000000 + * For temperature, we use shift=16, so the full scale is ±2^(31-16) = ±32768°C + * This gives us good resolution for typical temperature ranges (-40°C to +125°C) + * microcelsius * 2^16 / 1000000 = microcelsius * 65536 / 1000000 + */ + *q31_out = (q31_t)(((int64_t)microcelsius << ALS31300_TEMP_SHIFT) / 1000000); +} + +/** + * @brief Get frame count for decoder + */ +static int als31300_decoder_get_frame_count(const uint8_t *buffer, + struct sensor_chan_spec chan_spec, + uint16_t *frame_count) +{ + const struct als31300_encoded_data *edata = (const struct als31300_encoded_data *)buffer; + + if (chan_spec.chan_idx != 0) { + return -ENOTSUP; + } + + uint8_t channel_request = als31300_encode_channel(chan_spec.chan_type); + + /* Filter unknown channels and having no data */ + if ((edata->header.channels & channel_request) != channel_request) { + return -ENODATA; + } + + *frame_count = 1; + return 0; +} + +/** + * @brief Get size info for decoder + */ +static int als31300_decoder_get_size_info(struct sensor_chan_spec chan_spec, size_t *base_size, + size_t *frame_size) +{ + switch (chan_spec.chan_type) { + case SENSOR_CHAN_MAGN_X: + case SENSOR_CHAN_MAGN_Y: + case SENSOR_CHAN_MAGN_Z: + case SENSOR_CHAN_MAGN_XYZ: + *base_size = sizeof(struct sensor_three_axis_data); + *frame_size = sizeof(struct sensor_three_axis_sample_data); + return 0; + case SENSOR_CHAN_AMBIENT_TEMP: + *base_size = sizeof(struct sensor_q31_data); + *frame_size = sizeof(struct sensor_q31_sample_data); + return 0; + default: + return -ENOTSUP; + } +} + +/** + * @brief Decode function for RTIO + */ +static int als31300_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, + uint32_t *fit, uint16_t max_count, void *data_out) +{ + const struct als31300_encoded_data *edata = (const struct als31300_encoded_data *)buffer; + + if (*fit != 0) { + return 0; + } + + /* Parse raw payload data using common helper */ + struct als31300_readings readings; + + als31300_parse_registers(edata->payload, &readings); + + switch (chan_spec.chan_type) { + case SENSOR_CHAN_MAGN_X: + case SENSOR_CHAN_MAGN_Y: + case SENSOR_CHAN_MAGN_Z: + case SENSOR_CHAN_MAGN_XYZ: { + struct sensor_three_axis_data *out = data_out; + + out->header.base_timestamp_ns = edata->header.timestamp; + out->header.reading_count = 1; + out->shift = ALS31300_MAGN_SHIFT; + + /* Convert raw readings to Q31 format */ + als31300_convert_raw_to_q31_magn(readings.x, &out->readings[0].x); + als31300_convert_raw_to_q31_magn(readings.y, &out->readings[0].y); + als31300_convert_raw_to_q31_magn(readings.z, &out->readings[0].z); + *fit = 1; + return 1; + } + case SENSOR_CHAN_AMBIENT_TEMP: { + struct sensor_q31_data *out = data_out; + + out->header.base_timestamp_ns = edata->header.timestamp; + out->header.reading_count = 1; + out->shift = ALS31300_TEMP_SHIFT; + + als31300_convert_temp_to_q31(readings.temp, &out->readings[0].temperature); + *fit = 1; + return 1; + } + default: + return -ENOTSUP; + } +} + +SENSOR_DECODER_API_DT_DEFINE() = { + .get_frame_count = als31300_decoder_get_frame_count, + .get_size_info = als31300_decoder_get_size_info, + .decode = als31300_decoder_decode, +}; + +int als31300_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder) +{ + ARG_UNUSED(dev); + *decoder = &SENSOR_DECODER_NAME(); + return 0; +} diff --git a/drivers/sensor/apds9306/apds9306.c b/drivers/sensor/apds9306/apds9306.c index be685a6cfc64c..73bddedb391bb 100644 --- a/drivers/sensor/apds9306/apds9306.c +++ b/drivers/sensor/apds9306/apds9306.c @@ -1,5 +1,7 @@ -/* Copyright (c) 2024 Daniel Kampert - * Author: Daniel Kampert +/* + * Copyright (c) 2024 Daniel Kampert + * + * SPDX-License-Identifier: Apache-2.0 */ #include @@ -128,7 +130,7 @@ static void apds9306_worker(struct k_work *p_work) } reg = APDS9306_REGISTER_ALS_DATA_0; - if (i2c_write_read_dt(&config->i2c, ®, sizeof(reg), &buffer, sizeof(buffer)) < 0) { + if (i2c_write_read_dt(&config->i2c, ®, sizeof(reg), buffer, sizeof(buffer)) < 0) { return; } @@ -237,10 +239,13 @@ static int apds9306_attr_get(const struct device *dev, enum sensor_channel chann if (attribute == SENSOR_ATTR_SAMPLING_FREQUENCY) { value->val1 = data->measurement_period_idx; + value->val2 = 0; } else if (attribute == SENSOR_ATTR_GAIN) { value->val1 = data->gain_idx; + value->val2 = 0; } else if (attribute == SENSOR_ATTR_RESOLUTION) { value->val1 = data->resolution_idx; + value->val2 = 0; } else { return -ENOTSUP; } diff --git a/drivers/sensor/microchip/CMakeLists.txt b/drivers/sensor/microchip/CMakeLists.txt index f26696ba1bb1c..49fc2c206cdc1 100644 --- a/drivers/sensor/microchip/CMakeLists.txt +++ b/drivers/sensor/microchip/CMakeLists.txt @@ -1,9 +1,11 @@ # Copyright (c) 2024 Analog Devices, Inc. +# Copyright (c) 2025 Microchip Technology Inc. # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start add_subdirectory_ifdef(CONFIG_MCP9600 mcp9600) add_subdirectory_ifdef(CONFIG_MCP970X mcp970x) +add_subdirectory_ifdef(CONFIG_MTCH9010 mtch9010) add_subdirectory_ifdef(CONFIG_TACH_XEC mchp_tach_xec) add_subdirectory_ifdef(CONFIG_TCN75A tcn75a) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/microchip/Kconfig b/drivers/sensor/microchip/Kconfig index dd33798135af9..981e82c96b5cb 100644 --- a/drivers/sensor/microchip/Kconfig +++ b/drivers/sensor/microchip/Kconfig @@ -1,9 +1,11 @@ # Copyright (c) 2024 Analog Devices, Inc. +# Copyright (c) 2025 Microchip Technology Inc. # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start source "drivers/sensor/microchip/mchp_tach_xec/Kconfig" source "drivers/sensor/microchip/mcp9600/Kconfig" source "drivers/sensor/microchip/mcp970x/Kconfig" +source "drivers/sensor/microchip/mtch9010/Kconfig" source "drivers/sensor/microchip/tcn75a/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/microchip/mtch9010/CMakeLists.txt b/drivers/sensor/microchip/mtch9010/CMakeLists.txt new file mode 100644 index 0000000000000..7ce061bd29906 --- /dev/null +++ b/drivers/sensor/microchip/mtch9010/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(mtch9010.c) diff --git a/drivers/sensor/microchip/mtch9010/Kconfig b/drivers/sensor/microchip/mtch9010/Kconfig new file mode 100644 index 0000000000000..44fd6f17c626f --- /dev/null +++ b/drivers/sensor/microchip/mtch9010/Kconfig @@ -0,0 +1,61 @@ +# Copyright (c) 2025 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +menuconfig MTCH9010 + bool "MTCH9010" + default y + depends on DT_HAS_MICROCHIP_MTCH9010_ENABLED + help + Configure the MTCH9010 driver + +if MTCH9010 + + config MTCH9010_RESET_ON_STARTUP + bool "Reset MTCH9010 on Startup" + default y + help + Resets the MTCH9010 before the driver configures it. + If disabled and the MTCH9010 was configured already, configuration will fail. + + config MTCH9010_LOCK_ON_STARTUP + bool "Save MTCH9010 Settings on Startup" + default n + help + If set, this option will assert SYS_LK after initialization. + The sensor will use these parameters if SYS_LK is asserted on the next POR. + + config MTCH9010_SAMPLE_DELAY_TIMEOUT_MS + int "Maximum wait time to get a sample (ms)" + default 500 + help + Sets the maximum amount of time in milliseconds to wait for a response from the MTCH9010 + when asking for a sample. Conductive mode is much faster than capacitive mode. + + config MTCH9010_OVERRIDE_DELAY_ENABLE + bool "Override Delay if not Wake on Request" + default y + help + If the MTCH9010 has a sleep period defined, the wake pin will not wake the device. + If this option is set, the API will allow for length + delays during fetch. Otherwise, the API will use the normal timeout, and likely fail. + + config MTCH9010_REFERENCE_AVERAGING_COUNT + int "Reference Averaging Count" + default 1 + range 1 64 + help + If the MTCH9010 is using the current measurement as its reference, then this + is the number of samples to average. + + config MTCH9010_HEARTBEAT_MONITORING_ENABLE + bool "Heartbeat Monitoring" + default y + help + Configures monitoring of the heartbeat output + + # Logging Settings + module = MTCH9010 + module-str = MTCH9010 + source "subsys/logging/Kconfig.template.log_config" + +endif diff --git a/drivers/sensor/microchip/mtch9010/mtch9010.c b/drivers/sensor/microchip/mtch9010/mtch9010.c new file mode 100644 index 0000000000000..e5ddd6d3f8c45 --- /dev/null +++ b/drivers/sensor/microchip/mtch9010/mtch9010.c @@ -0,0 +1,948 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT microchip_mtch9010 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtch9010_priv.h" + +LOG_MODULE_REGISTER(mtch9010); + +#define MTCH9010_INTERNAL_BUFFER_SIZE 64u + +/* Private Function Declarations */ +static int mtch9010_init(const struct device *dev); +static void mtch9010_verify_uart(const struct device *dev); +static int mtch9010_configure_device(const struct device *dev); +static int mtch9010_set_mode(const struct device *dev); +static int mtch9010_set_data_format(const struct device *dev); +static int mtch9010_set_reference(const struct device *dev, char *temp_buffer); +static int mtch9010_command_send(const struct device *dev, const char *str); +static int mtch9010_configure_gpio(const struct device *dev); +static int mtch9010_configure_int_gpio(const struct device *dev); +static int mtch9010_device_reset(const struct device *dev); +static int mtch9010_timeout_receive(const struct device *dev, char *buffer, uint8_t buffer_len, + uint16_t milliseconds); +static int mtch9010_lock_settings(const struct device *dev); + +/* Callbacks */ +static void mtch9010_heartbeat_callback(const struct device *dev, struct gpio_callback *cb, + uint32_t pins); + +/* API Functions */ +static int mtch9010_sample_fetch(const struct device *dev, enum sensor_channel chan); +static int mtch9010_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val); + +/* Private Function Implementations */ +static void mtch9010_verify_uart(const struct device *dev) +{ + const struct mtch9010_config *config = dev->config; + const struct device *uart_dev = config->uart_dev; + + /* Verify UART Setup */ + struct uart_config uart_cfg; + + if (uart_config_get(uart_dev, &uart_cfg) < 0) { + LOG_INST_WRN(config->log, "Failed to read UART Config; Settings were not verified"); + } else { + __ASSERT(uart_cfg.baudrate == MTCH9010_UART_BAUDRATE, + "Incorrect UART baudrate for MTCH9010"); + __ASSERT(uart_cfg.parity == MTCH9010_UART_PARITY, + "Incorrect UART parity for MTCH9010"); + __ASSERT(uart_cfg.stop_bits == MTCH9010_UART_STOP_BITS, + "Incorrect number of UART stop bits for MTCH9010"); + __ASSERT(uart_cfg.data_bits == MTCH9010_UART_DATA_BITS, + "Incorrect number of UART data bits for MTCH9010"); + } +} + +static int mtch9010_set_reference(const struct device *dev, char *temp_buffer) +{ + const struct mtch9010_config *config = dev->config; + struct mtch9010_data *data = dev->data; + + /* Convert the first value */ + struct mtch9010_result result = {0, 0, 0}; + + if (mtch9010_decode_char_buffer(temp_buffer, MTCH9010_OUTPUT_FORMAT_CURRENT, &result) < 0) { + LOG_INST_ERR(config->log, "Failed to decode reference value"); + return -EINVAL; + } + +#if (CONFIG_MTCH9010_REFERENCE_AVERAGING_COUNT == 1) + /* No Averaging */ + if (mtch9010_command_send(dev, MTCH9010_CMD_STR_REF_MODE_CURRENT_VALUE) < 0) { + LOG_INST_ERR(config->log, "Failed to send reference mode command"); + return -EIO; + } + data->reference = result.measurement; +#else + uint32_t total = result.measurement; + + /* Average the value out */ + LOG_INST_DBG(config->log, "Averaging values"); + + uint8_t samples = 1; + + while (samples < CONFIG_MTCH9010_REFERENCE_AVERAGING_COUNT) { + if (mtch9010_command_send(dev, MTCH9010_CMD_STR_REF_MODE_REPEAT_MEAS) < 0) { + LOG_INST_ERR(config->log, "Failed to send measurement repeat command"); + return -EIO; + } + + if (mtch9010_timeout_receive(dev, temp_buffer, sizeof(temp_buffer), + CONFIG_MTCH9010_SAMPLE_DELAY_TIMEOUT_MS) == 0) { + LOG_INST_ERR(config->log, "Reference value timed " + "out during averaging"); + temp_buffer[0] = '\0'; + return -EIO; + } + + if (mtch9010_decode_char_buffer(temp_buffer, MTCH9010_OUTPUT_FORMAT_CURRENT, + &result) < 0) { + LOG_INST_ERR(config->log, "Failed to decode reference value"); + return -EINVAL; + } + + total += result.measurement; + + samples++; + } + + /* Check to see if we received averages correctly */ + uint16_t calc_ref_val = lround(total / CONFIG_MTCH9010_REFERENCE_AVERAGING_COUNT); + + if (calc_ref_val > MTCH9010_MAX_RESULT) { + LOG_INST_ERR(config->log, "Computed reference out of range"); + return -EIO; + } + + /* Update the reference value */ + data->reference = calc_ref_val; + + LOG_INST_DBG(config->log, "Average reference value = %u", calc_ref_val); + + /* Set the average value as a custom value */ + if (mtch9010_command_send(dev, MTCH9010_CMD_STR_REF_MODE_CUSTOM) < 0) { + LOG_INST_ERR(config->log, "Failed to send custom reference value " + "command (for averaging)"); + return -EIO; + } + + /* Send the computed reference */ + snprintf(temp_buffer, MTCH9010_INTERNAL_BUFFER_SIZE, "%u", data->reference); + if (mtch9010_command_send(dev, temp_buffer) < 0) { + LOG_INST_ERR(config->log, "Failed to send averaged reference value"); + return -EIO; + } +#endif /* CONFIG_MTCH9010_REFERENCE_AVERAGING_COUNT == 1*/ + + return 0; +} + +static int mtch9010_set_mode(const struct device *dev) +{ + const struct mtch9010_config *config = dev->config; + char *val_str; + + if (config->mode == MTCH9010_CAPACITIVE) { + val_str = MTCH9010_CMD_STR_CAPACITIVE_MODE; + } else if (config->mode == MTCH9010_CONDUCTIVE) { + val_str = MTCH9010_CMD_STR_CONDUCTIVE_MODE; + } else { + /* Should never get here */ + return -EINVAL; + } + + if (mtch9010_command_send(dev, val_str) < 0) { + return -EIO; + } + + return 0; +} + +static int mtch9010_set_data_format(const struct device *dev) +{ + const struct mtch9010_config *config = dev->config; + + /* Extended Mode Enable */ + if (config->extended_mode_enable) { + /* Extended Mode */ + if (mtch9010_command_send(dev, MTCH9010_CMD_STR_EXTENDED_MODE_EN) < 0) { + return -EIO; + } + LOG_INST_DBG(config->log, "Extended mode is enabled"); + + if (config->format == MTCH9010_OUTPUT_FORMAT_DELTA) { + if (mtch9010_command_send(dev, MTCH9010_CMD_STR_EXTENDED_FORMAT_DELTA) < + 0) { + return -EIO; + } + } else if (config->format == MTCH9010_OUTPUT_FORMAT_CURRENT) { + if (mtch9010_command_send(dev, MTCH9010_CMD_STR_EXTENDED_FORMAT_CURRENT) < + 0) { + return -EIO; + } + } else if (config->format == MTCH9010_OUTPUT_FORMAT_BOTH) { + if (mtch9010_command_send(dev, MTCH9010_CMD_STR_EXTENDED_FORMAT_BOTH) < 0) { + return -EIO; + } + } else if (config->format == MTCH9010_OUTPUT_FORMAT_MPLAB_DATA_VISUALIZER) { + if (mtch9010_command_send(dev, MTCH9010_CMD_STR_EXTENDED_FORMAT_MPLAB_DV) < + 0) { + return -EIO; + } + } else { + return -EINVAL; + } + } else { + /* Extended Config Disabled */ + if (mtch9010_command_send(dev, MTCH9010_CMD_STR_EXTENDED_MODE_DIS) < 0) { + return -EIO; + } + LOG_INST_DBG(config->log, "Extended mode is not enabled"); + } + + return 0; +} + +/* This function handles the UART init routine*/ +static int mtch9010_configure_device(const struct device *dev) +{ + const struct mtch9010_config *config = dev->config; + struct mtch9010_data *data = dev->data; + + /* Temp Char Buffer */ + char temp_buffer[MTCH9010_INTERNAL_BUFFER_SIZE]; + + /* Set the operating mode (capacitive or conductive) */ + if (mtch9010_set_mode(dev) < 0) { + LOG_INST_ERR(config->log, "Failed to set operating mode"); + return -EIO; + } + + /* Sleep Mode - enum matched to strings */ + snprintf(temp_buffer, sizeof(temp_buffer), "%d", config->sleep_time); + if (mtch9010_command_send(dev, temp_buffer) < 0) { + LOG_INST_ERR(config->log, "Failed to send sleep mode command"); + return -EIO; + } + + /* Configure UART Output formatting */ + if (mtch9010_set_data_format(dev) < 0) { + LOG_INST_ERR(config->log, "Failed to set output format"); + return -EIO; + } + + /* Now, the device will send it's electrode reference value */ + if (mtch9010_timeout_receive(dev, temp_buffer, sizeof(temp_buffer), + CONFIG_MTCH9010_SAMPLE_DELAY_TIMEOUT_MS) == 0) { + LOG_INST_ERR(config->log, "Reference value was not received"); + return -EIO; + } + + /* Reference Value */ + if (config->ref_mode == MTCH9010_REFERENCE_CURRENT_VALUE) { + + if (mtch9010_set_reference(dev, temp_buffer) < 0) { + LOG_INST_ERR(config->log, "Failed to set reference value"); + return -EIO; + } + } else if (config->ref_mode == MTCH9010_REFERENCE_CUSTOM_VALUE) { + /* The user manually set a value */ + if (mtch9010_command_send(dev, MTCH9010_CMD_STR_REF_MODE_CUSTOM) < 0) { + LOG_INST_ERR(config->log, "Failed to send custom reference value command"); + return -EIO; + } + snprintf(temp_buffer, MTCH9010_INTERNAL_BUFFER_SIZE, "%u", data->reference); + if (mtch9010_command_send(dev, temp_buffer) < 0) { + LOG_INST_ERR(config->log, "Failed to send custom reference value"); + return -EIO; + } + } else { + LOG_INST_ERR(config->log, "Invalid reference mode"); + return -EINVAL; + } + + /* Detection Threshold */ + snprintf(temp_buffer, MTCH9010_INTERNAL_BUFFER_SIZE, "%u", data->threshold); + if (mtch9010_command_send(dev, temp_buffer) < 0) { + LOG_INST_ERR(config->log, "Failed to send detection threshold value"); + return -EIO; + } + + mtch9010_lock_settings(dev); + + return 0; +} + +static int mtch9010_init(const struct device *dev) +{ + const struct mtch9010_config *config = dev->config; + struct mtch9010_data *data = dev->data; + const struct device *uart_dev = config->uart_dev; + + LOG_INST_DBG(config->log, "Starting device configuration"); + + /* Verify UART setup */ + mtch9010_verify_uart(dev); + + /* Configure heartbeat timing */ + k_sem_init(&data->heartbeat_sem, 0, 1); + + /* Configure device I/O, as needed */ + mtch9010_configure_gpio(dev); + + /* Configure INT I/O, as needed */ + mtch9010_configure_int_gpio(dev); + + /* Assert device reset, if set */ + mtch9010_device_reset(dev); + + /* Set the last heartbeat to post reset time */ + data->last_heartbeat = k_uptime_get(); + + /* Wait for boot-up */ + k_msleep(MTCH9010_BOOT_TIME_MS); + + if (config->uart_init) { + + if (!device_is_ready(uart_dev)) { + LOG_INST_ERR(config->log, "UART is not ready; Configuration skipped"); + return -EBUSY; + } + + int code = mtch9010_configure_device(dev); + + if (code < 0) { + return code; + } + } else { + LOG_INST_DBG(config->log, "UART setup not enabled"); + } + +#ifdef CONFIG_MTCH9010_OVERRIDE_DELAY_ENABLE + /* Print warning */ + if (config->sleep_time != 0) { + uint16_t timeout = + (config->sleep_time) * 1000 + CONFIG_MTCH9010_SAMPLE_DELAY_TIMEOUT_MS; + LOG_INST_WRN(config->log, "Device will wait up-to %u ms when fetching samples", + (timeout)); + } +#endif + + LOG_INST_DBG(config->log, "MTCH9010 configuration complete"); + + return 0; +} + +static int mtch9010_command_send(const struct device *dev, const char *str) +{ + const struct mtch9010_config *config = (const struct mtch9010_config *)dev->config; + const struct device *uart_dev = config->uart_dev; + + LOG_INST_INF(config->log, "\"%s\"", str); + + uint8_t len = strlen(str); + + for (uint8_t i = 0; i < len; i++) { + uart_poll_out(uart_dev, str[i]); + } + + uart_poll_out(uart_dev, MTCH9010_SUBMIT_CHAR); + + char temp_buffer[4] = {'\0', '\0', '\0', '\0'}; + + if (mtch9010_timeout_receive(dev, &temp_buffer[0], sizeof(temp_buffer), + MTCH9010_UART_COMMAND_TIMEOUT_MS) == 0) { + LOG_INST_ERR(config->log, "CMD Timeout waiting for response"); + return -EIO; + } + + if (temp_buffer[0] == MTCH9010_ACK_CHAR) { + LOG_INST_DBG(config->log, "ACK received"); + return 0; + } else if (temp_buffer[0] == MTCH9010_NACK_CHAR) { + LOG_INST_ERR(config->log, "NACK received from command"); + } else { + LOG_INST_ERR(config->log, "Unknown character received during setup"); + } + return -EIO; +} + +/* Returns the number of bytes received */ +static int mtch9010_timeout_receive(const struct device *dev, char *buffer, uint8_t buffer_len, + uint16_t milliseconds) +{ + const struct mtch9010_config *config = (const struct mtch9010_config *)dev->config; + const struct device *uart_dev = config->uart_dev; + + uint8_t count = 0; + k_timepoint_t end = sys_timepoint_calc(K_MSEC(milliseconds)); + + while ((count < (buffer_len - 1)) && (!sys_timepoint_expired(end))) { + int code = uart_poll_in(uart_dev, &buffer[count]); + + if (code == 0) { + count++; + if ((count >= 2) && (buffer[count - 1] == '\r') && + (buffer[count - 2] == '\n')) { + /* Found end of packet - exit early */ + buffer[count] = '\0'; + return count; + } + } + } + + buffer[count] = '\0'; + return count; +} + +static int mtch9010_configure_gpio(const struct device *dev) +{ + const struct mtch9010_config *config = (const struct mtch9010_config *)dev->config; + struct mtch9010_data *data = (struct mtch9010_data *)dev->data; + + /* Note: nRESET is handled in device reset function */ + int rtn = 0; + + /* UART EN (active LOW) */ + if (gpio_is_ready_dt(&config->enable_uart_gpio)) { + if (config->uart_init) { + gpio_pin_configure_dt(&config->enable_uart_gpio, + GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW); + } else { + gpio_pin_configure_dt(&config->enable_uart_gpio, + GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH); + } + } else { + LOG_INST_DBG(config->log, "UART EN line is not ready"); + } + + /* CFG EN */ + if (gpio_is_ready_dt(&config->enable_cfg_gpio)) { + if (config->extended_mode_enable) { + gpio_pin_configure_dt(&config->enable_cfg_gpio, + GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW); + } else { + gpio_pin_configure_dt(&config->enable_cfg_gpio, + GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH); + } + } else { + LOG_INST_DBG(config->log, "ECFG line is not ready"); + } + + /* OUT */ + if (gpio_is_ready_dt(&config->out_gpio)) { + /* Setup as Input */ + gpio_pin_configure_dt(&config->out_gpio, GPIO_INPUT); + data->last_out_state = gpio_pin_get_dt(&config->out_gpio); + } else { + LOG_INST_DBG(config->log, "OUT line is not ready"); + data->last_out_state = -EIO; + } + + /* SYSTEM LOCK */ + if (gpio_is_ready_dt(&config->lock_gpio)) { + /* Keep HIGH until ready to configure */ + gpio_pin_configure_dt(&config->lock_gpio, GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH); + } else { + LOG_INST_DBG(config->log, "System Lock line is not ready"); + } + + /* WAKE */ + if (gpio_is_ready_dt(&config->wake_gpio)) { + /* Keep HIGH until ready to assert WU / WAKE */ + gpio_pin_configure_dt(&config->wake_gpio, GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH); + } else { + LOG_INST_DBG(config->log, "Wake line is not ready."); + } + + /* MODE */ + if (gpio_is_ready_dt(&config->mode_gpio)) { + /* Keep HIGH until ready to assert */ + if (config->mode == MTCH9010_CAPACITIVE) { + gpio_pin_configure_dt(&config->mode_gpio, + GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH); + } else if (config->mode == MTCH9010_CONDUCTIVE) { + gpio_pin_configure_dt(&config->mode_gpio, + GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW); + } else { + LOG_INST_ERR(config->log, "Invalid operating mode specified"); + return -EINVAL; + } + } else { + LOG_INST_DBG(config->log, "Wake line is not ready."); + } + + return rtn; +} + +static int mtch9010_configure_int_gpio(const struct device *dev) +{ + const struct mtch9010_config *config = (const struct mtch9010_config *)dev->config; + struct mtch9010_data *data = (struct mtch9010_data *)dev->data; + + int rtn = 0; + + /* In some cases, data may not be used */ + (void)data; + + /* HEARTBEAT */ + if (gpio_is_ready_dt(&config->heartbeat_gpio)) { + gpio_pin_configure_dt(&config->heartbeat_gpio, GPIO_INPUT); +#ifdef CONFIG_MTCH9010_HEARTBEAT_MONITORING_ENABLE + gpio_init_callback(&data->heartbeat_cb, mtch9010_heartbeat_callback, + BIT(config->heartbeat_gpio.pin)); + rtn = gpio_add_callback_dt(&config->heartbeat_gpio, &data->heartbeat_cb); + if (rtn == 0) { + rtn = gpio_pin_interrupt_configure_dt(&config->heartbeat_gpio, + GPIO_INT_EDGE_RISING); + if (rtn < 0) { + LOG_INST_ERR(config->log, "Unable to configure interrupt; code %d", + rtn); + } else { + LOG_INST_DBG(config->log, "Configured Heartbeat Interrupt"); + } + } else { + LOG_INST_ERR(config->log, "Unable to add callback; code %d", rtn); + } +#endif + } else { + LOG_INST_DBG(config->log, "Heartbeat line is not ready."); + } + + return rtn; +} + +static int mtch9010_device_reset(const struct device *dev) +{ + const struct mtch9010_config *config = (const struct mtch9010_config *)dev->config; + +#ifndef CONFIG_MTCH9010_RESET_ON_STARTUP + LOG_INST_DBG(config->log, "MTCH9010 reset on startup is disabled."); + + return -ENOSYS; +#else + const struct gpio_dt_spec *reset_gpio_ptr = &config->reset_gpio; + + if (!gpio_is_ready_dt(reset_gpio_ptr)) { + LOG_INST_WRN(config->log, "Reset line is not ready. Reset was not performed."); + return -EBUSY; + } + + gpio_pin_configure_dt(reset_gpio_ptr, GPIO_OUTPUT_LOW); + + LOG_INST_DBG(config->log, "Resetting MTCH9010"); + k_msleep(MTCH9010_RESET_TIME_MS); + + gpio_pin_set_dt(reset_gpio_ptr, 1); + + return 0; +#endif +} + +int mtch9010_decode_char_buffer(const char *buffer, uint8_t format, struct mtch9010_result *result) +{ + if (result == NULL) { + return -EINVAL; + } + + /* Check to see if the first digit is valid */ + if (isdigit(buffer[0]) == 0) { + return -EINVAL; + } + + char *end_str_ptr = NULL; + long temp = 0; + + /* Ensure that these variables are always used*/ + (void)temp; + (void)end_str_ptr; + + switch (format) { + case MTCH9010_OUTPUT_FORMAT_CURRENT: + /* Data: \n\r */ + temp = strtol(buffer, &end_str_ptr, 10); + + if ((temp > MTCH9010_MAX_RESULT) || (temp < MTCH9010_MIN_RESULT)) { + return -EINVAL; + } + + result->prev_measurement = result->measurement; + result->measurement = (uint16_t)temp; + break; + case MTCH9010_OUTPUT_FORMAT_DELTA: + /* Data: \n\r */ + temp = strtol(buffer, &end_str_ptr, 10); + + /* Note: Delta can go negative */ + if ((temp > MTCH9010_MAX_RESULT) || (temp < -MTCH9010_MAX_RESULT)) { + return -EINVAL; + } + + result->delta = (int16_t)temp; + break; + case MTCH9010_OUTPUT_FORMAT_BOTH: + /* Data: \n\r */ + temp = strtol(buffer, &end_str_ptr, 10); + + if ((temp > MTCH9010_MAX_RESULT) || (temp < MTCH9010_MIN_RESULT)) { + return -EINVAL; + } + + result->prev_measurement = result->measurement; + result->measurement = (uint16_t)temp; + + if (*end_str_ptr == ' ') { + /* Increment string pointer to the next number */ + end_str_ptr++; + + temp = strtol(end_str_ptr, &end_str_ptr, 10); + + if ((temp > MTCH9010_MAX_RESULT) || (temp < -MTCH9010_MAX_RESULT)) { + return -EINVAL; + } + + result->delta = (int16_t)temp; + } else { + return -EINVAL; + } + + break; + case MTCH9010_OUTPUT_FORMAT_MPLAB_DATA_VISUALIZER: + /* Data: <~start> */ + return -ENOTSUP; + default: + return -EIO; + } + + /* Verify the \n\r is at the end */ + if ((*end_str_ptr == '\n') && (*(end_str_ptr + 1) == '\r')) { + return 0; + } + + return -EINVAL; +} + +static int mtch9010_lock_settings(const struct device *dev) +{ +#ifdef CONFIG_MTCH9010_LOCK_ON_STARTUP + const struct mtch9010_config *config = dev->config; + + if (config->lock_gpio.port == NULL) { + LOG_INST_ERR(config->log, "Lock line not ready"); + return -EIO; + } + + LOG_INST_INF(config->log, "Locking MTCH9010"); + + /* Set lock line */ + gpio_pin_set_dt(&config->lock_gpio, 0); +#endif + + return 0; +} + +static int mtch9010_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct mtch9010_config *config = dev->config; + struct mtch9010_data *data = dev->data; + + switch ((int)chan) { + case SENSOR_CHAN_MTCH9010_OUT_STATE: { + /* I/O output state - poll GPIO */ + + data->last_out_state = gpio_pin_get_dt(&config->out_gpio); + if (data->last_out_state < 0) { + LOG_ERR("GPIO Error %d", data->last_out_state); + return -EIO; + } + + return 0; + } + case SENSOR_CHAN_MTCH9010_REFERENCE_VALUE: { + /* Constant value - nothing to do */ + return 0; + } + case SENSOR_CHAN_MTCH9010_THRESHOLD_VALUE: { + /* Constant value - nothing to do */ + return 0; + } + case SENSOR_CHAN_ALL: + case SENSOR_CHAN_MTCH9010_SW_OUT_STATE: + case SENSOR_CHAN_MTCH9010_MEAS_RESULT: + case SENSOR_CHAN_MTCH9010_MEAS_DELTA: { + /* Get the Out State */ + + if (config->out_gpio.port != NULL) { + /* Hardware OUT State - SW OUT calculated elsewhere */ + data->last_out_state = gpio_pin_get_dt(&config->out_gpio); + } + + /* Check to see if >150 ms have passed */ + if (!sys_timepoint_expired(data->last_wake)) { + LOG_INST_ERR(config->log, "Insufficient time between wake provided"); + return -EBUSY; + } + + /* Blocking Wait for Sensor Data */ + uint16_t timeout = CONFIG_MTCH9010_SAMPLE_DELAY_TIMEOUT_MS; + + if (config->sleep_time != 0) { + +#ifdef CONFIG_MTCH9010_OVERRIDE_DELAY_ENABLE + timeout = (config->sleep_time) * 1000 + + CONFIG_MTCH9010_SAMPLE_DELAY_TIMEOUT_MS; +#else + LOG_INST_ERR(config->log, "Wake mode is disabled if sleep period is " + "defined. Use SENSOR_CHAN_MTCH9010_OUT_STATE or " + "set CONFIG_MTCH9010_OVERRIDE_DELAY_ENABLE."); + return -EBUSY; +#endif + } else { + const struct gpio_dt_spec *wake_gpio = &config->wake_gpio; + + if (!gpio_is_ready_dt(wake_gpio)) { + LOG_INST_ERR(config->log, "Wake GPIO is not ready"); + return -EIO; + } + + /* Wake is falling edge detected */ + gpio_pin_set_dt(wake_gpio, 0); + k_msleep(MTCH9010_WAKE_PULSE_WIDTH_MS); + gpio_pin_set_dt(wake_gpio, 1); + + /* Update last call */ + data->last_wake = sys_timepoint_calc(K_MSEC(MTCH9010_WAKE_TIME_BETWEEN_MS)); + } + + if (config->uart_dev == NULL) { + LOG_INST_ERR(config->log, "UART device is not ready"); + return -ENODEV; + } + + LOG_INST_DBG(config->log, "Fetching sample"); + char temp_buffer[MTCH9010_INTERNAL_BUFFER_SIZE]; + + int char_count = mtch9010_timeout_receive(dev, &temp_buffer[0], sizeof(temp_buffer), + timeout); + + if (char_count == 0) { + LOG_INST_ERR(config->log, "Unable to receive data during fetch."); + return -EIO; + } + + if (mtch9010_decode_char_buffer(&temp_buffer[0], config->format, + &data->last_result) < 0) { + LOG_INST_ERR(config->log, "Unable to decode result for channel %u", chan); + return -EINVAL; + } + } break; + case SENSOR_CHAN_MTCH9010_HEARTBEAT_ERROR_STATE: { + /* Returns true if the heartbeat is an error state */ +#ifdef CONFIG_MTCH9010_HEARTBEAT_MONITORING_ENABLE + if (k_sem_take(&data->heartbeat_sem, K_MSEC(MTCH9010_UART_COMMAND_TIMEOUT_MS)) < + 0) { + return -EBUSY; + } + + /* Compute the last access time */ + int64_t time_delta = k_uptime_delta(&data->last_heartbeat); + + k_sem_give(&data->heartbeat_sem); + + if (time_delta < MTCH9010_ERROR_PERIOD_MS) { + data->heartbeat_error_state = true; + } else { + data->heartbeat_error_state = false; + } + + return 0; +#else + return -ENOTSUP; +#endif + } + default: { + return -ENOTSUP; + } + } + + return 0; +} + +static int mtch9010_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct mtch9010_data *data = dev->data; + const struct mtch9010_config *config = dev->config; + + /* Val2 is not used */ + val->val2 = 0; + + switch ((int)chan) { + case SENSOR_CHAN_MTCH9010_OUT_STATE: { + /* I/O output state */ + val->val1 = data->last_out_state; + break; + } + case SENSOR_CHAN_MTCH9010_SW_OUT_STATE: { + /* Calculates if the OUT line would be asserted based on previous result */ + + if (config->format == MTCH9010_OUTPUT_FORMAT_DELTA) { + LOG_INST_ERR(config->log, "Cannot support SW decode in Delta mode"); + return -ENOTSUP; + } + + if ((data->last_result.measurement - data->reference) >= data->threshold) { + val->val1 = 1; + } else { + val->val1 = 0; + } + + break; + } + case SENSOR_CHAN_MTCH9010_REFERENCE_VALUE: { + /* Returns the reference value set for the sensor */ + val->val1 = data->reference; + break; + } + case SENSOR_CHAN_MTCH9010_THRESHOLD_VALUE: { + /* Returns the threshold value set for the sensor */ + val->val1 = data->threshold; + break; + } + case SENSOR_CHAN_MTCH9010_MEAS_RESULT: { + /* Returns the last measured result */ + val->val1 = data->last_result.measurement; + break; + } + case SENSOR_CHAN_MTCH9010_MEAS_DELTA: { + /* Returns the last delta */ + if ((config->format == MTCH9010_OUTPUT_FORMAT_DELTA) || + (config->format == MTCH9010_OUTPUT_FORMAT_BOTH)) { + val->val1 = data->last_result.delta; + } else if (config->format == MTCH9010_OUTPUT_FORMAT_CURRENT) { + /* Calculate delta from last measurement */ + val->val1 = + data->last_result.measurement - data->last_result.prev_measurement; + } else { + return -ENOTSUP; + } + + break; + } + case SENSOR_CHAN_MTCH9010_HEARTBEAT_ERROR_STATE: { + /* Returns true if the heartbeat is an error state */ + val->val1 = data->heartbeat_error_state; + break; + } + default: { + return -ENOTSUP; + } + } + + return 0; +} + +static void mtch9010_heartbeat_callback(const struct device *dev, struct gpio_callback *cb, + gpio_port_pins_t pins) +{ + (void)pins; + (void)dev; + + struct mtch9010_data *data = CONTAINER_OF(cb, struct mtch9010_data, heartbeat_cb); + + if (k_sem_take(&data->heartbeat_sem, K_NO_WAIT) == 0) { + data->last_heartbeat = k_uptime_get(); + k_sem_give(&data->heartbeat_sem); + } +} + +/* Sensor APIs */ +static DEVICE_API(sensor, mtch9010_api_funcs) = { + .sample_fetch = mtch9010_sample_fetch, + .channel_get = mtch9010_channel_get, +}; + +/* Device Init Macros */ +#define MTCH9010_OPERATING_MODE_INIT(inst) DT_STRING_UPPER_TOKEN(DT_DRV_INST(inst), operating_mode) + +#define MTCH9010_SLEEP_TIME_INIT(inst) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, sleep_period),\ + (DT_INST_ENUM_IDX(inst, sleep_period)), (0)) + +#define MTCH9010_OUTPUT_MODE_INIT(inst) \ + COND_CODE_0(DT_INST_PROP_OR(inst, extended_output_enable, false),\ + (MTCH9010_OUTPUT_FORMAT_CURRENT),\ + (DT_STRING_UPPER_TOKEN(DT_DRV_INST(inst), extended_output_format))) + +#define MTCH9010_REF_MODE_INIT(inst) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst,\ + reference_value),\ + (MTCH9010_REFERENCE_CUSTOM_VALUE), (MTCH9010_REFERENCE_CURRENT_VALUE)) + +#define MTCH9010_REF_VAL_INIT(inst) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst,\ + reference_value),\ + (DT_INST_PROP(inst, reference_value)),\ + (0)) + +#define MTCH9010_USER_LABEL(inst) inst + +#define MTCH9010_DEFINE(inst) \ + LOG_INSTANCE_REGISTER(mtch9010, MTCH9010_USER_LABEL(inst), CONFIG_MTCH9010_LOG_LEVEL); \ + static struct mtch9010_data mtch9010_data_##inst = { \ + .reference = MTCH9010_REF_VAL_INIT(inst), \ + .threshold = DT_INST_PROP(inst, detect_value), \ + .heartbeat_error_state = false, \ + .last_wake = {0}, \ + .last_result = {0, 0, 0}, \ + }; \ + static const struct mtch9010_config mtch9010_config_##inst = { \ + .uart_init = DT_PROP(DT_DRV_INST(inst), uart_config_enable), \ + .uart_dev = DEVICE_DT_GET(DT_PARENT(DT_DRV_INST(inst))), \ + .reset_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(inst), reset_gpios, {0}), \ + .mode_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(inst), mode_gpios, {0}), \ + .wake_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(inst), wake_gpios, {0}), \ + .out_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(inst), output_gpios, {0}), \ + .heartbeat_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(inst), heartbeat_gpios, {0}), \ + .lock_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(inst), system_lock_gpios, {0}), \ + .enable_uart_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(inst), uart_en_gpios, {0}), \ + .enable_cfg_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(inst), cfg_en_gpios, {0}), \ + .mode = MTCH9010_OPERATING_MODE_INIT(inst), \ + .sleep_time = MTCH9010_SLEEP_TIME_INIT(inst), \ + .extended_mode_enable = DT_INST_PROP_OR(inst, extended_output_enable, false), \ + .format = MTCH9010_OUTPUT_MODE_INIT(inst), \ + .ref_mode = MTCH9010_REF_MODE_INIT(inst), \ + LOG_INSTANCE_PTR_INIT(log, mtch9010, MTCH9010_USER_LABEL(inst))}; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, mtch9010_init, NULL, &mtch9010_data_##inst, \ + &mtch9010_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &mtch9010_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(MTCH9010_DEFINE) diff --git a/drivers/sensor/microchip/mtch9010/mtch9010_priv.h b/drivers/sensor/microchip/mtch9010/mtch9010_priv.h new file mode 100644 index 0000000000000..a6c3efc77ff45 --- /dev/null +++ b/drivers/sensor/microchip/mtch9010/mtch9010_priv.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_MICROCHIP_MTCH9010_PRIV_H_ +#define ZEPHYR_DRIVERS_SENSOR_MICROCHIP_MTCH9010_PRIV_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Character to submit requests */ +#define MTCH9010_SUBMIT_CHAR '\r' + +/* Characters for determining if commands were accepted / rejected */ +#define MTCH9010_ACK_CHAR 0x06u +#define MTCH9010_NACK_CHAR 0x15u + +/* Command Strings w/o submit character */ +#define MTCH9010_CMD_STR_CAPACITIVE_MODE "0" +#define MTCH9010_CMD_STR_CONDUCTIVE_MODE "1" + +/* WOR - Wake on Request */ +#define MTCH9010_CMD_STR_SLEEP_TIME_WOR "0" +#define MTCH9010_CMD_STR_SLEEP_TIME_1S "1" +#define MTCH9010_CMD_STR_SLEEP_TIME_2S "2" +#define MTCH9010_CMD_STR_SLEEP_TIME_4S "3" +#define MTCH9010_CMD_STR_SLEEP_TIME_8S "4" +#define MTCH9010_CMD_STR_SLEEP_TIME_16S "5" +#define MTCH9010_CMD_STR_SLEEP_TIME_32S "6" +#define MTCH9010_CMD_STR_SLEEP_TIME_64S "7" +#define MTCH9010_CMD_STR_SLEEP_TIME_128S "8" +#define MTCH9010_CMD_STR_SLEEP_TIME_256S "9" + +#define MTCH9010_CMD_STR_EXTENDED_MODE_DIS "0" +#define MTCH9010_CMD_STR_EXTENDED_MODE_EN "1" + +#define MTCH9010_CMD_STR_EXTENDED_FORMAT_DELTA "0" +#define MTCH9010_CMD_STR_EXTENDED_FORMAT_CURRENT "1" +#define MTCH9010_CMD_STR_EXTENDED_FORMAT_BOTH "2" +#define MTCH9010_CMD_STR_EXTENDED_FORMAT_MPLAB_DV "3" + +#define MTCH9010_CMD_STR_REF_MODE_CURRENT_VALUE "0" +#define MTCH9010_CMD_STR_REF_MODE_REPEAT_MEAS "1" +#define MTCH9010_CMD_STR_REF_MODE_CUSTOM "2" + +/* Device Constants */ +#define MTCH9010_RESET_TIME_MS 10u +#define MTCH9010_BOOT_TIME_MS 10u +#define MTCH9010_UART_COMMAND_TIMEOUT_MS 20u +#define MTCH9010_WAKE_PULSE_WIDTH_MS 1u +#define MTCH9010_ERROR_PERIOD_MS 220u + +/* UART Constants */ +#define MTCH9010_UART_BAUDRATE 38400u +#define MTCH9010_UART_DATA_BITS UART_CFG_DATA_BITS_8 +#define MTCH9010_UART_PARITY UART_CFG_PARITY_NONE +#define MTCH9010_UART_STOP_BITS UART_CFG_STOP_BITS_1 + +/* Time between wake requests */ +#define MTCH9010_WAKE_TIME_BETWEEN_MS 150u + +struct mtch9010_result { + /* Received Reference Value */ + uint16_t measurement; + /* Last Measurement Value */ + uint16_t prev_measurement; + /* Received Delta Value */ + int16_t delta; +}; + +enum mtch9010_reference_value_init { + /* MTCH9010 sets the current value as the reference value */ + MTCH9010_REFERENCE_CURRENT_VALUE = 0, + /* MTCH9010 re-runs the measurement */ + MTCH9010_REFERENCE_RERUN_VALUE, + /* MTCH9010 sets the reference to the value the user defines */ + MTCH9010_REFERENCE_CUSTOM_VALUE +}; + +struct mtch9010_data { + /* Threshold of the Sensor */ + uint16_t threshold; + /* Reference (Dry) value of the Sensor */ + uint16_t reference; + /* Last time we asked for data */ + k_timepoint_t last_wake; + /* Last time a heartbeat was detected */ + int64_t last_heartbeat; + /* Semaphore for accessing heartbeat */ + struct k_sem heartbeat_sem; + /* Heartbeat GPIO Callback */ + struct gpio_callback heartbeat_cb; + /* Last state of the OUT pin */ + int last_out_state; + /* If true, the heartbeat is sending the error pattern */ + bool heartbeat_error_state; + /* Last result received from the sensor */ + struct mtch9010_result last_result; +}; + +struct mtch9010_config { + /* Set to true if the init function should configure the device */ + bool uart_init; + /* Pointer to UART Bus */ + const struct device *uart_dev; + /* OP_MODE Signal for I/O mode */ + const struct gpio_dt_spec mode_gpio; + /* nRESET Signal for MTCH9010 */ + const struct gpio_dt_spec reset_gpio; + /* Wake-Up (WU) Signal for MTCH9010 */ + const struct gpio_dt_spec wake_gpio; + /* OUT Signal for MTCH9010 */ + const struct gpio_dt_spec out_gpio; + /* SYS_LK Signal to Program Startup Settings */ + const struct gpio_dt_spec lock_gpio; + /* nUART_EN Signal to Enable UART Communication */ + const struct gpio_dt_spec enable_uart_gpio; + /* nCFG_EN Signal for I/O Mode*/ + const struct gpio_dt_spec enable_cfg_gpio; + /* Heartbeat (HB) Output of MTCH9010 */ + const struct gpio_dt_spec heartbeat_gpio; + /* Operating mode (Capacitive / Conductive) */ + uint8_t mode; + /* Sleep Time of device in seconds. Set to 0 for Wake on Request */ + int sleep_time; + /* Set to true if extended format output is configured */ + bool extended_mode_enable; + /* Format of the UART Output Data */ + uint8_t format; + /* Initialization mode of the reference */ + enum mtch9010_reference_value_init ref_mode; + /* Logging Instance */ + LOG_INSTANCE_PTR_DECLARE(log); +}; + +/* Helper function to decode a NULL-terminated string packet */ +int mtch9010_decode_char_buffer(const char *buffer, uint8_t format, + struct mtch9010_result *result); + +#endif /* ZEPHYR_DRIVERS_SENSOR_MICROCHIP_MTCH9010_PRIV_H_ */ diff --git a/drivers/sensor/tdk/icm42x70/icm42x70.c b/drivers/sensor/tdk/icm42x70/icm42x70.c index 5252b483464b6..265ac3f56c8c7 100644 --- a/drivers/sensor/tdk/icm42x70/icm42x70.c +++ b/drivers/sensor/tdk/icm42x70/icm42x70.c @@ -482,12 +482,17 @@ static void icm42x70_convert_accel(struct sensor_value *val, int16_t raw_val, ui val->val2 = conv_val % 1000000; } -static void icm42x70_convert_temp(struct sensor_value *val, int16_t raw_val) +static void icm42x70_convert_temp(struct sensor_value *val, int16_t raw_val, bool hires) { int64_t conv_val; /* see datasheet section 15.9 for details */ - conv_val = 25 * 1000000 + ((int64_t)raw_val * 1000000 / 2); + if (hires) { + conv_val = (25 * 1000000) + ((int64_t)raw_val * 1000000 / 128); + } else { + conv_val = (25 * 1000000) + ((int64_t)raw_val * 1000000 / 2); + } + val->val1 = conv_val / 1000000; val->val2 = conv_val % 1000000; } @@ -530,7 +535,15 @@ static int icm42x70_channel_get(const struct device *dev, enum sensor_channel ch icm42670_convert_gyro(val, data->gyro_z, data->gyro_fs); #endif } else if (chan == SENSOR_CHAN_DIE_TEMP) { - icm42x70_convert_temp(val, data->temp); + /* see datasheet section 15.9 for details */ + if (IS_ENABLED(CONFIG_ICM42X70_TRIGGER)) { + icm42x70_convert_temp(val, data->temp, data->driver.fifo_highres_enabled); + } else { + /* The temperature data read in non-fifo mode is of 2-bytes; + * which is same as FIFO with high resolution temp data. + */ + icm42x70_convert_temp(val, data->temp, true); + } #ifdef CONFIG_TDK_APEX } else if ((enum sensor_channel_tdk_apex)chan == SENSOR_CHAN_APEX_MOTION) { if (cfg->apex == TDK_APEX_PEDOMETER) { diff --git a/drivers/sensor/tdk/icm45686/icm45686.c b/drivers/sensor/tdk/icm45686/icm45686.c index 98424423ceb53..5b77757d72407 100644 --- a/drivers/sensor/tdk/icm45686/icm45686.c +++ b/drivers/sensor/tdk/icm45686/icm45686.c @@ -425,6 +425,7 @@ static int icm45686_init(const struct device *dev) .lpf = DT_INST_PROP_OR(inst, gyro_lpf, 0), \ }, \ .fifo_watermark = DT_INST_PROP_OR(inst, fifo_watermark, 0), \ + .fifo_watermark_equals = DT_INST_PROP(inst, fifo_watermark_equals), \ }, \ .int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \ }; \ diff --git a/drivers/sensor/tdk/icm45686/icm45686.h b/drivers/sensor/tdk/icm45686/icm45686.h index f6a4918c36a13..01cacfabd01dc 100644 --- a/drivers/sensor/tdk/icm45686/icm45686.h +++ b/drivers/sensor/tdk/icm45686/icm45686.h @@ -160,6 +160,7 @@ struct icm45686_config { uint8_t lpf : 3; } gyro; uint16_t fifo_watermark; + bool fifo_watermark_equals : 1; } settings; struct gpio_dt_spec int_gpio; }; diff --git a/drivers/sensor/tdk/icm45686/icm45686_stream.c b/drivers/sensor/tdk/icm45686/icm45686_stream.c index 0d6281433b15b..9f294f5890e3f 100644 --- a/drivers/sensor/tdk/icm45686/icm45686_stream.c +++ b/drivers/sensor/tdk/icm45686/icm45686_stream.c @@ -126,7 +126,9 @@ static void icm45686_complete_handler(struct rtio *ctx, { const struct device *dev = (const struct device *)arg; struct icm45686_data *data = dev->data; + const struct icm45686_config *cfg = dev->config; const struct sensor_read_config *read_cfg = data->stream.iodev_sqe->sqe.iodev->data; + const bool wm_gt_ths = !cfg->settings.fifo_watermark_equals; uint8_t int_status = data->stream.data.int_status; int err; @@ -157,7 +159,7 @@ static void icm45686_complete_handler(struct rtio *ctx, if (should_flush_fifo(read_cfg, int_status)) { uint8_t write_reg = REG_FIFO_CONFIG2_FIFO_FLUSH(true) | - REG_FIFO_CONFIG2_FIFO_WM_GT_THS(true); + REG_FIFO_CONFIG2_FIFO_WM_GT_THS(wm_gt_ths); LOG_WRN("Flushing FIFO: %d", int_status); err = icm45686_prep_reg_write_rtio_async(&data->bus, REG_FIFO_CONFIG2, &write_reg, @@ -372,6 +374,7 @@ void icm45686_stream_submit(const struct device *dev, const struct sensor_read_config *read_cfg = iodev_sqe->sqe.iodev->data; struct icm45686_data *data = dev->data; const struct icm45686_config *cfg = dev->config; + const bool wm_gt_ths = !cfg->settings.fifo_watermark_equals; uint8_t val = 0; int err; @@ -473,7 +476,7 @@ void icm45686_stream_submit(const struct device *dev, uint16_t fifo_ths = data->stream.settings.enabled.fifo_ths ? cfg->settings.fifo_watermark : 0; - val = REG_FIFO_CONFIG2_FIFO_WM_GT_THS(true) | + val = REG_FIFO_CONFIG2_FIFO_WM_GT_THS(wm_gt_ths) | REG_FIFO_CONFIG2_FIFO_FLUSH(true); err = icm45686_reg_write_rtio(&data->bus, REG_FIFO_CONFIG2, &val, 1); if (err) { diff --git a/drivers/spi/spi_cc23x0.c b/drivers/spi/spi_cc23x0.c index fb235dedcdc1a..79b111f40d240 100644 --- a/drivers/spi/spi_cc23x0.c +++ b/drivers/spi/spi_cc23x0.c @@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(spi_cc23x0, CONFIG_SPI_LOG_LEVEL); #include #include #include +#include +#include +#include #include #include @@ -307,6 +310,8 @@ static int spi_cc23x0_transceive(const struct device *dev, }; #endif + pm_policy_device_power_lock_get(dev); + spi_context_lock(ctx, false, NULL, NULL, config); ret = spi_cc23x0_configure(dev, config); @@ -339,16 +344,22 @@ static int spi_cc23x0_transceive(const struct device *dev, block_cfg_rx.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT; block_cfg_rx.block_size = SPI_CC23_DFS * data->tx_len_left; - ret = dma_config(cfg->dma_dev, cfg->dma_channel_tx, &dma_cfg_tx); + ret = pm_device_runtime_get(cfg->dma_dev); if (ret) { - LOG_ERR("Failed to configure DMA TX channel"); + LOG_ERR("Failed to resume DMA (%d)", ret); goto int_disable; } + ret = dma_config(cfg->dma_dev, cfg->dma_channel_tx, &dma_cfg_tx); + if (ret) { + LOG_ERR("Failed to configure DMA TX channel (%d)", ret); + goto dma_suspend; + } + ret = dma_config(cfg->dma_dev, cfg->dma_channel_rx, &dma_cfg_rx); if (ret) { - LOG_ERR("Failed to configure DMA RX channel"); - goto int_disable; + LOG_ERR("Failed to configure DMA RX channel (%d)", ret); + goto dma_suspend; } /* Disable DMA triggers */ @@ -364,7 +375,7 @@ static int spi_cc23x0_transceive(const struct device *dev, ret = spi_context_wait_for_completion(&data->ctx); if (ret) { LOG_ERR("SPI transfer failed (%d)", ret); - goto int_disable; + goto dma_suspend; } spi_context_update_tx(ctx, SPI_CC23_DFS, data->tx_len_left); @@ -372,6 +383,11 @@ static int spi_cc23x0_transceive(const struct device *dev, LOG_DBG("SPI transfer completed"); +dma_suspend: + ret = pm_device_runtime_put(cfg->dma_dev); + if (ret) { + LOG_ERR("Failed to suspend DMA (%d)", ret); + } int_disable: SPIDisableInt(cfg->base, SPI_CC23_INT_MASK); #else @@ -388,6 +404,7 @@ static int spi_cc23x0_transceive(const struct device *dev, ctx_release: spi_context_release(ctx, ret); + pm_policy_device_power_lock_put(dev); return ret; } @@ -446,6 +463,29 @@ static int spi_cc23x0_init(const struct device *dev) return 0; } +#ifdef CONFIG_PM_DEVICE + +static int spi_cc23x0_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct spi_cc23x0_config *cfg = dev->config; + struct spi_cc23x0_data *data = dev->data; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + SPIDisable(cfg->base); + CLKCTLDisable(CLKCTL_BASE, CLKCTL_SPI0); + return 0; + case PM_DEVICE_ACTION_RESUME: + /* Force SPI to be reconfigured at next transfer */ + data->ctx.config = NULL; + return 0; + default: + return -ENOTSUP; + } +} + +#endif /* CONFIG_PM_DEVICE */ + #ifdef CONFIG_SPI_CC23X0_DMA_DRIVEN #define SPI_CC23X0_DMA_INIT(n) \ .dma_dev = DEVICE_DT_GET(TI_CC23X0_DT_INST_DMA_CTLR(n, tx)), \ @@ -459,6 +499,7 @@ static int spi_cc23x0_init(const struct device *dev) #define SPI_CC23X0_INIT(n) \ PINCTRL_DT_INST_DEFINE(n); \ + PM_DEVICE_DT_INST_DEFINE(n, spi_cc23x0_pm_action); \ \ static void spi_irq_config_func_##n(void) \ { \ @@ -484,7 +525,7 @@ static int spi_cc23x0_init(const struct device *dev) \ DEVICE_DT_INST_DEFINE(n, \ spi_cc23x0_init, \ - NULL, \ + PM_DEVICE_DT_INST_GET(n), \ &spi_cc23x0_data_##n, \ &spi_cc23x0_config_##n, \ POST_KERNEL, \ diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index 79dd64761d9b7..36dee04c9e6a0 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -1430,6 +1430,7 @@ static int spi_stm32_pinctrl_apply(const struct device *dev, uint8_t id) static int spi_stm32_pm_action(const struct device *dev, enum pm_device_action action) { + struct spi_stm32_data *data = dev->data; const struct spi_stm32_config *config = dev->config; const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); int err; @@ -1447,6 +1448,12 @@ static int spi_stm32_pm_action(const struct device *dev, LOG_ERR("Could not enable SPI clock"); return err; } + /* (re-)init SPI context and all CS configuration */ + err = spi_context_cs_configure_all(&data->ctx); + if (err < 0) { + return err; + } + spi_context_unlock_unconditionally(&data->ctx); break; case PM_DEVICE_ACTION_SUSPEND: /* Stop device clock. */ @@ -1511,13 +1518,6 @@ static int spi_stm32_init(const struct device *dev) #endif /* CONFIG_SPI_STM32_DMA */ - err = spi_context_cs_configure_all(&data->ctx); - if (err < 0) { - return err; - } - - spi_context_unlock_unconditionally(&data->ctx); - return pm_device_driver_init(dev, spi_stm32_pm_action); } diff --git a/drivers/stepper/CMakeLists.txt b/drivers/stepper/CMakeLists.txt index bd3677500704b..30dc1602277c9 100644 --- a/drivers/stepper/CMakeLists.txt +++ b/drivers/stepper/CMakeLists.txt @@ -4,10 +4,13 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/stepper.h) # zephyr-keep-sorted-start -add_subdirectory_ifdef(CONFIG_STEPPER_ADI_TMC adi_tmc) -add_subdirectory_ifdef(CONFIG_STEPPER_ALLEGRO allegro) -add_subdirectory_ifdef(CONFIG_STEPPER_TI ti) -add_subdirectory_ifdef(CONFIG_STEP_DIR_STEPPER step_dir) +add_subdirectory(adi_tmc) +add_subdirectory(allegro) +add_subdirectory(ti) +# zephyr-keep-sorted-stop + +# zephyr-keep-sorted-start +add_subdirectory(step_dir) # zephyr-keep-sorted-stop zephyr_library() diff --git a/drivers/stepper/adi_tmc/CMakeLists.txt b/drivers/stepper/adi_tmc/CMakeLists.txt index dbf4121447d9c..e8d48f079cc29 100644 --- a/drivers/stepper/adi_tmc/CMakeLists.txt +++ b/drivers/stepper/adi_tmc/CMakeLists.txt @@ -8,4 +8,4 @@ zephyr_library_sources_ifdef(CONFIG_STEPPER_ADI_TMC2209 tmc22xx.c) zephyr_library_sources_ifdef(CONFIG_STEPPER_ADI_TMC50XX tmc50xx.c) add_subdirectory_ifdef(CONFIG_STEPPER_ADI_TMC51XX tmc51xx) -add_subdirectory_ifdef(CONFIG_STEPPER_ADI_TMC bus) +add_subdirectory(bus) diff --git a/drivers/stepper/adi_tmc/Kconfig b/drivers/stepper/adi_tmc/Kconfig index 0221fbc187a8a..004b736eaf2a7 100644 --- a/drivers/stepper/adi_tmc/Kconfig +++ b/drivers/stepper/adi_tmc/Kconfig @@ -1,33 +1,10 @@ # SPDX-FileCopyrightText: Copyright (c) 2024 Carl Zeiss Meditec AG # SPDX-License-Identifier: Apache-2.0 -menuconfig STEPPER_ADI_TMC - bool "Trinamic Stepper Controller" - depends on STEPPER - default y - help - Enable trinamic stepper controller +comment "ADI Trinamic Stepper Drivers" -if STEPPER_ADI_TMC - -config STEPPER_ADI_TMC_SPI - bool "Use Trinamic Stepper Controller with SPI" - depends on STEPPER_ADI_TMC - select SPI - help - A Trinamic Stepper Controller with SPI is enabled - -config STEPPER_ADI_TMC_UART - bool "Use Trinamic Stepper Controller with single wire UART" - depends on STEPPER_ADI_TMC - select UART - help - A Trinamic Stepper Controller with single wire UART is enabled - -comment "Trinamic Stepper Drivers" +rsource "bus/Kconfig" rsource "Kconfig.tmc22xx" rsource "Kconfig.tmc50xx" -rsource "Kconfig.tmc51xx" - -endif # STEPPER_ADI_TMC +rsource "tmc51xx/Kconfig.tmc51xx" diff --git a/drivers/stepper/adi_tmc/Kconfig.tmc50xx b/drivers/stepper/adi_tmc/Kconfig.tmc50xx index eeb17293456a5..a423c88430597 100644 --- a/drivers/stepper/adi_tmc/Kconfig.tmc50xx +++ b/drivers/stepper/adi_tmc/Kconfig.tmc50xx @@ -4,10 +4,14 @@ config STEPPER_ADI_TMC50XX bool "Activate trinamic tmc50xx stepper driver" - depends on DT_HAS_ADI_TMC50XX_ENABLED && STEPPER_ADI_TMC + depends on DT_HAS_ADI_TMC50XX_ENABLED select STEPPER_ADI_TMC_SPI default y +if STEPPER_ADI_TMC50XX + module = TMC50XX module-str = tmc50xx rsource "Kconfig.tmc_rampgen_template" + +endif # STEPPER_ADI_TMC51XX diff --git a/drivers/stepper/adi_tmc/bus/Kconfig b/drivers/stepper/adi_tmc/bus/Kconfig new file mode 100644 index 0000000000000..b16208f749442 --- /dev/null +++ b/drivers/stepper/adi_tmc/bus/Kconfig @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya +# SPDX-License-Identifier: Apache-2.0 + +config STEPPER_ADI_TMC_SPI + bool "Use Trinamic Stepper Controller with SPI" + select SPI + help + A Trinamic Stepper Controller with SPI is enabled + +config STEPPER_ADI_TMC_UART + bool "Use Trinamic Stepper Controller with single wire UART" + select UART + help + A Trinamic Stepper Controller with single wire UART is enabled diff --git a/drivers/stepper/adi_tmc/Kconfig.tmc51xx b/drivers/stepper/adi_tmc/tmc51xx/Kconfig.tmc51xx similarity index 74% rename from drivers/stepper/adi_tmc/Kconfig.tmc51xx rename to drivers/stepper/adi_tmc/tmc51xx/Kconfig.tmc51xx index 41ef6d7ea5d15..702329d86e7c1 100644 --- a/drivers/stepper/adi_tmc/Kconfig.tmc51xx +++ b/drivers/stepper/adi_tmc/tmc51xx/Kconfig.tmc51xx @@ -3,11 +3,15 @@ config STEPPER_ADI_TMC51XX bool "Activate trinamic tmc51xx stepper driver" - depends on DT_HAS_ADI_TMC51XX_ENABLED && STEPPER_ADI_TMC + depends on DT_HAS_ADI_TMC51XX_ENABLED select STEPPER_ADI_TMC_UART if $(dt_compat_on_bus,$(DT_COMPAT_ADI_TMC51XX),uart) select STEPPER_ADI_TMC_SPI if $(dt_compat_on_bus,$(DT_COMPAT_ADI_TMC51XX),spi) default y +if STEPPER_ADI_TMC51XX + module = TMC51XX module-str = tmc51xx -rsource "Kconfig.tmc_rampgen_template" +rsource "../Kconfig.tmc_rampgen_template" + +endif # STEPPER_ADI_TMC51XX diff --git a/drivers/stepper/allegro/Kconfig b/drivers/stepper/allegro/Kconfig index 39d24bdf1f97d..02fc491957770 100644 --- a/drivers/stepper/allegro/Kconfig +++ b/drivers/stepper/allegro/Kconfig @@ -1,19 +1,8 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 Carl Zeiss Meditec AG # SPDX-License-Identifier: Apache-2.0 -menuconfig STEPPER_ALLEGRO - bool "Allegro Stepper Controller" - depends on STEPPER - default y - help - Enable allegro stepper controller - -if STEPPER_ALLEGRO - comment "Allegro Stepper Drivers" # zephyr-keep-sorted-start rsource "Kconfig.a4979" # zephyr-keep-sorted-stop - -endif # STEPPER_ALLEGRO diff --git a/drivers/stepper/ti/Kconfig b/drivers/stepper/ti/Kconfig index 18804a89094a9..4e41280f28c86 100644 --- a/drivers/stepper/ti/Kconfig +++ b/drivers/stepper/ti/Kconfig @@ -1,8 +1,6 @@ # SPDX-FileCopyrightText: Copyright (c) 2024 Navimatix GmbH # SPDX-License-Identifier: Apache-2.0 -config STEPPER_TI - bool - depends on STEPPER +comment "TI Stepper Drivers" rsource "Kconfig.drv84xx" diff --git a/drivers/stepper/ti/Kconfig.drv84xx b/drivers/stepper/ti/Kconfig.drv84xx index e5466890c66da..58ccc50bb7c52 100644 --- a/drivers/stepper/ti/Kconfig.drv84xx +++ b/drivers/stepper/ti/Kconfig.drv84xx @@ -5,7 +5,6 @@ config DRV84XX bool "TI DRV84XX stepper motor driver" default y depends on DT_HAS_TI_DRV84XX_ENABLED - select STEPPER_TI select STEP_DIR_STEPPER select STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS help diff --git a/drivers/video/CMakeLists.txt b/drivers/video/CMakeLists.txt index 2f6a3244b5ad9..73ee2ea5e70a9 100644 --- a/drivers/video/CMakeLists.txt +++ b/drivers/video/CMakeLists.txt @@ -27,5 +27,6 @@ zephyr_library_sources_ifdef(CONFIG_VIDEO_IMX335 imx335.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_ST_MIPID02 video_st_mipid02.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_STM32_DCMIPP video_stm32_dcmipp.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_RENESAS_RA_CEU video_renesas_ra_ceu.c) +zephyr_library_sources_ifdef(CONFIG_VIDEO_STM32_JPEG video_stm32_jpeg.c) zephyr_linker_sources(DATA_SECTIONS video.ld) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e8f7c321cb02e..7c532c15ef605 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -106,4 +106,6 @@ source "drivers/video/Kconfig.stm32_dcmipp" source "drivers/video/Kconfig.renesas_ra_ceu" +source "drivers/video/Kconfig.stm32_jpeg" + endif # VIDEO diff --git a/drivers/video/Kconfig.stm32_jpeg b/drivers/video/Kconfig.stm32_jpeg new file mode 100644 index 0000000000000..498f20163993b --- /dev/null +++ b/drivers/video/Kconfig.stm32_jpeg @@ -0,0 +1,17 @@ +# STM32 JPEG HW codec driver configuration options + +# Copyright (c) 2025 STMicroelectronics. +# SPDX-License-Identifier: Apache-2.0 + +config VIDEO_STM32_JPEG + bool "STM32 JPEG HW codec driver" + default y + depends on DT_HAS_ST_STM32_JPEG_ENABLED + depends on VIDEO_ENCODER_JPEG + select RESET + select USE_STM32_HAL_JPEG + select USE_STM32_HAL_DMA + select USE_STM32_HAL_DMA_EX + select USE_STM32_HAL_RIF if SOC_SERIES_STM32N6X + help + Enable driver for STM32 JPEG HW Codec peripheral diff --git a/drivers/video/video_stm32_jpeg.c b/drivers/video/video_stm32_jpeg.c new file mode 100644 index 0000000000000..d19281fcf300e --- /dev/null +++ b/drivers/video/video_stm32_jpeg.c @@ -0,0 +1,600 @@ +/* + * Copyright (c) 2025 STMicroelectronics. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "video_ctrls.h" +#include "video_device.h" + +#define DT_DRV_COMPAT st_stm32_jpeg + +LOG_MODULE_REGISTER(stm32_jpeg, CONFIG_VIDEO_LOG_LEVEL); + +typedef void (*irq_config_func_t)(const struct device *dev); + +struct video_common_header { + struct video_format fmt; + struct k_fifo fifo_in; + struct k_fifo fifo_out; + bool is_streaming; +}; + +struct video_m2m_common { + struct video_common_header in; + struct video_common_header out; +}; + +#define YCBCR_420_MCU_BLOCK_SIZE 384 /* 4 8x8 Y, 1 8x8 Cb, 1 8x8 Cr */ + +struct stm32_jpeg_data { + const struct device *dev; + struct video_m2m_common m2m; + JPEG_HandleTypeDef hjpeg; + struct k_mutex lock; + bool codec_is_running; + struct video_buffer *current_in; + struct video_buffer *current_out; + + struct video_ctrl jpeg_quality; + + uint32_t current_x_mcu; + uint32_t current_y_mcu; + uint8_t mcu_ycbcr[YCBCR_420_MCU_BLOCK_SIZE]; +}; + +struct stm32_jpeg_config { + const struct stm32_pclken jpeg_hclken[1]; + irq_config_func_t irq_config; + const struct reset_dt_spec reset_jpeg; +}; + +struct stm32_jpeg_fmt_conf { + uint32_t pixelformat; + uint32_t subsampling; + uint8_t hmcu_div; + uint8_t vmcu_div; +}; + +static const struct stm32_jpeg_fmt_conf stm32_jpeg_confs[] = { + /* JPEG */ + { + .pixelformat = VIDEO_PIX_FMT_JPEG, + /* Meaningless but set to 1 to make set_fmt check working */ + .hmcu_div = 1, + .vmcu_div = 1, + }, + /* YCrCb 4:2:0 */ + { + .pixelformat = VIDEO_PIX_FMT_NV12, + .subsampling = JPEG_420_SUBSAMPLING, + .hmcu_div = 16, + .vmcu_div = 16, + }, + /* TODO: YCrCb 4:2:2 to be added */ + /* TODO: YCrCb 4:4:4 to be added */ +}; + +#define MCU_WIDTH 16 +#define MCU_HEIGHT 16 +#define MCU_BLOCK_SZ 8 + +static void stm32_jpeg_nv12_to_ycbcr_mcu(const uint8_t mcu_x, const uint8_t mcu_y, + const uint8_t *in_y, const uint8_t *in_uv, + uint8_t *out, uint32_t width) +{ + int mcu_idx = 0; + + /* Copy the 4 8x8 Y */ + for (int by = 0; by < 2; ++by) { + for (int bx = 0; bx < 2; ++bx) { + for (int y = 0; y < MCU_BLOCK_SZ; ++y) { + int src_y = mcu_y * MCU_HEIGHT + by * MCU_BLOCK_SZ + y; + int src_x = mcu_x * MCU_WIDTH + bx * MCU_BLOCK_SZ; + const uint8_t *src = in_y + src_y * width + src_x; + uint8_t *dst = out + mcu_idx; + + memcpy(dst, src, MCU_BLOCK_SZ); + mcu_idx += MCU_BLOCK_SZ; + } + } + } + + /* Copy 1 8x8 Cb block */ + for (int y = 0; y < MCU_BLOCK_SZ; ++y) { + int src_y = (mcu_y * MCU_HEIGHT) / 2 + y; + int src_x = (mcu_x * MCU_WIDTH) / 2; + const uint8_t *src = in_uv + (src_y * width) + (src_x * 2); + uint8_t *dst = out + mcu_idx; + + for (int x = 0; x < MCU_BLOCK_SZ; ++x) { + dst[x] = src[x * 2]; + } + mcu_idx += MCU_BLOCK_SZ; + } + + /* Copy 1 8x8 Cr block */ + for (int y = 0; y < MCU_BLOCK_SZ; ++y) { + int src_y = (mcu_y * MCU_HEIGHT) / 2 + y; + int src_x = (mcu_x * MCU_WIDTH) / 2; + const uint8_t *src = in_uv + (src_y * width) + (src_x * 2); + uint8_t *dst = out + mcu_idx; + + for (int x = 0; x < MCU_BLOCK_SZ; ++x) { + dst[x] = src[x * 2 + 1]; + } + mcu_idx += MCU_BLOCK_SZ; + } +} + +static const struct stm32_jpeg_fmt_conf *stm32_jpeg_get_conf(uint32_t pixelformat) +{ + for (size_t i = 0; i < ARRAY_SIZE(stm32_jpeg_confs); i++) { + if (stm32_jpeg_confs[i].pixelformat == pixelformat) { + return &stm32_jpeg_confs[i]; + } + } + + return NULL; +} + +static void stm32_jpeg_convert_next_mcu(struct stm32_jpeg_data *data) +{ + stm32_jpeg_nv12_to_ycbcr_mcu(data->current_x_mcu++, data->current_y_mcu, + data->current_in->buffer, data->current_in->buffer + + data->m2m.in.fmt.width * data->m2m.in.fmt.height, + data->mcu_ycbcr, data->m2m.in.fmt.width); + if (data->current_x_mcu >= data->m2m.in.fmt.width / MCU_WIDTH) { + data->current_x_mcu = 0; + data->current_y_mcu++; + } +} + +static int stm32_jpeg_start_codec(const struct device *dev) +{ + struct stm32_jpeg_data *data = dev->data; + struct k_fifo *in_fifo_in = &data->m2m.in.fifo_in; + struct k_fifo *out_fifo_in = &data->m2m.out.fifo_in; + int ret; + + if (k_fifo_is_empty(in_fifo_in) || k_fifo_is_empty(out_fifo_in)) { + /* Nothing to do */ + data->codec_is_running = false; + return 0; + } + + data->current_in = k_fifo_get(in_fifo_in, K_NO_WAIT); + data->current_out = k_fifo_get(out_fifo_in, K_NO_WAIT); + + if (data->m2m.in.fmt.pixelformat != VIDEO_PIX_FMT_JPEG) { + const struct stm32_jpeg_fmt_conf *conf = + stm32_jpeg_get_conf(data->m2m.in.fmt.pixelformat); + JPEG_ConfTypeDef jpeg_conf = {0}; + HAL_StatusTypeDef hret; + + __ASSERT_NO_MSG(conf != NULL); + + /* Reset value of current MCU and output buffer offset */ + data->current_x_mcu = 0; + data->current_y_mcu = 0; + + /* JPEG Encoding */ + jpeg_conf.ColorSpace = JPEG_YCBCR_COLORSPACE; + jpeg_conf.ChromaSubsampling = conf->subsampling; + jpeg_conf.ImageWidth = data->m2m.in.fmt.width; + jpeg_conf.ImageHeight = data->m2m.in.fmt.height; + jpeg_conf.ImageQuality = data->jpeg_quality.val; + + hret = HAL_JPEG_ConfigEncoding(&data->hjpeg, &jpeg_conf); + if (hret != HAL_OK) { + LOG_ERR("Failed to configure codec for encoding"); + ret = -EIO; + goto error; + } + + data->codec_is_running = true; + + /* Convert the first MCU (and store it into mcu_ycbcr) */ + stm32_jpeg_convert_next_mcu(data); + + hret = HAL_JPEG_Encode_IT(&data->hjpeg, data->mcu_ycbcr, YCBCR_420_MCU_BLOCK_SIZE, + data->current_out->buffer, data->current_out->size); + if (hret != HAL_OK) { + LOG_ERR("Failed to request encoding"); + ret = -EIO; + goto error; + } + } else { + LOG_ERR("Decoder not yet implemented"); + ret = -EINVAL; + goto error; + } + + return 0; + +error: + data->codec_is_running = false; + return ret; +} + +/* Function called when the data have been generated by the JPEG block */ +void HAL_JPEG_DataReadyCallback(JPEG_HandleTypeDef *hjpeg, uint8_t *data_out, + uint32_t data_length) +{ + struct stm32_jpeg_data *data = + CONTAINER_OF(hjpeg, struct stm32_jpeg_data, hjpeg); + + ARG_UNUSED(data_out); + + k_mutex_lock(&data->lock, K_FOREVER); + + /* Store the output data size and timestamp */ + data->current_out->bytesused = data_length; + data->current_out->timestamp = k_uptime_get_32(); + + k_mutex_unlock(&data->lock); +} + +/* + * Function called when all processing is finished, at that moment we can be + * sure that buffers won't be used anymore + */ +void HAL_JPEG_EncodeCpltCallback(JPEG_HandleTypeDef *hjpeg) +{ + struct stm32_jpeg_data *data = CONTAINER_OF(hjpeg, struct stm32_jpeg_data, hjpeg); + int ret = 0; + + k_mutex_lock(&data->lock, K_FOREVER); + + /* Give back the buffers to the application */ + k_fifo_put(&data->m2m.in.fifo_out, data->current_in); + k_fifo_put(&data->m2m.out.fifo_out, data->current_out); + + /* Try to restart the next processing if needed */ + ret = stm32_jpeg_start_codec(data->dev); + if (ret) { + LOG_ERR("Failed to start codec, err: %d", ret); + goto out; + } + +out: + k_mutex_unlock(&data->lock); +} + +void HAL_JPEG_ErrorCallback(JPEG_HandleTypeDef *hjpeg) +{ + ARG_UNUSED(hjpeg); + + __ASSERT(false, "Got %s", __func__); +} + +/* + * This function is called whenever new input data (MCU) must be given in + * order to proceed the frame + */ +void HAL_JPEG_GetDataCallback(JPEG_HandleTypeDef *hjpeg, uint32_t nb_encoded_data) +{ + struct stm32_jpeg_data *data = + CONTAINER_OF(hjpeg, struct stm32_jpeg_data, hjpeg); + + ARG_UNUSED(nb_encoded_data); + + /* Convert the next MCU */ + stm32_jpeg_convert_next_mcu(data); + + HAL_JPEG_ConfigInputBuffer(hjpeg, data->mcu_ycbcr, YCBCR_420_MCU_BLOCK_SIZE); +} + +static int stm32_jpeg_get_fmt(const struct device *dev, struct video_format *fmt) +{ + struct stm32_jpeg_data *data = dev->data; + + *fmt = fmt->type == VIDEO_BUF_TYPE_INPUT ? data->m2m.in.fmt : data->m2m.out.fmt; + + return 0; +} + +static int stm32_jpeg_set_fmt(const struct device *dev, struct video_format *fmt) +{ + struct stm32_jpeg_data *data = dev->data; + struct video_common_header *common = + fmt->type == VIDEO_BUF_TYPE_INPUT ? &data->m2m.in : &data->m2m.out; + const struct stm32_jpeg_fmt_conf *conf; + int ret = 0; + + /* Validate the settings */ + conf = stm32_jpeg_get_conf(fmt->pixelformat); + if (conf == NULL) { + return -EINVAL; + } + if (fmt->width % conf->hmcu_div || fmt->height % conf->vmcu_div) { + LOG_ERR("Format %s: %d pixels width / %d pixels height multiple required", + VIDEO_FOURCC_TO_STR(fmt->pixelformat), conf->hmcu_div, conf->vmcu_div); + return -EINVAL; + } + + /* + * For the time being only encode is supported, aka NV12 as input and JPEG as output. + * Once decode will also be supported this test can be removed. + */ + if ((fmt->type == VIDEO_BUF_TYPE_INPUT && fmt->pixelformat != VIDEO_PIX_FMT_NV12) || + (fmt->type == VIDEO_BUF_TYPE_OUTPUT && fmt->pixelformat != VIDEO_PIX_FMT_JPEG)) { + return -ENOTSUP; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + if (common->is_streaming) { + ret = -EBUSY; + goto out; + } + + ret = video_estimate_fmt_size(fmt); + if (ret < 0) { + goto out; + } + + common->fmt = *fmt; + +out: + k_mutex_unlock(&data->lock); + + return ret; +} + +static int stm32_jpeg_set_stream(const struct device *dev, bool enable, enum video_buf_type type) +{ + struct stm32_jpeg_data *data = dev->data; + struct video_common_header *common = + type == VIDEO_BUF_TYPE_INPUT ? &data->m2m.in : &data->m2m.out; + int ret = 0; + + k_mutex_lock(&data->lock, K_FOREVER); + + /* Input & Output resolutions are always same so ensure this here */ + if (data->m2m.in.fmt.width != data->m2m.out.fmt.width || + data->m2m.in.fmt.height != data->m2m.out.fmt.height) { + LOG_ERR("Input & output resolution should match"); + return -EINVAL; + } + + if (enable == common->is_streaming) { + ret = -EALREADY; + goto out; + } + + common->is_streaming = enable; + + if (enable) { + ret = stm32_jpeg_start_codec(dev); + } else { + data->codec_is_running = false; + } + +out: + k_mutex_unlock(&data->lock); + + return ret; +} + +static int stm32_jpeg_enqueue(const struct device *dev, struct video_buffer *vbuf) +{ + struct stm32_jpeg_data *data = dev->data; + struct video_common_header *common = + vbuf->type == VIDEO_BUF_TYPE_INPUT ? &data->m2m.in : &data->m2m.out; + int ret = 0; + + /* TODO - need to check for buffer size here */ + + k_mutex_lock(&data->lock, K_FOREVER); + + k_fifo_put(&common->fifo_in, vbuf); + + /* Try to start codec if necessary */ + if (!data->codec_is_running) { + ret = stm32_jpeg_start_codec(dev); + if (ret) { + LOG_ERR("Failed to start codec, err: %d", ret); + goto out; + } + } + +out: + k_mutex_unlock(&data->lock); + + return ret; +} + +static int stm32_jpeg_dequeue(const struct device *dev, struct video_buffer **vbuf, + k_timeout_t timeout) +{ + struct stm32_jpeg_data *data = dev->data; + struct video_common_header *common = + (*vbuf)->type == VIDEO_BUF_TYPE_INPUT ? &data->m2m.in : &data->m2m.out; + + *vbuf = k_fifo_get(&common->fifo_out, timeout); + if (*vbuf == NULL) { + return -EAGAIN; + } + + return 0; +} + +static const struct video_format_cap stm32_jpeg_in_fmts[] = { + { + .pixelformat = VIDEO_PIX_FMT_NV12, + .width_min = 16, + .width_max = 65520, + .height_min = 16, + .height_max = 65520, + .width_step = 16, + .height_step = 16, + }, + {0} +}; + +static const struct video_format_cap stm32_jpeg_out_fmts[] = { + { + .pixelformat = VIDEO_PIX_FMT_JPEG, + .width_min = 16, + .width_max = 65520, + .height_min = 16, + .height_max = 65520, + .width_step = 16, + .height_step = 16, + }, + {0} +}; + +static int stm32_jpeg_get_caps(const struct device *dev, struct video_caps *caps) +{ + if (caps->type == VIDEO_BUF_TYPE_OUTPUT) { + caps->format_caps = stm32_jpeg_out_fmts; + } else { + caps->format_caps = stm32_jpeg_in_fmts; + } + + caps->min_vbuf_count = 1; + + return 0; +} + +static DEVICE_API(video, stm32_jpeg_driver_api) = { + .set_format = stm32_jpeg_set_fmt, + .get_format = stm32_jpeg_get_fmt, + .set_stream = stm32_jpeg_set_stream, + .enqueue = stm32_jpeg_enqueue, + .dequeue = stm32_jpeg_dequeue, + .get_caps = stm32_jpeg_get_caps, +}; + +static int stm32_jpeg_enable_clock(const struct device *dev) +{ + const struct stm32_jpeg_config *config = dev->config; + const struct device *cc_node = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + + if (!device_is_ready(cc_node)) { + LOG_ERR("clock control device not ready"); + return -ENODEV; + } + + /* Turn on JPEG peripheral clock */ + return clock_control_on(cc_node, (clock_control_subsys_t)&config->jpeg_hclken); +} + +static int stm32_jpeg_init(const struct device *dev) +{ + const struct stm32_jpeg_config *cfg = dev->config; + struct stm32_jpeg_data *data = dev->data; + HAL_StatusTypeDef hret; + int ret; + + data->dev = dev; + + ret = stm32_jpeg_enable_clock(dev); + if (ret < 0) { + LOG_ERR("Clock enabling failed."); + return ret; + } + + if (!device_is_ready(cfg->reset_jpeg.dev)) { + LOG_ERR("reset controller not ready"); + return -ENODEV; + } + ret = reset_line_toggle_dt(&cfg->reset_jpeg); + if (ret < 0 && ret != -ENOSYS) { + LOG_ERR("Failed to reset the device."); + return ret; + } + + /* Run IRQ init */ + cfg->irq_config(dev); + +#if defined(CONFIG_SOC_SERIES_STM32N6X) + HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_JPEG, + RIF_ATTRIBUTE_PRIV | RIF_ATTRIBUTE_SEC); +#endif + + /* Initialise default input / output formats */ + k_mutex_init(&data->lock); + k_fifo_init(&data->m2m.in.fifo_in); + k_fifo_init(&data->m2m.in.fifo_out); + k_fifo_init(&data->m2m.out.fifo_in); + k_fifo_init(&data->m2m.out.fifo_out); + + /* Initialize default formats */ + data->m2m.in.fmt.type = VIDEO_BUF_TYPE_INPUT; + data->m2m.in.fmt.width = stm32_jpeg_in_fmts[0].width_min; + data->m2m.in.fmt.height = stm32_jpeg_in_fmts[0].height_min; + data->m2m.in.fmt.pixelformat = stm32_jpeg_in_fmts[0].pixelformat; + data->m2m.out.fmt.type = VIDEO_BUF_TYPE_OUTPUT; + data->m2m.out.fmt.width = stm32_jpeg_out_fmts[0].width_min; + data->m2m.out.fmt.height = stm32_jpeg_out_fmts[0].height_min; + data->m2m.out.fmt.pixelformat = stm32_jpeg_out_fmts[0].pixelformat; + + ret = video_init_ctrl(&data->jpeg_quality, dev, VIDEO_CID_JPEG_COMPRESSION_QUALITY, + (struct video_ctrl_range) {.min = 5, .max = 100, + .step = 1, .def = 50}); + if (ret < 0) { + return ret; + } + + /* Initialize JPEG peripheral */ + hret = HAL_JPEG_Init(&data->hjpeg); + if (hret != HAL_OK) { + LOG_ERR("JPEG initialization failed."); + return -EIO; + } + + LOG_DBG("%s initialized", dev->name); + + return 0; +} + +static void stm32_jpeg_isr(const struct device *dev) +{ + struct stm32_jpeg_data *jpeg = dev->data; + + HAL_JPEG_IRQHandler(&jpeg->hjpeg); +} + +#define STM32_JPEG_INIT(n) \ + static void stm32_jpeg_irq_config_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + stm32_jpeg_isr, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static struct stm32_jpeg_data stm32_jpeg_data_##n = { \ + .hjpeg = { \ + .Instance = (JPEG_TypeDef *)DT_INST_REG_ADDR(n), \ + }, \ + }; \ + \ + static const struct stm32_jpeg_config stm32_jpeg_config_##n = { \ + .jpeg_hclken = STM32_DT_INST_CLOCKS(n), \ + .irq_config = stm32_jpeg_irq_config_##n, \ + .reset_jpeg = RESET_DT_SPEC_INST_GET_BY_IDX(n, 0), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &stm32_jpeg_init, \ + NULL, &stm32_jpeg_data_##n, \ + &stm32_jpeg_config_##n, \ + POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \ + &stm32_jpeg_driver_api); \ + \ + VIDEO_DEVICE_DEFINE(jpeg_##n, DEVICE_DT_INST_GET(n), NULL); + +DT_INST_FOREACH_STATUS_OKAY(STM32_JPEG_INIT) diff --git a/drivers/wifi/infineon/Kconfig.airoc b/drivers/wifi/infineon/Kconfig.airoc index 2df845e964046..44ad9b1a02603 100644 --- a/drivers/wifi/infineon/Kconfig.airoc +++ b/drivers/wifi/infineon/Kconfig.airoc @@ -254,6 +254,11 @@ config CYW955573M2IPA1_SM bool "CYW955573M2IPA1_SM" help Infineon CYW955573M2IPA1 (SM) module + +config CYW55513IUBG_SM + bool "CYW55513IUBG_SM" + help + Infineon CYW55513IUBG (SM) module endchoice endif # AIROC_WIFI diff --git a/dts/arm/nxp/nxp_mcxw71.dtsi b/dts/arm/nxp/nxp_mcxw71.dtsi index 54f1f16383487..7de0893cf7998 100644 --- a/dts/arm/nxp/nxp_mcxw71.dtsi +++ b/dts/arm/nxp/nxp_mcxw71.dtsi @@ -24,17 +24,10 @@ &stcm { ranges = <0x0 0x30000000 DT_SIZE_K(112)>; - - stcm1: system_memory@1a000 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x1a000 DT_SIZE_K(8)>; - zephyr,memory-region = "RetainedMem"; - }; }; &stcm0 { - /* With only the first 64KB having ECC */ - reg = <0x0 DT_SIZE_K(104)>; + reg = <0x0 DT_SIZE_K(112)>; }; &pbridge2 { diff --git a/dts/arm/silabs/xg21/xg21.dtsi b/dts/arm/silabs/xg21/xg21.dtsi index 15a07b76f4e70..8356421e8a780 100644 --- a/dts/arm/silabs/xg21/xg21.dtsi +++ b/dts/arm/silabs/xg21/xg21.dtsi @@ -442,6 +442,12 @@ status = "disabled"; }; + buram: retained-memory@50080000 { + compatible = "silabs,buram"; + reg = <0x50080000 0x80>; + status = "disabled"; + }; + rtcc0: stimer0: rtcc@58000000 { compatible = "silabs,gecko-stimer"; reg = <0x58000000 0x4000>; diff --git a/dts/arm/silabs/xg22/xg22.dtsi b/dts/arm/silabs/xg22/xg22.dtsi index 2e4d3d429629d..0177e3f85dd54 100644 --- a/dts/arm/silabs/xg22/xg22.dtsi +++ b/dts/arm/silabs/xg22/xg22.dtsi @@ -475,6 +475,13 @@ status = "disabled"; }; + buram: retained-memory@50080000 { + compatible = "silabs,buram"; + reg = <0x50080000 0x80>; + clocks = <&cmu CLOCK_BURAM CLOCK_BRANCH_INVALID>; + status = "disabled"; + }; + dcdc: dcdc@50094000 { compatible = "silabs,series2-dcdc"; reg = <0x50094000 0x4000>; diff --git a/dts/arm/silabs/xg23/xg23.dtsi b/dts/arm/silabs/xg23/xg23.dtsi index a8649047a1a07..93bc1006d6f6b 100644 --- a/dts/arm/silabs/xg23/xg23.dtsi +++ b/dts/arm/silabs/xg23/xg23.dtsi @@ -477,6 +477,13 @@ status = "disabled"; }; + buram: retained-memory@50080000 { + compatible = "silabs,buram"; + reg = <0x50080000 0x80>; + clocks = <&cmu CLOCK_BURAM CLOCK_BRANCH_INVALID>; + status = "disabled"; + }; + dcdc: dcdc@50094000 { compatible = "silabs,series2-dcdc"; reg = <0x50094000 0x4000>; diff --git a/dts/arm/silabs/xg24/xg24.dtsi b/dts/arm/silabs/xg24/xg24.dtsi index da3309d671a69..da17df1f25f3b 100644 --- a/dts/arm/silabs/xg24/xg24.dtsi +++ b/dts/arm/silabs/xg24/xg24.dtsi @@ -469,6 +469,13 @@ status = "disabled"; }; + buram: retained-memory@50080000 { + compatible = "silabs,buram"; + reg = <0x50080000 0x80>; + clocks = <&cmu CLOCK_BURAM CLOCK_BRANCH_INVALID>; + status = "disabled"; + }; + dcdc: dcdc@50094000 { compatible = "silabs,series2-dcdc"; reg = <0x50094000 0x4000>; diff --git a/dts/arm/silabs/xg27/xg27.dtsi b/dts/arm/silabs/xg27/xg27.dtsi index 03d3cf613599c..1f97b67cd50ea 100644 --- a/dts/arm/silabs/xg27/xg27.dtsi +++ b/dts/arm/silabs/xg27/xg27.dtsi @@ -475,6 +475,13 @@ status = "disabled"; }; + buram: retained-memory@50080000 { + compatible = "silabs,buram"; + reg = <0x50080000 0x80>; + clocks = <&cmu CLOCK_BURAM CLOCK_BRANCH_PCLK>; + status = "disabled"; + }; + dcdc: dcdc@50094000 { compatible = "silabs,series2-dcdc"; reg = <0x50094000 0x4000>; diff --git a/dts/arm/silabs/xg28/xg28.dtsi b/dts/arm/silabs/xg28/xg28.dtsi index 741419b7d2726..92a188f1acbd0 100644 --- a/dts/arm/silabs/xg28/xg28.dtsi +++ b/dts/arm/silabs/xg28/xg28.dtsi @@ -477,6 +477,13 @@ status = "disabled"; }; + buram: retained-memory@50080000 { + compatible = "silabs,buram"; + reg = <0x50080000 0x80>; + clocks = <&cmu CLOCK_BURAM CLOCK_BRANCH_INVALID>; + status = "disabled"; + }; + dcdc: dcdc@50094000 { compatible = "silabs,series2-dcdc"; reg = <0x50094000 0x4000>; diff --git a/dts/arm/silabs/xg29/xg29.dtsi b/dts/arm/silabs/xg29/xg29.dtsi index bc185c7845d18..17eb20f2a765a 100644 --- a/dts/arm/silabs/xg29/xg29.dtsi +++ b/dts/arm/silabs/xg29/xg29.dtsi @@ -480,6 +480,13 @@ status = "disabled"; }; + buram: retained-memory@50080000 { + compatible = "silabs,buram"; + reg = <0x50080000 0x80>; + clocks = <&cmu CLOCK_BURAM CLOCK_BRANCH_PCLK>; + status = "disabled"; + }; + dcdc: dcdc@50094000 { compatible = "silabs,series2-dcdc"; reg = <0x50094000 0x4000>; diff --git a/dts/arm/st/h7rs/stm32h7rs.dtsi b/dts/arm/st/h7rs/stm32h7rs.dtsi index 62ed844fcb40e..15be4b8c3c18d 100644 --- a/dts/arm/st/h7rs/stm32h7rs.dtsi +++ b/dts/arm/st/h7rs/stm32h7rs.dtsi @@ -853,6 +853,29 @@ status = "disabled"; }; + ethernet@40028000 { + reg = <0x40028000 0x8000>; + compatible = "st,stm32-ethernet-controller"; + clock-names = "stm-eth"; + clocks = <&rcc STM32_CLOCK(AHB1, 15)>; + + mac: ethernet { + compatible = "st,stm32h7-ethernet", "st,stm32-ethernet"; + interrupts = <92 0>; + clock-names = "mac-clk-tx", "mac-clk-rx"; + clocks = <&rcc STM32_CLOCK(AHB1, 16)>, + <&rcc STM32_CLOCK(AHB1, 17)>; + status = "disabled"; + }; + + mdio: mdio { + compatible = "st,stm32-mdio"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; + usbotg_fs: usb@40080000 { compatible = "st,stm32-otgfs"; reg = <0x40080000 0x40000>; diff --git a/dts/arm/st/mp1/stm32mp157.dtsi b/dts/arm/st/mp1/stm32mp157.dtsi index 39f60441624fb..76d506ddbc5b6 100644 --- a/dts/arm/st/mp1/stm32mp157.dtsi +++ b/dts/arm/st/mp1/stm32mp157.dtsi @@ -42,6 +42,15 @@ reg = <0x10000000 DT_SIZE_K(320)>; }; + clocks { + /* NOTE: clocks must be enabled by Cortex-A */ + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "st,stm32-hse-clock"; + status = "disabled"; + }; + }; + soc { compatible = "st,stm32mp157", "st,stm32mp1", "simple-bus"; diff --git a/dts/arm/st/n6/stm32n6.dtsi b/dts/arm/st/n6/stm32n6.dtsi index a1df3ec1b4214..a61a70f7ed366 100644 --- a/dts/arm/st/n6/stm32n6.dtsi +++ b/dts/arm/st/n6/stm32n6.dtsi @@ -1314,6 +1314,15 @@ resets = <&rctl STM32_RESET(APB5, 5)>; status = "disabled"; }; + + jpeg: codec@58023000 { + compatible = "st,stm32-jpeg"; + reg = <0x58023000 0x1000>; + interrupts = <61 0>; + clocks = <&rcc STM32_CLOCK(AHB5, 3)>; + resets = <&rctl STM32_RESET(AHB5, 3)>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/st/u0/stm32u0.dtsi b/dts/arm/st/u0/stm32u0.dtsi index 7e8ca062175e0..a3937f138dc59 100644 --- a/dts/arm/st/u0/stm32u0.dtsi +++ b/dts/arm/st/u0/stm32u0.dtsi @@ -77,13 +77,6 @@ status = "disabled"; }; - clk_hsi48: clk-hsi48 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = ; - status = "disabled"; - }; - clk_msi: clk-msi { #clock-cells = <0>; compatible = "st,stm32-msi-clock"; @@ -111,6 +104,13 @@ compatible = "st,stm32u0-pll-clock"; status = "disabled"; }; + + clk48: clk48 { + #clock-cells = <0>; + compatible = "st,stm32-clock-mux"; + clocks = <&rcc STM32_SRC_MSI CLK48_SEL(1)>; + status = "disabled"; + }; }; soc { @@ -397,7 +397,8 @@ rng: rng@40025000 { compatible = "st,stm32-rng"; reg = <0x40025000 0x400>; - clocks = <&rcc STM32_CLOCK(AHB1, 18)>; + clocks = <&rcc STM32_CLOCK(AHB1, 18)>, + <&rcc STM32_SRC_CK48 NO_SEL>; interrupts = <31 0>; status = "disabled"; }; diff --git a/dts/arm/st/u0/stm32u073.dtsi b/dts/arm/st/u0/stm32u073.dtsi index afa493db5cdaf..8122543d95554 100644 --- a/dts/arm/st/u0/stm32u073.dtsi +++ b/dts/arm/st/u0/stm32u073.dtsi @@ -57,7 +57,17 @@ ram-size = <1024>; maximum-speed = "full-speed"; phys = <&usb_fs_phy>; - clocks = <&rcc STM32_CLOCK(APB1, 13)>; + clocks = <&rcc STM32_CLOCK(APB1, 13)>, + <&rcc STM32_SRC_CK48 NO_SEL>; + status = "disabled"; + }; + }; + + clocks { + clk_hsi48: clk-hsi48 { + #clock-cells = <0>; + compatible = "st,stm32-hsi48-clock"; + clock-frequency = ; status = "disabled"; }; }; diff --git a/dts/arm/st/u5/stm32u599.dtsi b/dts/arm/st/u5/stm32u599.dtsi index 21540ca9bb35e..4cb5fbd902df7 100644 --- a/dts/arm/st/u5/stm32u599.dtsi +++ b/dts/arm/st/u5/stm32u599.dtsi @@ -26,6 +26,20 @@ status = "disabled"; }; + mipi_dsi: dsihost@40016c00 { + compatible = "st,stm32u5-mipi-dsi", "st,stm32-mipi-dsi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40016C00 0x1000>; + clock-names = "dsiclk", "dsisrc", "refclk", "pixelclk"; + clocks = <&rcc STM32_CLOCK(APB2, 27U)>, + <&rcc STM32_SRC_DSIPHY DSI_SEL(1)>, + <&rcc STM32_SRC_HSE NO_SEL>, + <&rcc STM32_SRC_PLL3_R NO_SEL>; + resets = <&rctl STM32_RESET(APB2, 27U)>; + status = "disabled"; + }; + xspi1: spi@420d3400 { compatible = "st,stm32-xspi"; reg = <0x420d3400 0x400>, diff --git a/dts/arm/ti/cc23x0.dtsi b/dts/arm/ti/cc23x0.dtsi index 691d7a6a86fcd..76e0559399838 100644 --- a/dts/arm/ti/cc23x0.dtsi +++ b/dts/arm/ti/cc23x0.dtsi @@ -121,6 +121,7 @@ reg = <0x40026000 0x524>; interrupts = <8 0>; #dma-cells = <2>; + zephyr,pm-device-runtime-auto; status = "disabled"; }; @@ -132,6 +133,7 @@ interrupts = <10 0>; dmas = <&dma 0 0>, <&dma 1 1>; dma-names = "tx", "rx"; + zephyr,disabling-power-states = <&state0 &state1>; status = "disabled"; }; diff --git a/dts/bindings/mipi-dsi/st,stm32u5-mipi-dsi.yaml b/dts/bindings/mipi-dsi/st,stm32u5-mipi-dsi.yaml new file mode 100644 index 0000000000000..0d58d8c282d6a --- /dev/null +++ b/dts/bindings/mipi-dsi/st,stm32u5-mipi-dsi.yaml @@ -0,0 +1,132 @@ +# +# Copyright (c) 2025 Charles Dias +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: | + STM32U5 series MIPI DSI controller. + +compatible: "st,stm32u5-mipi-dsi" + +include: + - name: st,stm32-mipi-dsi.yaml + property-blocklist: + - clock-names + +properties: + clock-names: + type: string-array + required: true + description: | + "dsiclk" DSI clock enable. + "dsisrc" DSI clock source. + "refclk" External crystal or oscillator clock. + "pixelclk" LTDC pixel clock. + "refclk" and "pixelclk" are only used to retrieve the frequency for timing calculation. + + phy-freq-range: + required: true + type: int + enum: + - 0x0 + - 0x1 + - 0x2 + - 0x3 + - 0x4 + - 0x5 + - 0x6 + - 0x7 + - 0x8 + description: | + D-PHY PLL input frequency range. This is used to select the appropriate + frequency range for the D-PHY PLL operation. + 0x0 : DSI_DPHY_FRANGE_80MHZ_100MHZ + 0x1 : DSI_DPHY_FRANGE_100MHZ_120MHZ + 0x2 : DSI_DPHY_FRANGE_120MHZ_160MHZ + 0x3 : DSI_DPHY_FRANGE_160MHZ_200MHZ + 0x4 : DSI_DPHY_FRANGE_200MHZ_240MHZ + 0x5 : DSI_DPHY_FRANGE_240MHZ_320MHZ + 0x6 : DSI_DPHY_FRANGE_320MHZ_390MHZ + 0x7 : DSI_DPHY_FRANGE_390MHZ_450MHZ + 0x8 : DSI_DPHY_FRANGE_450MHZ_510MHZ + + phy-low-power-offset: + required: true + type: int + enum: + - 0x0 + - 0x1 + - 0x2 + - 0x3 + - 0x4 + - 0x5 + - 0x6 + - 0x7 + - 0x8 + - 0x9 + - 0xA + - 0xB + - 0xC + - 0xD + - 0xE + - 0xF + description: | + D-PHY low power offset configuration specific to STM32U5 series. + 0x0 : PHY_LP_OFFSSET_0_CLKP (0 CLKP) + 0x1 : PHY_LP_OFFSSET_1_CLKP (+1 CLKP) + 0x2 : PHY_LP_OFFSSET_2_CLKP (+2 CLKP) + 0x3 : PHY_LP_OFFSSET_3_CLKP (+3 CLKP) + 0x4 : PHY_LP_OFFSSET_4_CLKP (+4 CLKP) + 0x5 : PHY_LP_OFFSSET_5_CLKP (+5 CLKP) + 0x6 : PHY_LP_OFFSSET_6_CLKP (+6 CLKP) + 0x7 : PHY_LP_OFFSSET_7_CLKP (+7 CLKP) + 0x8 : PHY_LP_OFFSSET_MINUS_1_CLKP (-1 CLKP) + 0x9 : PHY_LP_OFFSSET_MINUS_2_CLKP (-2 CLKP) + 0xA : PHY_LP_OFFSSET_MINUS_3_CLKP (-3 CLKP) + 0xB : PHY_LP_OFFSSET_MINUS_4_CLKP (-4 CLKP) + 0xC : PHY_LP_OFFSSET_MINUS_5_CLKP (-5 CLKP) + 0xD : PHY_LP_OFFSSET_MINUS_6_CLKP (-6 CLKP) + 0xE : PHY_LP_OFFSSET_MINUS_7_CLKP (-7 CLKP) + 0xF : PHY_LP_OFFSSET_MINUS_8_CLKP (-8 CLKP) + + pll-vco-range: + required: true + type: int + enum: + - 0x0 + - 0x1 + description: | + PLL VCO frequency range configuration for STM32U5 D-PHY. + 0x0 : DSI_DPHY_VCO_FRANGE_500MHZ_800MHZ + 0x1 : DSI_DPHY_VCO_FRANGE_800MHZ_1GHZ + + pll-charge-pump: + required: true + type: int + enum: + - 0x0 + - 0x1 + - 0x2 + - 0x3 + description: | + PLL charge pump configuration for STM32U5 D-PHY. + Valid values: + 0x0 : DSI_PLL_CHARGE_PUMP_2000HZ_4400HZ + 0x1 : DSI_PLL_CHARGE_PUMP_4400HZ_14100HZ + 0x0 : DSI_PLL_CHARGE_PUMP_14100HZ_30900HZ + 0x3 : DSI_PLL_CHARGE_PUMP_30900HZ_45700HZ + 0x2 : DSI_PLL_CHARGE_PUMP_45700HZ_50000HZ + + pll-tuning: + required: true + type: int + enum: + - 0x0 + - 0x1 + - 0x2 + description: | + PLL tuning parameter (loop filter) for STM32U5 D-PHY. + 0x0 : DSI_PLL_LOOP_FILTER_2000HZ_4400HZ + 0x1 : DSI_PLL_LOOP_FILTER_4400HZ_30900HZ + 0x2 : DSI_PLL_LOOP_FILTER_30900HZ_50000HZ diff --git a/dts/bindings/mtd/infineon,fm25xxx.yaml b/dts/bindings/mtd/infineon,fm25xxx.yaml new file mode 100644 index 0000000000000..d2aa89cbcb056 --- /dev/null +++ b/dts/bindings/mtd/infineon,fm25xxx.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2025 Luna Pes +# SPDX-License-Identifier: Apache-2.0 + +description: Infineon FM25XXX SPI FRAM + +compatible: "infineon,fm25xxx" + +include: ["eeprom-base.yaml", spi-device.yaml] + +properties: + size: + required: true + description: Total FRAM size in bytes. diff --git a/dts/bindings/retained_mem/silabs,buram.yaml b/dts/bindings/retained_mem/silabs,buram.yaml new file mode 100644 index 0000000000000..2c263c6f7145c --- /dev/null +++ b/dts/bindings/retained_mem/silabs,buram.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2025 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +title: Silicon Labs Series 2 BURAM (Back-Up Random Access Memory) + +description: | + The Back-Up RAM (BURAM) is a dedicated 128-byte memory that remains powered when the system enters + EM4. Upon exit from EM4, the data retained in the BURAM can be accessed by the application + software. + +compatible: "silabs,buram" + +include: base.yaml + +properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + reg: + required: true diff --git a/dts/bindings/sensor/allegro,als31300.yaml b/dts/bindings/sensor/allegro,als31300.yaml new file mode 100644 index 0000000000000..2469517429d9e --- /dev/null +++ b/dts/bindings/sensor/allegro,als31300.yaml @@ -0,0 +1,7 @@ +# ALS31300 Device Tree Binding + +description: Allegro ALS31300 3D Linear Hall Effect Sensor + +compatible: "allegro,als31300" + +include: [sensor-device.yaml, i2c-device.yaml] diff --git a/dts/bindings/sensor/invensense,icm45686-common.yaml b/dts/bindings/sensor/invensense,icm45686-common.yaml index e89e94c019a04..9bf4c78be48b4 100644 --- a/dts/bindings/sensor/invensense,icm45686-common.yaml +++ b/dts/bindings/sensor/invensense,icm45686-common.yaml @@ -147,3 +147,12 @@ properties: Specify the FIFO watermark level in frame count. Default is power-up configuration (disabled). Valid range: 0 - 104 + + fifo-watermark-equals: + type: boolean + description: | + This value changes the FIFO watermark interrupt behavior by only triggering when the number + of samples is equal to the threshold (count = watermark). + + Otherwise, it will generate interrupts when the level is greater or equals the FIFO Watermark + Threshold (count >= watermark). diff --git a/dts/bindings/sensor/microchip,mtch9010.yaml b/dts/bindings/sensor/microchip,mtch9010.yaml new file mode 100644 index 0000000000000..1f72de98af7fa --- /dev/null +++ b/dts/bindings/sensor/microchip,mtch9010.yaml @@ -0,0 +1,127 @@ +# Copyright (c) 2025 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +title: MTCH9010 Liquid Detector + +description: | + Microchip MTCH9010 liquid leak detector + + - Detects liquid leaks using capacitance or conductance + - Interrupt driven or UART output + + - For more information: + - https://www.microchip.com/en-us/product/mtch9010 + +compatible: "microchip,mtch9010" + +include: [sensor-device.yaml, uart-device.yaml] + +properties: + operating-mode: + type: string + required: true + description: | + Sets moisture detection mode (capacitive or conductive) + Keep in sync with dt-bindings/sensor/mtch9010.h + enum: + - "MTCH9010_CAPACITIVE" + - "MTCH9010_CONDUCTIVE" + + sleep-period: + type: int + description: | + Amount of time (in seconds) the sensor will sleep between each check. + Leave undefined or at 0 to sleep until wake. + enum: + - 0 + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + - 256 + + uart-config-enable: + type: boolean + description: | + If set, the MTCH9010 is configured over the UART Interface. + To be disabled if the sensor is configured through its + I/O or a start-up configuration was previously defined. + + extended-output-enable: + type: boolean + description: | + If set, the output format of the MTCH9010 can be changed. + If not set, the MTCH9010 uses the default formatting. + + extended-output-format: + type: string + description: | + Output data formatting configuration. + enum: + - "MTCH9010_OUTPUT_FORMAT_DELTA" + - "MTCH9010_OUTPUT_FORMAT_CURRENT" + - "MTCH9010_OUTPUT_FORMAT_BOTH" + - "MTCH9010_OUTPUT_FORMAT_MPLAB_DATA_VISUALIZER" + + reference-value: + type: int + description: | + Set the reference "dry" value. + If not defined, the POR value of the sensor is used. + KConfig symbol MTCH9010_REFERENCE_AVERAGING_COUNT + can be used to setup averaging of this value. + + detect-value: + type: int + required: true + description: | + Set the detection threshold value. + + output-gpios: + type: phandle-array + description: Output Status Line for the MTCH9010 + + system-lock-gpios: + type: phandle-array + description: | + System lock I/O for the MTCH9010 + Unused if SYSTEM LOCK is not used. + + mode-gpios: + type: phandle-array + description: | + Mode select I/O for the MTCH9010 + Unused if device is configured with UART or connected externally. + + reset-gpios: + type: phandle-array + description: | + Reset I/O for MTCH9010 + Pulled low to reset the device. + + wake-gpios: + type: phandle-array + description: | + Wake I/O for the MTCH9010 + Not used if a sleep period is defined. + + uart-en-gpios: + type: phandle-array + description: | + UART enable line for the MTCH9010 + Unused if the UART EN pin is connected externally. + + cfg-en-gpios: + type: phandle-array + description: | + Enhanced configuration enable for the MTCH9010 + Unused if device is configured with UART or connected externally. + + heartbeat-gpios: + type: phandle-array + description: | + Heartbeat output of MTCH9010 diff --git a/dts/bindings/video/st,stm32-jpeg.yaml b/dts/bindings/video/st,stm32-jpeg.yaml new file mode 100644 index 0000000000000..b2549f26a3204 --- /dev/null +++ b/dts/bindings/video/st,stm32-jpeg.yaml @@ -0,0 +1,28 @@ +# +# Copyright (c) 2025 STMicroelectronics. +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: | + STM32 JPEG HW Codec. + + The STM32 JPEG HW codec can decode JPEG compressed frames + and encode uncompressed frames to the JPEG format. + +compatible: "st,stm32-jpeg" + +include: [base.yaml, reset-device.yaml] + +properties: + reg: + required: true + + clocks: + required: true + + interrupts: + required: true + + resets: + required: true diff --git a/include/zephyr/arch/riscv/structs.h b/include/zephyr/arch/riscv/structs.h index 11e4935a51283..691b67a922a0a 100644 --- a/include/zephyr/arch/riscv/structs.h +++ b/include/zephyr/arch/riscv/structs.h @@ -22,6 +22,15 @@ struct _cpu_arch { atomic_ptr_val_t fpu_owner; uint32_t fpu_state; #endif +#if defined(CONFIG_CPP) && !defined(CONFIG_USERSPACE) && \ + !(defined(CONFIG_SMP) || (CONFIG_MP_MAX_NUM_CPUS > 1)) && !defined(CONFIG_FPU_SHARING) + /* Empty struct has size 0 in C, size 1 in C++. Force them to be the same. */ + uint8_t unused_cpp_size_compatibility; +#endif }; +#if defined(CONFIG_CPP) +BUILD_ASSERT(sizeof(struct _cpu_arch) >= 1); +#endif + #endif /* ZEPHYR_INCLUDE_RISCV_STRUCTS_H_ */ diff --git a/include/zephyr/arch/riscv/thread.h b/include/zephyr/arch/riscv/thread.h index 81376681cdbe6..2ae6f5cce927b 100644 --- a/include/zephyr/arch/riscv/thread.h +++ b/include/zephyr/arch/riscv/thread.h @@ -82,8 +82,17 @@ struct _thread_arch { unsigned long m_mode_pmpaddr_regs[CONFIG_PMP_SLOTS]; unsigned long m_mode_pmpcfg_regs[CONFIG_PMP_SLOTS / sizeof(unsigned long)]; #endif +#if defined(CONFIG_CPP) && !defined(CONFIG_FPU_SHARING) && !defined(CONFIG_USERSPACE) && \ + !defined(CONFIG_PMP_STACK_GUARD) + /* Empty struct has size 0 in C, size 1 in C++. Force them to be the same. */ + uint8_t unused_cpp_size_compatibility; +#endif }; +#if defined(CONFIG_CPP) +BUILD_ASSERT(sizeof(struct _thread_arch) >= 1); +#endif + typedef struct _thread_arch _thread_arch_t; #endif /* _ASMLANGUAGE */ diff --git a/include/zephyr/drivers/sensor/mtch9010.h b/include/zephyr/drivers/sensor/mtch9010.h new file mode 100644 index 0000000000000..787af3aefd6e5 --- /dev/null +++ b/include/zephyr/drivers/sensor/mtch9010.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_MTCH9010_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_MTCH9010_H_ + +#include + +#include +#include +#include +#include +#include + +#define MTCH9010_MAX_RESULT 65535 +#define MTCH9010_MIN_RESULT 0 + +enum sensor_channel_mtch9010 { + /* Polls the state of the OUT line */ + SENSOR_CHAN_MTCH9010_OUT_STATE = SENSOR_CHAN_PRIV_START, + /* Calculates if the OUT line would be asserted based on previous result */ + SENSOR_CHAN_MTCH9010_SW_OUT_STATE, + /* Returns the reference value set for the sensor */ + SENSOR_CHAN_MTCH9010_REFERENCE_VALUE, + /* Returns the threshold value set for the sensor */ + SENSOR_CHAN_MTCH9010_THRESHOLD_VALUE, + /* Returns the last measured result */ + SENSOR_CHAN_MTCH9010_MEAS_RESULT, + /* Returns the last measured result */ + SENSOR_CHAN_MTCH9010_MEAS_DELTA, + /* Returns true if the heartbeat is an error state */ + SENSOR_CHAN_MTCH9010_HEARTBEAT_ERROR_STATE +}; + +#endif diff --git a/include/zephyr/dt-bindings/clock/stm32u0_clock.h b/include/zephyr/dt-bindings/clock/stm32u0_clock.h index 50e76c573d781..d4d135d72c727 100644 --- a/include/zephyr/dt-bindings/clock/stm32u0_clock.h +++ b/include/zephyr/dt-bindings/clock/stm32u0_clock.h @@ -35,6 +35,7 @@ #define STM32_SRC_PLL_P (STM32_SRC_PCLK + 1) #define STM32_SRC_PLL_Q (STM32_SRC_PLL_P + 1) #define STM32_SRC_PLL_R (STM32_SRC_PLL_Q + 1) +#define STM32_SRC_CK48 (STM32_SRC_PLL_R + 1) /** @brief RCC_CCIPR register offset */ #define CCIPR_REG 0x88 diff --git a/include/zephyr/dt-bindings/clock/stm32u5_clock.h b/include/zephyr/dt-bindings/clock/stm32u5_clock.h index 68d74fe40add1..6a68e6ae8a686 100644 --- a/include/zephyr/dt-bindings/clock/stm32u5_clock.h +++ b/include/zephyr/dt-bindings/clock/stm32u5_clock.h @@ -38,6 +38,8 @@ #define STM32_SRC_PLL3_P (STM32_SRC_PLL2_R + 1) #define STM32_SRC_PLL3_Q (STM32_SRC_PLL3_P + 1) #define STM32_SRC_PLL3_R (STM32_SRC_PLL3_Q + 1) +/** DSI PHY clock */ +#define STM32_SRC_DSIPHY (STM32_SRC_PLL3_R + 1) /** Clock muxes */ /* #define STM32_SRC_ICLK TBD */ @@ -89,7 +91,7 @@ #define SAE_SEL(val) STM32_DT_CLOCK_SELECT((val), 1, 11, CCIPR2_REG) #define RNG_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 12, CCIPR2_REG) #define SDMMC_SEL(val) STM32_DT_CLOCK_SELECT((val), 1, 14, CCIPR2_REG) -#define DSIHOST_SEL(val) STM32_DT_CLOCK_SELECT((val), 1, 15, CCIPR2_REG) +#define DSI_SEL(val) STM32_DT_CLOCK_SELECT((val), 1, 15, CCIPR2_REG) #define USART6_SEL(val) STM32_DT_CLOCK_SELECT((val), 1, 16, CCIPR2_REG) #define LTDC_SEL(val) STM32_DT_CLOCK_SELECT((val), 1, 18, CCIPR2_REG) #define OCTOSPI_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 20, CCIPR2_REG) diff --git a/include/zephyr/dt-bindings/sensor/mtch9010.h b/include/zephyr/dt-bindings/sensor/mtch9010.h new file mode 100644 index 0000000000000..678c40aa0f180 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/mtch9010.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_MTCH9010_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_MTCH9010_H_ + +/* Operating Mode */ +#define MTCH9010_CAPACITIVE 0x0 +#define MTCH9010_CONDUCTIVE 0x1 + +/* Output UART Data Formats */ +#define MTCH9010_OUTPUT_FORMAT_DELTA 0x0 +#define MTCH9010_OUTPUT_FORMAT_CURRENT 0x1 +#define MTCH9010_OUTPUT_FORMAT_BOTH 0x2 +#define MTCH9010_OUTPUT_FORMAT_MPLAB_DATA_VISUALIZER 0x3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_MTCH9010_H_ */ diff --git a/modules/hal_infineon/CMakeLists.txt b/modules/hal_infineon/CMakeLists.txt index dbdc0c890d062..dd400d5ef3b00 100644 --- a/modules/hal_infineon/CMakeLists.txt +++ b/modules/hal_infineon/CMakeLists.txt @@ -71,8 +71,8 @@ if(CONFIG_SOC_FAMILY_INFINEON_EDGE) endif() ## Add Wi-Fi assets for AIROC devices -if(CONFIG_WIFI_AIROC) - add_subdirectory(wifi-host-driver) +if (CONFIG_WIFI_AIROC) + add_subdirectory(whd-expansion) ## Add core-lib sources for CAT1 devices add_subdirectory_ifndef(CONFIG_SOC_FAMILY_INFINEON_CAT1 core-lib) diff --git a/modules/hal_infineon/wifi-host-driver/CMakeLists.txt b/modules/hal_infineon/whd-expansion/CMakeLists.txt similarity index 50% rename from modules/hal_infineon/wifi-host-driver/CMakeLists.txt rename to modules/hal_infineon/whd-expansion/CMakeLists.txt index 9317a146886f4..2b1c29440749c 100644 --- a/modules/hal_infineon/wifi-host-driver/CMakeLists.txt +++ b/modules/hal_infineon/whd-expansion/CMakeLists.txt @@ -1,4 +1,5 @@ -# Copyright (c) 2023 Cypress Semiconductor Corporation. +# Copyright (c) 2025 Infineon Technologies AG, +# or an affiliate of Infineon Technologies AG. # # SPDX-License-Identifier: Apache-2.0 @@ -9,8 +10,8 @@ else() endif() set(hal_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}) -set(hal_wifi_dir ${hal_dir}/wifi-host-driver) -set(hal_wifi_dir_resources ${hal_dir}/wifi-host-driver/WHD/${whd_wifi_ver}/resources) +set(hal_wifi_dir ${hal_dir}/whd-expansion) +set(hal_wifi_dir_resources ${hal_dir}/whd-expansion/WHD/${whd_wifi_ver}/resources) set(hal_blobs_dir ${hal_dir}/zephyr/blobs/img/whd/resources) set(blob_gen_dir ${ZEPHYR_BINARY_DIR}/include/generated) @@ -31,38 +32,46 @@ if(CONFIG_WHD_DISABLE_SDIO_PULLUP_DURING_SPI_SLEEP) zephyr_compile_definitions(WHD_DISABLE_SDIO_PULLUP_DURING_SPI_SLEEP) endif() +zephyr_compile_definitions(WHD_ZEPHYR) + # Add WHD includes zephyr_include_directories(${hal_wifi_dir}) zephyr_include_directories(${hal_wifi_dir}/WHD/${whd_wifi_ver}/inc) zephyr_include_directories(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src) zephyr_include_directories(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/include) +zephyr_include_directories(${hal_wifi_dir}/WHD/${whd_wifi_ver}/resources) zephyr_include_directories(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/bus_protocols) zephyr_include_directories(${hal_wifi_dir}/WHD/${whd_wifi_ver}/resources/resource_imp) +# common/inc +zephyr_include_directories(${hal_wifi_dir}/WHD/COMMON/inc) + +# common/src +zephyr_library_sources(${hal_wifi_dir}/WHD/COMMON/src/whd_bus_common.c) +zephyr_library_sources(${hal_wifi_dir}/WHD/COMMON/src/whd_cdc_bdc.c) +zephyr_library_sources(${hal_wifi_dir}/WHD/COMMON/src/whd_clm.c) +zephyr_library_sources(${hal_wifi_dir}/WHD/COMMON/src/whd_sdpcm.c) +zephyr_library_sources(${hal_wifi_dir}/WHD/COMMON/src/whd_utils.c) +zephyr_library_sources(${hal_wifi_dir}/WHD/COMMON/src/whd_wifi.c) +zephyr_library_sources(${hal_wifi_dir}/WHD/COMMON/src/whd_logging.c) +zephyr_library_sources(${hal_wifi_dir}/WHD/COMMON/src/whd_debug.c) + # src zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_ap.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_buffer_api.c) -zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_cdc_bdc.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_chip.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_chip_constants.c) -zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_clm.c) -zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_debug.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_events.c) -zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_logging.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_management.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_network_if.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_proto.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_resource_if.c) -zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_sdpcm.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_thread.c) -zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_utils.c) -zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_wifi.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_wifi_api.c) zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/whd_wifi_p2p.c) # src/bus_protocols zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/bus_protocols/whd_bus.c) -zephyr_library_sources(${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/bus_protocols/whd_bus_common.c) zephyr_library_sources_ifdef(CONFIG_AIROC_WIFI_BUS_SDIO ${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/bus_protocols/whd_bus_sdio_protocol.c) zephyr_library_sources_ifdef(CONFIG_AIROC_WIFI_BUS_SPI ${hal_wifi_dir}/WHD/${whd_wifi_ver}/src/bus_protocols/whd_bus_spi_protocol.c) @@ -82,64 +91,55 @@ endif() # CYW43012 firmware if(CONFIG_CYW43012 AND NOT CONFIG_AIROC_WIFI_CUSTOM) - # firmware if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_43012/43012C0-mfgtest_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_43012/43012C0-mfgtest.bin) else() - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_43012/43012C0_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_43012/43012C0.bin) endif() endif() # CYW43022 firmware if(CONFIG_CYW43022 AND NOT CONFIG_AIROC_WIFI_CUSTOM) - # firmware if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_43022/COMPONENT_SM/43022C1-mfgtest_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_43022/COMPONENT_SM/43022C1-mfgtest.trxs) else() - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_43022/COMPONENT_SM/43022C1_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_43022/COMPONENT_SM/43022C1.trxs) endif() endif() # CYW4343W firmware if(CONFIG_CYW4343W AND NOT CONFIG_AIROC_WIFI_CUSTOM) - # firmware if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_4343W/4343WA1-mfgtest_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_4343W/4343WA1-mfgtest.bin) else() - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_4343W/4343WA1_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_4343W/4343WA1.bin) endif() endif() -# CYW43438 firmware/clm +# CYW43438 firmware if(CONFIG_CYW43438 AND NOT CONFIG_AIROC_WIFI_CUSTOM) - # firmware/clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_43438/43438A1-mfgtest_bin.c) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_43438/43438A1-mfgtest_clm_blob.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_43438/43438A1-mfgtest.bin) else() - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_43438/43438A1_bin.c) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_43438/43438A1_clm_blob.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_43438/43438A1.bin) endif() - endif() # CYW43439 firmware if(CONFIG_CYW43439 AND NOT CONFIG_AIROC_WIFI_CUSTOM) - # firmware if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_43439/43439A0-mfgtest_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_43439/43439A0-mfgtest.bin) else() - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_43439/43439a0_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_43439/43439A0.bin) endif() endif() # CYW4373 firmware if(CONFIG_CYW4373 AND NOT CONFIG_AIROC_WIFI_CUSTOM) - # firmware if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_4373/4373A0-mfgtest_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_4373/4373A0-mfgtest.bin) else() - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_4373/4373A0_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_4373/4373A0.bin) endif() endif() @@ -147,104 +147,96 @@ endif() if(CONFIG_CYW43012_MURATA_1LV AND NOT CONFIG_AIROC_WIFI_CUSTOM) # clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_43012/43012C0-mfgtest_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_43012/COMPONENT_MURATA-1LV/43012C0-mfgtest.clm_blob) else() - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_43012/43012C0_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_43012/COMPONENT_MURATA-1LV/43012C0.clm_blob) endif() - # nvram - zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_43012/COMPONENT_MURATA-1LV) + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_43012/COMPONENT_MURATA-1LV/cyw9cy8ckit_062S2_43012.txt) endif() # CYW43022CUB clm/nvram if(CONFIG_CYW43022CUB AND NOT CONFIG_AIROC_WIFI_CUSTOM) # clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_43022/43022C1-mfgtest_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_43022/COMPONENT_CYW43022CUB/43022C1-mfgtest.clm_blob) else() - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_43022/43022C1_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_43022/COMPONENT_CYW43022CUB/43022C1.clm_blob) endif() - # nvram - zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_43022/COMPONENT_CYW43022CUB) + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_43022/COMPONENT_CYW43022CUB/cyw943022sdm2wlipa_rev3.1.txt) endif() # CYW4343W_MURATA_1DX clm/nvram if(CONFIG_CYW4343W_MURATA_1DX AND NOT CONFIG_AIROC_WIFI_CUSTOM) # clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_4343W/4343WA1-mfgtest_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_4343W/COMPONENT_MURATA-1DX/4343WA1-mfgtest.clm_blob) else() - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_4343W/4343WA1_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_4343W/COMPONENT_MURATA-1DX/4343WA1.clm_blob) endif() - # nvram - zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_4343W/COMPONENT_MURATA-1DX) + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_4343W/COMPONENT_MURATA-1DX/cyw94343cy8cmod.txt) endif() -# CYW43439_MURATA_1YN +# CYW43439_MURATA_1YN clm/nvram if(CONFIG_CYW43439_MURATA_1YN AND NOT CONFIG_AIROC_WIFI_CUSTOM) # clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_43439/43439A0-mfgtest_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_43439/COMPONENT_MURATA-1YN/43439A0-mfgtest.clm_blob) else() - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_43439/43439A0_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_43439/COMPONENT_MURATA-1YN/43439A0.clm_blob) endif() - # nvram - zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_43439/COMPONENT_MURATA-1YN) + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_43439/COMPONENT_MURATA-1YN/cyfmac43439-1YN.txt) endif() # CYW43439_STERLING_LWBPLUS if(CONFIG_CYW43439_STERLING_LWBPLUS AND NOT CONFIG_AIROC_WIFI_CUSTOM) # clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_43439/43439A0-mfgtest_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_43439/COMPONENT_STERLING-LWBplus/43439A0-mfgtest.clm_blob) else() - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_43439/43439A0_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_43439/COMPONENT_STERLING-LWBplus/43439A0.clm_blob) endif() - # nvram - zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_43439/COMPONENT_STERLING-LWBplus) + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_43439/COMPONENT_STERLING-LWBplus/cyfmac43439-1YN.txt) endif() # CYW4373_STERLING_LWB5PLUS if(CONFIG_CYW4373_STERLING_LWB5PLUS AND NOT CONFIG_AIROC_WIFI_CUSTOM) # clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/4373A0-mfgtest_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/4373A0-mfgtest.clm_blob) else() - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/4373A0_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/4373A0.clm_blob) endif() - # nvram - zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_4373/COMPONENT_STERLING-LWB5plus) + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/cyfmac4373-2AE.txt) endif() # CYW4373_MURATA-2AE if(CONFIG_CYW4373_MURATA_2AE AND NOT CONFIG_AIROC_WIFI_CUSTOM) # clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_MURATA-2AE/4373A0-mfgtest_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_MURATA-2AE/4373A0-mfgtest.clm_blob) else() - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_MURATA-2AE/4373A0_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_MURATA-2AE/4373A0.clm_blob) endif() - # nvram - zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_4373/COMPONENT_MURATA-2AE) + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_4373/COMPONENT_MURATA-2AE/cyfmac4373-2AE.txt) endif() # CYW4373_MURATA-2BC if(CONFIG_CYW4373_MURATA_2BC AND NOT CONFIG_AIROC_WIFI_CUSTOM) # clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_MURATA-2BC/4373A0-mfgtest_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_MURATA-2BC/4373A0-mfgtest.clm_blob) else() - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_MURATA-2BC/4373A0_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_4373/COMPONENT_MURATA-2BC/4373A0.clm_blob) endif() - # nvram - zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_4373/COMPONENT_MURATA-2BC) + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_4373/COMPONENT_MURATA-2BC/cyfmac4373-2BC.txt) endif() ############################################################################################################ @@ -258,53 +250,74 @@ endif() # CYW55500 firmware if(CONFIG_CYW55500 AND NOT CONFIG_AIROC_WIFI_CUSTOM) - # firmware if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_55500/COMPONENT_SM/55500A1-mfgtest_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_55500/COMPONENT_SM/55500A1-mfgtest.trxcse) else() - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_55500/COMPONENT_SM/55500A1_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_55500/COMPONENT_SM/55500A1.trxcse) endif() endif() # CYW55572 firmware if(CONFIG_CYW55572 AND NOT CONFIG_AIROC_WIFI_CUSTOM) - # firmware if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_55572/COMPONENT_SM/55572A1-mfgtest_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_55572/COMPONENT_SM/55572A1-mfgtest.trxse) else() - zephyr_library_sources(${hal_blobs_dir}/firmware/COMPONENT_55572/COMPONENT_SM/55572A1_bin.c) + set(FW_IMAGE_NAME ${hal_blobs_dir}/firmware/COMPONENT_55572/COMPONENT_SM/55572A1-mfgtest.trxse) endif() endif() - -# CYW955513SDM2WLIPA_SM +# CYW955513SDM2WLIPA_SM clm, nvram if(CONFIG_CYW955513SDM2WLIPA_SM AND NOT CONFIG_AIROC_WIFI_CUSTOM) - # clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_55500/55500A1-mfgtest_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_55500/COMPONENT_CYW955513SDM2WLIPA/55500A1-mfgtest.clm_blob) else() - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_55500/55500A1_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_55500/COMPONENT_CYW955513SDM2WLIPA/55500A1.clm_blob) endif() + # nvram + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_55500/COMPONENT_CYW955513SDM2WLIPA/cyw955513sdm2wlipa.txt) +endif() +# CYW55513IUBG_SM clm, nvram +if(CONFIG_CYW55513IUBG_SM AND NOT CONFIG_AIROC_WIFI_CUSTOM) + # clm + if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_55500/COMPONENT_CYW55513IUBG/55500A1-mfgtest.clm_blob) + else() + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_55500/COMPONENT_CYW55513IUBG/55500A1.clm_blob) + endif() # nvram - zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_55500/COMPONENT_CYW955513SDM2WLIPA) + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_55500/COMPONENT_CYW55513IUBG/cyw955513wlipa_rev103.txt) endif() # CYW955573M2IPA1_SM if(CONFIG_CYW955573M2IPA1_SM AND NOT CONFIG_AIROC_WIFI_CUSTOM) - # clm if(CONFIG_AIROC_WLAN_MFG_FIRMWARE) - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_55572/55572A1-mfgtest_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_55572/COMPONENT_CYW955573M2IPA1/55572A1-mfgtest.clm_blob) else() - zephyr_library_sources(${hal_blobs_dir}/clm/COMPONENT_55572/55572A1_clm_blob.c) + set(CLM_IMAGE_NAME ${hal_blobs_dir}/clm/COMPONENT_55572/COMPONENT_CYW955573M2IPA1/55572A1.clm_blob) endif() # nvram - zephyr_include_directories(${hal_wifi_dir_resources}/nvram/COMPONENT_55572/COMPONENT_CYW955573M2IPA1) + set(NVRAM_IMAGE_NAME ${hal_wifi_dir_resources}/nvram/COMPONENT_55572/COMPONENT_CYW955573M2IPA1/cyw955573m2ipa1_rev1.01.txt) endif() +# set fw size +file(SIZE ${FW_IMAGE_NAME} FW_IMAGE_SIZE) +zephyr_compile_definitions(FW_IMAGE_NAME="${FW_IMAGE_NAME}") +zephyr_compile_definitions(FW_IMAGE_SIZE=${FW_IMAGE_SIZE}) + +# set clm size +file(SIZE ${CLM_IMAGE_NAME} CLM_IMAGE_SIZE) +zephyr_compile_definitions(CLM_IMAGE_NAME="${CLM_IMAGE_NAME}") +zephyr_compile_definitions(CLM_IMAGE_SIZE=${CLM_IMAGE_SIZE}) + +# set nvram size +file(SIZE ${NVRAM_IMAGE_NAME} NVRAM_IMAGE_SIZE) +zephyr_compile_definitions(NVRAM_IMAGE_NAME="${NVRAM_IMAGE_NAME}") +zephyr_compile_definitions(NVRAM_IMAGE_SIZE=${NVRAM_IMAGE_SIZE}) + # generate FW inc_blob from fw_bin if(EXISTS ${airoc_wifi_fw_bin}) message(INFO " generate include of blob FW file: ${airoc_wifi_fw_bin}") diff --git a/modules/mbedtls/CMakeLists.txt b/modules/mbedtls/CMakeLists.txt index b3dcfcf5fefbe..0c549860e7511 100644 --- a/modules/mbedtls/CMakeLists.txt +++ b/modules/mbedtls/CMakeLists.txt @@ -125,11 +125,11 @@ zephyr_interface_library_named(mbedTLS) zephyr_library_sources_ifdef(CONFIG_MBEDTLS_SHELL shell.c) zephyr_library_app_memory(k_mbedtls_partition) - if(CONFIG_ARCH_POSIX AND CONFIG_ASAN AND NOT CONFIG_64BIT) + if(CONFIG_ARCH_POSIX AND CONFIG_ASAN AND NOT CONFIG_64BIT AND NOT CONFIG_NO_OPTIMIZATIONS) # i386 assembly code used in MBEDTLS does not compile with size optimization # if address sanitizer is enabled, as such switch default optimization level # to speed - set_property(SOURCE ${ZEPHYR_CURRENT_MODULE_DIR}/mbedtls/library/bignum.c APPEND PROPERTY COMPILE_OPTIONS + set_property(SOURCE ${ZEPHYR_CURRENT_MODULE_DIR}/library/bignum_core.c APPEND PROPERTY COMPILE_OPTIONS "${COMPILER_OPTIMIZE_FOR_SPEED_FLAG}") endif () diff --git a/modules/mbedtls/Kconfig.mbedtls b/modules/mbedtls/Kconfig.mbedtls index 4a71ec4961421..69f7b63de25ca 100644 --- a/modules/mbedtls/Kconfig.mbedtls +++ b/modules/mbedtls/Kconfig.mbedtls @@ -653,6 +653,15 @@ config MBEDTLS_PSA_KEY_SLOT_COUNT * the heap-allocated memory to store the key material of a given slot, if it is used and MBEDTLS_PSA_STATIC_KEY_SLOTS is not set. +config MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS + bool "Built-in key support in PSA Crypto core" + help + Enable support for platform built-in keys in PSA Crypto. Built-in keys + are typically derived from a hardware unique key or stored in a secure + element. Mbed TLS uses key IDs from MBEDTLS_PSA_KEY_ID_BUILTIN_MIN to + MBEDTLS_PSA_KEY_ID_BUILTIN_MAX for built-in keys. The platform must + implement mbedtls_psa_platform_get_builtin_key(). + endif # MBEDTLS_PSA_CRYPTO_C config MBEDTLS_SSL_DTLS_CONNECTION_ID diff --git a/modules/mbedtls/configs/config-mbedtls.h b/modules/mbedtls/configs/config-mbedtls.h index d6d4f737aba1a..64b2bbf678053 100644 --- a/modules/mbedtls/configs/config-mbedtls.h +++ b/modules/mbedtls/configs/config-mbedtls.h @@ -510,6 +510,10 @@ #define MBEDTLS_USE_PSA_CRYPTO #endif +#if defined(CONFIG_MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) +#define MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS +#endif + #if defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) #define MBEDTLS_PSA_CRYPTO_CLIENT #define MBEDTLS_PSA_CRYPTO_CONFIG diff --git a/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_jpegenc.conf b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_jpegenc.conf new file mode 100644 index 0000000000000..c22b234f66af0 --- /dev/null +++ b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_jpegenc.conf @@ -0,0 +1,22 @@ +# Video buffer pool +CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=154000 +CONFIG_VIDEO_BUFFER_POOL_NUM_MAX=4 + +CONFIG_FPU=y + +# Capture +CONFIG_VIDEO_CAPTURE_N_BUFFERING=2 + +# Video encoder +CONFIG_VIDEO_ENCODER_JPEG=y +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_VIDEO_ENCODED_PIXEL_FORMAT="JPEG" + +# Default frame size +CONFIG_VIDEO_PIXEL_FORMAT="NV12" +CONFIG_VIDEO_FRAME_WIDTH=320 +CONFIG_VIDEO_FRAME_HEIGHT=240 + +# Network buffers +CONFIG_NET_BUF_RX_COUNT=4 +CONFIG_NET_BUF_TX_COUNT=8 diff --git a/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_jpegenc.overlay b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_jpegenc.overlay new file mode 100644 index 0000000000000..d4215429ed0e8 --- /dev/null +++ b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_jpegenc.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2025 STMicroelectronics + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,videoenc = &jpeg; + }; +}; diff --git a/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_fsbl_jpegenc.conf b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_fsbl_jpegenc.conf new file mode 100644 index 0000000000000..c22b234f66af0 --- /dev/null +++ b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_fsbl_jpegenc.conf @@ -0,0 +1,22 @@ +# Video buffer pool +CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=154000 +CONFIG_VIDEO_BUFFER_POOL_NUM_MAX=4 + +CONFIG_FPU=y + +# Capture +CONFIG_VIDEO_CAPTURE_N_BUFFERING=2 + +# Video encoder +CONFIG_VIDEO_ENCODER_JPEG=y +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_VIDEO_ENCODED_PIXEL_FORMAT="JPEG" + +# Default frame size +CONFIG_VIDEO_PIXEL_FORMAT="NV12" +CONFIG_VIDEO_FRAME_WIDTH=320 +CONFIG_VIDEO_FRAME_HEIGHT=240 + +# Network buffers +CONFIG_NET_BUF_RX_COUNT=4 +CONFIG_NET_BUF_TX_COUNT=8 diff --git a/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_fsbl_jpegenc.overlay b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_fsbl_jpegenc.overlay new file mode 100644 index 0000000000000..d4215429ed0e8 --- /dev/null +++ b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_fsbl_jpegenc.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2025 STMicroelectronics + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,videoenc = &jpeg; + }; +}; diff --git a/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_sb_jpegenc.conf b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_sb_jpegenc.conf new file mode 100644 index 0000000000000..c22b234f66af0 --- /dev/null +++ b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_sb_jpegenc.conf @@ -0,0 +1,22 @@ +# Video buffer pool +CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=154000 +CONFIG_VIDEO_BUFFER_POOL_NUM_MAX=4 + +CONFIG_FPU=y + +# Capture +CONFIG_VIDEO_CAPTURE_N_BUFFERING=2 + +# Video encoder +CONFIG_VIDEO_ENCODER_JPEG=y +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_VIDEO_ENCODED_PIXEL_FORMAT="JPEG" + +# Default frame size +CONFIG_VIDEO_PIXEL_FORMAT="NV12" +CONFIG_VIDEO_FRAME_WIDTH=320 +CONFIG_VIDEO_FRAME_HEIGHT=240 + +# Network buffers +CONFIG_NET_BUF_RX_COUNT=4 +CONFIG_NET_BUF_TX_COUNT=8 diff --git a/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_sb_jpegenc.overlay b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_sb_jpegenc.overlay new file mode 100644 index 0000000000000..d4215429ed0e8 --- /dev/null +++ b/samples/drivers/video/tcpserversink/boards/stm32n6570_dk_stm32n657xx_sb_jpegenc.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2025 STMicroelectronics + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,videoenc = &jpeg; + }; +}; diff --git a/samples/net/capture/README.rst b/samples/net/capture/README.rst index c6846e5d55252..29ba23fd5254c 100644 --- a/samples/net/capture/README.rst +++ b/samples/net/capture/README.rst @@ -31,10 +31,17 @@ Build the sample application like this: .. zephyr-app-commands:: :zephyr-app: samples/net/capture :board: - :conf: :goals: build :compact: +Example building for :zephyr:board:`native_sim`: + +.. zephyr-app-commands:: + :zephyr-app: samples/net/capture + :board: native_sim + :gen-args: -DEXTRA_CONF_FILE=overlay-tunnel.conf + :goals: build + :compact: Network Configuration ********************* diff --git a/samples/net/openthread/shell/README.rst b/samples/net/openthread/shell/README.rst index 2b44d00e9b833..906f65cf9229f 100644 --- a/samples/net/openthread/shell/README.rst +++ b/samples/net/openthread/shell/README.rst @@ -46,10 +46,20 @@ Example building for NXP's RW612 FRDM (RCP host). .. zephyr-app-commands:: :zephyr-app: samples/net/openthread/shell :board: frdm_rw612 - :conf: "prj.conf overlay-ot-rcp-host-nxp.conf" + :conf: "prj-ot-host.conf" :goals: build :compact: +Example building for NXP's MCXW72 FRDM (host). + +.. zephyr-app-commands:: + :zephyr-app: samples/net/openthread/shell + :board: frdm_mcxw72 + :conf: "prj-ot-host.conf" + :goals: build + :compact: + + Sample console interaction ========================== diff --git a/samples/net/openthread/shell/boards/frdm_mcxw71.conf b/samples/net/openthread/shell/boards/frdm_mcxw71.conf new file mode 100644 index 0000000000000..292c9be5cd647 --- /dev/null +++ b/samples/net/openthread/shell/boards/frdm_mcxw71.conf @@ -0,0 +1,9 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +# OS +CONFIG_HEAP_MEM_POOL_SIZE=2048 +CONFIG_MAIN_STACK_SIZE=2048 + +#shell +CONFIG_SHELL_STACK_SIZE=2048 diff --git a/samples/net/openthread/shell/boards/frdm_mcxw72_mcxw727c_cpu0.conf b/samples/net/openthread/shell/boards/frdm_mcxw72_mcxw727c_cpu0.conf new file mode 100644 index 0000000000000..6135e80dc09e0 --- /dev/null +++ b/samples/net/openthread/shell/boards/frdm_mcxw72_mcxw727c_cpu0.conf @@ -0,0 +1,9 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +# OS +CONFIG_HEAP_MEM_POOL_SIZE=4096 +CONFIG_MAIN_STACK_SIZE=4096 + +#shell +CONFIG_SHELL_STACK_SIZE=4096 diff --git a/samples/net/openthread/shell/boards/frdm_rw612.conf b/samples/net/openthread/shell/boards/frdm_rw612.conf new file mode 100644 index 0000000000000..90152b55298d3 --- /dev/null +++ b/samples/net/openthread/shell/boards/frdm_rw612.conf @@ -0,0 +1,15 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +# OS +CONFIG_MAIN_STACK_SIZE=4096 + +#shell +CONFIG_SHELL_STACK_SIZE=5120 + +# IMU & FW loader +CONFIG_NXP_RF_IMU=y +CONFIG_NXP_FW_LOADER=y + +# Enable Openthread RCP host interface +CONFIG_HDLC_RCP_IF=y diff --git a/samples/net/openthread/shell/boards/mcxw72_evk_mcxw727c_cpu0.conf b/samples/net/openthread/shell/boards/mcxw72_evk_mcxw727c_cpu0.conf new file mode 100644 index 0000000000000..6135e80dc09e0 --- /dev/null +++ b/samples/net/openthread/shell/boards/mcxw72_evk_mcxw727c_cpu0.conf @@ -0,0 +1,9 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +# OS +CONFIG_HEAP_MEM_POOL_SIZE=4096 +CONFIG_MAIN_STACK_SIZE=4096 + +#shell +CONFIG_SHELL_STACK_SIZE=4096 diff --git a/samples/net/openthread/shell/boards/rd_rw612_bga.conf b/samples/net/openthread/shell/boards/rd_rw612_bga.conf new file mode 100644 index 0000000000000..90152b55298d3 --- /dev/null +++ b/samples/net/openthread/shell/boards/rd_rw612_bga.conf @@ -0,0 +1,15 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +# OS +CONFIG_MAIN_STACK_SIZE=4096 + +#shell +CONFIG_SHELL_STACK_SIZE=5120 + +# IMU & FW loader +CONFIG_NXP_RF_IMU=y +CONFIG_NXP_FW_LOADER=y + +# Enable Openthread RCP host interface +CONFIG_HDLC_RCP_IF=y diff --git a/samples/net/openthread/shell/overlay-ot-rcp-host-nxp.conf b/samples/net/openthread/shell/prj-ot-host.conf similarity index 68% rename from samples/net/openthread/shell/overlay-ot-rcp-host-nxp.conf rename to samples/net/openthread/shell/prj-ot-host.conf index 21501757b774e..ccd248c45d21d 100644 --- a/samples/net/openthread/shell/overlay-ot-rcp-host-nxp.conf +++ b/samples/net/openthread/shell/prj-ot-host.conf @@ -1,27 +1,39 @@ -# -# Copyright 2025, NXP -# +# SPDX-License-Identifier: Apache-2.0 -# OS -CONFIG_MAIN_STACK_SIZE=8192 +# Enable Networking and OpenThread stack +CONFIG_NETWORKING=y +CONFIG_NET_L2_OPENTHREAD=y + +# Use NVS as settings backend +CONFIG_NVS=y + +# Logging +CONFIG_LOG=y +CONFIG_NET_LOG=y + +# Networking and OpenThread shells +CONFIG_SHELL=y +CONFIG_NET_SHELL=y +CONFIG_OPENTHREAD_SHELL=y +CONFIG_NET_L2_IEEE802154_SHELL=y # CPP library CONFIG_CPP=y -# IMU & FW loader -CONFIG_NXP_RF_IMU=y -CONFIG_NXP_FW_LOADER=y - # Shell CONFIG_SHELL_ARGC_MAX=26 CONFIG_SHELL_CMD_BUFF_SIZE=512 -CONFIG_SHELL_STACK_SIZE=5120 +CONFIG_SHELL_DEFAULT_TERMINAL_WIDTH=1024 -# Enable Openthread RCP host interface -CONFIG_HDLC_RCP_IF=y -CONFIG_OPENTHREAD_MANUAL_START=y +# Flash +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_SETTINGS=y +CONFIG_SETTINGS_NVS=y +CONFIG_NVS=y # Enable OpenThread features set +CONFIG_OPENTHREAD_MANUAL_START=y CONFIG_OPENTHREAD_THREAD_VERSION_1_3=y CONFIG_OPENTHREAD_DHCP6_SERVER=y CONFIG_OPENTHREAD_COMMISSIONER=y diff --git a/samples/net/openthread/shell/sample.yaml b/samples/net/openthread/shell/sample.yaml index 6b67e66ced106..14caf2b3854d4 100644 --- a/samples/net/openthread/shell/sample.yaml +++ b/samples/net/openthread/shell/sample.yaml @@ -20,10 +20,18 @@ tests: extra_args: # Disabling monolithic since CI environment doesn't use blobs - CONFIG_NXP_MONOLITHIC_NBU=n - - EXTRA_CONF_FILE="overlay-ot-rcp-host-nxp.conf" platform_allow: - frdm_rw612 - rd_rw612_bga + sample.net.openthread.shell.mcxw_openthread_host: + build_only: true + extra_args: + # Disabling monolithic since CI environment doesn't use blobs + - CONFIG_NXP_MONOLITHIC_NBU=n + platform_allow: + - frdm_mcxw71 + - mcxw72_evk/mcxw727c/cpu0 + - frdm_mcxw72/mcxw727c/cpu0 sample.net.openthread.shell.esp: build_only: true extra_args: diff --git a/samples/net/wpan_serial/sample.yaml b/samples/net/wpan_serial/sample.yaml index a3b68c81b2c76..29ba738a8dc8a 100644 --- a/samples/net/wpan_serial/sample.yaml +++ b/samples/net/wpan_serial/sample.yaml @@ -15,6 +15,7 @@ tests: - thingy53/nrf5340/cpuapp/ns - raytac_mdbt53_db_40/nrf5340/cpuapp/ns - raytac_mdbt53_db_40/nrf5340/cpuapp + - nucleo_wba65ri integration_platforms: - usb_kw24d512 sample.net.wpan_serial.frdm_cr20a: diff --git a/samples/sensor/dht_polling/sample.yaml b/samples/sensor/dht_polling/sample.yaml index 38da487dd1d45..8d0b182a8c330 100644 --- a/samples/sensor/dht_polling/sample.yaml +++ b/samples/sensor/dht_polling/sample.yaml @@ -15,10 +15,12 @@ tests: - nucleo_f401re platform_allow: - adafruit_qt_py_rp2040/rp2040 + - adafruit_feather_rp2040/rp2040 - adafruit_feather_canbus_rp2040/rp2040 - nucleo_f401re extra_args: - platform:adafruit_qt_py_rp2040/rp2040:SHIELD="adafruit_aht20" + - platform:adafruit_feather_rp2040/rp2040:SHIELD="adafruit_sht4x" - platform:adafruit_feather_canbus_rp2040/rp2040:SHIELD="sparkfun_shtc3" harness: console harness_config: diff --git a/soc/bflb/bl61x/CMakeLists.txt b/soc/bflb/bl61x/CMakeLists.txt index 73622c1849b4f..bf2533d93674b 100644 --- a/soc/bflb/bl61x/CMakeLists.txt +++ b/soc/bflb/bl61x/CMakeLists.txt @@ -8,7 +8,7 @@ zephyr_sources(soc.c) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") zephyr_code_relocate( - FILES ${ZEPHYR_BASE}/arch/riscv/core/xuantie/cache_xtheadcmo.c LOCATION ITCM NOKEEP) + FILES ${ZEPHYR_BASE}/arch/riscv/custom/thead/cache_xtheadcmo.c LOCATION ITCM NOKEEP) zephyr_code_relocate_ifdef(CONFIG_UART_BFLB LIBRARY drivers__serial LOCATION ITCM NOKEEP) zephyr_code_relocate_ifdef(CONFIG_RISCV_MACHINE_TIMER LIBRARY drivers__timer LOCATION ITCM NOKEEP) diff --git a/soc/nxp/common/nxp_nbu.c b/soc/nxp/common/nxp_nbu.c index dc179f100cf53..a6eb10bd0af01 100644 --- a/soc/nxp/common/nxp_nbu.c +++ b/soc/nxp/common/nxp_nbu.c @@ -42,12 +42,10 @@ void nxp_nbu_init(void) #if defined(CONFIG_BT) || defined(CONFIG_IEEE802154) /* NBU interface Interrupt */ IRQ_CONNECT(NBU_RX_IRQ_N, NBU_RX_IRQ_P, nbu_handler, 0, 0); - irq_enable(NBU_RX_IRQ_N); #if DT_INST_IRQ_HAS_NAME(0, wakeup_int) /* Wake up done interrupt */ IRQ_CONNECT(NBU_WAKE_UP_IRQ_N, NBU_WAKE_UP_IRQ_P, nbu_wakeup_done_handler, 0, 0); - irq_enable(NBU_WAKE_UP_IRQ_N); #endif #if (DT_INST_PROP(0, wakeup_source)) && CONFIG_PM NXP_ENABLE_WAKEUP_SIGNAL(NBU_RX_IRQ_N); diff --git a/soc/st/stm32/Kconfig.defconfig b/soc/st/stm32/Kconfig.defconfig index c30bf5e1b15a1..767b6c2321c5c 100644 --- a/soc/st/stm32/Kconfig.defconfig +++ b/soc/st/stm32/Kconfig.defconfig @@ -20,6 +20,21 @@ config CLOCK_CONTROL config CORTEX_M_SYSTICK default n if STM32_LPTIM_TIMER +# Reduce kernel stack sizes to fit MCUs with 8 KiB RAM or less +config MAIN_STACK_SIZE + default 320 if SRAM_SIZE <= 2 + default 512 if SRAM_SIZE <= 4 + default 640 if SRAM_SIZE <= 8 + +config IDLE_STACK_SIZE + default 100 if SRAM_SIZE <= 2 + default 150 if SRAM_SIZE <= 4 + default 200 if SRAM_SIZE <= 8 + +config ISR_STACK_SIZE + default 256 if SRAM_SIZE <= 2 + default 512 if SRAM_SIZE <= 8 + DT_STM32_RCC_PATH := $(dt_nodelabel_path,rcc) DT_STM32_RCC_CLOCK_FREQ := $(dt_node_int_prop_int,$(DT_STM32_RCC_PATH),clock-frequency) diff --git a/soc/st/stm32/stm32h7rsx/CMakeLists.txt b/soc/st/stm32/stm32h7rsx/CMakeLists.txt index 724ce9fb094fd..031c132ef9f48 100644 --- a/soc/st/stm32/stm32h7rsx/CMakeLists.txt +++ b/soc/st/stm32/stm32h7rsx/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_sources( ) zephyr_sources(mpu_regions.c) +zephyr_linker_sources(SECTIONS sections.ld) zephyr_include_directories(.) diff --git a/soc/st/stm32/stm32h7rsx/mpu_regions.c b/soc/st/stm32/stm32h7rsx/mpu_regions.c index 0e3339917536e..72995b85216e6 100644 --- a/soc/st/stm32/stm32h7rsx/mpu_regions.c +++ b/soc/st/stm32/stm32h7rsx/mpu_regions.c @@ -26,6 +26,20 @@ static const struct arm_mpu_region mpu_regions[] = { /* Region 3 */ MPU_REGION_ENTRY("SRAM_0", CONFIG_SRAM_BASE_ADDRESS, REGION_RAM_ATTR(REGION_SRAM_SIZE)), + + /* Region 4 - Ready only flash with unique device id */ + MPU_REGION_ENTRY("ID", 0x08FFF800, REGION_FLASH_ATTR(REGION_2K)), + +#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(mac)) +#define sram_eth_node DT_NODELABEL(sram2) +#if DT_NODE_HAS_STATUS_OKAY(sram_eth_node) + /* Region 5 - Ethernet DMA buffer RAM */ + MPU_REGION_ENTRY("SRAM_ETH_BUF", DT_REG_ADDR(sram_eth_node), + REGION_RAM_NOCACHE_ATTR(REGION_16K)), + /* Region 6 - Ethernet DMA descriptor RAM (overlays the first 256B of SRAM_ETH_BUF)*/ + MPU_REGION_ENTRY("SRAM_ETH_DESC", DT_REG_ADDR(sram_eth_node), REGION_PPB_ATTR(REGION_256B)), +#endif +#endif }; const struct arm_mpu_config mpu_config = { diff --git a/soc/st/stm32/stm32h7rsx/sections.ld b/soc/st/stm32/stm32h7rsx/sections.ld new file mode 100644 index 0000000000000..7f1209682dcca --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/sections.ld @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020 Mario Jaun + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(mac)) +#define sram_eth_node DT_NODELABEL(sram2) +#if DT_NODE_HAS_STATUS_OKAY(sram_eth_node) +SECTION_DATA_PROLOGUE(eth_stm32,(NOLOAD),) +{ + . = ABSOLUTE(DT_REG_ADDR(sram_eth_node)); + *(.eth_stm32_desc) + . = ABSOLUTE(DT_REG_ADDR(sram_eth_node)) + 256; + *(.eth_stm32_buf) + . = ABSOLUTE(DT_REG_ADDR(sram_eth_node)) + 16K; +} GROUP_DATA_LINK_IN(LINKER_DT_NODE_REGION_NAME(sram_eth_node), LINKER_DT_NODE_REGION_NAME(sram_eth_node)) +#endif /* DT_NODE_HAS_STATUS_OKAY(sram_eth_node) */ + +#endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(mac)) */ diff --git a/subsys/bluetooth/mesh/app_keys.c b/subsys/bluetooth/mesh/app_keys.c index 5afd887a8e803..f573add5a3243 100644 --- a/subsys/bluetooth/mesh/app_keys.c +++ b/subsys/bluetooth/mesh/app_keys.c @@ -666,6 +666,10 @@ static int app_key_set(const char *name, size_t len_rd, uint16_t app_idx; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; diff --git a/subsys/bluetooth/mesh/brg_cfg.c b/subsys/bluetooth/mesh/brg_cfg.c index 58d1aada550d4..d0bdaef7f05ec 100644 --- a/subsys/bluetooth/mesh/brg_cfg.c +++ b/subsys/bluetooth/mesh/brg_cfg.c @@ -52,6 +52,10 @@ static int brg_en_set(const char *name, size_t len_rd, settings_read_cb read_cb, { int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { brg_enabled = 0; LOG_DBG("Cleared bridge enable state"); diff --git a/subsys/bluetooth/mesh/cdb.c b/subsys/bluetooth/mesh/cdb.c index 310108d7b7567..dc2725a7a3275 100644 --- a/subsys/bluetooth/mesh/cdb.c +++ b/subsys/bluetooth/mesh/cdb.c @@ -180,6 +180,10 @@ static int cdb_net_set(const char *name, size_t len_rd, struct net_val net; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("val (null)"); return 0; @@ -219,6 +223,10 @@ static int cdb_node_set(const char *name, size_t len_rd, uint16_t addr; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; @@ -281,6 +289,10 @@ static int cdb_subnet_set(const char *name, size_t len_rd, uint16_t net_idx; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; @@ -347,6 +359,10 @@ static int cdb_app_key_set(const char *name, size_t len_rd, uint16_t app_idx; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; diff --git a/subsys/bluetooth/mesh/cfg.c b/subsys/bluetooth/mesh/cfg.c index 155c2e616d558..e5563b95c3c11 100644 --- a/subsys/bluetooth/mesh/cfg.c +++ b/subsys/bluetooth/mesh/cfg.c @@ -429,6 +429,10 @@ static int cfg_set(const char *name, size_t len_rd, struct cfg_val cfg; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("Cleared configuration state"); return 0; diff --git a/subsys/bluetooth/mesh/heartbeat.c b/subsys/bluetooth/mesh/heartbeat.c index 133c552620f51..0ad4828279c20 100644 --- a/subsys/bluetooth/mesh/heartbeat.c +++ b/subsys/bluetooth/mesh/heartbeat.c @@ -416,6 +416,10 @@ static int hb_pub_set(const char *name, size_t len_rd, struct hb_pub_val hb_val; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + err = bt_mesh_settings_set(read_cb, cb_arg, &hb_val, sizeof(hb_val)); if (err) { LOG_ERR("Failed to set \'hb_val\'"); diff --git a/subsys/bluetooth/mesh/net.c b/subsys/bluetooth/mesh/net.c index 276728bd9a452..b2e1cc695f94f 100644 --- a/subsys/bluetooth/mesh/net.c +++ b/subsys/bluetooth/mesh/net.c @@ -1005,6 +1005,10 @@ static int net_set(const char *name, size_t len_rd, settings_read_cb read_cb, struct bt_mesh_key key; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("val (null)"); @@ -1042,6 +1046,10 @@ static int iv_set(const char *name, size_t len_rd, settings_read_cb read_cb, struct iv_val iv; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("IV deleted"); @@ -1074,6 +1082,10 @@ static int seq_set(const char *name, size_t len_rd, settings_read_cb read_cb, struct seq_val seq; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("val (null)"); @@ -1113,6 +1125,10 @@ static int dev_key_cand_set(const char *name, size_t len_rd, settings_read_cb re int err; struct bt_mesh_key key; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("val (null)"); diff --git a/subsys/bluetooth/mesh/rpl.c b/subsys/bluetooth/mesh/rpl.c index 581c94771c81d..7c9317fcc94cb 100644 --- a/subsys/bluetooth/mesh/rpl.c +++ b/subsys/bluetooth/mesh/rpl.c @@ -272,6 +272,10 @@ static int rpl_set(const char *name, size_t len_rd, int err; uint16_t src; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; diff --git a/subsys/bluetooth/mesh/solicitation.c b/subsys/bluetooth/mesh/solicitation.c index a2872daecb03d..2d863dc57dc58 100644 --- a/subsys/bluetooth/mesh/solicitation.c +++ b/subsys/bluetooth/mesh/solicitation.c @@ -120,6 +120,10 @@ static int sseq_set(const char *name, size_t len_rd, { int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + err = bt_mesh_settings_set(read_cb, cb_arg, &sseq_out, sizeof(sseq_out)); if (err) { LOG_ERR("Failed to set \'sseq\'"); @@ -365,6 +369,10 @@ static int srpl_set(const char *name, size_t len_rd, } } + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + err = bt_mesh_settings_set(read_cb, cb_arg, &sseq, sizeof(sseq)); if (err) { LOG_ERR("Failed to set \'sseq\'"); diff --git a/subsys/bluetooth/mesh/subnet.c b/subsys/bluetooth/mesh/subnet.c index b17b9a497400a..7f2943365976b 100644 --- a/subsys/bluetooth/mesh/subnet.c +++ b/subsys/bluetooth/mesh/subnet.c @@ -971,6 +971,10 @@ static int net_key_set(const char *name, size_t len_rd, int err; uint16_t net_idx; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; diff --git a/subsys/bluetooth/mesh/va.c b/subsys/bluetooth/mesh/va.c index fb81f36251cf3..0b83e93e1c8db 100644 --- a/subsys/bluetooth/mesh/va.c +++ b/subsys/bluetooth/mesh/va.c @@ -219,6 +219,10 @@ static int va_set(const char *name, size_t len_rd, uint16_t index; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; diff --git a/subsys/debug/thread_analyzer/thread_analyzer.c b/subsys/debug/thread_analyzer/thread_analyzer.c index 360b79ed53387..8f136034f8fe1 100644 --- a/subsys/debug/thread_analyzer/thread_analyzer.c +++ b/subsys/debug/thread_analyzer/thread_analyzer.c @@ -171,7 +171,7 @@ static void thread_analyze_cb(const struct k_thread *cthread, void *user_data) cb(&info); -#if IS_ENABLED(CONFIG_THREAD_ANALYZER_LONG_FRAME_PER_INTERVAL) +#ifdef CONFIG_THREAD_ANALYZER_LONG_FRAME_PER_INTERVAL k_thread_runtime_stats_longest_frame_reset(thread); #endif @@ -257,7 +257,7 @@ void thread_analyzer_auto(void *a, void *b, void *c) } } -#if IS_ENABLED(CONFIG_THREAD_ANALYZER_AUTO_SEPARATE_CORES) +#ifdef CONFIG_THREAD_ANALYZER_AUTO_SEPARATE_CORES static K_THREAD_STACK_ARRAY_DEFINE(analyzer_thread_stacks, CONFIG_MP_MAX_NUM_CPUS, CONFIG_THREAD_ANALYZER_AUTO_STACK_SIZE); diff --git a/subsys/fs/zms/zms.c b/subsys/fs/zms/zms.c index 068e6685d8f25..93d140663f5c5 100644 --- a/subsys/fs/zms/zms.c +++ b/subsys/fs/zms/zms.c @@ -1175,6 +1175,8 @@ static int zms_init(struct zms_fs *fs) uint32_t i; uint32_t closed_sectors = 0; bool zms_magic_exist = false; + bool ebw_required = + flash_params_get_erase_cap(fs->flash_parameters) & FLASH_ERASE_C_EXPLICIT; k_mutex_lock(&fs->zms_lock, K_FOREVER); @@ -1321,9 +1323,30 @@ static int zms_init(struct zms_fs *fs) if (rc) { goto end; } - if (!zms_ate_valid(fs, &last_ate)) { - /* found empty location */ - break; + + /* Verify that the next location is empty. + * For devices that do not need erase this should be a non valid ATE. + * For devices that needs erase this should be filled with erase_value. + */ + if (ebw_required) { + size_t byte; + + for (byte = 0; byte < sizeof(last_ate); byte++) { + if (((uint8_t *)&last_ate)[byte] != + (uint8_t)fs->flash_parameters->erase_value) { + break; /* break from the comparison loop */ + } + } + + if (byte == sizeof(last_ate)) { + /* found ff empty location */ + break; + } + } else { + if (!zms_ate_valid(fs, &last_ate)) { + /* found empty location */ + break; + } } /* ate on the last position within the sector is diff --git a/subsys/modbus/modbus_serial.c b/subsys/modbus/modbus_serial.c index 1cfbd53f74053..0f7410b59b867 100644 --- a/subsys/modbus/modbus_serial.c +++ b/subsys/modbus/modbus_serial.c @@ -34,7 +34,7 @@ static void modbus_serial_tx_on(struct modbus_context *ctx) struct modbus_serial_config *cfg = ctx->cfg; if (cfg->de != NULL) { - gpio_pin_set(cfg->de->port, cfg->de->pin, 1); + gpio_pin_set_dt(cfg->de, 1); } if (IS_ENABLED(CONFIG_MODBUS_SERIAL_ASYNC_API)) { @@ -58,7 +58,7 @@ static void modbus_serial_tx_off(struct modbus_context *ctx) } if (cfg->de != NULL) { - gpio_pin_set(cfg->de->port, cfg->de->pin, 0); + gpio_pin_set_dt(cfg->de, 0); } } @@ -78,7 +78,7 @@ static void modbus_serial_rx_on(struct modbus_context *ctx) struct modbus_serial_config *cfg = ctx->cfg; if (cfg->re != NULL) { - gpio_pin_set(cfg->re->port, cfg->re->pin, 1); + gpio_pin_set_dt(cfg->re, 1); } atomic_set_bit(&ctx->state, MODBUS_STATE_RX_ENABLED); @@ -108,7 +108,7 @@ static void modbus_serial_rx_off(struct modbus_context *ctx) atomic_clear_bit(&ctx->state, MODBUS_STATE_RX_ENABLED); if (cfg->re != NULL) { - gpio_pin_set(cfg->re->port, cfg->re->pin, 0); + gpio_pin_set_dt(cfg->re, 0); } } @@ -509,7 +509,7 @@ static int configure_gpio(struct modbus_context *ctx) struct modbus_serial_config *cfg = ctx->cfg; if (cfg->de != NULL) { - if (!device_is_ready(cfg->de->port)) { + if (!gpio_is_ready_dt(cfg->de)) { return -ENODEV; } @@ -520,7 +520,7 @@ static int configure_gpio(struct modbus_context *ctx) if (cfg->re != NULL) { - if (!device_is_ready(cfg->re->port)) { + if (!gpio_is_ready_dt(cfg->re)) { return -ENODEV; } diff --git a/subsys/net/lib/config/Kconfig b/subsys/net/lib/config/Kconfig index 3e9685643172f..39eed79d35c82 100644 --- a/subsys/net/lib/config/Kconfig +++ b/subsys/net/lib/config/Kconfig @@ -215,6 +215,16 @@ config NET_CONFIG_CLOCK_SNTP_INIT if NET_CONFIG_CLOCK_SNTP_INIT +ZEPHYR_RTC := zephyr,rtc + +config NET_CONFIG_CLOCK_SNTP_SET_RTC + bool "Set RTC on SNTP response" + depends on RTC + depends on $(dt_chosen_enabled,$(ZEPHYR_RTC)) + help + Set RTC when an SNTP response is received. + Requires `zephyr,rtc` chosen. + config NET_CONFIG_SNTP_INIT_SERVER string "SNTP server to use for system clock init" default "" diff --git a/subsys/net/lib/config/init_clock_sntp.c b/subsys/net/lib/config/init_clock_sntp.c index 5eeae0a8df5a1..e0b3063eb1db0 100644 --- a/subsys/net/lib/config/init_clock_sntp.c +++ b/subsys/net/lib/config/init_clock_sntp.c @@ -4,11 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include LOG_MODULE_DECLARE(net_config, CONFIG_NET_CONFIG_LOG_LEVEL); #include +#include #include #include #include @@ -46,6 +48,40 @@ static int sntp_init_helper(struct sntp_time *tm) CONFIG_NET_CONFIG_SNTP_INIT_TIMEOUT, tm); } +__maybe_unused static int timespec_to_rtc_time(const struct timespec *in, struct rtc_time *out) +{ + if (gmtime_r(&in->tv_sec, rtc_time_to_tm(out)) == NULL) { + return -EINVAL; + } + + out->tm_nsec = in->tv_nsec; + + return 0; +} + +static void sntp_set_rtc(__maybe_unused const struct timespec *tspec) +{ +#ifdef CONFIG_NET_CONFIG_CLOCK_SNTP_SET_RTC + const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_rtc)); + struct rtc_time rtctime; + int res; + + if (!device_is_ready(dev)) { + return; + } + + if (timespec_to_rtc_time(tspec, &rtctime) != 0) { + LOG_ERR("Convert timespec to set RTC failed"); + return; + } + + res = rtc_set_time(dev, &rtctime); + if (res != 0) { + LOG_ERR("Set RTC failed: %d", res); + } +#endif +} + int net_init_clock_via_sntp(void) { struct sntp_time ts; @@ -60,6 +96,9 @@ int net_init_clock_via_sntp(void) tspec.tv_sec = ts.seconds; tspec.tv_nsec = ((uint64_t)ts.fraction * (1000 * 1000 * 1000)) >> 32; res = sys_clock_settime(SYS_CLOCK_REALTIME, &tspec); + + sntp_set_rtc(&tspec); + LOG_DBG("Time synced using SNTP"); end: diff --git a/tests/bluetooth/tester/boards/native_sim.conf b/tests/bluetooth/tester/boards/native_sim.conf index 9781be36b6917..60aac42bd264a 100644 --- a/tests/bluetooth/tester/boards/native_sim.conf +++ b/tests/bluetooth/tester/boards/native_sim.conf @@ -1,3 +1,4 @@ CONFIG_UART_PIPE=n CONFIG_SERIAL=y CONFIG_UART_NATIVE_PTY=y +CONFIG_ASAN=y diff --git a/tests/drivers/build_all/eeprom/app.overlay b/tests/drivers/build_all/eeprom/app.overlay index fcc4bbe9e0852..ff20fd2c83bc5 100644 --- a/tests/drivers/build_all/eeprom/app.overlay +++ b/tests/drivers/build_all/eeprom/app.overlay @@ -99,6 +99,13 @@ spi-max-frequency = ; size = ; }; + + test_spi_fm25xxx: fm25xxx@2 { + compatible = "infineon,fm25xxx"; + reg = <0x2>; + spi-max-frequency = ; + size = <8000>; + }; }; }; }; diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index eb505c663f7ff..cf21635773b54 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -1417,3 +1417,8 @@ test_i2c_ina7xx: ina7xx@bc { tct = <5>; avg = <3>; }; + +test_i2c_als31300: als31300@bd { + compatible = "allegro,als31300"; + reg = <0xbd>; +}; diff --git a/tests/drivers/pwm/pwm_loopback/src/test_pwm_loopback.c b/tests/drivers/pwm/pwm_loopback/src/test_pwm_loopback.c index 5320d087de560..73448d018d630 100644 --- a/tests/drivers/pwm/pwm_loopback/src/test_pwm_loopback.c +++ b/tests/drivers/pwm/pwm_loopback/src/test_pwm_loopback.c @@ -96,12 +96,12 @@ static void test_capture(uint32_t period, uint32_t pulse, enum test_pwm_unit uni if (flags & PWM_CAPTURE_TYPE_PERIOD) { zassert_within(period_capture, period, period / 100, - "period capture off by more than 1%"); + "period capture off by more than 1%%"); } if (flags & PWM_CAPTURE_TYPE_PULSE) { zassert_within(pulse_capture, pulse, pulse / 100, - "pulse capture off by more than 1%"); + "pulse capture off by more than 1%%"); } } @@ -272,10 +272,10 @@ ZTEST(pwm_loopback, test_continuous_capture) if (data.pulse_capture) { zassert_within(usec, TEST_PWM_PULSE_USEC, TEST_PWM_PULSE_USEC / 100, - "pulse capture off by more than 1%"); + "pulse capture off by more than 1%%"); } else { zassert_within(usec, TEST_PWM_PERIOD_USEC, TEST_PWM_PERIOD_USEC / 100, - "period capture off by more than 1%"); + "period capture off by more than 1%%"); } } } diff --git a/tests/drivers/retained_mem/api/boards/slwrb4180b.overlay b/tests/drivers/retained_mem/api/boards/slwrb4180b.overlay new file mode 100644 index 0000000000000..0346a8552ea8c --- /dev/null +++ b/tests/drivers/retained_mem/api/boards/slwrb4180b.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + retainedmemtestdevice = &buram; + }; +}; + +&buram { + status = "okay"; +}; diff --git a/tests/drivers/retained_mem/api/boards/xg24_rb4187c.overlay b/tests/drivers/retained_mem/api/boards/xg24_rb4187c.overlay new file mode 100644 index 0000000000000..0346a8552ea8c --- /dev/null +++ b/tests/drivers/retained_mem/api/boards/xg24_rb4187c.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + retainedmemtestdevice = &buram; + }; +}; + +&buram { + status = "okay"; +}; diff --git a/tests/drivers/retained_mem/api/boards/xg29_rb4412a.overlay b/tests/drivers/retained_mem/api/boards/xg29_rb4412a.overlay new file mode 100644 index 0000000000000..0346a8552ea8c --- /dev/null +++ b/tests/drivers/retained_mem/api/boards/xg29_rb4412a.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + retainedmemtestdevice = &buram; + }; +}; + +&buram { + status = "okay"; +}; diff --git a/tests/drivers/retained_mem/api/testcase.yaml b/tests/drivers/retained_mem/api/testcase.yaml index b01a5e9adef2b..7a2c49d92d400 100644 --- a/tests/drivers/retained_mem/api/testcase.yaml +++ b/tests/drivers/retained_mem/api/testcase.yaml @@ -29,3 +29,11 @@ tests: tags: - drivers - retained_mem + drivers.retained_mem.api.buram: + platform_allow: + - slwrb4180b + - xg24_rb4187c + - xg29_rb4412a + tags: + - drivers + - retained_mem diff --git a/tests/drivers/sensor/mtch9010/CMakeLists.txt b/tests/drivers/sensor/mtch9010/CMakeLists.txt new file mode 100644 index 0000000000000..56608a1f75707 --- /dev/null +++ b/tests/drivers/sensor/mtch9010/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2025 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(device) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) + +zephyr_include_directories(${ZEPHYR_BASE}/drivers/sensor/microchip/mtch9010) +zephyr_include_directories(./src) diff --git a/tests/drivers/sensor/mtch9010/prj.conf b/tests/drivers/sensor/mtch9010/prj.conf new file mode 100644 index 0000000000000..dfcf3ee5fec0a --- /dev/null +++ b/tests/drivers/sensor/mtch9010/prj.conf @@ -0,0 +1,13 @@ +CONFIG_ZTEST=y +CONFIG_GPIO=y +CONFIG_SERIAL=y + +# Device +CONFIG_SENSOR=y +CONFIG_MTCH9010=y + +# Emulation Settings +CONFIG_EMUL=y +CONFIG_GPIO_EMUL=y +CONFIG_UART_EMUL=y +CONFIG_LOG=y diff --git a/tests/drivers/sensor/mtch9010/src/main.c b/tests/drivers/sensor/mtch9010/src/main.c new file mode 100644 index 0000000000000..f24238776c00f --- /dev/null +++ b/tests/drivers/sensor/mtch9010/src/main.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../drivers/sensor/microchip/mtch9010/mtch9010_priv.h" +#include "zephyr/drivers/sensor/mtch9010.h" + +#define DUT_NODE DT_NODELABEL(dut) + +ZTEST_SUITE(mtch9010_utility, NULL, NULL, NULL, NULL, NULL); + +ZTEST(mtch9010_utility, test_result_decode) +{ + /* Basic Decode Tests */ + const char *test_pattern_1 = "12345\n\r"; + const char *test_pattern_2 = "10\n\r"; + const char *test_pattern_3 = "999 12405\n\r"; + const char *test_pattern_4 = "0 1234\n\r"; + const char *test_pattern_5 = "100 -99\n\r"; + + /* Bad Decodes */ + const char *bad_decode_pattern_1 = "10\n\r"; + const char *bad_decode_pattern_2 = "655636\n\r"; + const char *bad_decode_pattern_3 = "-100\n\r"; + const char *bad_decode_pattern_4 = "100"; + const char *bad_decode_pattern_5 = "100\t\n"; + const char *bad_decode_pattern_6 = "a100\n\r"; + + struct mtch9010_result test_result; + + /* Test Current decode */ + int ret = mtch9010_decode_char_buffer(test_pattern_1, MTCH9010_OUTPUT_FORMAT_CURRENT, + &test_result); + + zassert_equal(ret, 0, "Unable to decode test_pattern_1"); + zassert_equal(test_result.measurement, 12345, "Decoded value does not match expected"); + + /* Test DELTA decode */ + ret = mtch9010_decode_char_buffer(test_pattern_2, MTCH9010_OUTPUT_FORMAT_DELTA, + &test_result); + + zassert_equal(ret, 0, "Unable to decode test_pattern_2"); + zassert_equal(test_result.delta, 10, "Decoded value does not match expected"); + + /* Test Current and Delta decode */ + ret = mtch9010_decode_char_buffer(test_pattern_3, MTCH9010_OUTPUT_FORMAT_BOTH, + &test_result); + + zassert_equal(ret, 0, "Unable to decode test_pattern_3"); + zassert_equal(test_result.prev_measurement, 12345, + "Previous value does not match expected"); + zassert_equal(test_result.measurement, 999, "Decoded value does not match expected"); + zassert_equal(test_result.delta, 12405, "Decoded value does not match expected"); + + /* Test MPLAB Data Visualizer Format (should fail) */ + ret = mtch9010_decode_char_buffer( + test_pattern_4, MTCH9010_OUTPUT_FORMAT_MPLAB_DATA_VISUALIZER, &test_result); + zassert_equal(ret, -ENOTSUP, "Incorrectly decoded test_pattern_4"); + + /* Test Negative Delta */ + ret = mtch9010_decode_char_buffer(test_pattern_5, MTCH9010_OUTPUT_FORMAT_BOTH, + &test_result); + zassert_equal(ret, 0, "Unable to decode test_pattern_5"); + zassert_equal(test_result.measurement, 100, "Decoded value does not match expected"); + zassert_equal(test_result.delta, -99, "Decoded value does not match expected"); + + /* Test Bad Decode 1 - Incorrect format */ + ret = mtch9010_decode_char_buffer(bad_decode_pattern_1, MTCH9010_OUTPUT_FORMAT_BOTH, + &test_result); + zassert_equal(ret, -EINVAL, "Incorrectly decoded bad_decode_pattern_1"); + + /* Test Bad Decode 2 - UINT16 Buffer Overflow */ + ret = mtch9010_decode_char_buffer(bad_decode_pattern_2, MTCH9010_OUTPUT_FORMAT_CURRENT, + &test_result); + zassert_equal(ret, -EINVAL, "Incorrectly decoded bad_decode_pattern_2"); + + /* Test Bad Decode 3 - Negative Values */ + ret = mtch9010_decode_char_buffer(bad_decode_pattern_3, MTCH9010_OUTPUT_FORMAT_CURRENT, + &test_result); + zassert_equal(ret, -EINVAL, "Incorrectly decoded bad_decode_pattern_3"); + + /* Test Bad Decode 4 - Missing Return */ + ret = mtch9010_decode_char_buffer(bad_decode_pattern_4, MTCH9010_OUTPUT_FORMAT_CURRENT, + &test_result); + zassert_equal(ret, -EINVAL, "Incorrectly decoded bad_decode_pattern_4"); + + /* Test Bad Decode 5 - Invalid Return */ + ret = mtch9010_decode_char_buffer(bad_decode_pattern_5, MTCH9010_OUTPUT_FORMAT_CURRENT, + &test_result); + zassert_equal(ret, -EINVAL, "Incorrectly decoded bad_decode_pattern_5"); + + /* Test Bad Decode 6 - Invalid Starting Character */ + ret = mtch9010_decode_char_buffer(bad_decode_pattern_6, MTCH9010_OUTPUT_FORMAT_CURRENT, + &test_result); + zassert_equal(ret, -EINVAL, "Incorrectly decoded bad_decode_pattern_6"); +} + +struct mtch9010_config_fixture { + const struct device *dev; +}; + +static void *mtch9010_setup(void) +{ + static struct mtch9010_config_fixture fixture = { + .dev = DEVICE_DT_GET(DUT_NODE), + }; + + /* Verify we found a device */ + zassert_not_null(fixture.dev); + + /* Create the reference configuration */ + return &fixture; +} + +ZTEST_SUITE(mtch9010_config, NULL, mtch9010_setup, NULL, NULL, NULL); + +/* Check UART */ +ZTEST_F(mtch9010_config, test_uart_init) +{ + const struct mtch9010_config *config = fixture->dev->config; + + /* Verify the boolean flag */ + if (config->uart_init) { + zassert_true(DT_PROP_OR(DUT_NODE, mtch9010_uart_config_enable, false), + "UART Init was enabled, but was not set"); + } else { + zassert_false(DT_PROP_OR(DUT_NODE, mtch9010_uart_config_enable, false), + "UART Init was disabled, but was set"); + } + + /* Verify the UART Bus Pointer */ + const struct device *bus = DEVICE_DT_GET_OR_NULL(DT_BUS(DUT_NODE)); + + zassert_equal_ptr(bus, config->uart_dev, "UART Bus is not correctly assigned"); +} + +/* Check GPIO Assignments */ +ZTEST_F(mtch9010_config, test_gpio_bindings) +{ + const struct mtch9010_config *config = fixture->dev->config; + + /* GPIOs to Test */ + const struct gpio_dt_spec mode_gpio = + GPIO_DT_SPEC_GET_OR(DUT_NODE, mtch9010_mode_gpios, {0}); + const struct gpio_dt_spec output_gpio = + GPIO_DT_SPEC_GET_OR(DUT_NODE, mtch9010_output_gpios, {0}); + const struct gpio_dt_spec lock_gpio = + GPIO_DT_SPEC_GET_OR(DUT_NODE, mtch9010_system_lock_gpios, {0}); + const struct gpio_dt_spec reset_gpio = + GPIO_DT_SPEC_GET_OR(DUT_NODE, mtch9010_reset_gpios, {0}); + const struct gpio_dt_spec wake_gpio = + GPIO_DT_SPEC_GET_OR(DUT_NODE, mtch9010_wake_gpios, {0}); + const struct gpio_dt_spec uart_en_gpio = + GPIO_DT_SPEC_GET_OR(DUT_NODE, mtch9010_uart_en_gpios, {0}); + const struct gpio_dt_spec cfg_en_gpio = + GPIO_DT_SPEC_GET_OR(DUT_NODE, mtch9010_cfg_en_gpios, {0}); + const struct gpio_dt_spec heartbeat_gpio = + GPIO_DT_SPEC_GET_OR(DUT_NODE, mtch9010_heartbeat_gpios, {0}); + + if (mode_gpio.port != NULL) { + zassert_not_null(config->mode_gpio.port, "mode_gpio is NULL, but was assigned"); + } else { + zassert_is_null(config->mode_gpio.port, + "mode_gpio is not NULL, but was not assigned"); + } + + if (output_gpio.port != NULL) { + zassert_not_null(config->out_gpio.port, "output_gpio is NULL, but was assigned"); + } else { + zassert_is_null(config->out_gpio.port, + "output_gpio is not NULL, but was not assigned"); + } + + if (lock_gpio.port != NULL) { + zassert_not_null(config->lock_gpio.port, "lock_gpio is NULL, but was assigned"); + } else { + zassert_is_null(config->lock_gpio.port, + "lock_gpio is not NULL, but was not assigned"); + } + + if (reset_gpio.port != NULL) { + zassert_not_null(config->reset_gpio.port, "reset_gpio is NULL, but was assigned"); + } else { + zassert_is_null(config->reset_gpio.port, + "reset_gpio is not NULL, but was not assigned"); + } + + if (wake_gpio.port != NULL) { + zassert_not_null(config->wake_gpio.port, "wake_gpio is NULL, but was assigned"); + } else { + zassert_is_null(config->wake_gpio.port, + "wake_gpio is not NULL, but was not assigned"); + } + + if (uart_en_gpio.port != NULL) { + zassert_not_null(config->enable_uart_gpio.port, + "uart_en_gpio is NULL, but was assigned"); + } else { + zassert_is_null(config->enable_uart_gpio.port, + "uart_en_gpio is not NULL, but was not assigned"); + } + + if (cfg_en_gpio.port != NULL) { + zassert_not_null(config->enable_cfg_gpio.port, + "cfg_en_gpio is NULL, but was assigned"); + } else { + zassert_is_null(config->enable_cfg_gpio.port, + "cfg_en_gpio is not NULL, but was not assigned"); + } + + if (heartbeat_gpio.port != NULL) { + zassert_not_null(config->heartbeat_gpio.port, + "heartbeat_gpio is NULL, but was assigned"); + } else { + zassert_is_null(config->heartbeat_gpio.port, + "heartbeat_gpio is not NULL, but was not assigned"); + } +} + +ZTEST_F(mtch9010_config, test_sleep_time) +{ + const struct mtch9010_config *config = fixture->dev->config; + + zassert((config->sleep_time == DT_PROP_OR(DUT_NODE, mtch9010_sleep_period, 0)), + "sleepTime was not correctly assigned."); +} + +ZTEST_F(mtch9010_config, test_output_format) +{ + const struct mtch9010_config *config = fixture->dev->config; + + if (config->extended_mode_enable) { + zassert_true(DT_PROP_OR(DUT_NODE, extended_output_enable, false), + "Extended output was disabled, but was set"); + } else { + zassert_false(DT_PROP_OR(DUT_NODE, extended_output_enable, false), + "Extended output was enabled, but not set"); + + zassert_true((config->format == MTCH9010_OUTPUT_FORMAT_CURRENT), + "Current output format was not correctly implied"); + } +} + +ZTEST_F(mtch9010_config, test_custom_value) +{ + const struct mtch9010_config *config = fixture->dev->config; + const struct mtch9010_data *data = fixture->dev->data; + int custom_value = DT_PROP_OR(DUT_NODE, reference_value, -1); + + switch (config->ref_mode) { + case MTCH9010_REFERENCE_CURRENT_VALUE: { + zassert_equal(custom_value, -1, "Incorrect reference initialization mode set"); + break; + } + case MTCH9010_REFERENCE_CUSTOM_VALUE: { + zassert_not_equal(custom_value, -1, "Incorrect reference initialization mode set"); + zassert_equal(custom_value, data->reference, + "Reference value was not set to custom value"); + break; + } + case MTCH9010_REFERENCE_RERUN_VALUE: { + zassert_unreachable("Illegal reference value mode set"); + break; + } + default: { + zassert_unreachable("Unknown Reference Value set"); + break; + } + } +} + +ZTEST_F(mtch9010_config, test_threshold_value) +{ + const struct mtch9010_data *data = fixture->dev->data; + int custom_value = DT_PROP(DUT_NODE, detect_value); + + zassert_equal(data->threshold, custom_value, "Threshold value was not set to custom value"); +} diff --git a/tests/drivers/sensor/mtch9010/test_configs/data_format/both.overlay b/tests/drivers/sensor/mtch9010/test_configs/data_format/both.overlay new file mode 100644 index 0000000000000..df9a0640f9a40 --- /dev/null +++ b/tests/drivers/sensor/mtch9010/test_configs/data_format/both.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +&uart1 { + status = "okay"; + current-speed = <38400>; + + dut: mtch9010 { + status = "okay"; + compatible = "microchip,mtch9010"; + + /* Device Configuration */ + operating-mode = "MTCH9010_CONDUCTIVE"; + extended-output-enable; + extended-output-format = "MTCH9010_OUTPUT_FORMAT_BOTH"; + reference-value = <0>; + detect-value = <600>; + }; +}; diff --git a/tests/drivers/sensor/mtch9010/test_configs/data_format/current.overlay b/tests/drivers/sensor/mtch9010/test_configs/data_format/current.overlay new file mode 100644 index 0000000000000..40a34497a6344 --- /dev/null +++ b/tests/drivers/sensor/mtch9010/test_configs/data_format/current.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +&uart1 { + status = "okay"; + current-speed = <38400>; + + dut: mtch9010 { + status = "okay"; + compatible = "microchip,mtch9010"; + + /* Device Configuration */ + operating-mode = "MTCH9010_CAPACITIVE"; + extended-output-enable; + extended-output-format = "MTCH9010_OUTPUT_FORMAT_CURRENT"; + reference-value = <0>; + detect-value = <600>; + }; +}; diff --git a/tests/drivers/sensor/mtch9010/test_configs/data_format/data_visualizer.overlay b/tests/drivers/sensor/mtch9010/test_configs/data_format/data_visualizer.overlay new file mode 100644 index 0000000000000..90d4d88a95546 --- /dev/null +++ b/tests/drivers/sensor/mtch9010/test_configs/data_format/data_visualizer.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +&uart1 { + status = "okay"; + current-speed = <38400>; + + dut: mtch9010 { + status = "okay"; + compatible = "microchip,mtch9010"; + + /* Device Configuration */ + operating-mode = "MTCH9010_CONDUCTIVE"; + extended-output-enable; + extended-output-format = "MTCH9010_OUTPUT_FORMAT_MPLAB_DATA_VISUALIZER"; + reference-value = <0>; + detect-value = <600>; + }; +}; diff --git a/tests/drivers/sensor/mtch9010/test_configs/data_format/delta.overlay b/tests/drivers/sensor/mtch9010/test_configs/data_format/delta.overlay new file mode 100644 index 0000000000000..e72caaec2cb12 --- /dev/null +++ b/tests/drivers/sensor/mtch9010/test_configs/data_format/delta.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +&uart1 { + status = "okay"; + current-speed = <38400>; + + dut: mtch9010 { + status = "okay"; + compatible = "microchip,mtch9010"; + + /* Device Configuration */ + operating-mode = "MTCH9010_CAPACITIVE"; + extended-output-enable; + extended-output-format = "MTCH9010_OUTPUT_FORMAT_DELTA"; + reference-value = <0>; + detect-value = <600>; + }; +}; diff --git a/tests/drivers/sensor/mtch9010/test_configs/data_format/unspecified.overlay b/tests/drivers/sensor/mtch9010/test_configs/data_format/unspecified.overlay new file mode 100644 index 0000000000000..a642a85e31743 --- /dev/null +++ b/tests/drivers/sensor/mtch9010/test_configs/data_format/unspecified.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +&uart1 { + status = "okay"; + current-speed = <38400>; + + dut: mtch9010 { + status = "okay"; + compatible = "microchip,mtch9010"; + + /* Device Configuration */ + operating-mode = "MTCH9010_CONDUCTIVE"; + reference-value = <0>; + detect-value = <600>; + }; +}; diff --git a/tests/drivers/sensor/mtch9010/test_configs/operating_mode/capacitive.overlay b/tests/drivers/sensor/mtch9010/test_configs/operating_mode/capacitive.overlay new file mode 100644 index 0000000000000..e72caaec2cb12 --- /dev/null +++ b/tests/drivers/sensor/mtch9010/test_configs/operating_mode/capacitive.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +&uart1 { + status = "okay"; + current-speed = <38400>; + + dut: mtch9010 { + status = "okay"; + compatible = "microchip,mtch9010"; + + /* Device Configuration */ + operating-mode = "MTCH9010_CAPACITIVE"; + extended-output-enable; + extended-output-format = "MTCH9010_OUTPUT_FORMAT_DELTA"; + reference-value = <0>; + detect-value = <600>; + }; +}; diff --git a/tests/drivers/sensor/mtch9010/test_configs/operating_mode/conductive.overlay b/tests/drivers/sensor/mtch9010/test_configs/operating_mode/conductive.overlay new file mode 100644 index 0000000000000..cf971aaf9e5fa --- /dev/null +++ b/tests/drivers/sensor/mtch9010/test_configs/operating_mode/conductive.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +&uart1 { + status = "okay"; + current-speed = <38400>; + + dut: mtch9010 { + status = "okay"; + compatible = "microchip,mtch9010"; + + /* Device Configuration */ + operating-mode = "MTCH9010_CONDUCTIVE"; + extended-output-enable; + extended-output-format = "MTCH9010_OUTPUT_FORMAT_DELTA"; + reference-value = <0>; + detect-value = <600>; + }; +}; diff --git a/tests/drivers/sensor/mtch9010/testcase.yaml b/tests/drivers/sensor/mtch9010/testcase.yaml new file mode 100644 index 0000000000000..47ffb071847ad --- /dev/null +++ b/tests/drivers/sensor/mtch9010/testcase.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2025 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +common: + tags: + - drivers + - sensor + - subsys + platform_allow: + - native_sim +tests: + drivers.sensor.mtch9010_capacitive: + extra_args: EXTRA_DTC_OVERLAY_FILE=./test_configs/operating_mode/capacitive.overlay + drivers.sensor.mtch9010_conductive: + extra_args: EXTRA_DTC_OVERLAY_FILE=./test_configs/operating_mode/conductive.overlay + drivers.sensor.mtch9010_current_output: + extra_args: EXTRA_DTC_OVERLAY_FILE=./test_configs/data_format/current.overlay + drivers.sensor.mtch9010_delta_output: + extra_args: EXTRA_DTC_OVERLAY_FILE=./test_configs/data_format/delta.overlay + drivers.sensor.mtch9010_both_outputs: + extra_args: EXTRA_DTC_OVERLAY_FILE=./test_configs/data_format/both.overlay + drivers.sensor.mtch9010_data_visualizer_output: + extra_args: EXTRA_DTC_OVERLAY_FILE=./test_configs/data_format/data_visualizer.overlay + drivers.sensor.mtch9010_unspecified_output: + extra_args: EXTRA_DTC_OVERLAY_FILE=./test_configs/data_format/unspecified.overlay diff --git a/west.yml b/west.yml index a286e3058e6f6..882a15ba4e733 100644 --- a/west.yml +++ b/west.yml @@ -169,7 +169,7 @@ manifest: groups: - hal - name: hal_espressif - revision: 21ff951cc2ca1c3ae6a096a4f9bc3b7f2f2c5409 + revision: 78fb21d5bcd88adcc787fff9591da6975c80c5eb path: modules/hal/espressif west-commands: west/west-commands.yml groups: @@ -185,7 +185,7 @@ manifest: groups: - hal - name: hal_infineon - revision: 3ef39bda93a67cf2ef735f1679aee5a103f92275 + revision: 58ce131beba8ad94e58837b7d0f5e31a7894790a path: modules/hal/infineon groups: - hal @@ -210,7 +210,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 18a86af73c63e37420a1044108c40fcb35635f5b + revision: 6adb4c509dc86d5702f48b952f209b7c91270250 path: modules/hal/nxp groups: - hal @@ -364,7 +364,7 @@ manifest: groups: - debug - name: trusted-firmware-a - revision: 713ffbf96c5bcbdeab757423f10f73eb304eff07 + revision: 0a29cac8fe0f7bdb835b469d9ea11b8e17377a92 path: modules/tee/tf-a/trusted-firmware-a groups: - tee