This is an automated email from the ASF dual-hosted git repository.

anchao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 1588fbe28f83dde26e074b95ac37bfc637272ac5
Author: Ricard Rosson <[email protected]>
AuthorDate: Tue Oct 27 01:48:35 2026 +0000

    boards/arm/rp23xx: Add Raspberry Pi Pico 2 W board.
    
    Add a board port for the Raspberry Pi Pico 2 W: RP2350A, 4 MiB flash and
    an Infineon CYW43439 Wi-Fi chip.
    
    The Wi-Fi chip uses the existing rp23xx gSPI CYW43439 driver and the
    common rp23xx_firmware.c, wired the same way as on pimoroni-pico-plus-2-w:
    the CYW43439 is on GPIO 23 (power), 24 (data/IRQ), 25 (chip select) and
    29 (clock).  The onboard LED hangs off the CYW43439's own GPIO 0, so the
    board supports CONFIG_USERLED but not CONFIG_ARCH_LEDS.  Flash size and
    memory maps follow raspberrypi-pico-2.
    
    A telnet defconfig associates to an AP (NETINIT WAPI), obtains a DHCP
    lease and exposes an NSH shell over telnet.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Ricard Rosson <[email protected]>
---
 .../rp23xx/boards/raspberrypi-pico-2-w/index.rst   | 157 ++++++++
 boards/Kconfig                                     |  12 +
 .../arm/rp23xx/raspberrypi-pico-2-w/CMakeLists.txt |  40 +++
 boards/arm/rp23xx/raspberrypi-pico-2-w/Kconfig     |  54 +++
 .../raspberrypi-pico-2-w/configs/telnet/defconfig  |  89 +++++
 .../rp23xx/raspberrypi-pico-2-w/include/board.h    | 141 ++++++++
 .../include/rp23xx_extra_gpio.h                    | 139 ++++++++
 .../raspberrypi-pico-2-w/include/rp23xx_i2cdev.h   |  72 ++++
 .../raspberrypi-pico-2-w/include/rp23xx_i2sdev.h   |  72 ++++
 .../raspberrypi-pico-2-w/include/rp23xx_spidev.h   |  69 ++++
 .../raspberrypi-pico-2-w/include/rp23xx_spisd.h    |  85 +++++
 .../rp23xx/raspberrypi-pico-2-w/scripts/Make.defs  |  43 +++
 .../scripts/memmap_copy_to_ram.ld                  | 340 ++++++++++++++++++
 .../raspberrypi-pico-2-w/scripts/memmap_default.ld | 353 ++++++++++++++++++
 .../scripts/memmap_no_flash.ld                     | 294 +++++++++++++++
 .../rp23xx/raspberrypi-pico-2-w/src/CMakeLists.txt |  62 ++++
 .../arm/rp23xx/raspberrypi-pico-2-w/src/Make.defs  |  89 +++++
 .../src/rp23xx_boardinitialize.c                   | 115 ++++++
 .../raspberrypi-pico-2-w/src/rp23xx_bringup.c      | 118 ++++++
 .../rp23xx/raspberrypi-pico-2-w/src/rp23xx_gpio.c  | 396 +++++++++++++++++++++
 .../rp23xx/raspberrypi-pico-2-w/src/rp23xx_pico.h  |  53 +++
 .../raspberrypi-pico-2-w/src/rp23xx_userleds.c     |  94 +++++
 22 files changed, 2887 insertions(+)

diff --git 
a/Documentation/platforms/arm/rp23xx/boards/raspberrypi-pico-2-w/index.rst 
b/Documentation/platforms/arm/rp23xx/boards/raspberrypi-pico-2-w/index.rst
new file mode 100644
index 00000000000..0f4ab64827c
--- /dev/null
+++ b/Documentation/platforms/arm/rp23xx/boards/raspberrypi-pico-2-w/index.rst
@@ -0,0 +1,157 @@
+=====================
+Raspberry Pi Pico 2 W
+=====================
+
+.. tags:: arch:arm, chip:rp23xx, part:rp2350, vendor:raspberry-pi
+
+The `Raspberry Pi Pico 2 W 
<https://www.raspberrypi.com/products/raspberry-pi-pico-2/>`_
+is the Raspberry Pi Pico 2 with an Infineon CYW43439 added for 2.4 GHz WiFi and
+Bluetooth.
+
+Features
+========
+
+* RP2350 microcontroller chip
+* Dual-core ARM Cortex-M33 processor, flexible clock running up to 150 MHz
+* 520 kB of SRAM, and 4 MB of on-board Flash memory
+* Castellated module allows soldering direct to carrier boards
+* USB 1.1 Host and Device support
+* Low-power sleep and dormant modes
+* Drag & drop programming using mass storage over USB
+* 26 multi-function GPIO pins
+* 2x SPI, 2x I2C, 2x UART, 3x 12-bit ADC, 16x controllable PWM channels
+* Accurate clock and timer on-chip
+* Temperature sensor
+* Accelerated floating point libraries on-chip
+* 12 x Programmable IO (PIO) state machines for custom peripheral support
+* Infineon CYW43439 for 2.4 GHz WiFi 4 (802.11n) and Bluetooth
+
+Serial Console
+==============
+
+By default the serial console is UART0 on GPIO 0 (TX, pin 1) and GPIO 1
+(RX, pin 2), at 115200-8N1.
+
+The ``composite`` configuration instead puts the console on the USB
+connection, as a CDC-ACM serial device.
+
+Wireless Communication
+======================
+
+The on-board CYW43439 is driven over a half-duplex gSPI bus by a PIO state
+machine, implemented in ``arch/arm/src/rp23xx/rp23xx_cyw43439.c`` (the same
+driver as the :doc:`../pimoroni-pico-plus-2-w/index`).  It appears as the
+``wlan0`` network device and supports 2.4 GHz WiFi 4 (802.11n) in station
+mode.  Bluetooth is not supported.  The chip's firmware is downloaded when
+``wlan0`` is brought up.
+
+The CYW43439 is wired to the RP2350 as on the RP2040 Pico W:
+
+* GPIO23 Output - power / on-off control
+* GPIO24 I/O    - gSPI data, also the interrupt line
+* GPIO25 Output - chip select
+* GPIO29 Output - gSPI clock
+
+CYW43439 firmware
+-----------------
+
+The wireless chip's firmware and CLM blob are linked into the NuttX binary
+from ``CONFIG_CYW43439_FIRMWARE_BIN_PATH``, which defaults to the copy in the
+Raspberry Pi Pico SDK::
+
+  ${PICO_SDK_PATH}/lib/cyw43-driver/firmware/43439A0-7.95.49.00.combined
+
+pico-sdk 2.x ships that file only as a C header; the
+:doc:`../pimoroni-pico-plus-2-w/index` page shows how to convert it back.  If
+the file is missing the build still succeeds, but the wireless chip will not
+come up.
+
+User LED
+========
+
+The board's LED is wired to GPIO 0 of the CYW43439, not to a pin of the
+RP2350, so setting it means a request over the gSPI bus:
+
+* The LED does not respond until ``wlan0`` has been brought up.
+* It cannot be driven from interrupt context, so ``CONFIG_ARCH_LEDS`` is not
+  supported; a build with it enabled is rejected with an explicit error.
+
+With ``CONFIG_USERLED`` the LED appears as ``/dev/userleds`` and can be
+driven with the ``leds`` example.
+
+Buttons
+=======
+
+The BOOTSEL button, if held down when power is first applied to the board,
+makes the RP2350 boot into programming mode and appear as a storage device to
+a computer connected via USB.  Saving a .UF2 file to this device replaces the
+Flash ROM contents.  BOOTSEL is not readable as a GPIO.
+
+Supported Capabilities
+======================
+
+NuttX supports the following Pico 2 W capabilities:
+
+* UART (console port)
+
+  * GPIO 0 (UART0 TX) and GPIO 1 (UART0 RX) are used for the console.
+
+* WiFi station mode (CYW43439, 2.4 GHz 802.11n)
+* I2C
+* SPI (master only)
+* DMAC
+* PWM
+* ADC
+* Watchdog
+* USB device
+
+  * CDC/ACM serial, CDC-NCM network and a composite of the two.
+  * CDC/ACM serial device can be used for the console.
+
+* PIO (RP2350 Programmable I/O)
+* Flash ROM Boot
+* SRAM Boot
+
+Installation
+============
+
+The Pico 2 W shares the tool-chain and SDK setup of the
+:doc:`../raspberrypi-pico-2/index`; follow the Installation steps of the main
+:doc:`RP2350 documentation <../../index>` to install the Pico SDK and
+``picotool`` and to set ``PICO_SDK_PATH``, which also provides the CYW43439
+firmware.
+
+Configurations
+==============
+
+All configurations listed below can be configured using the following command
+in the ``nuttx`` directory:
+
+.. code:: console
+
+   $ ./tools/configure.sh raspberrypi-pico-2-w:<configname>
+
+telnet
+------
+
+NuttShell on UART0 (115200 bps), with WiFi station mode brought up at boot and
+a telnet server, so the shell is reachable over the network once the board
+has associated.
+
+Set the network credentials before building, with ``make menuconfig`` under
+Application Configuration -> Network Utilities -> Network initialization ->
+WAPI Configuration; the shipped defconfig carries placeholders only.
+
+composite
+---------
+
+NuttShell on a USB CDC-ACM console, plus a CDC-NCM network interface
+(``eth0``) on the same USB connection, and a telnet server.  ``eth0`` only
+exists once the USB console has connected, so give it an address from the
+console, for example:
+
+.. code:: console
+
+   nsh> ifconfig eth0 192.168.7.1
+
+and put the host's end of the USB link in the same subnet.
diff --git a/boards/Kconfig b/boards/Kconfig
index 35bd0a6273b..6484cc2880d 100644
--- a/boards/Kconfig
+++ b/boards/Kconfig
@@ -2482,6 +2482,14 @@ config ARCH_BOARD_RASPBERRYPI_PICO_2
        ---help---
                This is a port to the Raspberry Pi Pico 2 board.
 
+config ARCH_BOARD_RASPBERRYPI_PICO_2_W
+       bool "Raspberry Pi Pico 2 W board"
+       depends on ARCH_CHIP_RP23XX
+       select ARCH_HAVE_LEDS
+       ---help---
+               This is a port to the Raspberry Pi Pico 2 W board, with support 
for
+               the onboard Infineon CYW43439 Wi-Fi chip.
+
 config ARCH_BOARD_RASPBERRYPI_PICO_2_RV
        bool "Raspberry Pi Pico 2 board RISC-V (not Pico, not W)"
        depends on ARCH_CHIP_RP23XX_RV
@@ -4347,6 +4355,7 @@ config ARCH_BOARD
        default "adafruit-qt-py-rp2040"        if 
ARCH_BOARD_ADAFRUIT_QT_PY_RP2040
        default "waveshare-rp2040-lcd-1.28"    if 
ARCH_BOARD_WAVESHARE_RP2040_LCD_1_28
        default "raspberrypi-pico-2"           if ARCH_BOARD_RASPBERRYPI_PICO_2
+       default "raspberrypi-pico-2-w"         if 
ARCH_BOARD_RASPBERRYPI_PICO_2_W
        default "raspberrypi-pico-2-rv"        if 
ARCH_BOARD_RASPBERRYPI_PICO_2_RV
        default "xiao-rp2350"                  if ARCH_BOARD_XIAO_RP2350
        default "pimoroni-pico-2-plus"         if 
ARCH_BOARD_PIMORONI_PICO_2_PLUS
@@ -4915,6 +4924,9 @@ endif
 if ARCH_BOARD_RASPBERRYPI_PICO_2
 source "boards/arm/rp23xx/raspberrypi-pico-2/Kconfig"
 endif
+if ARCH_BOARD_RASPBERRYPI_PICO_2_W
+source "boards/arm/rp23xx/raspberrypi-pico-2-w/Kconfig"
+endif
 if ARCH_BOARD_XIAO_RP2350
 source "boards/arm/rp23xx/xiao-rp2350/Kconfig"
 endif
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/CMakeLists.txt 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/CMakeLists.txt
new file mode 100644
index 00000000000..cfc17c73011
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/CMakeLists.txt
@@ -0,0 +1,40 @@
+# 
##############################################################################
+# boards/arm/rp23xx/raspberrypi-pico-2-w/CMakeLists.txt
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements.  See the NOTICE file distributed with this work for
+# additional information regarding copyright ownership.  The ASF licenses this
+# file to you under the Apache License, Version 2.0 (the "License"); you may 
not
+# use this file except in compliance with the License.  You may obtain a copy 
of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+#
+# 
##############################################################################
+
+add_subdirectory(src)
+
+add_custom_target(
+  nuttx_post_build
+  DEPENDS nuttx
+  WORKING_DIRECTORY ${NUTTX_BINARY_DIR}
+  COMMENT "Regenerate nuttx.uf2")
+
+# The uf2 command to convert ELF/BIN to UF2
+add_custom_command(
+  TARGET nuttx_post_build
+  POST_BUILD
+  COMMAND picotool ARGS uf2 convert --quiet -t elf nuttx nuttx.uf2
+  COMMAND_EXPAND_LISTS
+  COMMAND ${CMAKE_COMMAND} -E echo "nuttx.uf2" >>
+          ${NUTTX_BINARY_DIR}/nuttx.manifest
+  WORKING_DIRECTORY ${NUTTX_BINARY_DIR}
+  COMMENT "Regenerate nuttx.uf2")
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/Kconfig 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/Kconfig
new file mode 100644
index 00000000000..5cc7b9618e8
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/Kconfig
@@ -0,0 +1,54 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+if ARCH_BOARD_RASPBERRYPI_PICO_2_W
+
+# The board's only LED hangs off a GPIO of the CYW43439, so setting it means a
+# transaction on the gSPI bus.  board_autoled_on() is called from interrupt
+# handlers and from assertion handling, where that is not permissible, so this
+# board supports the CONFIG_USERLED interface only.  Override the generic
+# "default y" so that a fresh configuration does not select something this
+# board cannot implement.
+
+config ARCH_LEDS
+       default n
+
+menuconfig RP23XX_INFINEON_CYW43439
+       bool "Has Infineon cyw43439 WiFi chip"
+       depends on IEEE80211_INFINEON_CYW43439
+       default y
+
+endif
+
+if RP23XX_INFINEON_CYW43439
+
+config CYW43439_FIRMWARE_BIN_PATH
+       string "Path to Infineon 43439 firmware file"
+       default 
"${PICO_SDK_PATH}/lib/cyw43-driver/firmware/43439A0-7.95.49.00.combined"
+       ---help---
+               This should be a path to a file containing both the cyw43439 
firmware and
+               the CLM blob.  The firmware should be padded to a 256 byte 
boundary and
+               then the CLM blob should be appended.
+
+               If this file is updated, check the CYW43439_FIRMWARE_LEN below 
to make sure
+               it reflects the un-padded length of the firmware part.
+
+               pico-sdk 2.x no longer ships this blob as a binary, only as the 
C header
+               lib/cyw43-driver/firmware/w43439A0_7_95_49_00_combined.h.  If 
that is all
+               you have, convert the byte array in that header back to a 
binary and point
+               this option at the result.
+
+config CYW43439_FIRMWARE_LEN
+       int "Infineon 43439 firmware length (bytes)"
+       default 224190
+       ---help---
+               This is the length of just the base firmware in the firmware 
file specified
+               by the "Path to Infineon 43439 firmware file" configuration 
option.
+
+               This length does not include the length of any padding nor the 
length of
+               the appended clm_blob. If a clm_blob is present in the firmware 
file, this
+               length will be less than the length of the whole file.
+
+endif
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/configs/telnet/defconfig 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/configs/telnet/defconfig
new file mode 100644
index 00000000000..9cd72d790ba
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/configs/telnet/defconfig
@@ -0,0 +1,89 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed 
.config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that 
includes your
+# modifications.
+#
+# CONFIG_ARCH_LEDS is not set
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_DISABLE_DATE is not set
+# CONFIG_NSH_DISABLE_LOSMART is not set
+# CONFIG_STANDARD_SERIAL is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="raspberrypi-pico-2-w"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_RASPBERRYPI_PICO_2_W=y
+CONFIG_ARCH_CHIP="rp23xx"
+CONFIG_ARCH_CHIP_RP23XX=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_RAMVECTORS=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=10450
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DISABLE_POSIX_TIMERS=y
+CONFIG_DRIVERS_IEEE80211=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_EXAMPLES_HELLO=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_PROCFS_REGISTER=y
+CONFIG_IEEE80211_BROADCOM_DEFAULT_COUNTRY="XX"
+CONFIG_IEEE80211_BROADCOM_DMABUF_ALIGNMENT=16
+CONFIG_IEEE80211_BROADCOM_FRAME_POOL_SIZE=32
+CONFIG_IEEE80211_BROADCOM_FULLMAC_GSPI=y
+CONFIG_IEEE80211_INFINEON_CYW43439=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_IOB_NBUFFERS=196
+CONFIG_IOB_NCHAINS=24
+CONFIG_NET=y
+CONFIG_NETDB_DNSCLIENT=y
+CONFIG_NETDB_DNSCLIENT_RECV_TIMEOUT=3
+CONFIG_NETDEV_LATEINIT=y
+CONFIG_NETDEV_WIRELESS_IOCTL=y
+CONFIG_NETINIT_DHCPC=y
+CONFIG_NETINIT_DNS=y
+CONFIG_NETINIT_DNSIPADDR=0x08080808
+CONFIG_NETINIT_WAPI_PASSPHRASE="-ssid-passphrase-"
+CONFIG_NETINIT_WAPI_SSID="-my-ssid-"
+CONFIG_NETUTILS_TELNETD=y
+CONFIG_NET_BROADCAST=y
+CONFIG_NET_ICMP_SOCKET=y
+CONFIG_NET_LOOPBACK=y
+CONFIG_NET_LOOPBACK_PKTSIZE=1024
+CONFIG_NET_TCP=y
+CONFIG_NET_TCP_DELAYED_ACK=y
+CONFIG_NET_UDP=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_READLINE=y
+CONFIG_RAM_SIZE=532480
+CONFIG_RAM_START=0x20000000
+CONFIG_READLINE_CMD_HISTORY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_START_DAY=9
+CONFIG_START_MONTH=2
+CONFIG_START_YEAR=2021
+CONFIG_SYSLOG_BUFFER=y
+CONFIG_SYSLOG_INTBUFFER=y
+CONFIG_SYSLOG_INTBUFSIZE=2048
+CONFIG_SYSLOG_PROCESSID=y
+CONFIG_SYSTEM_DHCPC_RENEW=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_PING=y
+CONFIG_SYSTEM_TELNET_CLIENT=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_TTY_SIGINT=y
+CONFIG_TTY_SIGTSTP=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USERLED=y
+CONFIG_USERLED_LOWER=y
+CONFIG_WIRELESS_WAPI=y
+CONFIG_WIRELESS_WAPI_CMDTOOL=y
+CONFIG_WQUEUE_NOTIFIER=y
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/include/board.h 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/board.h
new file mode 100644
index 00000000000..ac15e2245f6
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/board.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/include/board.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_BOARD_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_BOARD_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "rp23xx_i2cdev.h"
+#include "rp23xx_spidev.h"
+#include "rp23xx_i2sdev.h"
+#include "rp23xx_spisd.h"
+
+#ifndef __ASSEMBLY__
+#  include <stdint.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Clocking *****************************************************************/
+
+#define MHZ                     1000000
+
+#define BOARD_XOSC_FREQ         (12 * MHZ)
+#define BOARD_XOSC_STARTUPDELAY 1
+#define BOARD_PLL_SYS_FREQ      (150 * MHZ)
+#define BOARD_PLL_USB_FREQ      (48 * MHZ)
+
+#define BOARD_REF_FREQ          (12 * MHZ)
+#define BOARD_SYS_FREQ          (150 * MHZ)
+#define BOARD_PERI_FREQ         (150 * MHZ)
+#define BOARD_USB_FREQ          (48 * MHZ)
+#define BOARD_ADC_FREQ          (48 * MHZ)
+#define BOARD_HSTX_FREQ         (150 * MHZ)
+
+#define BOARD_UART_BASEFREQ     BOARD_PERI_FREQ
+
+#define BOARD_TICK_CLOCK        (1 * MHZ)
+
+/* definitions for pico-sdk */
+
+/* GPIO definitions *********************************************************/
+
+#define BOARD_NGPIOOUT          1
+#define BOARD_NGPIOIN           1
+#define BOARD_NGPIOINT          1
+
+/* LED definitions **********************************************************/
+
+/* The only LED on this board is wired to GPIO 0 of the CYW43439 wireless
+ * chip, not to a GPIO of the RP2350.  Driving it means sending an iovar
+ * request over the gSPI bus, which can only be done from task context and
+ * only once the wireless chip has been activated by bringing wlan0 up.
+ *
+ * That rules out CONFIG_ARCH_LEDS -- board_autoled_on() is called from
+ * interrupt handlers and from assertion handling, where a bus transaction
+ * is not permissible.  So this board provides the user LED interface only
+ * (CONFIG_USERLED) and does not select ARCH_HAVE_LEDS.
+ */
+
+/* LED index values for use with board_userled() */
+
+#define BOARD_LED1        0
+#define BOARD_NLEDS       1
+
+#define BOARD_LED_GREEN   BOARD_LED1
+
+/* LED bits for use with board_userled_all() */
+
+#define BOARD_LED1_BIT    (1 << BOARD_LED1)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rp23xx_boardearlyinitialize
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+void rp23xx_boardearlyinitialize(void);
+
+/****************************************************************************
+ * Name: rp23xx_boardinitialize
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+void rp23xx_boardinitialize(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_BOARD_H */
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_extra_gpio.h 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_extra_gpio.h
new file mode 100644
index 00000000000..65efb38b9ac
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_extra_gpio.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_extra_gpio.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_EXTRA_GPIO_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_EXTRA_GPIO_H
+
+/****************************************************************************
+ *  These functions control the GPIO pins on the CYW43439 wireless chip, not
+ *  the GPIO pins of the RP2350.  The pin assignments for the Pimoroni Pico
+ *  Plus 2 W are:
+ *
+ *  GPIO 0 - output - controls the onboard LED
+ *  GPIO 1 - output - controls the onboard voltage regulator mode.
+ *  GPIO 2 - input  - Reads as non-zero if power supplied by USB or VBUS pin.
+ *
+ *  These only work once the wireless chip has been activated, which happens
+ *  when the wlan0 network interface is brought up.  Until then every access
+ *  fails with -EIO.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/wireless/ieee80211/bcmf_gpio.h>
+#include <nuttx/wireless/ieee80211/bcmf_gspi.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define RP23XX_EXTRA_GPIO_NUM    3     /* Number of extra GPIO pins */
+
+#define RP23XX_EXTRA_GPIO_LED    0     /* Onboard LED               */
+#define RP23XX_EXTRA_GPIO_VREG   1     /* Voltage regulator mode    */
+#define RP23XX_EXTRA_GPIO_VBUS   2     /* VBUS present              */
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+EXTERN gspi_dev_t *g_cyw43439;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rp23xx_extra_gpio_put
+ *
+ * Description:
+ *   Change the state of a GPIO pin on the CYW43439.
+ *
+ * Returned Value:
+ *   OK on success, or a negated errno.  -EIO means the wireless chip is not
+ *   running yet, which is the case until wlan0 has been brought up.
+ *
+ ****************************************************************************/
+
+static inline int rp23xx_extra_gpio_put(uint32_t gpio, bool value)
+{
+  DEBUGASSERT(gpio < RP23XX_EXTRA_GPIO_NUM);
+
+  if (g_cyw43439 == NULL)
+    {
+      return -EIO;
+    }
+
+  return bcmf_set_gpio(g_cyw43439->priv, gpio, value);
+}
+
+/****************************************************************************
+ * Name: rp23xx_extra_gpio_get
+ *
+ * Description:
+ *   Read the state of a GPIO pin on the CYW43439.
+ *
+ * Returned Value:
+ *   OK on success, or a negated errno.  -EIO means the wireless chip is not
+ *   running yet, which is the case until wlan0 has been brought up.
+ *
+ ****************************************************************************/
+
+static inline int rp23xx_extra_gpio_get(uint32_t gpio, bool *value)
+{
+  DEBUGASSERT(gpio < RP23XX_EXTRA_GPIO_NUM);
+
+  if (g_cyw43439 == NULL)
+    {
+      return -EIO;
+    }
+
+  return bcmf_get_gpio(g_cyw43439->priv, gpio, value);
+}
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_EXTRA_GPIO_H 
*/
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_i2cdev.h 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_i2cdev.h
new file mode 100644
index 00000000000..7baa2017676
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_i2cdev.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_i2cdev.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_I2CDEV_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_I2CDEV_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_i2cdev_initialize
+ *
+ * Description:
+ *   Initialize i2c driver and register the /dev/i2c device.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RP23XX_I2C_DRIVER
+int board_i2cdev_initialize(int bus);
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_I2CDEV_H */
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_i2sdev.h 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_i2sdev.h
new file mode 100644
index 00000000000..c7ba25f3b9f
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_i2sdev.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_i2sdev.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_I2SDEV_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_I2SDEV_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_i2sdev_initialize
+ *
+ * Description:
+ *   Initialize i2s driver and register the /dev/audio/pcm0 device.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RP23XX_I2S
+int board_i2sdev_initialize(int bus);
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_I2SDEV_H */
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_spidev.h 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_spidev.h
new file mode 100644
index 00000000000..5d1c201ff6b
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_spidev.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_spidev.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_SPIDEV_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_SPIDEV_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_spidev_initialize
+ *
+ * Description:
+ *   Initialize spi driver and register the /dev/spi device.
+ *
+ ****************************************************************************/
+
+int board_spidev_initialize(int bus);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_SPIDEV_H */
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_spisd.h 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_spisd.h
new file mode 100644
index 00000000000..c3b3d65b69f
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_spisd.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_spisd.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_SPISD_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_SPISD_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_spisd_initialize
+ *
+ * Description:
+ *   Initialize the SPI-based SD card.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RP23XX_SPISD
+int board_spisd_initialize(int minor, int bus);
+#endif
+
+/****************************************************************************
+ * Name: board_spisd_status
+ *
+ * Description:
+ *   Get the status whether SD Card is present or not.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RP23XX_SPISD
+uint8_t board_spisd_status(struct spi_dev_s *dev, uint32_t devid);
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_INCLUDE_RP23XX_SPISD_H */
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/Make.defs 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/Make.defs
new file mode 100644
index 00000000000..a543d134f7b
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/Make.defs
@@ -0,0 +1,43 @@
+############################################################################
+# boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(TOPDIR)/.config
+include $(TOPDIR)/tools/Config.mk
+include $(TOPDIR)/tools/rp23xx/Config.mk
+include $(TOPDIR)/arch/arm/src/armv8-m/Toolchain.defs
+
+ifeq ($(CONFIG_BOOT_RUNFROMFLASH),y)
+  LDSCRIPT = memmap_default.ld
+else ifeq ($(CONFIG_BOOT_COPYTORAM),y)
+  LDSCRIPT = memmap_copy_to_ram.ld
+else
+  LDSCRIPT = memmap_no_flash.ld
+endif
+
+ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)
+
+CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) 
$(ARCHDEFINES) $(EXTRAFLAGS) -pipe
+CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) 
$(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe
+CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS)
+AFLAGS := $(CFLAGS) -D__ASSEMBLY__
+
+NXFLATLDFLAGS1 = -r -d -warn-common
+NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) 
-T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections
+LDNXFLATFLAGS = -e main -s 2048
diff --git 
a/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_copy_to_ram.ld 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_copy_to_ram.ld
new file mode 100644
index 00000000000..2d73a7f4b6c
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_copy_to_ram.ld
@@ -0,0 +1,340 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_copy_to_ram.ld
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Based on GCC ARM embedded samples.
+   Defines the following symbols for use by code:
+    __exidx_start
+    __exidx_end
+    __etext
+    __data_start__
+    __preinit_array_start
+    __preinit_array_end
+    __init_array_start
+    __init_array_end
+    __fini_array_start
+    __fini_array_end
+    __data_end__
+    __bss_start__
+    __bss_end__
+    __end__
+    end
+    __HeapLimit
+    __StackLimit
+    __StackTop
+    __stack (== StackTop)
+*/
+
+MEMORY
+{
+    FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 4096k
+    RAM(rwx) : ORIGIN =  0x20000000, LENGTH = 512k
+    SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
+    SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
+}
+
+ENTRY(_entry_point)
+
+SECTIONS
+{
+    /* Second stage bootloader is prepended to the image. It must be 256 bytes 
big
+       and checksummed. It is usually built by the boot_stage2 target
+       in the Raspberry Pi Pico SDK
+    */
+
+    .flash_begin : {
+        __flash_binary_start = .;
+    } > FLASH
+
+    /* The bootrom will enter the image at the point indicated in your
+       IMAGE_DEF, which is usually the reset handler of your vector table.
+
+       The debugger will use the ELF entry point, which is the _entry_point
+       symbol, and in our case is *different from the bootrom's entry point.*
+       This is used to go back through the bootrom on debugger launches only,
+       to perform the same initial flash setup that would be performed on a
+       cold boot.
+    */
+
+    .flashtext : {
+        __logical_binary_start = .;
+        KEEP (*(.vectors))
+        KEEP (*(.binary_info_header))
+        __binary_info_header_end = .;
+        KEEP (*(.embedded_block))
+        __embedded_block_end = .;
+        KEEP (*(.reset))
+        . = ALIGN(4);
+    } > FLASH
+
+    /* Note the boot2 section is optional, and should be discarded if there is
+       no reference to it *inside* the binary, as it is not called by the
+       bootrom. (The bootrom performs a simple best-effort XIP setup and
+       leaves it to the binary to do anything more sophisticated.) However
+       there is still a size limit of 256 bytes, to ensure the boot2 can be
+       stored in boot RAM.
+
+       Really this is a "XIP setup function" -- the name boot2 is historic and
+       refers to its dual-purpose on RP2040, where it also handled vectoring
+       from the bootrom into the user image.
+    */
+
+    .boot2 : {
+        __boot2_start__ = .;
+        *(.boot2)
+        __boot2_end__ = .;
+    } > FLASH
+
+    ASSERT(__boot2_end__ - __boot2_start__ <= 256,
+        "ERROR: Pico second stage bootloader must be no more than 256 bytes in 
size")
+
+    .rodata : {
+        /* segments not marked as .flashdata are instead pulled into .data (in 
RAM) to avoid accidental flash accesses */
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
+        . = ALIGN(4);
+    } > FLASH
+
+    .ARM.extab :
+    {
+        *(.ARM.extab* .gnu.linkonce.armextab.*)
+    } > FLASH
+
+    __exidx_start = .;
+    .ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+    } > FLASH
+    __exidx_end = .;
+
+    /* Machine inspectable binary information */
+    . = ALIGN(4);
+    __binary_info_start = .;
+    .binary_info :
+    {
+        KEEP(*(.binary_info.keep.*))
+        *(.binary_info.*)
+    } > FLASH
+    __binary_info_end = .;
+    . = ALIGN(4);
+
+    /* Vector table goes first in RAM, to avoid large alignment hole */
+    .ram_vector_table (NOLOAD): {
+        *(.ram_vector_table)
+    } > RAM
+
+    .uninitialized_data (NOLOAD): {
+        . = ALIGN(4);
+        *(.uninitialized_data*)
+    } > RAM
+
+    .text : {
+        __ram_text_start__ = .;
+        *(.init)
+        *(.text*)
+        *(.fini)
+        /* Pull all c'tors into .text */
+        *crtbegin.o(.ctors)
+        *crtbegin?.o(.ctors)
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+        *(SORT(.ctors.*))
+        *(.ctors)
+        /* Followed by destructors */
+        *crtbegin.o(.dtors)
+        *crtbegin?.o(.dtors)
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+        *(SORT(.dtors.*))
+        *(.dtors)
+
+        *(.eh_frame*)
+        . = ALIGN(4);
+        __ram_text_end__ = .;
+    } > RAM AT> FLASH
+    __ram_text_source__ = LOADADDR(.text);
+    . = ALIGN(4);
+
+    .data : {
+        __data_start__ = .;
+        *(vtable)
+
+        *(.time_critical*)
+
+        . = ALIGN(4);
+        *(.rodata*)
+        *(.srodata*)
+        . = ALIGN(4);
+
+        *(.data*)
+        *(.sdata*)
+
+        /* GOT/PLT must live INSIDE the copied .data range so a flat
+         * -fPIC object (e.g. a PIC static library linked into an app)
+         * gets an initialised GOT in RAM at boot; otherwise an orphan
+         * .got lands after _edata, is never copied, and every GOT-
+         * indirected access reads a NULL pointer (hardfault). */
+        . = ALIGN(4);
+        *(.got)
+        *(.got.plt)
+        *(.got*)
+
+        . = ALIGN(4);
+        *(.after_data.*)
+        . = ALIGN(4);
+        /* preinit data */
+        PROVIDE_HIDDEN (__mutex_array_start = .);
+        KEEP(*(SORT(.mutex_array.*)))
+        KEEP(*(.mutex_array))
+        PROVIDE_HIDDEN (__mutex_array_end = .);
+
+        . = ALIGN(4);
+        /* preinit data */
+        PROVIDE_HIDDEN (__preinit_array_start = .);
+        KEEP(*(SORT(.preinit_array.*)))
+        KEEP(*(.preinit_array))
+        PROVIDE_HIDDEN (__preinit_array_end = .);
+
+        . = ALIGN(4);
+        /* init data */
+        PROVIDE_HIDDEN (__init_array_start = .);
+        KEEP(*(SORT(.init_array.*)))
+        KEEP(*(.init_array))
+        PROVIDE_HIDDEN (__init_array_end = .);
+
+        . = ALIGN(4);
+        /* finit data */
+        PROVIDE_HIDDEN (__fini_array_start = .);
+        *(SORT(.fini_array.*))
+        *(.fini_array)
+        PROVIDE_HIDDEN (__fini_array_end = .);
+
+        *(.jcr)
+        . = ALIGN(4);
+    } > RAM AT> FLASH
+
+    .tdata : {
+        . = ALIGN(4);
+               *(.tdata .tdata.* .gnu.linkonce.td.*)
+        /* All data end */
+        __tdata_end = .;
+    } > RAM AT> FLASH
+    PROVIDE(__data_end__ = .);
+
+    /* __etext is (for backwards compatibility) the name of the .data init 
source pointer (...) */
+    __etext = LOADADDR(.data);
+
+    .tbss (NOLOAD) : {
+        . = ALIGN(4);
+        __bss_start__ = .;
+        __tls_base = .;
+        *(.tbss .tbss.* .gnu.linkonce.tb.*)
+        *(.tcommon)
+
+        __tls_end = .;
+    } > RAM
+
+    .bss  : {
+        . = ALIGN(4);
+        __tbss_end = .;
+
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
+        *(COMMON)
+        PROVIDE(__global_pointer$ = . + 2K);
+        *(.sbss*)
+        . = ALIGN(4);
+        __bss_end__ = .;
+    } > RAM
+
+    .heap (NOLOAD):
+    {
+        __end__ = .;
+        end = __end__;
+        KEEP(*(.heap*))
+    } > RAM
+    /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, 
however
+       to be more compatible, we now set __HeapLimit explicitly to where the 
end of the heap is */
+    __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
+
+    /* Start and end symbols must be word-aligned */
+    .scratch_x : {
+        __scratch_x_start__ = .;
+        *(.scratch_x.*)
+        . = ALIGN(4);
+        __scratch_x_end__ = .;
+    } > SCRATCH_X AT > FLASH
+    __scratch_x_source__ = LOADADDR(.scratch_x);
+
+    .scratch_y : {
+        __scratch_y_start__ = .;
+        *(.scratch_y.*)
+        . = ALIGN(4);
+        __scratch_y_end__ = .;
+    } > SCRATCH_Y AT > FLASH
+    __scratch_y_source__ = LOADADDR(.scratch_y);
+
+    /* .stack*_dummy section doesn't contains any symbols. It is only
+     * used for linker to calculate size of stack sections, and assign
+     * values to stack symbols later
+     *
+     * stack1 section may be empty/missing if platform_launch_core1 is not 
used */
+
+    /* by default we put core 0 stack at the end of scratch Y, so that if core 
1
+     * stack is not used then all of SCRATCH_X is free.
+     */
+    .stack1_dummy (NOLOAD):
+    {
+        *(.stack1*)
+    } > SCRATCH_X
+    .stack_dummy (NOLOAD):
+    {
+        KEEP(*(.stack*))
+    } > SCRATCH_Y
+
+    .flash_end : {
+        KEEP(*(.embedded_end_block*))
+        PROVIDE(__flash_binary_end = .);
+    } > FLASH =0xaa
+
+    /* stack limit is poorly named, but historically is maximum heap ptr */
+    __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
+    __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
+    __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
+    __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
+    __StackBottom = __StackTop - SIZEOF(.stack_dummy);
+    PROVIDE(__stack = __StackTop);
+
+    /* picolibc and LLVM */
+    PROVIDE (__heap_start = __end__);
+    PROVIDE (__heap_end = __HeapLimit);
+    PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
+    PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align 
- 1));
+    PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
+
+    /* llvm-libc */
+    PROVIDE (_end = __end__);
+    PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
+
+    /* Check if data + heap + stack exceeds RAM limit */
+    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
+
+    ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary 
info must be in first 1024 bytes of the binary")
+    ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded 
block must be in first 4096 bytes of the binary")
+
+    /* todo assert on extra code */
+}
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_default.ld 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_default.ld
new file mode 100644
index 00000000000..8ee703d75fb
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_default.ld
@@ -0,0 +1,353 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_default.ld
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Based on GCC ARM embedded samples.
+   Defines the following symbols for use by code:
+    __exidx_start
+    __exidx_end
+    __etext
+    __data_start__
+    __preinit_array_start
+    __preinit_array_end
+    __init_array_start
+    __init_array_end
+    __fini_array_start
+    __fini_array_end
+    __data_end__
+    __bss_start__
+    __bss_end__
+    __end__
+    end
+    __HeapLimit
+    __StackLimit
+    __StackTop
+    __stack (== StackTop)
+*/
+
+MEMORY
+{
+    FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 4096k
+    RAM(rwx) : ORIGIN =  0x20000000, LENGTH = 512k
+    SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
+    SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
+}
+
+ENTRY(_entry_point)
+
+SECTIONS
+{
+    .flash_begin : {
+        __flash_binary_start = .;
+    } > FLASH
+
+    /* The bootrom will enter the image at the point indicated in your
+       IMAGE_DEF, which is usually the reset handler of your vector table.
+
+       The debugger will use the ELF entry point, which is the _entry_point
+       symbol, and in our case is *different from the bootrom's entry point.*
+       This is used to go back through the bootrom on debugger launches only,
+       to perform the same initial flash setup that would be performed on a
+       cold boot.
+    */
+
+    .text : {
+        __logical_binary_start = .;
+        _stext = ABSOLUTE(.);
+
+        KEEP (*(.vectors))
+
+        LONG(0xffffded3)
+        LONG(0x10210142)
+        LONG(0x000001ff)
+        LONG(0x00000000)
+        LONG(0xab123579)
+
+        KEEP (*(.binary_info_header))
+        __binary_info_header_end = .;
+        KEEP (*(.embedded_block))
+        __embedded_block_end = .;
+        KEEP (*(.reset))
+        /* TODO revisit this now memset/memcpy/float in ROM */
+        /* bit of a hack right now to exclude all floating point and time 
critical (e.g. memset, memcpy) code from
+         * FLASH ... we will include any thing excluded here in .data below by 
default */
+        *(.init)
+        *libgcc.a:cmse_nonsecure_call.o
+        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
+        *(.fini)
+        /* Pull all c'tors into .text */
+        *crtbegin.o(.ctors)
+        *crtbegin?.o(.ctors)
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+        *(SORT(.ctors.*))
+        *(.ctors)
+        /* Followed by destructors */
+        *crtbegin.o(.dtors)
+        *crtbegin?.o(.dtors)
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+        *(SORT(.dtors.*))
+        *(.dtors)
+
+        . = ALIGN(4);
+        /* preinit data */
+        PROVIDE_HIDDEN (__preinit_array_start = .);
+        KEEP(*(SORT(.preinit_array.*)))
+        KEEP(*(.preinit_array))
+        PROVIDE_HIDDEN (__preinit_array_end = .);
+
+        . = ALIGN(4);
+        /* init data */
+        PROVIDE_HIDDEN (__init_array_start = .);
+        KEEP(*(SORT(.init_array.*)))
+        KEEP(*(.init_array))
+        PROVIDE_HIDDEN (__init_array_end = .);
+
+        . = ALIGN(4);
+        /* finit data */
+        PROVIDE_HIDDEN (__fini_array_start = .);
+        *(SORT(.fini_array.*))
+        *(.fini_array)
+        PROVIDE_HIDDEN (__fini_array_end = .);
+
+        *(.eh_frame*)
+        . = ALIGN(4);
+        _etext = ABSOLUTE(.);
+    } > FLASH
+
+    /* Note the boot2 section is optional, and should be discarded if there is
+       no reference to it *inside* the binary, as it is not called by the
+       bootrom. (The bootrom performs a simple best-effort XIP setup and
+       leaves it to the binary to do anything more sophisticated.) However
+       there is still a size limit of 256 bytes, to ensure the boot2 can be
+       stored in boot RAM.
+
+       Really this is a "XIP setup function" -- the name boot2 is historic and
+       refers to its dual-purpose on RP2040, where it also handled vectoring
+       from the bootrom into the user image.
+    */
+
+    .boot2 : {
+        __boot2_start__ = .;
+        *(.boot2)
+        __boot2_end__ = .;
+    } > FLASH
+
+    ASSERT(__boot2_end__ - __boot2_start__ <= 256,
+        "ERROR: Pico second stage bootloader must be no more than 256 bytes in 
size")
+
+    .rodata : {
+        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
+        *(.srodata*)
+        . = ALIGN(4);
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
+        . = ALIGN(4);
+    } > FLASH
+
+    .ARM.extab :
+    {
+        *(.ARM.extab* .gnu.linkonce.armextab.*)
+    } > FLASH
+
+    __exidx_start = .;
+    .ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+    } > FLASH
+    __exidx_end = .;
+
+    /* Machine inspectable binary information */
+    . = ALIGN(4);
+    __binary_info_start = .;
+    .binary_info :
+    {
+        KEEP(*(.binary_info.keep.*))
+        *(.binary_info.*)
+    } > FLASH
+    _eronly = ABSOLUTE(.);
+    __binary_info_end = .;
+    . = ALIGN(4);
+
+    .ram_vector_table (NOLOAD): {
+        *(.ram_vector_table)
+    } > RAM
+
+    .uninitialized_data (NOLOAD): {
+        . = ALIGN(4);
+        *(.uninitialized_data*)
+    } > RAM
+
+    .data : {
+        __data_start__ = .;
+        _sdata = ABSOLUTE(.);
+
+        *(vtable)
+
+        *(.time_critical*)
+
+        /* remaining .text and .rodata; i.e. stuff we exclude above because we 
want it in RAM */
+        *(.text*)
+        . = ALIGN(4);
+        *(.rodata*)
+        . = ALIGN(4);
+
+        *(.data*)
+        *(.sdata*)
+
+        /* GOT/PLT must live INSIDE the copied .data range so a flat
+         * -fPIC object (e.g. a PIC static library linked into an app)
+         * gets an initialised GOT in RAM at boot; otherwise an orphan
+         * .got lands after _edata, is never copied, and every GOT-
+         * indirected access reads a NULL pointer (hardfault). */
+        . = ALIGN(4);
+        *(.got)
+        *(.got.plt)
+        *(.got*)
+
+        . = ALIGN(4);
+        *(.after_data.*)
+        . = ALIGN(4);
+        /* preinit data */
+        PROVIDE_HIDDEN (__mutex_array_start = .);
+        KEEP(*(SORT(.mutex_array.*)))
+        KEEP(*(.mutex_array))
+        PROVIDE_HIDDEN (__mutex_array_end = .);
+
+        *(.jcr)
+        . = ALIGN(4);
+        _edata = ABSOLUTE(.);
+    } > RAM AT> FLASH
+
+    .tdata : {
+        _stdata = ABSOLUTE(.);
+        . = ALIGN(4);
+               *(.tdata .tdata.* .gnu.linkonce.td.*)
+        /* All data end */
+        __tdata_end = .;
+        _etdata = ABSOLUTE(.);
+    } > RAM AT> FLASH
+    PROVIDE(__data_end__ = .);
+
+    /* __etext is (for backwards compatibility) the name of the .data init 
source pointer (...) */
+    __etext = LOADADDR(.data);
+
+    .tbss (NOLOAD) : {
+        _stbss = ABSOLUTE(.);
+        . = ALIGN(4);
+        __bss_start__ = .;
+        _sbss = ABSOLUTE(.);
+        __tls_base = .;
+        *(.tbss .tbss.* .gnu.linkonce.tb.*)
+        *(.tcommon)
+
+        __tls_end = .;
+        _etbss = ABSOLUTE(.);
+    } > RAM
+
+    .bss (NOLOAD) : {
+        . = ALIGN(4);
+        __tbss_end = .;
+
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
+        *(COMMON)
+        PROVIDE(__global_pointer$ = . + 2K);
+        *(.sbss*)
+        . = ALIGN(8);
+        __bss_end__ = .;
+        _ebss = ABSOLUTE(.);
+    } > RAM
+
+    .heap (NOLOAD):
+    {
+        __end__ = .;
+        end = __end__;
+        KEEP(*(.heap*))
+    } > RAM
+    /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, 
however
+       to be more compatible, we now set __HeapLimit explicitly to where the 
end of the heap is */
+    __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
+
+    /* Start and end symbols must be word-aligned */
+    .scratch_x : {
+        __scratch_x_start__ = .;
+        *(.scratch_x.*)
+        . = ALIGN(4);
+        __scratch_x_end__ = .;
+    } > SCRATCH_X AT > FLASH
+    __scratch_x_source__ = LOADADDR(.scratch_x);
+
+    .scratch_y : {
+        __scratch_y_start__ = .;
+        *(.scratch_y.*)
+        . = ALIGN(4);
+        __scratch_y_end__ = .;
+    } > SCRATCH_Y AT > FLASH
+    __scratch_y_source__ = LOADADDR(.scratch_y);
+
+    /* .stack*_dummy section doesn't contains any symbols. It is only
+     * used for linker to calculate size of stack sections, and assign
+     * values to stack symbols later
+     *
+     * stack1 section may be empty/missing if platform_launch_core1 is not 
used */
+
+    /* by default we put core 0 stack at the end of scratch Y, so that if core 
1
+     * stack is not used then all of SCRATCH_X is free.
+     */
+    .stack1_dummy (NOLOAD):
+    {
+        *(.stack1*)
+    } > SCRATCH_X
+    .stack_dummy (NOLOAD):
+    {
+        KEEP(*(.stack*))
+    } > SCRATCH_Y
+
+    .flash_end : {
+        KEEP(*(.embedded_end_block*))
+        PROVIDE(__flash_binary_end = .);
+    } > FLASH =0xaa
+
+    /* stack limit is poorly named, but historically is maximum heap ptr */
+    __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
+    __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
+    __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
+    __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
+    __StackBottom = __StackTop - SIZEOF(.stack_dummy);
+    PROVIDE(__stack = __StackTop);
+
+    /* picolibc and LLVM */
+    PROVIDE (__heap_start = __end__);
+    PROVIDE (__heap_end = __HeapLimit);
+    PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
+    PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align 
- 1));
+    PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
+
+    /* llvm-libc */
+    PROVIDE (_end = __end__);
+    PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
+
+    /* Check if data + heap + stack exceeds RAM limit */
+    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
+
+    ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary 
info must be in first 1024 bytes of the binary")
+    ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded 
block must be in first 4096 bytes of the binary")
+
+    /* todo assert on extra code */
+}
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_no_flash.ld 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_no_flash.ld
new file mode 100644
index 00000000000..a85a5c88865
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_no_flash.ld
@@ -0,0 +1,294 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_no_flash.ld
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Based on GCC ARM embedded samples.
+   Defines the following symbols for use by code:
+    __exidx_start
+    __exidx_end
+    __etext
+    __data_start__
+    __preinit_array_start
+    __preinit_array_end
+    __init_array_start
+    __init_array_end
+    __fini_array_start
+    __fini_array_end
+    __data_end__
+    __bss_start__
+    __bss_end__
+    __end__
+    end
+    __HeapLimit
+    __StackLimit
+    __StackTop
+    __stack (== StackTop)
+*/
+
+MEMORY
+{
+    RAM(rwx) : ORIGIN =  0x20000000, LENGTH = 512k
+    SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
+    SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
+}
+
+ENTRY(_entry_point)
+
+SECTIONS
+{
+    /* Note unlike RP2040, we start the image with a vector table even for
+       NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the
+       image by default; on RISC-V, the default is to enter the image at its
+       lowest address, so an IMAGEDEF item is required to specify the
+       nondefault entry point. */
+
+    .text : {
+        __logical_binary_start = .;
+        _stext = ABSOLUTE(.);
+        /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used,
+           so we would waste RAM if the vector table were not at the
+           start. */
+        KEEP (*(.vectors))
+        KEEP (*(.binary_info_header))
+        __binary_info_header_end = .;
+        KEEP (*(.embedded_block))
+        __embedded_block_end = .;
+        __reset_start = .;
+        KEEP (*(.reset))
+        __reset_end = .;
+        *(.time_critical*)
+        *(.text*)
+        . = ALIGN(4);
+        *(.init)
+        *(.fini)
+        /* Pull all c'tors into .text */
+        *crtbegin.o(.ctors)
+        *crtbegin?.o(.ctors)
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+        *(SORT(.ctors.*))
+        *(.ctors)
+        /* Followed by destructors */
+        *crtbegin.o(.dtors)
+        *crtbegin?.o(.dtors)
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+        *(SORT(.dtors.*))
+        *(.dtors)
+
+        *(.eh_frame*)
+    } > RAM
+
+    .rodata : {
+        . = ALIGN(4);
+        *(.rodata*)
+        *(.srodata*)
+        . = ALIGN(4);
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
+        . = ALIGN(4);
+    } > RAM
+
+    .ARM.extab :
+    {
+        *(.ARM.extab* .gnu.linkonce.armextab.*)
+    } > RAM
+
+    __exidx_start = .;
+    .ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+    } > RAM
+    __exidx_end = .;
+
+    /* Machine inspectable binary information */
+    . = ALIGN(4);
+    __binary_info_start = .;
+    .binary_info :
+    {
+        KEEP(*(.binary_info.keep.*))
+        *(.binary_info.*)
+    } > RAM
+    __binary_info_end = .;
+    . = ALIGN(4);
+
+    .data : {
+        __data_start__ = .;
+        *(vtable)
+        *(.data*)
+        *(.sdata*)
+
+        /* GOT/PLT must live INSIDE the copied .data range so a flat
+         * -fPIC object (e.g. a PIC static library linked into an app)
+         * gets an initialised GOT in RAM at boot; otherwise an orphan
+         * .got lands after _edata, is never copied, and every GOT-
+         * indirected access reads a NULL pointer (hardfault). */
+        . = ALIGN(4);
+        *(.got)
+        *(.got.plt)
+        *(.got*)
+
+        . = ALIGN(4);
+        *(.after_data.*)
+        . = ALIGN(4);
+        /* preinit data */
+        PROVIDE_HIDDEN (__mutex_array_start = .);
+        KEEP(*(SORT(.mutex_array.*)))
+        KEEP(*(.mutex_array))
+        PROVIDE_HIDDEN (__mutex_array_end = .);
+
+        . = ALIGN(4);
+        /* preinit data */
+        PROVIDE_HIDDEN (__preinit_array_start = .);
+        KEEP(*(SORT(.preinit_array.*)))
+        KEEP(*(.preinit_array))
+        PROVIDE_HIDDEN (__preinit_array_end = .);
+
+        . = ALIGN(4);
+        /* init data */
+        PROVIDE_HIDDEN (__init_array_start = .);
+        KEEP(*(SORT(.init_array.*)))
+        KEEP(*(.init_array))
+        PROVIDE_HIDDEN (__init_array_end = .);
+
+        . = ALIGN(4);
+        /* finit data */
+        PROVIDE_HIDDEN (__fini_array_start = .);
+        *(SORT(.fini_array.*))
+        *(.fini_array)
+        PROVIDE_HIDDEN (__fini_array_end = .);
+
+        *(.jcr)
+        . = ALIGN(4);
+   } > RAM
+
+    .tdata : {
+        . = ALIGN(4);
+               *(.tdata .tdata.* .gnu.linkonce.td.*)
+        /* All data end */
+        __tdata_end = .;
+    } > RAM
+    PROVIDE(__data_end__ = .);
+
+    .uninitialized_data (NOLOAD): {
+        . = ALIGN(4);
+        *(.uninitialized_data*)
+    } > RAM
+    /* __etext is (for backwards compatibility) the name of the .data init 
source pointer (...) */
+    __etext = LOADADDR(.data);
+    _etext = LOADADDR(.data);
+
+
+    .tbss (NOLOAD) : {
+        . = ALIGN(4);
+        __bss_start__ = .;
+        _stbss = ABSOLUTE(.);
+        __tls_base = .;
+        *(.tbss .tbss.* .gnu.linkonce.tb.*)
+        *(.tcommon)
+
+        __tls_end = .;
+        _etbss = ABSOLUTE(.);
+    } > RAM
+
+    .bss (NOLOAD) : {
+        . = ALIGN(4);
+        _sbss = ABSOLUTE(.);
+        __tbss_end = .;
+
+        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
+        *(COMMON)
+        PROVIDE(__global_pointer$ = . + 2K);
+        *(.sbss*)
+        . = ALIGN(8);
+        __bss_end__ = .;
+        _ebss = ABSOLUTE(.);
+    } > RAM
+
+    .heap (NOLOAD):
+    {
+        __end__ = .;
+        end = __end__;
+        KEEP(*(.heap*))
+    } > RAM
+    /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, 
however
+       to be more compatible, we now set __HeapLimit explicitly to where the 
end of the heap is */
+    __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
+
+    /* Start and end symbols must be word-aligned */
+    .scratch_x : {
+        __scratch_x_start__ = .;
+        *(.scratch_x.*)
+        . = ALIGN(4);
+        __scratch_x_end__ = .;
+    } > SCRATCH_X
+    __scratch_x_source__ = LOADADDR(.scratch_x);
+
+    .scratch_y : {
+        __scratch_y_start__ = .;
+        *(.scratch_y.*)
+        . = ALIGN(4);
+        __scratch_y_end__ = .;
+    } > SCRATCH_Y
+    __scratch_y_source__ = LOADADDR(.scratch_y);
+
+    /* .stack*_dummy section doesn't contains any symbols. It is only
+     * used for linker to calculate size of stack sections, and assign
+     * values to stack symbols later
+     *
+     * stack1 section may be empty/missing if platform_launch_core1 is not 
used */
+
+    /* by default we put core 0 stack at the end of scratch Y, so that if core 
1
+     * stack is not used then all of SCRATCH_X is free.
+     */
+    .stack1_dummy (NOLOAD):
+    {
+        *(.stack1*)
+    } > SCRATCH_X
+    .stack_dummy (NOLOAD):
+    {
+        KEEP(*(.stack*))
+    } > SCRATCH_Y
+
+    /* stack limit is poorly named, but historically is maximum heap ptr */
+    __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
+    __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
+    __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
+    __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
+    __StackBottom = __StackTop - SIZEOF(.stack_dummy);
+    PROVIDE(__stack = __StackTop);
+
+    /* picolibc and LLVM */
+    PROVIDE (__heap_start = __end__);
+    PROVIDE (__heap_end = __HeapLimit);
+    PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
+    PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align 
- 1));
+    PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
+
+    /* llvm-libc */
+    PROVIDE (_end = __end__);
+    PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
+
+    /* Check if data + heap + stack exceeds RAM limit */
+    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
+
+    ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary 
info must be in first 1024 bytes of the binary")
+    ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded 
block must be in first 4096 bytes of the binary")
+
+    /* todo assert on extra code */
+}
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/CMakeLists.txt 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/CMakeLists.txt
new file mode 100644
index 00000000000..56aad5eede2
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/CMakeLists.txt
@@ -0,0 +1,62 @@
+# 
##############################################################################
+# boards/arm/rp23xx/raspberrypi-pico-2-w/src/CMakeLists.txt
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements.  See the NOTICE file distributed with this work for
+# additional information regarding copyright ownership.  The ASF licenses this
+# file to you under the Apache License, Version 2.0 (the "License"); you may 
not
+# use this file except in compliance with the License.  You may obtain a copy 
of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+#
+# 
##############################################################################
+
+set(SRCS rp23xx_boardinitialize.c rp23xx_bringup.c)
+
+if(CONFIG_DEV_GPIO)
+  list(APPEND SRCS rp23xx_gpio.c)
+endif()
+
+# This board has no LED on an RP2350 pin -- its only LED hangs off the 
CYW43439,
+# and reaching it means a gSPI bus transaction.  That rules out
+# CONFIG_ARCH_LEDS, whose board_autoled_on() is called from interrupt handlers
+# and from assertion handling, so there is no rp23xx_autoleds.c.  It also means
+# there is no LED at all without the wireless chip.  See rp23xx_userleds.c.
+
+if(CONFIG_ARCH_LEDS)
+  message(
+    FATAL_ERROR
+      "CONFIG_ARCH_LEDS is not supported on this board: the LED hangs off the "
+      "CYW43439 and cannot be driven from interrupt context.  "
+      "Use CONFIG_USERLED instead.")
+endif()
+
+if(CONFIG_RP23XX_INFINEON_CYW43439)
+  list(APPEND SRCS rp23xx_userleds.c)
+endif()
+
+# rp23xx_firmware.c, which carries the CYW43439 firmware blob, is built from
+# boards/arm/rp23xx/common/src.
+
+target_sources(board PRIVATE ${SRCS})
+
+if(CONFIG_BOOT_RUNFROMFLASH)
+  set_property(GLOBAL PROPERTY LD_SCRIPT
+                               "${NUTTX_BOARD_DIR}/scripts/memmap_default.ld")
+elseif(CONFIG_BOOT_COPYTORAM)
+  set_property(
+    GLOBAL PROPERTY LD_SCRIPT
+                    "${NUTTX_BOARD_DIR}/scripts/memmap_copy_to_ram.ld")
+else()
+  set_property(GLOBAL PROPERTY LD_SCRIPT
+                               "${NUTTX_BOARD_DIR}/scripts/memmap_no_flash.ld")
+endif()
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/Make.defs 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/Make.defs
new file mode 100644
index 00000000000..271b9e5ce80
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/Make.defs
@@ -0,0 +1,89 @@
+############################################################################
+# boards/arm/rp23xx/raspberrypi-pico-2-w/src/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+CSRCS = rp23xx_boardinitialize.c
+CSRCS += rp23xx_bringup.c
+
+ifeq ($(CONFIG_DEV_GPIO),y)
+CSRCS += rp23xx_gpio.c
+endif
+
+# This board has no LED on an RP2350 pin -- its only LED hangs off the
+# CYW43439, and reaching it means a gSPI bus transaction.  That rules out
+# CONFIG_ARCH_LEDS, whose board_autoled_on() is called from interrupt handlers
+# and from assertion handling, so there is no rp23xx_autoleds.c.  It also
+# means there is no LED at all without the wireless chip.
+# See src/rp23xx_userleds.c.
+
+ifeq ($(CONFIG_ARCH_LEDS),y)
+$(error CONFIG_ARCH_LEDS is not supported on this board: the LED hangs off \
+        the CYW43439 and cannot be driven from interrupt context. \
+        Use CONFIG_USERLED instead)
+endif
+
+ifeq ($(CONFIG_RP23XX_INFINEON_CYW43439),y)
+CSRCS += rp23xx_userleds.c
+endif
+
+DEPPATH += --dep-path board
+VPATH += :board
+CFLAGS += 
${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board
+
+############################################################################
+# The rules below stage the cyw43439 blob out of pico_sdk so that the
+# .incbin in rp23xx_firmware.c can pick it up.
+#
+# rp23xx_firmware.c lives in the *common* src directory, which is both on the
+# include path (added by common/src/Make.defs) and reachable via VPATH, so the
+# blob is staged next to it there.  This mirrors what rp2040 does for the
+# Raspberry Pi Pico W.
+############################################################################
+
+ifeq ($(CONFIG_IEEE80211_INFINEON_CYW43439),y)
+
+FIRMWARE = src$(DELIM)cyw43439.firmware.image
+
+# --- If PICO_SDK_PATH is not defined set a dummy path. --------------------
+#     See comment below.
+
+ifeq ($(PICO_SDK_PATH),)
+       PICO_SDK_PATH = /tmp
+endif
+
+FIRMWARE_SRC := $(patsubst "%",%,$(CONFIG_CYW43439_FIRMWARE_BIN_PATH))
+
+# --- If the firmware source does not exist create a dummy file. -----------
+#     NuttX built with the cyw43439 driver will not talk to the wireless
+#     chip when built with this dummy file.  The sole purpose of adding
+#     this dummy is so the CI build tests will not fail.
+
+$(FIRMWARE_SRC):
+       $(Q) mkdir -p `dirname $(FIRMWARE_SRC)`
+       $(Q) echo "dummy" >$(FIRMWARE_SRC)
+
+$(FIRMWARE): $(FIRMWARE_SRC)
+       $(call CATFILE, $(FIRMWARE), $(FIRMWARE_SRC))
+
+src$(DELIM)rp23xx_firmware.c: $(FIRMWARE)
+
+distclean::
+       $(call DELFILE, $(FIRMWARE))
+
+endif
diff --git 
a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_boardinitialize.c 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_boardinitialize.c
new file mode 100644
index 00000000000..f77454f6077
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_boardinitialize.c
@@ -0,0 +1,115 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_boardinitialize.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/debug.h>
+
+#include <nuttx/board.h>
+#include <arch/board/board.h>
+
+#include "rp23xx_gpio.h"
+
+#ifdef CONFIG_RP23XX_PSRAM
+#include "rp23xx_psram.h"
+#endif
+
+#ifdef CONFIG_ARCH_BOARD_COMMON
+#include "rp23xx_common_initialize.h"
+#endif /* CONFIG_ARCH_BOARD_COMMON */
+
+#include "rp23xx_pico.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rp23xx_boardearlyinitialize
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+void rp23xx_boardearlyinitialize(void)
+{
+  #ifdef CONFIG_ARCH_BOARD_COMMON
+  rp23xx_common_earlyinitialize();
+  #endif
+
+  /* --- Place any board specific early initialization here --- */
+
+  /* Nothing to do for the LED: it hangs off the CYW43439 wireless chip
+   * rather than an RP2350 pin, and cannot be touched this early.  See
+   * src/rp23xx_userleds.c.
+   */
+}
+
+/****************************************************************************
+ * Name: rp23xx_boardinitialize
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+void rp23xx_boardinitialize(void)
+{
+  #ifdef CONFIG_ARCH_BOARD_COMMON
+  rp23xx_common_initialize();
+  #endif
+
+  #ifdef CONFIG_RP23XX_PSRAM
+  rp23xx_psramconfig();
+  #endif
+
+  /* --- Place any board specific initialization here --- */
+}
+
+/****************************************************************************
+ * Name: board_late_initialize
+ *
+ * Description:
+ *   If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional
+ *   initialization call will be performed in the boot-up sequence to a
+ *   function called board_late_initialize(). board_late_initialize() will be
+ *   called immediately after up_initialize() is called and just before the
+ *   initial application is started.  This additional initialization phase
+ *   may be used, for example, to initialize board-specific device drivers.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BOARD_LATE_INITIALIZE
+void board_late_initialize(void)
+{
+  rp23xx_bringup();
+}
+#endif
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_bringup.c 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_bringup.c
new file mode 100644
index 00000000000..0e7d8059a1e
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_bringup.c
@@ -0,0 +1,118 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_bringup.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/debug.h>
+#include <stddef.h>
+#include <errno.h>
+
+#include <nuttx/fs/fs.h>
+
+#include <arch/board/board.h>
+
+#include "rp23xx_pico.h"
+
+#ifdef CONFIG_ARCH_BOARD_COMMON
+#include "rp23xx_common_bringup.h"
+#endif /* CONFIG_ARCH_BOARD_COMMON */
+
+#ifdef CONFIG_USERLED
+#  include <nuttx/leds/userled.h>
+#endif
+
+#ifdef CONFIG_RP23XX_INFINEON_CYW43439
+#  include "rp23xx_cyw43439.h"
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef CONFIG_RP23XX_INFINEON_CYW43439
+gspi_dev_t *g_cyw43439 = NULL;
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rp23xx_bringup
+ ****************************************************************************/
+
+int rp23xx_bringup(void)
+{
+  int ret;
+
+  UNUSED(ret);
+
+#ifdef CONFIG_ARCH_BOARD_COMMON
+
+  ret = rp23xx_common_bringup();
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+#endif /* CONFIG_ARCH_BOARD_COMMON */
+
+  /* --- Place any board specific bringup code here --- */
+
+#ifdef CONFIG_RP23XX_INFINEON_CYW43439
+  /* Bring up the CYW43439 wireless chip.  This registers the wlan0 network
+   * device; the chip's firmware is not downloaded until wlan0 is brought up.
+   *
+   * Do this before the LED driver, which drives a GPIO on this chip.
+   */
+
+  g_cyw43439 = rp23xx_cyw_setup(GPIO_CYW43439_ON,
+                                GPIO_CYW43439_CS,
+                                GPIO_CYW43439_DATA,
+                                GPIO_CYW43439_CLOCK,
+                                GPIO_CYW43439_DATA);
+
+  if (g_cyw43439 == NULL)
+    {
+      syslog(LOG_ERR,
+             "ERROR: failed to initialize the cyw43439 (WiFi chip): %d\n",
+             errno);
+    }
+#endif
+
+#if defined(CONFIG_USERLED_LOWER) && defined(CONFIG_RP23XX_INFINEON_CYW43439)
+  /* Register the LED driver.  The LED sits on the wireless chip, so there is
+   * nothing to register without it.
+   */
+
+  ret = userled_lower_initialize("/dev/userleds");
+  if (ret < 0)
+    {
+      syslog(LOG_ERR, \
+      "ERROR: userled_lower_initialize() failed: %d\n", ret);
+    }
+#endif
+
+  return OK;
+}
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_gpio.c 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_gpio.c
new file mode 100644
index 00000000000..01c090c9fd4
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_gpio.c
@@ -0,0 +1,396 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_gpio.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <syslog.h>
+#include <nuttx/irq.h>
+#include <arch/irq.h>
+#include <assert.h>
+#include <nuttx/debug.h>
+
+#include <nuttx/ioexpander/gpio.h>
+
+#include <arch/board/board.h>
+
+#include "arm_internal.h"
+#include "chip.h"
+#include "rp23xx_gpio.h"
+
+#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF)
+
+/* Output pins.
+ *
+ * There is no onboard LED on an RP2350 pin on this board -- it hangs off the
+ * CYW43439 -- so this is just a free header pin.  Note that GPIO 23, 24, 25
+ * and 29 are wired to the wireless chip and must not be used here.
+ */
+
+#define GPIO_OUT1     2
+
+/* Input pins.
+ */
+
+#define GPIO_IN1      6
+
+/* Interrupt pins.
+ */
+
+#define GPIO_IRQPIN1  14
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rp23xxgpio_dev_s
+{
+  struct gpio_dev_s gpio;
+  uint8_t id;
+};
+
+struct rp23xxgpint_dev_s
+{
+  struct rp23xxgpio_dev_s rp23xxgpio;
+  pin_interrupt_t callback;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+#if BOARD_NGPIOOUT > 0
+static int gpout_read(struct gpio_dev_s *dev, bool *value);
+static int gpout_write(struct gpio_dev_s *dev, bool value);
+#endif
+
+#if BOARD_NGPIOIN > 0
+static int gpin_read(struct gpio_dev_s *dev, bool *value);
+#endif
+
+#if BOARD_NGPIOINT > 0
+static int gpint_read(struct gpio_dev_s *dev, bool *value);
+static int gpint_attach(struct gpio_dev_s *dev,
+                        pin_interrupt_t callback);
+static int gpint_enable(struct gpio_dev_s *dev, bool enable);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#if BOARD_NGPIOOUT > 0
+static const struct gpio_operations_s gpout_ops =
+{
+  .go_read   = gpout_read,
+  .go_write  = gpout_write,
+  .go_attach = NULL,
+  .go_enable = NULL,
+};
+
+/* This array maps the GPIO pins used as OUTPUT */
+
+static const uint32_t g_gpiooutputs[BOARD_NGPIOOUT] =
+{
+  GPIO_OUT1
+};
+
+static struct rp23xxgpio_dev_s g_gpout[BOARD_NGPIOOUT];
+#endif
+
+#if BOARD_NGPIOIN > 0
+static const struct gpio_operations_s gpin_ops =
+{
+  .go_read   = gpin_read,
+  .go_write  = NULL,
+  .go_attach = NULL,
+  .go_enable = NULL,
+};
+
+/* This array maps the GPIO pins used as INTERRUPT INPUTS */
+
+static const uint32_t g_gpioinputs[BOARD_NGPIOIN] =
+{
+  GPIO_IN1
+};
+
+static struct rp23xxgpio_dev_s g_gpin[BOARD_NGPIOIN];
+#endif
+
+#if BOARD_NGPIOINT > 0
+static const struct gpio_operations_s gpint_ops =
+{
+  .go_read   = gpint_read,
+  .go_write  = NULL,
+  .go_attach = gpint_attach,
+  .go_enable = gpint_enable,
+};
+
+/* This array maps the GPIO pins used as INTERRUPT INPUTS */
+
+static const uint32_t g_gpiointinputs[BOARD_NGPIOINT] =
+{
+  GPIO_IRQPIN1,
+};
+
+static struct rp23xxgpint_dev_s g_gpint[BOARD_NGPIOINT];
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: gpout_read
+ ****************************************************************************/
+
+#if BOARD_NGPIOOUT > 0
+static int gpout_read(struct gpio_dev_s *dev, bool *value)
+{
+  struct rp23xxgpio_dev_s *rp23xxgpio =
+    (struct rp23xxgpio_dev_s *)dev;
+
+  DEBUGASSERT(rp23xxgpio != NULL && value != NULL);
+  DEBUGASSERT(rp23xxgpio->id < BOARD_NGPIOOUT);
+  gpioinfo("Reading...\n");
+
+  *value = rp23xx_gpio_get(g_gpiooutputs[rp23xxgpio->id]);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: gpout_write
+ ****************************************************************************/
+
+static int gpout_write(struct gpio_dev_s *dev, bool value)
+{
+  struct rp23xxgpio_dev_s *rp23xxgpio =
+    (struct rp23xxgpio_dev_s *)dev;
+
+  DEBUGASSERT(rp23xxgpio != NULL);
+  DEBUGASSERT(rp23xxgpio->id < BOARD_NGPIOOUT);
+  gpioinfo("Writing %d\n", (int)value);
+
+  rp23xx_gpio_put(g_gpiooutputs[rp23xxgpio->id], value);
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: gpin_read
+ ****************************************************************************/
+
+#if BOARD_NGPIOIN > 0
+static int gpin_read(struct gpio_dev_s *dev, bool *value)
+{
+  struct rp23xxgpio_dev_s *rp23xxgpio =
+    (struct rp23xxgpio_dev_s *)dev;
+
+  DEBUGASSERT(rp23xxgpio != NULL && value != NULL);
+  DEBUGASSERT(rp23xxgpio->id < BOARD_NGPIOIN);
+  gpioinfo("Reading... pin %d\n", (int)g_gpioinputs[rp23xxgpio->id]);
+
+  *value = rp23xx_gpio_get(g_gpioinputs[rp23xxgpio->id]);
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: rp23xxgpio_interrupt
+ ****************************************************************************/
+
+#if BOARD_NGPIOINT > 0
+static int rp23xxgpio_interrupt(int irq, void *context, void *arg)
+{
+  struct rp23xxgpint_dev_s *rp23xxgpint =
+    (struct rp23xxgpint_dev_s *)arg;
+
+  DEBUGASSERT(rp23xxgpint != NULL && rp23xxgpint->callback != NULL);
+  gpioinfo("Interrupt! callback=%p\n", rp23xxgpint->callback);
+
+  rp23xxgpint->callback(&rp23xxgpint->rp23xxgpio.gpio,
+                       rp23xxgpint->rp23xxgpio.id);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: gpint_read
+ ****************************************************************************/
+
+static int gpint_read(struct gpio_dev_s *dev, bool *value)
+{
+  struct rp23xxgpint_dev_s *rp23xxgpint =
+    (struct rp23xxgpint_dev_s *)dev;
+
+  DEBUGASSERT(rp23xxgpint != NULL && value != NULL);
+  DEBUGASSERT(rp23xxgpint->rp23xxgpio.id < BOARD_NGPIOINT);
+  gpioinfo("Reading int pin...\n");
+
+  *value = rp23xx_gpio_get(g_gpiointinputs[rp23xxgpint->rp23xxgpio.id]);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: gpint_attach
+ ****************************************************************************/
+
+static int gpint_attach(struct gpio_dev_s *dev,
+                        pin_interrupt_t callback)
+{
+  struct rp23xxgpint_dev_s *rp23xxgpint =
+    (struct rp23xxgpint_dev_s *)dev;
+  int irq = g_gpiointinputs[rp23xxgpint->rp23xxgpio.id];
+  int ret;
+
+  gpioinfo("Attaching the callback\n");
+
+  /* Make sure the interrupt is disabled */
+
+  rp23xx_gpio_disable_irq(irq);
+  ret = rp23xx_gpio_irq_attach(irq,
+                               RP23XX_GPIO_INTR_EDGE_LOW,
+                               rp23xxgpio_interrupt,
+                               &g_gpint[rp23xxgpint->rp23xxgpio.id]);
+  if (ret < 0)
+    {
+      syslog(LOG_ERR, "ERROR: gpint_attach() failed: %d\n", ret);
+      return ret;
+    }
+
+  gpioinfo("Attach %p\n", callback);
+  rp23xxgpint->callback = callback;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: gpint_enable
+ ****************************************************************************/
+
+static int gpint_enable(struct gpio_dev_s *dev, bool enable)
+{
+  struct rp23xxgpint_dev_s *rp23xxgpint =
+    (struct rp23xxgpint_dev_s *)dev;
+  int irq = g_gpiointinputs[rp23xxgpint->rp23xxgpio.id];
+
+  if (enable)
+    {
+      if (rp23xxgpint->callback != NULL)
+        {
+          gpioinfo("Enabling the interrupt\n");
+
+          /* Configure the interrupt for rising edge */
+
+          rp23xx_gpio_enable_irq(irq);
+        }
+    }
+  else
+    {
+      gpioinfo("Disable the interrupt\n");
+      rp23xx_gpio_disable_irq(irq);
+    }
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rp23xx_dev_gpio_init
+ ****************************************************************************/
+
+int rp23xx_dev_gpio_init(void)
+{
+  int i;
+  int pincount = 0;
+
+#if BOARD_NGPIOOUT > 0
+  for (i = 0; i < BOARD_NGPIOOUT; i++)
+    {
+      /* Setup and register the GPIO pin */
+
+      g_gpout[i].gpio.gp_pintype = GPIO_OUTPUT_PIN;
+      g_gpout[i].gpio.gp_ops     = &gpout_ops;
+      g_gpout[i].id              = i;
+      gpio_pin_register(&g_gpout[i].gpio, g_gpiooutputs[i]);
+
+      /* Configure the pins that will be used as output */
+
+      rp23xx_gpio_init(g_gpiooutputs[i]);
+      rp23xx_gpio_setdir(g_gpiooutputs[i], true);
+      rp23xx_gpio_put(g_gpiooutputs[i], false);
+
+      pincount++;
+    }
+#endif
+
+  pincount = 0;
+
+#if BOARD_NGPIOIN > 0
+  for (i = 0; i < BOARD_NGPIOIN; i++)
+    {
+      /* Setup and register the GPIO pin */
+
+      g_gpin[i].gpio.gp_pintype = GPIO_INPUT_PIN;
+      g_gpin[i].gpio.gp_ops     = &gpin_ops;
+      g_gpin[i].id              = i;
+      gpio_pin_register(&g_gpin[i].gpio, g_gpioinputs[i]);
+
+      /* Configure the pins that will be used as INPUT */
+
+      rp23xx_gpio_init(g_gpioinputs[i]);
+
+      pincount++;
+    }
+#endif
+
+  pincount = 0;
+
+#if BOARD_NGPIOINT > 0
+  for (i = 0; i < BOARD_NGPIOINT; i++)
+    {
+      /* Setup and register the GPIO pin */
+
+      g_gpint[i].rp23xxgpio.gpio.gp_pintype = GPIO_INTERRUPT_PIN;
+      g_gpint[i].rp23xxgpio.gpio.gp_ops     = &gpint_ops;
+      g_gpint[i].rp23xxgpio.id              = i;
+      gpio_pin_register(&g_gpint[i].rp23xxgpio.gpio, g_gpiointinputs[i]);
+
+      /* Configure the pins that will be used as interrupt input */
+
+      rp23xx_gpio_init(g_gpiointinputs[i]);
+
+      /* pull-up = false : pull-down = true */
+
+      rp23xx_gpio_set_pulls(g_gpiointinputs[i], false, true);
+
+      pincount++;
+    }
+#endif
+
+  return OK;
+}
+#endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_pico.h 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_pico.h
new file mode 100644
index 00000000000..5df23d2f243
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_pico.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_pico.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_SRC_RP23XX_PICO_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_SRC_RP23XX_PICO_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/* CYW43439 wireless chip
+ *
+ * The gSPI bus is half duplex -- a single data line carries both directions
+ * and doubles as the chip's interrupt request line.
+ */
+
+#define GPIO_CYW43439_ON      23  /* Drive high to power the chip up   */
+#define GPIO_CYW43439_DATA    24  /* Bidirectional data, also the IRQ  */
+#define GPIO_CYW43439_CS      25  /* Drive low to select the chip      */
+#define GPIO_CYW43439_CLOCK   29  /* gSPI clock                       */
+
+/* LEDs
+ *
+ * The board's only LED hangs off GPIO 0 of the CYW43439, see
+ * include/rp23xx_extra_gpio.h.  There is no LED on an RP2350 pin.
+ */
+
+int rp23xx_bringup(void);
+
+#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_ARCH_BOARD_COMMON)
+int rp23xx_dev_gpio_init(void);
+#endif
+
+#endif /* __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_W_SRC_RP23XX_PICO_H */
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_userleds.c 
b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_userleds.c
new file mode 100644
index 00000000000..34085ecb448
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_userleds.c
@@ -0,0 +1,94 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_userleds.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * The single LED on this board is wired to GPIO 0 of the CYW43439 wireless
+ * chip rather than to a pin of the RP2350, so setting it means sending an
+ * iovar request over the gSPI bus.  Two consequences:
+ *
+ *   - The LED only responds once the wireless chip is running, which happens
+ *     when wlan0 is brought up.  Before that every write fails with -EIO.
+ *   - Writing the LED blocks, so it must not be done from interrupt context.
+ *     That is why this board implements the user LED interface only and not
+ *     the CONFIG_ARCH_LEDS auto-LED interface.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <debug.h>
+
+#include <nuttx/board.h>
+#include <arch/board/board.h>
+#include <arch/board/rp23xx_extra_gpio.h>
+
+#if defined(CONFIG_RP23XX_INFINEON_CYW43439) && !defined(CONFIG_ARCH_LEDS)
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_userled_initialize
+ ****************************************************************************/
+
+uint32_t board_userled_initialize(void)
+{
+  /* Nothing to configure -- the LED lives on the wireless chip, which the
+   * board bringup has already set up.
+   */
+
+  return BOARD_NLEDS;
+}
+
+/****************************************************************************
+ * Name: board_userled
+ ****************************************************************************/
+
+void board_userled(int led, bool ledon)
+{
+  if (led == BOARD_LED1)
+    {
+      int ret = rp23xx_extra_gpio_put(RP23XX_EXTRA_GPIO_LED, ledon);
+
+      if (ret < 0)
+        {
+          lederr("ERROR: cannot reach the LED on the CYW43439: %d\n", ret);
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: board_userled_all
+ ****************************************************************************/
+
+void board_userled_all(uint32_t ledset)
+{
+  board_userled(BOARD_LED1, (ledset & BOARD_LED1_BIT) != 0);
+}
+
+#endif /* CONFIG_RP23XX_INFINEON_CYW43439 && !CONFIG_ARCH_LEDS */

Reply via email to