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 0000000000000..694b2932b0450
--- /dev/null
+++ b/Documentation/platforms/arm/rp23xx/boards/raspberrypi-pico-2-w/index.rst
@@ -0,0 +1,132 @@
+==============================
+Raspberry Pi Pico 2 W
+==============================
+
+.. tags:: chip:rp2350, wifi
+
+The `Raspberry Pi Pico 2 W `_
+is a general purpose board supplied by Raspberry Pi. The W variant adds an
+Infineon CYW43439 for built-in 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
+* Built in WiFi radio (Infineon CYW43439)
+
+Serial Console
+==============
+
+By default a serial console appears on pin 1 (TX GPIO0) and pin 2
+(RX GPIO1). This console runs at 115200-8N1.
+
+The board can be configured to use the USB connection as the serial console;
+see the ``usbnsh`` configuration of the base ``raspberrypi-pico-2`` board.
+
+Buttons and LEDs
+================
+
+The user LED is controlled by the CYW43439 wireless chip (not directly by an
+RP2350 GPIO), so networking must be brought up before it can be driven.
+
+A BOOTSEL button, which if held down when power is first applied to the board,
+will cause the RP2350 to boot into programming mode and appear as a storage
+device to a computer connected via USB. Saving a .UF2 file to this device
+will replace the Flash ROM contents on the Pico 2 W.
+
+Wireless Communication
+======================
+
+The on board Infineon CYW43439 supports 2.4 GHz WiFi 4 (802.11n). It is
+driven over a PIO-based gSPI link by the NuttX ``bcmf`` FullMAC driver, ported
+from the RP2040 ``raspberrypi-pico-w`` support.
+
+WiFi firmware blob
+------------------
+
+The CYW43439 requires a firmware/CLM blob that is **not** bundled with NuttX.
+It is fetched from the Raspberry Pi Pico SDK at build time; set
+``PICO_SDK_PATH`` (see Installation) or point
+``CONFIG_CYW43439_FIRMWARE_BIN_PATH`` at a local copy. When the blob is
+absent the build substitutes a dummy so that CI still passes, but an image
+built with the dummy will not associate to an access point.
+
+The board's NVRAM calibration data (``src/rp23xx_firmware.c``) is the same
+Broadcom-supplied table used by the RP2040 ``raspberrypi-pico-w`` board.
+
+RP2350 Wireless Pins
+====================
+
+The CYW43439 is wired to the RP2350 in the same arrangement as the RP2040
+Pico W:
+
+* GPIO23 Output - WiFi controller power / on-off control.
+* GPIO24 I/O - WiFi controller data line (gSPI).
+* GPIO25 Output - WiFi controller chip select line.
+* GPIO29 Output - WiFi controller clock line.
+
+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) via the ``bcmf`` driver
+* I2C
+* SPI (master only)
+* DMAC
+* PWM
+* ADC
+* Watchdog
+* USB device
+* PIO (RP2350 Programmable I/O)
+* Flash ROM Boot / SRAM Boot
+* Persistent flash filesystem in unused flash ROM
+
+Installation
+============
+
+The Pico 2 W shares the RP2350 tool-chain and SDK setup of the base
+``raspberrypi-pico-2`` board; 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 blob).
+
+Configurations
+==============
+
+All configurations listed below can be configured using the following command
+in the ``nuttx`` directory (consult the main :doc:`RP2350 documentation
+<../../index>`):
+
+.. code:: console
+
+ $ ./tools/configure.sh raspberrypi-pico-2-w:
+
+telnet
+------
+
+NuttShell configuration (console enabled on UART0, at 115200 bps) with WiFi
+station mode brought up at boot and a telnet server enabled, so the shell is
+reachable over the network once the board associates.
+
+Set your network credentials before building via ``make menuconfig`` under
+Application Configuration -> Network Utilities -> Network initialization ->
+WAPI Configuration (SSID and passphrase), and the country code under Device
+Drivers -> Wireless Device Support -> IEEE 802.11 Device Support. The shipped
+defconfig carries only placeholder credentials.
diff --git a/arch/arm/src/rp23xx/CMakeLists.txt b/arch/arm/src/rp23xx/CMakeLists.txt
index b67f08039aad2..40fb7f54fceec 100644
--- a/arch/arm/src/rp23xx/CMakeLists.txt
+++ b/arch/arm/src/rp23xx/CMakeLists.txt
@@ -89,4 +89,8 @@ if(CONFIG_CRYPTO_CRYPTODEV_HARDWARE)
list(APPEND SRCS rp23xx_crypto.c)
endif()
+if(CONFIG_IEEE80211_INFINEON_CYW43439)
+ list(APPEND SRCS rp23xx_cyw43439.c)
+endif()
+
target_sources(arch PRIVATE ${SRCS})
diff --git a/arch/arm/src/rp23xx/Make.defs b/arch/arm/src/rp23xx/Make.defs
index 0042124804909..ff27b2209dab4 100644
--- a/arch/arm/src/rp23xx/Make.defs
+++ b/arch/arm/src/rp23xx/Make.defs
@@ -92,3 +92,7 @@ endif
ifeq ($(CONFIG_CRYPTO_CRYPTODEV_HARDWARE),y)
CHIP_CSRCS += rp23xx_crypto.c
endif
+
+ifeq ($(CONFIG_IEEE80211_INFINEON_CYW43439),y)
+CHIP_CSRCS += rp23xx_cyw43439.c
+endif
diff --git a/arch/arm/src/rp23xx/rp23xx_cyw43439.c b/arch/arm/src/rp23xx/rp23xx_cyw43439.c
new file mode 100644
index 0000000000000..7631774d9e05a
--- /dev/null
+++ b/arch/arm/src/rp23xx/rp23xx_cyw43439.c
@@ -0,0 +1,879 @@
+/****************************************************************************
+ * arch/arm/src/rp23xx/rp23xx_cyw43439.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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "rp23xx_cyw43439.h"
+#include "rp23xx_pio.h"
+#include "rp23xx_pio_instructions.h"
+
+#ifdef CONFIG_NDEBUG
+# define PRINT_GSPI(block)
+#else
+void bcmf_hexdump(uint8_t *data, unsigned int len, unsigned long offset);
+bool g_print_gspi = false;
+# define PRINT_GSPI(block) if (g_print_gspi) { block }
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define GSPI_CLOCK_FREQ 31250000 /* Hz (Max: 50MHz) */
+
+#define PIO_WRAP_TARGET 0
+#define PIO_WRAP 5
+
+#define TX_FIFO_SIZE 4
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+typedef struct dma_info_s
+{
+ sem_t sem;
+ uint8_t status;
+} dma_info_t;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This is the PIO program to write and then read from the data pin.
+ *
+ * The X register is the output bit count register. It should be set
+ * to one less than the total number of BITS to be transmitted.
+ *
+ * The Y register is the input bit count register. It too must be set
+ * to one less than the total number of bits to be read.
+ *
+ * The PIO's state machine is set up to auto-pull data from the input
+ * fifo whenever the output shift register is empty. This happens at
+ * the start and every 32 bits thereafter.
+ *
+ * The state machine also auto-pushes whenever we have a full 32 bits
+ * in the input shift register. To make sure we receive all the data,
+ * we need to make sure that the read bit count is a multiple of 32.
+ * (Y = 32*N - 1 for some integer N)
+ */
+
+static const uint16_t cyw_program_instructions[] =
+{
+ 0x6001, /* 0: out pins, 1 side 0 # Write one bit */
+ 0x1040, /* 1: jmp x--, 0 side 1 # Loop until write count is zero */
+ 0xe080, /* 2: set pindirs, 0 side 0 # Make data pin an input */
+ 0xb042, /* 3: nop side 1 # Keep clock in sync */
+ 0x4001, /* 4: in pins, 1 side 0 # Read 1 bit */
+ 0x1084, /* 5: jmp y--, 4 side 1 # Loop until read count is zero */
+};
+
+static const rp23xx_pio_program_t pio_program =
+{
+ .instructions = cyw_program_instructions,
+ .length = 6, /* Six, count 'em, six. */
+ .origin = -1, /* Put it wherever it fits */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: dma_complete
+ *
+ * Description:
+ * Called on completion of the DMA transfer.
+ *
+ * Input Parameters:
+ * handle - handle to our DMA channel
+ * status - status of the transfer
+ * arg - Pointer to dma info structure.
+ *
+ ****************************************************************************/
+
+static void dma_complete(DMA_HANDLE handle, uint8_t status, void *arg)
+{
+ dma_info_t *dma_info = arg;
+
+ /* Remember the status and post the dma complete event. */
+
+ dma_info->status = status;
+ nxsem_post(&(dma_info->sem));
+}
+
+/****************************************************************************
+ * Name: rp23xx_cyw_init
+ *
+ * Description:
+ * Connect to and initialize the cyw43439.
+ *
+ ****************************************************************************/
+
+static int rp23xx_cyw_init(gspi_dev_t *gspi)
+{
+ rp23xx_gspi_t *rp_io = (rp23xx_gspi_t *)(gspi->io_dev);
+
+ uint32_t divisor;
+ irqstate_t flags;
+ rp23xx_pio_sm_config config =
+ {
+ 0
+ };
+
+ /* Make sure the cyw43439 chip is deselected, and off.
+ * so we know it is reset
+ */
+
+ rp23xx_gpio_put(rp_io->gpio_select, true); /* deselect */
+ rp23xx_gpio_put(rp_io->gpio_on, false); /* power off */
+
+ /* Pull the data line low so that we initialise to gSPI mode */
+
+ rp23xx_gpio_init(rp_io->gpio_data);
+ rp23xx_gpio_setdir(rp_io->gpio_data, true);
+ rp23xx_gpio_put(rp_io->gpio_data, false);
+
+ nxsched_usleep(50000); /* Leave off for at least 50ms. */
+
+ rp23xx_gpio_put(rp_io->gpio_on, true); /* power on */
+
+ nxsched_usleep(50000); /* Wait a bit to let the power come up. */
+
+ /* Don't let anyone else grab a PIO while we are doing so. */
+
+ flags = enter_critical_section();
+
+ /* Find a PIO instance and load program. */
+
+ for (rp_io->pio = 0; rp_io->pio < RP23XX_PIO_NUM; ++rp_io->pio)
+ {
+ /* Try to claim a state machine. */
+
+ rp_io->pio_sm = rp23xx_pio_claim_unused_sm(rp_io->pio, false);
+
+ /* If we did not get one try the next pio block, if any. */
+
+ if (rp_io->pio_sm < 0) continue;
+
+ /* See if we have space in this block to load our program. */
+
+ if (rp23xx_pio_can_add_program(rp_io->pio, &pio_program))
+ {
+ /* Great! load the program and exit the pio choice loop. */
+
+ rp_io->pio_location = rp23xx_pio_add_program(rp_io->pio,
+ &pio_program);
+
+ break;
+ }
+
+ /* Oops -- no room at the inn! Release sm and try next pio. */
+
+ rp23xx_pio_sm_unclaim(rp_io->pio, rp_io->pio_sm);
+ }
+
+ if (rp_io->pio >= RP23XX_PIO_NUM)
+ {
+ leave_critical_section(flags);
+ return -ENOMEM;
+ }
+
+ leave_critical_section(flags);
+
+ /* ==== Configure the PIO State Machine ==== */
+
+ /* Configure pins that are used by PIO. */
+
+ rp23xx_pio_gpio_init(rp_io->pio, rp_io->gpio_data);
+ rp23xx_pio_gpio_init(rp_io->pio, rp_io->gpio_clock);
+
+ rp23xx_gpio_set_input_hysteresis_enabled(rp_io->gpio_data, true);
+
+ rp23xx_gpio_set_slew_fast(rp_io->gpio_clock, true);
+ rp23xx_gpio_set_drive_strength(rp_io->gpio_clock,
+ RP23XX_PADS_BANK0_GPIO_DRIVE_12MA);
+
+ /* Set the clock divisor as appropriate for our system clock
+ * speed, so the pio clock runs the requested bit clock rate.
+ */
+
+ divisor = ((uint64_t)BOARD_SYS_FREQ << 8) / (2 * GSPI_CLOCK_FREQ);
+
+ rp23xx_sm_config_set_clkdiv_int_frac(&config,
+ divisor >> 8,
+ divisor & 0xff);
+
+ /* Set the wrap points as required by the program. */
+
+ rp23xx_sm_config_set_wrap(&config,
+ rp_io->pio_location + PIO_WRAP_TARGET,
+ rp_io->pio_location + PIO_WRAP);
+
+ /* set to shift left, 32 bits, with autopull/push */
+
+ rp23xx_sm_config_set_in_shift(&config, false, true, 32);
+ rp23xx_sm_config_set_out_shift(&config, false, true, 32);
+
+ /* Configure a single mandatory side-set pin. */
+
+ rp23xx_sm_config_set_sideset(&config, 1, false, false);
+
+ /* Configure our GPIO clock pin as side-set output. */
+
+ rp23xx_sm_config_set_sideset_pins(&config, rp_io->gpio_clock);
+
+ /* Configure out GPIO data pin as an OUT pin, SET pin, and IN pin */
+
+ rp23xx_sm_config_set_out_pins(&config, rp_io->gpio_data, 1);
+ rp23xx_sm_config_set_set_pins(&config, rp_io->gpio_data, 1);
+ rp23xx_sm_config_set_in_pins (&config, rp_io->gpio_data);
+
+ /* Load the configuration into the state machine. */
+
+ rp23xx_pio_sm_init(rp_io->pio,
+ rp_io->pio_sm,
+ rp_io->pio_location,
+ &config);
+
+ /* Disable the input synchronizers on the data pin */
+
+ rp23xx_pio_set_input_sync_bypass(rp_io->pio, rp_io->gpio_data, true);
+
+ wlinfo("finished\n");
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: rp23xx_cyw_set_isr
+ *
+ * Description:
+ * Setup the data line interrupt service routine.
+ *
+ ****************************************************************************/
+
+static int rp23xx_cyw_set_isr(gspi_dev_t *gspi,
+ xcpt_t thread_isr,
+ void *thread_isr_arg)
+{
+ rp23xx_gspi_t *rp_io = (rp23xx_gspi_t *)(gspi->io_dev);
+
+ /* Set up, but do not enable, interrupt service for the data pin */
+
+ rp23xx_gpio_irq_attach(rp_io->gpio_intr,
+ RP23XX_GPIO_INTR_LEVEL_HIGH,
+ thread_isr,
+ thread_isr_arg);
+
+ wlinfo("attached\n");
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: rp23xx_cyw_interrupt_enable
+ *
+ * Description:
+ * Setup the data line isr.
+ *
+ ****************************************************************************/
+
+static int rp23xx_cyw_interrupt_enable(gspi_dev_t *gspi,
+ bool enable)
+{
+ rp23xx_gspi_t *rp_io = (rp23xx_gspi_t *)(gspi->io_dev);
+ static int disable_count = 0;
+
+ if (enable)
+ {
+ if (--disable_count <= 0) rp23xx_gpio_enable_irq(rp_io->gpio_intr);
+ }
+ else
+ {
+ rp23xx_gpio_disable_irq(rp_io->gpio_intr);
+ ++disable_count;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: rp23xx_cyw_deinit
+ *
+ * Description:
+ * Disconnect from cyw43439 and cleanup.
+ *
+ ****************************************************************************/
+
+static int rp23xx_cyw_deinit(gspi_dev_t *gspi)
+{
+ rp23xx_gspi_t *rp_io = (rp23xx_gspi_t *)(gspi->io_dev);
+
+ rp23xx_gpio_irq_attach(rp_io->gpio_data,
+ RP23XX_GPIO_INTR_EDGE_LOW,
+ NULL,
+ NULL);
+
+ rp23xx_pio_sm_set_enabled(rp_io->pio, rp_io->pio_sm, false);
+ rp23xx_pio_remove_program(rp_io->pio, &pio_program, rp_io->pio_location);
+ rp23xx_pio_sm_unclaim(rp_io->pio, rp_io->pio_sm);
+
+ /* Turn the power off to the cyw43439. */
+
+ rp23xx_gpio_put(rp_io->gpio_on, false);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: rp23xx_cyw_write
+ *
+ * Description:
+ * write data to the cyw43439
+ *
+ ****************************************************************************/
+
+static int rp23xx_cyw_write(struct gspi_dev_s *gspi,
+ bool increment,
+ enum gspi_cmd_func_e function,
+ uint32_t address,
+ uint16_t length,
+ const uint32_t *data)
+{
+ rp23xx_gspi_t *rp_io = (rp23xx_gspi_t *)(gspi->io_dev);
+ dma_info_t dma_info;
+ DMA_HANDLE xfer_dma = rp23xx_dmachannel();
+ uint32_t command = (0x1 << 31)
+ | ((increment ? 1 : 0) << 30)
+ | ((function & 0x3) << 28)
+ | ((address & 0x1ffff) << 11)
+ | (length & 0x7ff);
+
+ dma_config_t dma_config =
+ {
+ .size = RP23XX_DMA_SIZE_WORD,
+ .noincr = false,
+ .dreq = rp23xx_pio_get_dreq(rp_io->pio,
+ rp_io->pio_sm,
+ true),
+ };
+
+ PRINT_GSPI(
+ printf("------ cmd: 0x%08lx [W %d %d 0x%05lX %d]\n", command,
+ increment,
+ function,
+ address,
+ length);
+ bcmf_hexdump((void *)data, length, (uint32_t)data);
+ )
+
+ /* Claim the exclusive lock */
+
+ nxmutex_lock(&gspi->lock);
+
+ /* Reset the PIO state machine just to be sure. */
+
+ rp23xx_pio_sm_set_enabled(rp_io->pio, rp_io->pio_sm, false);
+
+ rp23xx_pio_sm_clear_fifos(rp_io->pio, rp_io->pio_sm);
+
+ rp23xx_pio_sm_restart(rp_io->pio, rp_io->pio_sm);
+
+ rp23xx_pio_sm_clkdiv_restart(rp_io->pio, rp_io->pio_sm);
+
+ rp23xx_pio_sm_exec(rp_io->pio,
+ rp_io->pio_sm,
+ pio_encode_jmp(rp_io->pio_location));
+
+ /* Set the PIO X and Y registers.
+ *
+ * We load X (the TX bit length) with one less than the number of
+ * bits to transmit to the chip. This length includes the 32-bit
+ * command word and all the 32-bit data words. Since the length
+ * parameter is a byte count we round up just to be sure.
+ *
+ * We load Y (the RX bit length) with zero as we're not reading
+ * any data.
+ *
+ * This is slightly magical. The way we load the X is to first
+ * push the the number of bits to transmit onto the transmit fifo.
+ * Then we force the PIO state machine to execute the instruction
+ * "out x, 32" which transfers the word from the output shift
+ * register (OSR) to the X register. When this instruction executes
+ * the PIO will notice that the OSR is empty, so will automatically
+ * pull a value (the one we just added) from the input fifo.
+ *
+ * Loading the Y works the same way.
+ */
+
+ rp23xx_pio_sm_put(rp_io->pio, rp_io->pio_sm, 32 * ((length + 3) / 4) + 31);
+ rp23xx_pio_sm_exec(rp_io->pio, rp_io->pio_sm, pio_encode_out(pio_x, 32));
+
+ rp23xx_pio_sm_put(rp_io->pio, rp_io->pio_sm, 0);
+ rp23xx_pio_sm_exec(rp_io->pio, rp_io->pio_sm, pio_encode_out(pio_y, 32));
+
+ /* Disable interrupts so data won't trigger interrupt. */
+
+ rp23xx_cyw_interrupt_enable(gspi, false);
+
+ /* Make sure the clock and data pins direction set to output. */
+
+ rp23xx_pio_sm_set_pindirs_with_mask(rp_io->pio,
+ rp_io->pio_sm,
+ (1 << rp_io->gpio_data)
+ | (1 << rp_io->gpio_clock),
+ (1 << rp_io->gpio_data)
+ | (1 << rp_io->gpio_clock));
+
+ /* Make sure there is nothing in the fifos before starting DMA. */
+
+ rp23xx_pio_sm_clear_fifos(rp_io->pio, rp_io->pio_sm);
+
+ /* Load the command into the transmit fifo. */
+
+ if (function == gspi_f0_bus_rev16)
+ {
+ __asm ("rev16 %0, %0" : "+l" (command) : :);
+ }
+
+ __asm ("rev %0, %0" : "+l" (command) : :);
+
+ putreg32(command, RP23XX_PIO_TXF(rp_io->pio, rp_io->pio_sm));
+
+ /* Initialize and start the transmit DMA. It will
+ * keep adding data to the TX_FIFO until all data is sent.
+ */
+
+ nxsem_init(&dma_info.sem, 0, 0);
+
+ rp23xx_dmastop(xfer_dma);
+
+ rp23xx_txdmasetup(xfer_dma,
+ (uintptr_t) RP23XX_PIO_TXF(rp_io->pio,
+ rp_io->pio_sm),
+ (uintptr_t) data,
+ (length + 3) & 0xfffffffc,
+ dma_config);
+
+ modifyreg32(rp23xx_dma_register(xfer_dma,
+ RP23XX_DMA_CTRL_TRIG_OFFSET),
+ RP23XX_DMA_CTRL_TRIG_BSWAP,
+ RP23XX_DMA_CTRL_TRIG_BSWAP);
+
+ rp23xx_dmastart(xfer_dma, dma_complete, &dma_info);
+
+ /* Assert gpio_select by pulling line low */
+
+ rp23xx_gpio_put(rp_io->gpio_select, false);
+ UP_DMB();
+
+ /* Enable the state machine. This starts the pio program running */
+
+ rp23xx_pio_sm_set_enabled(rp_io->pio, rp_io->pio_sm, true);
+
+ /* Wait for transfer to complete */
+
+ nxsem_wait(&dma_info.sem);
+
+ /* At this point all the data has been queued but my not have all been
+ * sent. We know that the PIO program will make the data line an input
+ * once all the data is sent so we'll check for this.
+ *
+ * NOTE (RP2350 port): the RP2040 read this via the OEFROMPERI status
+ * bit. That bit does not exist on RP2350; the GPIO_STATUS register
+ * exposes OETOPAD (the output enable presented to the pad, after any
+ * register override). With the default OEOVER (drive from peripheral)
+ * the two are equivalent for our purposes -- the bit is set while the
+ * PIO is still driving the data pin as an output.
+ */
+
+ while (getreg32(RP23XX_IO_BANK0_GPIO_STATUS(rp_io->gpio_data))
+ & RP23XX_IO_BANK0_GPIO_STATUS_OETOPAD)
+ {
+ /* Just busy wait -- testing indicates a worst case of
+ * 20 loops (100 instructions).
+ */
+ }
+
+ /* Un-assert select by pulling line high. */
+
+ UP_DMB();
+ rp23xx_gpio_put(rp_io->gpio_select, true);
+
+ /* Free the DMA controller */
+
+ rp23xx_dmafree(xfer_dma);
+ nxsem_destroy(&dma_info.sem);
+
+ /* Disable the PIO */
+
+ rp23xx_pio_sm_set_enabled(rp_io->pio, rp_io->pio_sm, false);
+
+ /* At this point the data pin is input so it should have been
+ * pulled high by rp23xx's gpio pullup.
+ */
+
+ rp23xx_cyw_interrupt_enable(gspi, true);
+
+ /* Release the exclusive lock */
+
+ nxmutex_unlock(&gspi->lock);
+ return dma_info.status;
+}
+
+/****************************************************************************
+ * Name: rp23xx_cyw_read
+ *
+ * Description:
+ * read data to the cyw43439
+ *
+ ****************************************************************************/
+
+static int rp23xx_cyw_read(struct gspi_dev_s *gspi,
+ bool increment,
+ enum gspi_cmd_func_e function,
+ uint32_t address,
+ uint16_t length,
+ uint32_t *buffer)
+{
+ rp23xx_gspi_t *rp_io = (rp23xx_gspi_t *)(gspi->io_dev);
+ dma_info_t dma_info;
+ DMA_HANDLE xfer_dma = rp23xx_dmachannel();
+ DMA_HANDLE ctrl_dma = rp23xx_dmachannel();
+ uint32_t temp_word;
+ uint32_t bit_length;
+ uint32_t command = ((increment ? 1 : 0) << 30)
+ | ((function & 0x3) << 28)
+ | ((address & 0x1ffff) << 11)
+ | (length & 0x7ff);
+
+ uint32_t pacing = rp23xx_pio_get_dreq(rp_io->pio,
+ rp_io->pio_sm,
+ false);
+
+ dma_control_block_t ctrl_blks[] =
+ {
+ /* For F1 transfers we read 1 word that we throw away */
+
+ {
+ rp23xx_dma_ctrl_blk_ctrl(ctrl_dma,
+ RP23XX_DMA_SIZE_WORD,
+ pacing,
+ 0),
+ (uintptr_t) RP23XX_PIO_RXF(rp_io->pio, rp_io->pio_sm),
+ (uintptr_t) &temp_word,
+ 1,
+ },
+
+ /* Read requested data into output buffer */
+
+ {
+ rp23xx_dma_ctrl_blk_ctrl(ctrl_dma,
+ RP23XX_DMA_SIZE_WORD,
+ pacing,
+ RP23XX_DMA_CTRL_TRIG_INCR_WRITE
+ | RP23XX_DMA_CTRL_TRIG_BSWAP),
+ (uintptr_t) RP23XX_PIO_RXF(rp_io->pio, rp_io->pio_sm),
+ (uintptr_t) buffer,
+ (length + 3) / 4,
+ },
+
+ RP23XX_DMA_CTRL_BLOCK_END
+ };
+
+ PRINT_GSPI(
+ printf("------ cmd: 0x%08lx [R %d %d 0x%05lX %d]\n", command,
+ increment,
+ function,
+ address,
+ length);
+ )
+
+ /* Claim the exclusive lock */
+
+ nxmutex_lock(&gspi->lock);
+
+ /* Reset the PIO state machine just to be sure. */
+
+ rp23xx_pio_sm_set_enabled(rp_io->pio, rp_io->pio_sm, false);
+
+ rp23xx_pio_sm_clear_fifos(rp_io->pio, rp_io->pio_sm);
+
+ rp23xx_pio_sm_restart(rp_io->pio, rp_io->pio_sm);
+
+ rp23xx_pio_sm_clkdiv_restart(rp_io->pio, rp_io->pio_sm);
+
+ rp23xx_pio_sm_exec(rp_io->pio,
+ rp_io->pio_sm,
+ pio_encode_jmp(rp_io->pio_location));
+
+ /* Set the PIO X and Y registers.
+ *
+ * We load X (the TX bit length) with one less than the number of
+ * bits to transmit to the chip. Since we only send the 32-bit command
+ * word we set X to 31.
+ *
+ * We load Y with the number of bits to read. This is based on the
+ * byte count in "length" which we round up to a 32-bit boundary so the
+ * pio program will be sure to autopush the final data to the output fifo.
+ *
+ * This is slightly magical. The way we load the X is to first
+ * push the the number of bits to transmit onto the transmit fifo.
+ * Then we force the PIO state machine to execute the instruction
+ * "out x, 32" which transfers the word from the output shift
+ * register (OSR) to the X register. When this instruction executes
+ * the PIO will notice that the OSR is empty, so will automatically
+ * pull a value (the one we just added) from the input fifo.
+ *
+ * Loading the Y works the same way.
+ */
+
+ rp23xx_pio_sm_put(rp_io->pio, rp_io->pio_sm, 31);
+ rp23xx_pio_sm_exec(rp_io->pio, rp_io->pio_sm, pio_encode_out(pio_x, 32));
+
+ /* RX bit length is 32 bits for each 4 bytes requested. */
+
+ bit_length = 32 * ((length + 3) / 4);
+
+ /* For F1 reads add 32 bits for delay */
+
+ if (function == gspi_f1_backplane)
+ {
+ bit_length += 32;
+ }
+
+ rp23xx_pio_sm_put(rp_io->pio, rp_io->pio_sm, bit_length);
+ rp23xx_pio_sm_exec(rp_io->pio, rp_io->pio_sm, pio_encode_out(pio_y, 32));
+
+ /* Disable interrupts so data won't trigger interrupt. */
+
+ rp23xx_cyw_interrupt_enable(gspi, false);
+
+ /* Make sure the clock and data pins direction set to output. */
+
+ rp23xx_pio_sm_set_pindirs_with_mask(rp_io->pio,
+ rp_io->pio_sm,
+ (1 << rp_io->gpio_data)
+ | (1 << rp_io->gpio_clock),
+ (1 << rp_io->gpio_data)
+ | (1 << rp_io->gpio_clock));
+
+ /* Make sure there is nothing in the fifos before starting DMA. */
+
+ rp23xx_pio_sm_clear_fifos(rp_io->pio, rp_io->pio_sm);
+
+ /* Load the command into the transmit fifo. */
+
+ if (function == gspi_f0_bus_rev16)
+ {
+ __asm ("rev16 %0, %0" : "+l" (command) : :);
+ }
+
+ __asm ("rev %0, %0" : "+l" (command) : :);
+
+ putreg32(command, RP23XX_PIO_TXF(rp_io->pio, rp_io->pio_sm));
+
+ /* Initialize and start the control DMA. It will
+ * use the xfer_dma to transfer data from the chip.
+ */
+
+ nxsem_init(&dma_info.sem, 0, 0);
+
+ rp23xx_dmastop(ctrl_dma);
+ rp23xx_dmastop(xfer_dma);
+
+ /* Check the function bits if the command word to see if
+ * this is an F1 read. If it is we throw away the first
+ * four bytes read as this is a delay word.
+ */
+
+ rp23xx_ctrl_dmasetup(ctrl_dma,
+ xfer_dma,
+ &ctrl_blks[function == 1 ? 0 : 1],
+ dma_complete,
+ &dma_info);
+
+ rp23xx_dmastart(ctrl_dma, NULL, NULL);
+
+ /* Assert gpio_select by pulling line low */
+
+ rp23xx_gpio_put(rp_io->gpio_select, false);
+ UP_DMB();
+
+ /* Enable the state machine. This starts the pio program running */
+
+ rp23xx_pio_sm_set_enabled(rp_io->pio, rp_io->pio_sm, true);
+
+ /* Wait for transfer to complete */
+
+ nxsem_wait(&dma_info.sem);
+
+ PRINT_GSPI(
+ bcmf_hexdump((void *)buffer, length, (uint32_t)buffer);
+ )
+
+ /* Un-assert select by pulling line high. */
+
+ UP_DMB();
+ rp23xx_gpio_put(rp_io->gpio_select, true);
+
+ /* Free the DMA controllers */
+
+ rp23xx_dmafree(ctrl_dma);
+ rp23xx_dmafree(xfer_dma);
+
+ nxsem_destroy(&dma_info.sem);
+
+ /* Disable the PIO */
+
+ rp23xx_pio_sm_set_enabled(rp_io->pio, rp_io->pio_sm, false);
+
+ /* At this point the data pin is input so it should have been
+ * pulled high by rp23xx's gpio pullup.
+ */
+
+ rp23xx_cyw_interrupt_enable(gspi, true);
+
+ /* Release the exclusive lock */
+
+ nxmutex_unlock(&gspi->lock);
+ return dma_info.status;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rp23xx_cyw_setup
+ *
+ * Description:
+ * Initialize the cyw43439 private data and PIO communication.
+ *
+ ****************************************************************************/
+
+gspi_dev_t *rp23xx_cyw_setup(uint8_t gpio_on,
+ uint8_t gpio_select,
+ uint8_t gpio_data,
+ uint8_t gpio_clock,
+ uint8_t gpio_intr)
+{
+ gspi_dev_t *gspi;
+ rp23xx_gspi_t *rp_io;
+ int err;
+
+ wlinfo("entered.\n");
+
+ gspi = kmm_zalloc(sizeof(gspi_dev_t));
+
+ if (gspi == NULL)
+ {
+ set_errno(ENOMEM);
+ return NULL;
+ }
+
+ rp_io = kmm_zalloc(sizeof(rp23xx_gspi_t));
+
+ if (rp_io == NULL)
+ {
+ kmm_free(gspi);
+ set_errno(ENOMEM);
+ return NULL;
+ }
+
+ gspi->init = rp23xx_cyw_init;
+ gspi->deinit = rp23xx_cyw_deinit;
+ gspi->set_isr = rp23xx_cyw_set_isr;
+ gspi->interrupt_enable = rp23xx_cyw_interrupt_enable;
+ gspi->write = rp23xx_cyw_write;
+ gspi->read = rp23xx_cyw_read;
+ gspi->io_dev = rp_io;
+
+ rp_io->gpio_on = gpio_on;
+ rp_io->gpio_select = gpio_select;
+ rp_io->gpio_data = gpio_data;
+ rp_io->gpio_clock = gpio_clock;
+ rp_io->gpio_intr = gpio_intr;
+
+ nxmutex_init(&gspi->lock);
+
+ /* Initialize the cyw43439 power-on and chip select lines. */
+
+ rp23xx_gpio_init(gpio_on);
+ rp23xx_gpio_setdir(gpio_on, true);
+ rp23xx_gpio_put(gpio_on, false); /* set low to turn wifi chip off */
+
+ rp23xx_gpio_init(gpio_select);
+ rp23xx_gpio_setdir(gpio_select, true);
+ rp23xx_gpio_put(gpio_select, true); /* set high to deselect chip */
+
+ err = bcmf_gspi_initialize(gspi);
+
+ if (err != OK)
+ {
+ kmm_free(gspi);
+ kmm_free(rp_io);
+
+ set_errno(err);
+ return NULL;
+ }
+
+ wlinfo("setup complete. gspi = 0x%p\n", gspi);
+
+ return gspi;
+}
+
+/****************************************************************************
+ * Name: rp23xx_cyw_remove
+ *
+ * Description:
+ * Deinitialize the cyw43439 PIO communication.
+ *
+ ****************************************************************************/
+
+void rp23xx_cyw_remove(gspi_dev_t *gspi)
+{
+ /* gspi_deregister((gspi_dev_t *)gspi); */
+}
+
+/****************************************************************************
+ * Name: bcmf_board_etheraddr
+ ****************************************************************************/
+
+bool bcmf_board_etheraddr(struct ether_addr *ethaddr)
+{
+ return false;
+}
diff --git a/arch/arm/src/rp23xx/rp23xx_cyw43439.h b/arch/arm/src/rp23xx/rp23xx_cyw43439.h
new file mode 100644
index 0000000000000..76cda33e32937
--- /dev/null
+++ b/arch/arm/src/rp23xx/rp23xx_cyw43439.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+ * arch/arm/src/rp23xx/rp23xx_cyw43439.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 __ARCH_ARM_SRC_RP23XX_RP23XX_CYW43439_H
+#define __ARCH_ARM_SRC_RP23XX_RP23XX_CYW43439_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+
+#include
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+typedef struct rp23xx_gspi_s
+{
+ uint32_t pio; /* The pio instance we are using. */
+ uint32_t pio_sm; /* The state machine we are using. */
+ uint32_t pio_location; /* the program location in the pio. */
+ uint8_t gpio_on; /* Set high to power chip on */
+ uint8_t gpio_select; /* Pull low to select chip */
+ uint8_t gpio_data; /* Data line -- idle high */
+ uint8_t gpio_clock; /* Clock line -- idle low */
+ uint8_t gpio_intr; /* May be shared with data */
+} rp23xx_gspi_t;
+
+typedef struct cyw_pio_program_s
+{
+ const uint16_t *instructions;
+ uint8_t length;
+ int8_t origin; /* required instruction memory origin or -1 */
+} cyw_pio_program_t;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rp23xx_cyw_setup
+ *
+ * Description:
+ * Initialize the cyw43439 device.
+ *
+ * Returns:
+ * A pointer to the cyw43439 device
+ *
+ ****************************************************************************/
+
+gspi_dev_t *rp23xx_cyw_setup(uint8_t gpio_on,
+ uint8_t gpio_select,
+ uint8_t gpio_data,
+ uint8_t gpio_clock,
+ uint8_t gpio_intr);
+
+/****************************************************************************
+ * Name: rp23xx_cyw_remove
+ *
+ * Description:
+ * Deinitialize the cyw43439 device.
+ *
+ * Parameters:
+ * A pointer (as returned by rp23xx_cyw_setup) to the device to remove.
+ *
+ ****************************************************************************/
+
+void rp23xx_cyw_remove(gspi_dev_t *dev);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_RP23XX_RP23XX_CYW43439_H */
diff --git a/arch/arm/src/rp23xx/rp23xx_usbdev.c b/arch/arm/src/rp23xx/rp23xx_usbdev.c
index 582f9cd430730..f4652abc18d1c 100644
--- a/arch/arm/src/rp23xx/rp23xx_usbdev.c
+++ b/arch/arm/src/rp23xx/rp23xx_usbdev.c
@@ -218,6 +218,7 @@ struct rp23xx_req_s
{
struct usbdev_req_s req; /* Standard USB request */
struct rp23xx_req_s *flink; /* Supports a singly linked list */
+ bool armed; /* Hardware buffer armed for this request */
};
/* This is the internal representation of an endpoint */
@@ -472,6 +473,7 @@ static void rp23xx_update_buffer_control(struct rp23xx_ep_s *privep,
uint32_t or_mask)
{
uint32_t value = 0;
+ int i;
if (and_mask)
{
@@ -481,6 +483,24 @@ static void rp23xx_update_buffer_control(struct rp23xx_ep_s *privep,
if (or_mask)
{
value |= or_mask;
+
+ if (or_mask & RP23XX_USBCTRL_DPSRAM_EP_BUFF_CTRL_AVAIL)
+ {
+ /* RP2040 datasheet 4.1.2.5.1: the AVAILABLE bit must be set
+ * after the rest of the buffer control register has been
+ * written and had time to settle across the clock domain
+ * crossing, or the controller may act on a stale length/PID.
+ * 12 CPU cycles covers system clocks up to 12x clk_usb.
+ */
+
+ putreg32(value & ~RP23XX_USBCTRL_DPSRAM_EP_BUFF_CTRL_AVAIL,
+ privep->buf_ctrl);
+
+ for (i = 0; i < 12; i++)
+ {
+ __asm__ volatile("nop");
+ }
+ }
}
putreg32(value, privep->buf_ctrl);
@@ -534,6 +554,20 @@ static int rp23xx_epread(struct rp23xx_ep_s *privep, uint16_t nbytes)
uint32_t val;
irqstate_t flags;
+ /* The hardware receives a single USB packet into the buffer, and the
+ * buffer-control LEN field is only 10 bits wide. Arm the buffer for at
+ * most one maximum-size packet; rp23xx_rxcomplete accumulates the request
+ * across multiple packets and re-arms until it is satisfied or a short
+ * packet arrives. Passing the full (possibly multi-kByte) request length
+ * would overflow LEN and corrupt the neighbouring control bits, making the
+ * transfer complete immediately with zero bytes.
+ */
+
+ if (nbytes > privep->ep.maxpacket)
+ {
+ nbytes = privep->ep.maxpacket;
+ }
+
val = nbytes |
RP23XX_USBCTRL_DPSRAM_EP_BUFF_CTRL_AVAIL |
(privep->next_pid ?
@@ -631,6 +665,7 @@ static void rp23xx_reqcomplete(struct rp23xx_ep_s *privep, int16_t result)
static void rp23xx_txcomplete(struct rp23xx_ep_s *privep)
{
struct rp23xx_req_s *privreq;
+ bool completed = false;
privreq = rp23xx_rqpeek(privep);
if (!privreq)
@@ -647,10 +682,31 @@ static void rp23xx_txcomplete(struct rp23xx_ep_s *privep)
usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
privep->txnullpkt = 0;
rp23xx_reqcomplete(privep, OK);
+ completed = true;
+ }
+ }
+
+ if (completed)
+ {
+ /* Start the next queued request -- unless it was already armed. The
+ * completion callback above may have submitted a new request on the
+ * now idle endpoint; epsubmit then armed the hardware buffer itself,
+ * and arming it a second time here would toggle the data PID twice
+ * and make the host silently discard the packet as a retransmission.
+ */
+
+ privreq = rp23xx_rqpeek(privep);
+ if (privreq && !privreq->armed)
+ {
+ rp23xx_wrrequest(privep);
}
}
+ else if (privreq)
+ {
+ /* Continue with the next packet of the in-progress request */
- rp23xx_wrrequest(privep);
+ rp23xx_wrrequest(privep);
+ }
}
/****************************************************************************
@@ -683,6 +739,7 @@ static int rp23xx_wrrequest(struct rp23xx_ep_s *privep)
{
if (privep->epphy == 0)
{
+ privreq->armed = true;
rp23xx_epwrite(privep, NULL, 0);
}
else
@@ -708,6 +765,7 @@ static int rp23xx_wrrequest(struct rp23xx_ep_s *privep)
* bytes to send.
*/
+ privreq->armed = true;
privep->txnullpkt = 0;
if (bytesleft > privep->ep.maxpacket)
{
@@ -763,6 +821,16 @@ static void rp23xx_rxcomplete(struct rp23xx_ep_s *privep)
{
usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
rp23xx_reqcomplete(privep, OK);
+
+ /* Re-arm only if the completion callback didn't already do it by
+ * resubmitting a request (see rp23xx_txcomplete).
+ */
+
+ privreq = rp23xx_rqpeek(privep);
+ if (privreq && privreq->armed)
+ {
+ return;
+ }
}
rp23xx_rdrequest(privep);
@@ -793,6 +861,7 @@ static int rp23xx_rdrequest(struct rp23xx_ep_s *privep)
usbtrace(TRACE_READ(privep->epphy), privreq->req.len);
+ privreq->armed = true;
return rp23xx_epread(privep, privreq->req.len);
}
@@ -1622,6 +1691,7 @@ static int rp23xx_epsubmit(struct usbdev_ep_s *ep,
req->result = -EINPROGRESS;
req->xfrd = 0;
+ privreq->armed = false;
flags = enter_critical_section();
diff --git a/boards/Kconfig b/boards/Kconfig
index ad047a75f11ce..5af6902b95f68 100644
--- a/boards/Kconfig
+++ b/boards/Kconfig
@@ -2214,6 +2214,15 @@ 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. It adds support
+ for the onboard Infineon CYW43439 Wi-Fi device, driven over a
+ PIO-based gSPI bus (see arch/arm/src/rp23xx/rp23xx_cyw43439.c).
+
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
@@ -3895,6 +3904,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
@@ -4422,6 +4432,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/common/src/rp23xx_common_bringup.c b/boards/arm/rp23xx/common/src/rp23xx_common_bringup.c
index 10b941ce3c650..75cb29a92387b 100644
--- a/boards/arm/rp23xx/common/src/rp23xx_common_bringup.c
+++ b/boards/arm/rp23xx/common/src/rp23xx_common_bringup.c
@@ -28,6 +28,11 @@
#include
#include
#include
+#ifdef CONFIG_EXAMPLES_PORTALUP
+# include
+# include
+# include
+#endif
#include
@@ -74,6 +79,11 @@ int rp23xx_common_bringup(void)
{
int ret = 0;
+#ifdef CONFIG_EXAMPLES_PORTALUP
+ FAR char *portalup_argv[2];
+ pid_t portalup_pid;
+#endif
+
#ifdef CONFIG_RP23XX_I2C_DRIVER
#ifdef CONFIG_RP23XX_I2C0
ret = board_i2cdev_initialize(0);
@@ -520,5 +530,21 @@ int rp23xx_common_bringup(void)
}
#endif
+
+#ifdef CONFIG_EXAMPLES_PORTALUP
+ /* Autostart the access-device boot helper: bring up wlan0 and start the
+ * mDNS responder so the board is reachable by name at boot.
+ */
+
+ portalup_argv[0] = "portalup";
+ portalup_argv[1] = NULL;
+
+ if (posix_spawn(&portalup_pid, "portalup", NULL, NULL,
+ portalup_argv, NULL) != 0)
+ {
+ syslog(LOG_ERR, "ERROR: failed to spawn portalup: %d\n", errno);
+ }
+#endif
+
return ret;
}
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 0000000000000..2fcb33e653ed9
--- /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 ${CMAKE_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" >>
+ ${CMAKE_BINARY_DIR}/nuttx.manifest
+ WORKING_DIRECTORY ${CMAKE_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 0000000000000..5eeb2e8df5150
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/Kconfig
@@ -0,0 +1,42 @@
+#
+# 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
+
+menuconfig RP23XX_INFINEON_CYW43439
+ bool "Has Infineon cyw43439 WiFi chip"
+ depends on IEEE80211_INFINEON_CYW43439
+ default y
+ ---help---
+ The Raspberry Pi Pico 2 W has an onboard Infineon CYW43439 WiFi chip
+ connected to the RP2350 via a PIO-based gSPI interface.
+
+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 CLB 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.
+
+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/access/defconfig b/boards/arm/rp23xx/raspberrypi-pico-2-w/configs/access/defconfig
new file mode 100644
index 0000000000000..578d0a47ba820
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/configs/access/defconfig
@@ -0,0 +1,113 @@
+#
+# 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_DEV_CONSOLE 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_ALLOW_BSD_COMPONENTS=y
+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_CDCACM=y
+CONFIG_CDCACM_COMPOSITE=y
+CONFIG_CDCACM_CONSOLE=y
+CONFIG_CDCNCM_COMPOSITE=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_EXAMPLES_MDNSD=y
+CONFIG_EXAMPLES_MDNS_SERVICE="_http._tcp.local"
+CONFIG_EXAMPLES_MDNS_SERVICE_PORT="80"
+CONFIG_EXAMPLES_PORTALUP=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_LIBC_EXECFUNCS=y
+CONFIG_LIB_MDNS=y
+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="x6PWXaErWMJy"
+CONFIG_NETINIT_WAPI_SSID="SKYMGIII"
+CONFIG_NETUTILS_DHCPD=y
+CONFIG_NETUTILS_DHCPD_DNSIP=0x0
+CONFIG_NETUTILS_DHCPD_NETMASK=0xFFFFFF00
+CONFIG_NETUTILS_DHCPD_ROUTERIP=0x0
+CONFIG_NETUTILS_DHCPD_STARTIP=0xC0A80702
+CONFIG_NETUTILS_MDNS=y
+CONFIG_NETUTILS_MDNS_BIND_IFNAME="eth0"
+CONFIG_NETUTILS_MDNS_DAEMON=y
+CONFIG_NETUTILS_MDNS_STACKSIZE=8192
+CONFIG_NETUTILS_TELNETD=y
+CONFIG_NET_BROADCAST=y
+CONFIG_NET_CDCNCM=y
+CONFIG_NET_ICMP_SOCKET=y
+CONFIG_NET_IGMP=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_NSH_USBCONSOLE=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_SIGINT_CHAR=0x03
+CONFIG_TTY_SIGTSTP=y
+CONFIG_USBDEV=y
+CONFIG_USBDEV_BUSPOWERED=y
+CONFIG_USBDEV_COMPOSITE=y
+CONFIG_WIRELESS_WAPI=y
+CONFIG_WIRELESS_WAPI_CMDTOOL=y
+CONFIG_WQUEUE_NOTIFIER=y
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 0000000000000..b58624dd28c20
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/configs/telnet/defconfig
@@ -0,0 +1,88 @@
+#
+# 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_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_ALLOW_BSD_COMPONENTS=y
+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_ARCHINIT=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_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 0000000000000..37c8afc1d392c
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/board.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+ * 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_INCLUDE_BOARD_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_INCLUDE_BOARD_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include "rp23xx_i2cdev.h"
+#include "rp23xx_spidev.h"
+#include "rp23xx_i2sdev.h"
+#include "rp23xx_spisd.h"
+
+#ifndef __ASSEMBLY__
+# include
+#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_GPIO_LED_PIN 25
+#define BOARD_NGPIOOUT 1
+#define BOARD_NGPIOIN 1
+#define BOARD_NGPIOINT 1
+
+/* LED definitions **********************************************************/
+
+/* If CONFIG_ARCH_LEDS is not defined, then the user can control the LEDs
+ * in any way. The following definitions are used to access individual 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)
+
+/* This LED is not used by the board port unless CONFIG_ARCH_LEDS is
+ * defined. In that case, the usage by the board port is defined in
+ * include/board.h and src/rp23xx_autoleds.c. The LED is used to encode
+ * OS-related events as follows:
+ *
+ * -------------------- ----------------------------- ------
+ * SYMBOL Meaning LED
+ * -------------------- ----------------------------- ------
+ */
+
+#define LED_STARTED 0 /* NuttX has been started OFF */
+#define LED_HEAPALLOCATE 0 /* Heap has been allocated OFF */
+#define LED_IRQSENABLED 0 /* Interrupts enabled OFF */
+#define LED_STACKCREATED 1 /* Idle stack created ON */
+#define LED_INIRQ 2 /* In an interrupt N/C */
+#define LED_SIGNAL 2 /* In a signal handler N/C */
+#define LED_ASSERTION 2 /* An assertion failed N/C */
+#define LED_PANIC 3 /* The system has crashed FLASH */
+#undef LED_IDLE /* Not used */
+
+/* Thus if the LED is statically on, NuttX has successfully booted and is,
+ * apparently, running normally. If the LED is flashing at approximately
+ * 2Hz, then a fatal error has been detected and the system has halted.
+ */
+
+/* BUTTON definitions *******************************************************/
+
+#define NUM_BUTTONS 0
+
+#define BUTTON_USER1 0
+#define BUTTON_USER2 1
+#define BUTTON_USER1_BIT (1 << BUTTON_USER1)
+#define BUTTON_USER2_BIT (1 << BUTTON_USER2)
+
+/****************************************************************************
+ * 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_INCLUDE_BOARD_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 0000000000000..bf8a179935228
--- /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_INCLUDE_RP23XX_I2CDEV_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_INCLUDE_RP23XX_I2CDEV_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+
+/****************************************************************************
+ * 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_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 0000000000000..41d68d519c019
--- /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_INCLUDE_RP23XX_I2SDEV_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_INCLUDE_RP23XX_I2SDEV_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+
+/****************************************************************************
+ * 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_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 0000000000000..df4c73eae1731
--- /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_INCLUDE_RP23XX_SPIDEV_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_INCLUDE_RP23XX_SPIDEV_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+/****************************************************************************
+ * 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_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 0000000000000..1f71de10ee91f
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_spisd.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/include/rp23xx_spisd.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_INCLUDE_RP23XX_SPISD_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_INCLUDE_RP23XX_SPISD_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+/****************************************************************************
+ * 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_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 0000000000000..cf214e955c780
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/Make.defs
@@ -0,0 +1,47 @@
+############################################################################
+# 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)
+
+ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10
+
+CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe
+CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS)
+CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe
+CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS)
+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 0000000000000..db52cb5543507
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_copy_to_ram.ld
@@ -0,0 +1,331 @@
+/****************************************************************************
+ * 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*)
+
+ . = 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 0000000000000..07328ad23c211
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_default.ld
@@ -0,0 +1,343 @@
+/****************************************************************************
+ * 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*)
+
+ . = 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(4);
+ __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 0000000000000..0900fb9e61b9f
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/scripts/memmap_no_flash.ld
@@ -0,0 +1,284 @@
+/****************************************************************************
+ * 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*)
+
+ . = 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(4);
+ __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/.gitignore b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/.gitignore
new file mode 100644
index 0000000000000..608fca90dbfc2
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/.gitignore
@@ -0,0 +1 @@
+*.image
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 0000000000000..7c2dd142f342a
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/CMakeLists.txt
@@ -0,0 +1,61 @@
+# ##############################################################################
+# boards/arm/rp23xx/raspberrypi-pico-2-w/src/CMakeLists.txt
+#
+# 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()
+
+if(CONFIG_ARCH_LEDS)
+ list(APPEND SRCS rp23xx_autoleds.c)
+else()
+ list(APPEND SRCS rp23xx_userleds.c)
+endif()
+
+if(CONFIG_ARCH_BUTTONS)
+ list(APPEND SRCS rp23xx_buttons.c)
+endif()
+
+if(CONFIG_BOARDCTL)
+ list(APPEND SRCS rp23xx_appinit.c)
+endif()
+
+if(CONFIG_USBDEV_COMPOSITE)
+ list(APPEND SRCS rp23xx_composite.c)
+endif()
+
+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()
+
+if(CONFIG_ETC_ROMFS)
+ # TODO: etc/init.d/rc.sysinit etc/init.d/rcS
+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 0000000000000..c31c11f40548b
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/Make.defs
@@ -0,0 +1,95 @@
+############################################################################
+# 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.
+#
+############################################################################
+
+include $(TOPDIR)/Make.defs
+
+CSRCS = rp23xx_boardinitialize.c
+CSRCS += rp23xx_appinit.c
+CSRCS += rp23xx_bringup.c
+
+ifeq ($(CONFIG_DEV_GPIO),y)
+CSRCS += rp23xx_gpio.c
+endif
+
+ifeq ($(CONFIG_ARCH_LEDS),y)
+CSRCS += rp23xx_autoleds.c
+else
+CSRCS += rp23xx_userleds.c
+endif
+
+ifeq ($(CONFIG_ARCH_BUTTONS),y)
+ CSRCS += rp23xx_buttons.c
+endif
+
+CSRCS += rp23xx_firmware.c
+
+DEPPATH += --dep-path board
+VPATH += :board
+CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board
+
+############################################################################
+# The rules below copy the cyw43439 blob from the pico-sdk. The firmware
+# source path is configured via CONFIG_CYW43439_FIRMWARE_BIN_PATH.
+############################################################################
+
+ifeq ($(CONFIG_IEEE80211_INFINEON_CYW43439),y)
+
+# When CONFIG_ARCH_BOARD_COMMON is selected, the libboard build runs from
+# the common board directory and reaches these board-specific sources via
+# the "board" symlink (arch/arm/src/board/board -> this src dir). The
+# firmware blob is therefore generated alongside rp23xx_firmware.c so that
+# the assembler's ".incbin" (which searches the source file's directory)
+# can find it, and the object is made to depend on it so generation always
+# runs before the compile.
+
+FIRMWARE = board$(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 run successfully
+# when built with this dummy file. The sole purpose of adding
+# this dummy is so the build (and GitHub's validation tests) will
+# not fail when the real firmware blob is not present.
+
+$(FIRMWARE_SRC):
+ mkdir -p `dirname $(FIRMWARE_SRC)`
+ echo "dummy" >$(FIRMWARE_SRC)
+
+$(FIRMWARE): $(FIRMWARE_SRC)
+ $(call CATFILE, $(FIRMWARE), $(FIRMWARE_SRC))
+
+rp23xx_firmware$(OBJEXT): $(FIRMWARE)
+
+distclean::
+ $(call DELFILE, board$(DELIM)cyw43439.firmware.image)
+
+endif
+
+ifeq ($(CONFIG_USBDEV_COMPOSITE),y)
+CSRCS += rp23xx_composite.c
+endif
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_appinit.c b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_appinit.c
new file mode 100644
index 0000000000000..bea44c62dd2c8
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_appinit.c
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_appinit.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
+
+#include
+#include
+
+#include "rp23xx_pico.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_app_initialize
+ *
+ * Description:
+ * Perform application specific initialization. This function is never
+ * called directly from application code, but only indirectly via the
+ * (non-standard) boardctl() interface using the command BOARDIOC_INIT.
+ *
+ * Input Parameters:
+ * arg - The boardctl() argument is passed to the board_app_initialize()
+ * implementation without modification. The argument has no
+ * meaning to NuttX; the meaning of the argument is a contract
+ * between the board-specific initialization logic and the
+ * matching application logic. The value could be such things as a
+ * mode enumeration value, a set of DIP switch switch settings, a
+ * pointer to configuration data read from a file or serial FLASH,
+ * or whatever you would like to do with it. Every implementation
+ * should accept zero/NULL as a default configuration.
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; a negated errno value is returned on
+ * any failure to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+int board_app_initialize(uintptr_t arg)
+{
+#ifdef CONFIG_BOARD_LATE_INITIALIZE
+ /* Board initialization already performed by board_late_initialize() */
+
+ return OK;
+#else
+ /* Perform board-specific initialization */
+
+ return rp23xx_bringup();
+#endif
+}
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_autoleds.c b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_autoleds.c
new file mode 100644
index 0000000000000..cbe1ae50e60e8
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_autoleds.c
@@ -0,0 +1,165 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_autoleds.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.
+ *
+ ****************************************************************************/
+
+/* There are four LED status indicators located on the EVK Board. The
+ * functions of these LEDs include:
+ *
+ * - Main Power Supply(D3)
+ * Green: DC 5V main supply is normal.
+ * Red: J2 input voltage is over 5.6V.
+ * Off: The board is not powered.
+ * - Reset RED LED(D15)
+ * - OpenSDA LED(D16)
+ * - USER LED(D18)
+ *
+ * Only a single LED, D18, is under software control.
+ *
+ * This LED is not used by the board port unless CONFIG_ARCH_LEDS is
+ * defined. In that case, the usage by the board port is defined in
+ * include/board.h and src/rp23xx_autoleds.c. The LED is used to encode
+ * OS-related events as follows:
+ *
+ * -------------------- ----------------------- ------
+ * SYMBOL Meaning LED
+ * -------------------- ----------------------- ------
+ *
+ * LED_STARTED 0 NuttX has been started OFF
+ * LED_HEAPALLOCATE 0 Heap has been allocated OFF
+ * LED_IRQSENABLED 0 Interrupts enabled OFF
+ * LED_STACKCREATED 1 Idle stack created ON
+ * LED_INIRQ 2 In an interrupt N/C
+ * LED_SIGNAL 2 In a signal handler N/C
+ * LED_ASSERTION 2 An assertion failed N/C
+ * LED_PANIC 3 The system has crashed FLASH
+ * LED_IDLE Not used
+ *
+ * Thus if the LED is statically on, NuttX has successfully booted and is,
+ * apparently, running normally. If the LED is flashing at approximately
+ * 2Hz, then a fatal error has been detected and the system has halted.
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+#include
+
+#include "rp23xx_gpio.h"
+
+#include "rp23xx_pico.h"
+
+#ifdef CONFIG_ARCH_LEDS
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rp23xx_autoled_initialize
+ *
+ * Description:
+ * Initialize NuttX-controlled LED logic
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void board_autoled_initialize(void)
+{
+ /* Configure LED GPIO for output */
+
+ rp23xx_gpio_init(GPIO_LED1);
+ rp23xx_gpio_setdir(GPIO_LED1, true);
+}
+
+/****************************************************************************
+ * Name: board_autoled_on
+ *
+ * Description:
+ * Turn on the "logical" LED state
+ *
+ * Input Parameters:
+ * led - Identifies the "logical" LED state (see definitions in
+ * include/board.h)
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void board_autoled_on(int led)
+{
+ bool ledon = true;
+
+ switch (led)
+ {
+ case 0: /* LED Off */
+ ledon = false;
+ break;
+
+ case 2: /* LED No change */
+ return;
+
+ case 1: /* LED On */
+ case 3: /* LED On */
+ break;
+ }
+
+ rp23xx_gpio_put(GPIO_LED1, ledon); /* High illuminates */
+}
+
+/****************************************************************************
+ * Name: board_autoled_off
+ *
+ * Description:
+ * Turn off the "logical" LED state
+ *
+ * Input Parameters:
+ * led - Identifies the "logical" LED state (see definitions in
+ * include/board.h)
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void board_autoled_off(int led)
+{
+ switch (led)
+ {
+ case 0: /* LED Off */
+ case 1: /* LED Off */
+ case 3: /* LED Off */
+ break;
+
+ case 2: /* LED No change */
+ return;
+ }
+
+ rp23xx_gpio_put(GPIO_LED1, false); /* High illuminates */
+}
+
+#endif /* CONFIG_ARCH_LEDS */
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 0000000000000..7ffdda18fde3b
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_boardinitialize.c
@@ -0,0 +1,116 @@
+/****************************************************************************
+ * 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
+
+#include
+
+#include
+#include
+
+#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 --- */
+
+ /* Set board LED pin */
+
+ rp23xx_gpio_init(BOARD_GPIO_LED_PIN);
+ rp23xx_gpio_setdir(BOARD_GPIO_LED_PIN, true);
+ rp23xx_gpio_put(BOARD_GPIO_LED_PIN, true);
+}
+
+/****************************************************************************
+ * 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 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 0000000000000..d8455f40201c4
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_bringup.c
@@ -0,0 +1,151 @@
+/****************************************************************************
+ * 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
+
+#include
+#include
+#include
+
+#include
+
+#include
+
+#include
+
+#include "rp23xx_pico.h"
+
+#ifdef CONFIG_ARCH_BOARD_COMMON
+#include "rp23xx_common_bringup.h"
+#endif /* CONFIG_ARCH_BOARD_COMMON */
+
+#ifdef CONFIG_USERLED
+# include
+#endif
+
+#ifdef CONFIG_RP23XX_INFINEON_CYW43439
+#include "rp23xx_cyw43439.h"
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_RP23XX_INFINEON_CYW43439
+
+/* CYW43439 wireless host-interface GPIO assignments.
+ *
+ * These match the Raspberry Pi Pico W (RP2040) wiring, which the Pico 2 W
+ * carries over unchanged so that existing CYW43 software keeps working.
+ * The data line is bidirectional (single-wire gSPI), so it is also used as
+ * the host-wake interrupt line.
+ *
+ * VERIFY: Pico 2 W datasheet -- confirm these GPIO numbers against the
+ * official Raspberry Pi Pico 2 W datasheet / schematic before relying on a
+ * hardware bring-up.
+ */
+
+# define CYW43439_POWER_ON_GPIO 23 /* WL_ON - power/enable */
+# define CYW43439_CHIP_SELECT_GPIO 25 /* WL_CS - chip select (active 0) */
+# define CYW43439_DATA_GPIO 24 /* WL_D - bidirectional gSPI data */
+# define CYW43439_CLOCK_GPIO 29 /* WL_CLK - gSPI clock */
+
+#endif
+
+/****************************************************************************
+ * Global Data
+ ****************************************************************************/
+
+#ifdef CONFIG_RP23XX_INFINEON_CYW43439
+gspi_dev_t *g_cyw43439 = NULL;
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rp23xx_bringup
+ ****************************************************************************/
+
+int rp23xx_bringup(void)
+{
+ int ret = OK;
+
+#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_USERLED
+ /* Register the LED driver */
+
+ ret = userled_lower_initialize("/dev/userleds");
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, \
+ "ERROR: userled_lower_initialize() failed: %d\n", ret);
+ }
+#endif
+
+#ifdef CONFIG_INPUT_BUTTONS
+ /* Register the BUTTON driver */
+
+ ret = btn_lower_initialize("/dev/buttons");
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: btn_lower_initialize() failed: %d\n", ret);
+ }
+#endif
+
+#ifdef CONFIG_RP23XX_INFINEON_CYW43439
+ /* Initialize the cyw43439 (onboard WiFi chip) over PIO-based gSPI. */
+
+ g_cyw43439 = rp23xx_cyw_setup(CYW43439_POWER_ON_GPIO,
+ CYW43439_CHIP_SELECT_GPIO,
+ CYW43439_DATA_GPIO,
+ CYW43439_CLOCK_GPIO,
+ CYW43439_DATA_GPIO);
+
+ if (g_cyw43439 == NULL)
+ {
+ ret = errno;
+
+ syslog(LOG_ERR,
+ "Failed to initialize cyw43439 (WiFi chip): %d\n",
+ ret);
+
+ return ret;
+ }
+#endif
+
+ return ret;
+}
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_buttons.c b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_buttons.c
new file mode 100644
index 0000000000000..b984c6458e5fc
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_buttons.c
@@ -0,0 +1,177 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_buttons.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
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include "rp23xx_gpio.h"
+#include "rp23xx_pico.h"
+
+#if defined(CONFIG_ARCH_BUTTONS)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#if defined(CONFIG_INPUT_BUTTONS) && !defined(CONFIG_ARCH_IRQBUTTONS)
+# error "The NuttX Buttons Driver depends on IRQ support to work!\n"
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* Pin configuration for external raspberrypi-pico-2 buttons. */
+
+static const uint32_t g_buttons[NUM_BUTTONS] =
+{
+ GPIO_BTN_USER1, GPIO_BTN_USER2
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_button_initialize
+ *
+ * Description:
+ * board_button_initialize() must be called to initialize button resources.
+ * After that, board_buttons() may be called to collect the current state
+ * of all buttons or board_button_irq() may be called to register button
+ * interrupt handlers.
+ *
+ ****************************************************************************/
+
+uint32_t board_button_initialize(void)
+{
+ int i;
+
+ /* Configure the GPIO pins as inputs. And we will use interrupts */
+
+ for (i = 0; i < NUM_BUTTONS; i++)
+ {
+ /* Initialize input pin */
+
+ rp23xx_gpio_init(g_buttons[i]);
+
+ /* pull-up = false : pull-down = false */
+
+ rp23xx_gpio_set_pulls(g_buttons[i], false, false);
+ }
+
+ return NUM_BUTTONS;
+}
+
+/****************************************************************************
+ * Name: board_buttons
+ ****************************************************************************/
+
+uint32_t board_buttons(void)
+{
+ uint32_t ret = 0;
+ int i;
+
+ /* Check that state of each key */
+
+ for (i = 0; i < NUM_BUTTONS; i++)
+ {
+ /* A LOW value means that the key is pressed. */
+
+ bool released = rp23xx_gpio_get(g_buttons[i]);
+
+ /* Accumulate the set of depressed (not released) keys */
+
+ if (!released)
+ {
+ ret |= (1 << i);
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Button support.
+ *
+ * Description:
+ * board_button_initialize() must be called to initialize button resources.
+ * After that, board_buttons() may be called to collect the current state
+ * of all buttons or board_button_irq() may be called to register button
+ * interrupt handlers.
+ *
+ * After board_button_initialize() has been called, board_buttons() may be
+ * called to collect the state of all buttons. board_buttons() returns
+ * an 32-bit bit set with each bit associated with a button. See the
+ * BUTTON_*_BIT definitions in board.h for the meaning of each bit.
+ *
+ * board_button_irq() may be called to register an interrupt handler that
+ * will be called when a button is depressed or released. The ID value is
+ * a button enumeration value that uniquely identifies a button resource.
+ * See the BUTTON_* definitions in board.h for the meaning of enumeration
+ * value.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_IRQBUTTONS
+int board_button_irq(int id, xcpt_t irqhandler, void *arg)
+{
+ int ret = -EINVAL;
+
+ /* The following should be atomic */
+
+ if (id >= MIN_IRQBUTTON && id <= MAX_IRQBUTTON)
+ {
+ /* Make sure the interrupt is disabled */
+
+ rp23xx_gpio_disable_irq(g_buttons[id]);
+
+ /* Attach the interrupt handler */
+
+ ret = rp23xx_gpio_irq_attach(g_buttons[id],
+ RP23XX_GPIO_INTR_EDGE_LOW,
+ irqhandler,
+ arg);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: irq_attach() failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Enable interruption for this pin */
+
+ rp23xx_gpio_enable_irq(g_buttons[id]);
+ }
+
+ return ret;
+}
+#endif
+
+#endif /* CONFIG_ARCH_BUTTONS */
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_composite.c b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_composite.c
new file mode 100644
index 0000000000000..8dd9a8e4b6177
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_composite.c
@@ -0,0 +1,123 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_composite.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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#ifdef CONFIG_CDCACM_COMPOSITE
+# include
+#endif
+#ifdef CONFIG_CDCNCM_COMPOSITE
+# include
+#endif
+
+#if defined(CONFIG_BOARDCTL_USBDEVCTRL) && defined(CONFIG_USBDEV_COMPOSITE)
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_composite_initialize
+ ****************************************************************************/
+
+int board_composite_initialize(int port)
+{
+ return OK;
+}
+
+/****************************************************************************
+ * Name: board_composite_connect
+ *
+ * Description:
+ * Connect the CDC/ACM serial console + CDC/NCM network composite device.
+ * The two classes use disjoint endpoint numbers (ACM: 1/2/3, NCM: 4/5/6)
+ * so they can coexist in one configuration.
+ *
+ ****************************************************************************/
+
+void *board_composite_connect(int port, int configid)
+{
+ if (configid == 0)
+ {
+ struct composite_devdesc_s dev[2];
+ int ifnobase = 0;
+ int strbase = COMPOSITE_NSTRIDS;
+ int n = 0;
+
+#ifdef CONFIG_CDCACM_COMPOSITE
+ /* CDC/ACM serial console */
+
+ cdcacm_get_composite_devdesc(&dev[n]);
+
+ dev[n].classobject = cdcacm_classobject;
+ dev[n].uninitialize = cdcacm_uninitialize;
+
+ dev[n].devinfo.ifnobase = ifnobase;
+ dev[n].minor = 0;
+ dev[n].devinfo.strbase = strbase;
+
+ dev[n].devinfo.epno[CDCACM_EP_INTIN_IDX] = 1;
+ dev[n].devinfo.epno[CDCACM_EP_BULKIN_IDX] = 2;
+ dev[n].devinfo.epno[CDCACM_EP_BULKOUT_IDX] = 3;
+
+ ifnobase += dev[n].devinfo.ninterfaces;
+ strbase += dev[n].devinfo.nstrings;
+ n++;
+#endif
+
+#ifdef CONFIG_CDCNCM_COMPOSITE
+ /* CDC/NCM network device */
+
+ cdcncm_get_composite_devdesc(&dev[n]);
+
+ dev[n].devinfo.ifnobase = ifnobase;
+ dev[n].minor = 0;
+ dev[n].devinfo.strbase = strbase;
+
+ dev[n].devinfo.epno[CDCNCM_EP_INTIN_IDX] = 4;
+ dev[n].devinfo.epno[CDCNCM_EP_BULKIN_IDX] = 5;
+ dev[n].devinfo.epno[CDCNCM_EP_BULKOUT_IDX] = 6;
+
+ ifnobase += dev[n].devinfo.ninterfaces;
+ strbase += dev[n].devinfo.nstrings;
+ n++;
+#endif
+
+ return composite_initialize(composite_getdevdescs(), dev, n);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+#endif /* CONFIG_BOARDCTL_USBDEVCTRL && CONFIG_USBDEV_COMPOSITE */
diff --git a/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_firmware.c b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_firmware.c
new file mode 100644
index 0000000000000..58e071503702d
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_firmware.c
@@ -0,0 +1,158 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_firmware.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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ROUNDED_FIRMWARE_LEN ((CONFIG_CYW43439_FIRMWARE_LEN + 0xff) & ~0xff)
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef CONFIG_IEEE80211_INFINEON_CYW43439
+
+/****************************************************************************
+ * Character array of NVRAM image
+ * Generated from cyw943439wlpth_rev1_0.txt
+ * $ Copyright Broadcom Corporation $
+ ****************************************************************************/
+
+const uint8_t g_cyw43439_nvram_image[] __attribute__((aligned(4))) =
+ "NVRAMRev=$Rev$" "\x00"
+ "manfid=0x2d0" "\x00"
+ "prodid=0x0727" "\x00"
+ "vendid=0x14e4" "\x00"
+ "devid=0x43e2" "\x00"
+ "boardtype=0x0887" "\x00"
+ "boardrev=0x1100" "\x00"
+ "boardnum=22" "\x00"
+ "macaddr=00:A0:50:b5:59:5e" "\x00"
+ "sromrev=11" "\x00"
+ "boardflags=0x00404001" "\x00"
+ "boardflags3=0x04000000" "\x00"
+ "xtalfreq=37400" "\x00"
+ "nocrc=1" "\x00"
+ "ag0=255" "\x00"
+ "aa2g=1" "\x00"
+ "ccode=ALL" "\x00"
+ "pa0itssit=0x20" "\x00"
+ "extpagain2g=0" "\x00"
+ "pa2ga0=-168,6649,-778" "\x00"
+ "AvVmid_c0=0x0,0xc8" "\x00"
+ "cckpwroffset0=5" "\x00"
+ "maxp2ga0=84" "\x00"
+ "txpwrbckof=6" "\x00"
+ "cckbw202gpo=0" "\x00"
+ "legofdmbw202gpo=0x66111111" "\x00"
+ "mcsbw202gpo=0x77711111" "\x00"
+ "propbw202gpo=0xdd" "\x00"
+ "ofdmdigfilttype=18" "\x00"
+ "ofdmdigfilttypebe=18" "\x00"
+ "papdmode=1" "\x00"
+ "papdvalidtest=1" "\x00"
+ "pacalidx2g=45" "\x00"
+ "papdepsoffset=-30" "\x00"
+ "papdendidx=58" "\x00"
+ "ltecxmux=0" "\x00"
+ "ltecxpadnum=0x0102" "\x00"
+ "ltecxfnsel=0x44" "\x00"
+ "ltecxgcigpio=0x01" "\x00"
+ "il0macaddr=00:90:4c:c5:12:38" "\x00"
+ "wl0id=0x431b" "\x00"
+ "deadman_to=0xffffffff" "\x00"
+ "muxenab=0x100" "\x00"
+ "spurconfig=0x3" "\x00"
+ "glitch_based_crsmin=1" "\x00"
+ "btc_mode=1" "\x00"
+ "\x00\x00";
+
+const unsigned int g_cyw43439_nvram_len = sizeof(g_cyw43439_nvram_image);
+
+/****************************************************************************
+ * Include the firmware blob. This assembly code defines the global
+ * symbol g_cyw43439_firmware_image as the address of this included
+ * blob. This is similar in effect to the C statement:
+ * const uint8_t g_cyw43439_firmware_image[] = {...};
+ * const uint8_t ng_cyw43439_clm_blob_image[] = {...};
+ ****************************************************************************/
+
+/* These are defined as array because the symbols name an actual address
+ * not a pointer to an address. This is not one of the many cases where
+ * pointers and arrays are interchangeable in C.
+ */
+
+extern const uint8_t g_cyw43439_firmware_image[];
+extern const uint8_t g_cyw43439_clm_blob_image[];
+extern const unsigned int g_cyw43439_clm_blob_len;
+
+/* This assembly code does the following:
+ * - Force 16-byte alignment
+ * - Defines g_cyw43439_firmware_image as a location in memory
+ * - Copies the firmware image file data to that location.
+ * - Defines g_cyw43439_firmware_end as the location directly beyond
+ * that data.
+ * - Defines g_cyw43439_clm_blob_image as a location within that
+ * data where the clm_blob begins.
+ * - Force 4-byte alignment
+ * - Allocates an integer named g_cyw43439_clm_blob_len that
+ * contains the length of the clm_blob.
+ */
+
+__asm__("\n .balign 16"
+ "\n .globl g_cyw43439_firmware_image"
+ "\n .globl g_cyw43439_clm_blob_image"
+ "\n .globl g_cyw43439_clm_blob_len"
+ "\n g_cyw43439_firmware_image:"
+ "\n .incbin \"cyw43439.firmware.image\""
+ "\n firmware_end:"
+ "\n g_cyw43439_clm_blob_image=g_cyw43439_firmware_image+"
+ STRINGIFY(ROUNDED_FIRMWARE_LEN)
+ "\n .balign 4"
+ "\n g_cyw43439_clm_blob_len:"
+ "\n .word firmware_end-g_cyw43439_clm_blob_image"
+ "\n");
+
+/****************************************************************************
+ * Other CYW43439 Firmware global definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
+
+const unsigned int g_cyw43439_firmware_len = CONFIG_CYW43439_FIRMWARE_LEN;
+
+#endif /* CONFIG_IEEE80211_BROADCOM_FWFILES */
+
+#endif /* CONFIG_IEEE80211_INFINEON_CYW43439 */
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
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 0000000000000..cc6b3810ca39e
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_gpio.c
@@ -0,0 +1,392 @@
+/****************************************************************************
+ * 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
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+#include "arm_internal.h"
+#include "chip.h"
+#include "rp23xx_gpio.h"
+
+#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF)
+
+/* Output pins. GPIO25 is onboard LED any other outputs could be used.
+ */
+
+#define GPIO_OUT1 25
+
+/* 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 0000000000000..65bf3393709c8
--- /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_SRC_RP23XX_PICO_H
+#define __BOARDS_ARM_RP23XX_RASPBERRYPI_PICO_2_SRC_RP23XX_PICO_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+/* LEDs */
+
+#define GPIO_LED1 25 /* The board's LED is connected to this pin */
+
+/* Buttons */
+
+/* Buttons GPIO pins definition */
+
+#define GPIO_BTN_USER1 16
+#define GPIO_BTN_USER2 17
+
+/* Buttons IRQ definitions */
+
+#define MIN_IRQBUTTON BUTTON_USER1
+#define MAX_IRQBUTTON BUTTON_USER2
+#define NUM_IRQBUTTONS (BUTTON_USER1 - BUTTON_USER2 + 1)
+
+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_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 0000000000000..7e95de4917fcb
--- /dev/null
+++ b/boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_userleds.c
@@ -0,0 +1,214 @@
+/****************************************************************************
+ * boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_userleds.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
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "chip.h"
+#include "rp23xx_gpio.h"
+
+#include "rp23xx_pico.h"
+
+#ifndef CONFIG_ARCH_LEDS
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This array maps an LED number to GPIO pin configuration */
+
+static uint32_t g_ledcfg[BOARD_NLEDS] =
+{
+ GPIO_LED1,
+};
+
+/****************************************************************************
+ * Private Function Protototypes
+ ****************************************************************************/
+
+/* LED Power Management */
+
+#ifdef CONFIG_PM
+static void led_pm_notify(struct pm_callback_s *cb, int domain,
+ enum pm_state_e pmstate);
+static int led_pm_prepare(struct pm_callback_s *cb, int domain,
+ enum pm_state_e pmstate);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static struct pm_callback_s g_ledscb =
+{
+ .notify = led_pm_notify,
+ .prepare = led_pm_prepare,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: led_pm_notify
+ *
+ * Description:
+ * Notify the driver of new power state. This callback is called after
+ * all drivers have had the opportunity to prepare for the new power state.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static void led_pm_notify(struct pm_callback_s *cb, int domain,
+ enum pm_state_e pmstate)
+{
+ switch (pmstate)
+ {
+ case PM_NORMAL:
+ {
+ /* Restore normal LEDs operation */
+
+ board_userled(BOARD_LED, true);
+ }
+ break;
+
+ case PM_IDLE:
+ {
+ /* Entering IDLE mode - Turn leds off */
+
+ board_userled(BOARD_LED, false);
+ }
+ break;
+
+ case PM_STANDBY:
+ {
+ /* Entering STANDBY mode - Logic for PM_STANDBY goes here */
+ }
+ break;
+
+ case PM_SLEEP:
+ {
+ /* Entering SLEEP mode - Logic for PM_SLEEP goes here */
+ }
+ break;
+
+ default:
+ {
+ /* Should not get here */
+ }
+ break;
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: led_pm_prepare
+ *
+ * Description:
+ * Request the driver to prepare for a new power state. This is a warning
+ * that the system is about to enter into a new power state. The driver
+ * should begin whatever operations that may be required to enter power
+ * state. The driver may abort the state change mode by returning a
+ * non-zero value from the callback function.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static int led_pm_prepare(struct pm_callback_s *cb, int domain,
+ enum pm_state_e pmstate)
+{
+ /* No preparation to change power modes is required by the LEDs driver.
+ * We always accept the state change by returning OK.
+ */
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_userled_initialize
+ ****************************************************************************/
+
+uint32_t board_userled_initialize(void)
+{
+ /* Configure LED GPIO for output */
+
+ rp23xx_gpio_init(GPIO_LED1);
+ rp23xx_gpio_setdir(GPIO_LED1, true);
+
+ return BOARD_NLEDS;
+}
+
+/****************************************************************************
+ * Name: board_userled
+ ****************************************************************************/
+
+void board_userled(int led, bool ledon)
+{
+ if ((unsigned)led < BOARD_NLEDS)
+ {
+ rp23xx_gpio_put(g_ledcfg[led], ledon);
+ }
+}
+
+/****************************************************************************
+ * Name: board_userled_all
+ ****************************************************************************/
+
+void board_userled_all(uint32_t ledset)
+{
+ rp23xx_gpio_put(GPIO_LED1, (ledset & BOARD_LED1_BIT));
+}
+
+/****************************************************************************
+ * Name: rp23xx_led_pminitialize
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+void rp23xx_led_pminitialize(void)
+{
+ /* Register to receive power management callbacks */
+
+ int ret = pm_register(&g_ledscb);
+ if (ret != OK)
+ {
+ board_autoled_on(LED_ASSERTION);
+ }
+}
+#endif /* CONFIG_PM */
+
+#endif /* !CONFIG_ARCH_LEDS */