You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ma...@apache.org on 2021/03/08 08:06:16 UTC

[incubator-nuttx] 03/03: boards/raspberrypi-pico: Support SPI and SD card

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

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

commit b9c529422672e6d93e41fe71457b8eaa672794ce
Author: Yuichi Nakamura <y....@gmail.com>
AuthorDate: Fri Mar 5 23:11:37 2021 +0900

    boards/raspberrypi-pico: Support SPI and SD card
---
 boards/arm/rp2040/common/src/Make.defs             |   8 ++
 .../src/rp2040_spidev.c}                           |  52 ++++----
 boards/arm/rp2040/common/src/rp2040_spisd.c        | 134 +++++++++++++++++++++
 boards/arm/rp2040/raspberrypi-pico/Kconfig         |  12 ++
 boards/arm/rp2040/raspberrypi-pico/README.txt      |  17 ++-
 .../raspberrypi-pico/configs/spisd/defconfig       |  64 ++++++++++
 boards/arm/rp2040/raspberrypi-pico/include/board.h |   3 +
 .../rp2040_bringup.c => include/rp2040_spidev.h}   |  70 +++++------
 .../include/{board.h => rp2040_spisd.h}            |  56 +++------
 boards/arm/rp2040/raspberrypi-pico/src/Make.defs   |   4 +
 .../raspberrypi-pico/src/rp2040_boardinitialize.c  |  94 +++++++++------
 .../rp2040/raspberrypi-pico/src/rp2040_bringup.c   |  29 +++++
 .../arm/rp2040/raspberrypi-pico/src/rp2040_spi.c   | 110 +++++++++++++++++
 13 files changed, 508 insertions(+), 145 deletions(-)

diff --git a/boards/arm/rp2040/common/src/Make.defs b/boards/arm/rp2040/common/src/Make.defs
index 89d4a94..3c2587d 100644
--- a/boards/arm/rp2040/common/src/Make.defs
+++ b/boards/arm/rp2040/common/src/Make.defs
@@ -22,10 +22,18 @@ ifeq ($(CONFIG_RP2040_I2C_DRIVER),y)
 CSRCS += rp2040_i2cdev.c
 endif
 
+ifeq ($(CONFIG_RP2040_SPI_DRIVER),y)
+CSRCS += rp2040_spidev.c
+endif
+
 ifeq ($(CONFIG_LCD_SSD1306),y)
 CSRCS += rp2040_ssd1306.c
 endif
 
+ifeq ($(CONFIG_RP2040_SPISD),y)
+  CSRCS += rp2040_spisd.c
+endif
+
 DEPPATH += --dep-path src
 VPATH += :src
 CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src)
diff --git a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c b/boards/arm/rp2040/common/src/rp2040_spidev.c
similarity index 67%
copy from boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c
copy to boards/arm/rp2040/common/src/rp2040_spidev.c
index 68e7826..4f73ec1 100644
--- a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c
+++ b/boards/arm/rp2040/common/src/rp2040_spidev.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c
+ * boards/arm/rp2040/common/src/rp2040_spidev.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -24,54 +24,46 @@
 
 #include <nuttx/config.h>
 
+#include <stdio.h>
 #include <debug.h>
-#include <stddef.h>
+#include <errno.h>
+#include <nuttx/spi/spi_transfer.h>
 
-#include <nuttx/fs/fs.h>
-
-#include <arch/board/board.h>
-
-#include "rp2040_pico.h"
+#include "rp2040_spi.h"
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: rp2040_bringup
+ * Name: board_spidev_initialize
+ *
+ * Description:
+ *   Initialize and register spi driver for the specified spi port
+ *
  ****************************************************************************/
 
-int rp2040_bringup(void)
+int board_spidev_initialize(int port)
 {
-  int ret = 0;
+  int ret;
+  FAR struct spi_dev_s *spi;
 
-#ifdef CONFIG_RP2040_I2C_DRIVER
-  #ifdef CONFIG_RP2040_I2C0
-  ret = board_i2cdev_initialize(0);
-  if (ret < 0)
-    {
-      _err("ERROR: Failed to initialize I2C0.\n");
-    }
-  #endif
+  spiinfo("Initializing /dev/spi%d..\n", port);
 
-  #ifdef CONFIG_RP2040_I2C1
-  ret = board_i2cdev_initialize(1);
-  if (ret < 0)
+  /* Initialize spi device */
+
+  spi = rp2040_spibus_initialize(port);
+  if (!spi)
     {
-      _err("ERROR: Failed to initialize I2C1.\n");
+      spierr("ERROR: Failed to initialize spi%d.\n", port);
+      return -ENODEV;
     }
-  #endif
-#endif
-
-#ifdef CONFIG_FS_PROCFS
-  /* Mount the procfs file system */
 
-  ret = nx_mount(NULL, "/proc", "procfs", 0, NULL);
+  ret = spi_register(spi, port);
   if (ret < 0)
     {
-      serr("ERROR: Failed to mount procfs at %s: %d\n", "/proc", ret);
+      spierr("ERROR: Failed to register spi%d: %d\n", port, ret);
     }
-#endif
 
   return ret;
 }
diff --git a/boards/arm/rp2040/common/src/rp2040_spisd.c b/boards/arm/rp2040/common/src/rp2040_spisd.c
new file mode 100644
index 0000000..11ff0f7
--- /dev/null
+++ b/boards/arm/rp2040/common/src/rp2040_spisd.c
@@ -0,0 +1,134 @@
+/****************************************************************************
+ * boards/arm/rp2040/common/src/rp2040_spisd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+#include <nuttx/mmcsd.h>
+#include <nuttx/board.h>
+#include <nuttx/fs/fs.h>
+
+#include "rp2040_spi.h"
+#include "rp2040_gpio.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_RP2040_SPISD_SLOT_NO
+#  define CONFIG_RP2040_SPISD_SLOT_NO 0
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_spisd_initialize
+ *
+ * Description:
+ *   Initialize the SPI-based SD card.
+ *
+ ****************************************************************************/
+
+int board_spisd_initialize(int minor, int bus)
+{
+  int ret;
+  FAR struct spi_dev_s *spi;
+
+  /* Initialize spi deivce */
+
+  spi = rp2040_spibus_initialize(bus);
+  if (!spi)
+    {
+      ferr("ERROR: Failed to initialize spi%d.\n", bus);
+      return -ENODEV;
+    }
+
+  /* Pull up RX */
+
+#ifdef CONFIG_RP2040_SPI0
+  if (bus == 0)
+    {
+      rp2040_gpio_set_pulls(CONFIG_RP2040_SPI0_GPIO, true, false);
+    }
+#endif
+
+#ifdef CONFIG_RP2040_SPI1
+  if (bus == 1)
+    {
+      rp2040_gpio_set_pulls(CONFIG_RP2040_SPI1_GPIO, true, false);
+    }
+#endif
+
+  /* Get the SPI driver instance for the SD chip select */
+
+  finfo("Initializing SPI for the MMC/SD slot\n");
+
+  ret = mmcsd_spislotinitialize(minor, CONFIG_RP2040_SPISD_SLOT_NO, spi);
+  if (ret < 0)
+    {
+      ferr("ERROR: Failed to bind SPI device to MMC/SD slot %d: %d\n",
+           CONFIG_RP2040_SPISD_SLOT_NO, ret);
+      return ret;
+    }
+
+  /* Mount filesystem */
+
+  ret = nx_mount("/dev/mmcsd0", "/mnt/sd0", "vfat", 0, NULL);
+  if (ret < 0)
+    {
+      _err("ERROR: Failed to mount the SDCARD. %d\n", ret);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: board_spisd_status
+ *
+ * Description:
+ *   Get the status whether SD Card is present or not.
+ *   This function is called only from rp2040_spi.c.
+ *
+ * Returned Value:
+ *   Return SPI_STATUS_PRESENT if SD Card is present. Otherwise, return 0.
+ *
+ ****************************************************************************/
+
+uint8_t board_spisd_status(FAR struct spi_dev_s *dev, uint32_t devid)
+{
+  uint8_t ret = 0;
+
+  if (devid == SPIDEV_MMCSD(0))
+    {
+      /* Card detection is not supported yet */
+
+      ret = SPI_STATUS_PRESENT;
+    }
+
+  return ret;
+}
diff --git a/boards/arm/rp2040/raspberrypi-pico/Kconfig b/boards/arm/rp2040/raspberrypi-pico/Kconfig
index e77f724..7af06c3 100644
--- a/boards/arm/rp2040/raspberrypi-pico/Kconfig
+++ b/boards/arm/rp2040/raspberrypi-pico/Kconfig
@@ -51,4 +51,16 @@ config RP2040_I2C1_GPIO
 	range -1 29
 	depends on RP2040_I2C1
 
+config RP2040_SPI0_GPIO
+	int "SPI0 GPIO pin assign (0,4,16,20 or -1:no assign)"
+	default -1
+	range -1 29
+	depends on RP2040_SPI0
+
+config RP2040_SPI1_GPIO
+	int "SPI1 GPIO pin assign (8,12,24,28 or -1:no assign)"
+	default -1
+	range -1 29
+	depends on RP2040_SPI1
+
 endif
diff --git a/boards/arm/rp2040/raspberrypi-pico/README.txt b/boards/arm/rp2040/raspberrypi-pico/README.txt
index 9262d93..f0d0638 100644
--- a/boards/arm/rp2040/raspberrypi-pico/README.txt
+++ b/boards/arm/rp2040/raspberrypi-pico/README.txt
@@ -11,6 +11,7 @@ Currently only the following devices are suppored.
   - UART  (console port)
     - GPIO 0 (UART0 TX) and GPIO 1 (UART0 RX) are used for the console.
   - I2C
+  - SPI (DMA transfer is not supported yet)
   - Flash ROM Boot
   - SRAM Boot
     - If Pico SDK is available, nuttx.uf2 file which can be used in
@@ -51,7 +52,7 @@ Defconfigs
 ==========
 
 - nsh
-    Minimum configuration with NutShell
+    Minimum configuration with NuttShell
 
 - nshsram
     Load NuttX binary to SRAM
@@ -68,6 +69,20 @@ Defconfigs
            SDA ----- GP4 (I2C0 SDA) (Pin 6)
            SCL ----- GP5 (I2C0 SCL) (Pin 7)
 
+- spisd
+    SD card support (SPI connection)
+    Connection:
+      SD card slot   Raspberry Pi Pico
+       DAT2          (NC)
+       DAT3/CS ----- GP17 (SPI0 CSn) (Pin 22)
+       CMD /DI ----- GP19 (SPI0 TX)  (Pin 25)
+       VDD     ----- 3V3 OUT         (Pin 36)
+       CLK/SCK ----- GP18 (SPI0 SCK) (Pin 24)
+       VSS     ----- GND             (Pin 3 or 38 or ...)
+       DAT0/DO ----- GP16 (SPI0 RX)  (Pin 21)
+       DAT1          (NC)
+    * Card hot swapping is not supported.
+
 License exceptions
 ==================
 
diff --git a/boards/arm/rp2040/raspberrypi-pico/configs/spisd/defconfig b/boards/arm/rp2040/raspberrypi-pico/configs/spisd/defconfig
new file mode 100644
index 0000000..bc73733
--- /dev/null
+++ b/boards/arm/rp2040/raspberrypi-pico/configs/spisd/defconfig
@@ -0,0 +1,64 @@
+#
+# 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_FS_PROCFS_EXCLUDE_ENVIRON is not set
+# CONFIG_LIBC_LONG_LONG is not set
+# CONFIG_MMCSD_HAVE_CARDDETECT is not set
+# CONFIG_MMCSD_HAVE_WRITEPROTECT 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_NSH_DISABLE_PRINTF is not set
+# CONFIG_NSH_DISABLE_TRUNCATE is not set
+# CONFIG_SPI_CALLBACK is not set
+# CONFIG_STANDARD_SERIAL is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="raspberrypi-pico"
+CONFIG_ARCH_BOARD_RASPBERRYPI_PICO=y
+CONFIG_ARCH_CHIP="rp2040"
+CONFIG_ARCH_CHIP_RP2040=y
+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_EXAMPLES_HELLO=y
+CONFIG_FAT_LCNAMES=y
+CONFIG_FAT_LFN=y
+CONFIG_FS_FAT=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_PROCFS_REGISTER=y
+CONFIG_MAX_TASKS=8
+CONFIG_MMCSD=y
+CONFIG_NFILE_DESCRIPTORS=6
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_READLINE=y
+CONFIG_RAM_SIZE=270336
+CONFIG_RAM_START=0x20000000
+CONFIG_READLINE_CMD_HISTORY=y
+CONFIG_RP2040_SPI0=y
+CONFIG_RP2040_SPI0_GPIO=16
+CONFIG_RP2040_SPI=y
+CONFIG_RP2040_SPISD=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_START_DAY=9
+CONFIG_START_MONTH=2
+CONFIG_START_YEAR=2021
+CONFIG_SYSLOG_CONSOLE=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_SPITOOL=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/rp2040/raspberrypi-pico/include/board.h b/boards/arm/rp2040/raspberrypi-pico/include/board.h
index 31e26e9..7269745 100644
--- a/boards/arm/rp2040/raspberrypi-pico/include/board.h
+++ b/boards/arm/rp2040/raspberrypi-pico/include/board.h
@@ -28,6 +28,9 @@
 #include <nuttx/config.h>
 
 #include "rp2040_i2cdev.h"
+#include "rp2040_spidev.h"
+
+#include "rp2040_spisd.h"
 
 #ifndef __ASSEMBLY__
 # include <stdint.h>
diff --git a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c b/boards/arm/rp2040/raspberrypi-pico/include/rp2040_spidev.h
similarity index 60%
copy from boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c
copy to boards/arm/rp2040/raspberrypi-pico/include/rp2040_spidev.h
index 68e7826..f4753ff 100644
--- a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c
+++ b/boards/arm/rp2040/raspberrypi-pico/include/rp2040_spidev.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c
+ * boards/arm/rp2040/raspberrypi-pico/include/rp2040_spidev.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,60 +18,52 @@
  *
  ****************************************************************************/
 
+#ifndef __BOARDS_ARM_RP2040_RASPBERRYPI_PICO_INCLUDE_RP2040_SPIDEV_H
+#define __BOARDS_ARM_RP2040_RASPBERRYPI_PICO_INCLUDE_RP2040_SPIDEV_H
+
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 
 #include <nuttx/config.h>
 
-#include <debug.h>
-#include <stddef.h>
-
-#include <nuttx/fs/fs.h>
-
-#include <arch/board/board.h>
-
-#include "rp2040_pico.h"
-
 /****************************************************************************
- * Public Functions
+ * Public Types
  ****************************************************************************/
 
+#ifndef __ASSEMBLY__
+
 /****************************************************************************
- * Name: rp2040_bringup
+ * Public Data
  ****************************************************************************/
 
-int rp2040_bringup(void)
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
 {
-  int ret = 0;
+#else
+#define EXTERN extern
+#endif
 
-#ifdef CONFIG_RP2040_I2C_DRIVER
-  #ifdef CONFIG_RP2040_I2C0
-  ret = board_i2cdev_initialize(0);
-  if (ret < 0)
-    {
-      _err("ERROR: Failed to initialize I2C0.\n");
-    }
-  #endif
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
 
-  #ifdef CONFIG_RP2040_I2C1
-  ret = board_i2cdev_initialize(1);
-  if (ret < 0)
-    {
-      _err("ERROR: Failed to initialize I2C1.\n");
-    }
-  #endif
-#endif
+/****************************************************************************
+ * Name: board_spidev_initialize
+ *
+ * Description:
+ *   Initialize spi driver and register the /dev/spi device.
+ *
+ ****************************************************************************/
 
-#ifdef CONFIG_FS_PROCFS
-  /* Mount the procfs file system */
+int board_spidev_initialize(int bus);
 
-  ret = nx_mount(NULL, "/proc", "procfs", 0, NULL);
-  if (ret < 0)
-    {
-      serr("ERROR: Failed to mount procfs at %s: %d\n", "/proc", ret);
-    }
+#undef EXTERN
+#if defined(__cplusplus)
+}
 #endif
 
-  return ret;
-}
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_ARM_RP2040_RASPBERRYPI_PICO_INCLUDE_RP2040_SPIDEV_H */
diff --git a/boards/arm/rp2040/raspberrypi-pico/include/board.h b/boards/arm/rp2040/raspberrypi-pico/include/rp2040_spisd.h
similarity index 62%
copy from boards/arm/rp2040/raspberrypi-pico/include/board.h
copy to boards/arm/rp2040/raspberrypi-pico/include/rp2040_spisd.h
index 31e26e9..1269188 100644
--- a/boards/arm/rp2040/raspberrypi-pico/include/board.h
+++ b/boards/arm/rp2040/raspberrypi-pico/include/rp2040_spisd.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/arm/rp2040/raspberrypi-pico/include/board.h
+ * boards/arm/rp2040/raspberrypi-pico/include/rp2040_spisd.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,8 +18,8 @@
  *
  ****************************************************************************/
 
-#ifndef __BOARDS_ARM_RP2040_RASPBERRYPI_PICO_INCLUDE_BOARD_H
-#define __BOARDS_ARM_RP2040_RASPBERRYPI_PICO_INCLUDE_BOARD_H
+#ifndef __BOARDS_ARM_RP2040_RASPBERRYPI_PICO_INCLUDE_RP2040_SPISD_H
+#define __BOARDS_ARM_RP2040_RASPBERRYPI_PICO_INCLUDE_RP2040_SPISD_H
 
 /****************************************************************************
  * Included Files
@@ -27,39 +27,6 @@
 
 #include <nuttx/config.h>
 
-#include "rp2040_i2cdev.h"
-
-#ifndef __ASSEMBLY__
-# include <stdint.h>
-#endif
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/* Clocking *****************************************************************/
-
-#define MHZ                     1000000
-
-#define BOARD_XOSC_FREQ         (12 * MHZ)
-#define BOARD_PLL_SYS_FREQ      (125 * MHZ)
-#define BOARD_PLL_USB_FREQ      (48 * MHZ)
-
-#define BOARD_REF_FREQ          (12 * MHZ)
-#define BOARD_SYS_FREQ          (125 * MHZ)
-#define BOARD_PERI_FREQ         (125 * MHZ)
-#define BOARD_USB_FREQ          (48 * MHZ)
-#define BOARD_ADC_FREQ          (48 * MHZ)
-#define BOARD_RTC_FREQ          46875
-
-#define BOARD_UART_BASEFREQ     BOARD_PERI_FREQ
-
-#define BOARD_TICK_CLOCK        (1 * MHZ)
-
-/* GPIO definitions *********************************************************/
-
-#define BOARD_GPIO_LED_PIN      25
-
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -84,26 +51,33 @@ extern "C"
  ****************************************************************************/
 
 /****************************************************************************
- * Name: rp2040_boardearlyinitialize
+ * Name: board_spisd_initialize
  *
  * Description:
+ *   Initialize the SPI-based SD card.
  *
  ****************************************************************************/
 
-void rp2040_boardearlyinitialize(void);
+#ifdef CONFIG_RP2040_SPISD
+int board_spisd_initialize(int minor, int bus);
+#endif
 
 /****************************************************************************
- * Name: rp2040_boardinitialize
+ * Name: board_spisd_status
  *
  * Description:
+ *   Get the status whether SD Card is present or not.
  *
  ****************************************************************************/
 
-void rp2040_boardinitialize(void);
+#ifdef CONFIG_RP2040_SPISD
+uint8_t board_spisd_status(FAR struct spi_dev_s *dev, uint32_t devid);
+#endif
 
 #undef EXTERN
 #if defined(__cplusplus)
 }
 #endif
+
 #endif /* __ASSEMBLY__ */
-#endif /* __BOARDS_ARM_RP2040_RASPBERRYPI_PICO_INCLUDE_BOARD_H */
+#endif /* __BOARDS_ARM_RP2040_RASPBERRYPI_PICO_INCLUDE_RP2040_SPISD_H */
diff --git a/boards/arm/rp2040/raspberrypi-pico/src/Make.defs b/boards/arm/rp2040/raspberrypi-pico/src/Make.defs
index 64de118..51fc4ae 100644
--- a/boards/arm/rp2040/raspberrypi-pico/src/Make.defs
+++ b/boards/arm/rp2040/raspberrypi-pico/src/Make.defs
@@ -28,6 +28,10 @@ ifeq ($(CONFIG_BOARDCTL_RESET),y)
 CSRCS += rp2040_reset.c
 endif
 
+ifeq ($(CONFIG_SPI),y)
+CSRCS += rp2040_spi.c
+endif
+
 DEPPATH += --dep-path board
 VPATH += :board
 CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board)
diff --git a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_boardinitialize.c b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_boardinitialize.c
index 1f7da15..2d059c8 100644
--- a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_boardinitialize.c
+++ b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_boardinitialize.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/arm/rp2040/raspberrypi-pico/src/rp2040-boardinitialize.c
+ * boards/arm/rp2040/raspberrypi-pico/src/rp2040_boardinitialize.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -33,9 +33,6 @@
 #include "arm_internal.h"
 
 #include "rp2040_gpio.h"
-#include "hardware/rp2040_pads_bank0.h"
-#include "hardware/rp2040_io_bank0.h"
-#include "hardware/rp2040_sio.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -67,74 +64,103 @@ void rp2040_boardearlyinitialize(void)
 
   /* Set board LED pin */
 
-  rp2040_gpio_set_function(BOARD_GPIO_LED_PIN,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_SIO);
-  putreg32(1 << BOARD_GPIO_LED_PIN, RP2040_SIO_GPIO_OE_SET);
-
-  putreg32(1 << BOARD_GPIO_LED_PIN, RP2040_SIO_GPIO_OUT_SET);
+  rp2040_gpio_init(BOARD_GPIO_LED_PIN);
+  rp2040_gpio_setdir(BOARD_GPIO_LED_PIN, true);
+  rp2040_gpio_put(BOARD_GPIO_LED_PIN, true);
 
   /* Set default UART pin */
 
 #if defined(CONFIG_RP2040_UART0) && CONFIG_RP2040_UART0_GPIO >= 0
   rp2040_gpio_set_function(CONFIG_RP2040_UART0_GPIO,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_UART); /* TX */
+                           RP2040_GPIO_FUNC_UART);      /* TX */
   rp2040_gpio_set_function(CONFIG_RP2040_UART0_GPIO + 1,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_UART); /* RX */
+                           RP2040_GPIO_FUNC_UART);      /* RX */
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   rp2040_gpio_set_function(CONFIG_RP2040_UART0_GPIO + 2,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_UART); /* CTS */
+                           RP2040_GPIO_FUNC_UART);      /* CTS */
 #endif
 #ifdef CONFIG_SERIAL_IFLOWCONTROL
   rp2040_gpio_set_function(CONFIG_RP2040_UART0_GPIO + 3,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_UART); /* RTS */
+                           RP2040_GPIO_FUNC_UART);      /* RTS */
 #endif
 #endif
 
 #if defined(CONFIG_RP2040_UART1) && CONFIG_RP2040_UART1_GPIO >= 0
   rp2040_gpio_set_function(CONFIG_RP2040_UART1_GPIO,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_UART); /* TX */
+                           RP2040_GPIO_FUNC_UART);      /* TX */
   rp2040_gpio_set_function(CONFIG_RP2040_UART1_GPIO + 1,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_UART); /* RX */
+                           RP2040_GPIO_FUNC_UART);      /* RX */
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
   rp2040_gpio_set_function(CONFIG_RP2040_UART1_GPIO + 2,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_UART); /* CTS */
+                           RP2040_GPIO_FUNC_UART);      /* CTS */
 #endif
 #ifdef CONFIG_SERIAL_IFLOWCONTROL
   rp2040_gpio_set_function(CONFIG_RP2040_UART1_GPIO + 3,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_UART); /* RTS */
+                           RP2040_GPIO_FUNC_UART);      /* RTS */
 #endif
 #endif
+}
+
+/****************************************************************************
+ * Name: rp2040_boardinitialize
+ *
+ * Description:
+ *
+ ****************************************************************************/
 
+void rp2040_boardinitialize(void)
+{
   /* Set default I2C pin */
 
 #if defined(CONFIG_RP2040_I2C0) && CONFIG_RP2040_I2C0_GPIO >= 0
   rp2040_gpio_set_function(CONFIG_RP2040_I2C0_GPIO,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_I2C);  /* SDA */
+                           RP2040_GPIO_FUNC_I2C);       /* SDA */
   rp2040_gpio_set_function(CONFIG_RP2040_I2C0_GPIO + 1,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_I2C);  /* SCL */
+                           RP2040_GPIO_FUNC_I2C);       /* SCL */
 
-  rp2040_gpio_set_pulls(CONFIG_RP2040_I2C0_GPIO, false, true); /* Pull down */
-  rp2040_gpio_set_pulls(CONFIG_RP2040_I2C0_GPIO + 1, false, true);
+  rp2040_gpio_set_pulls(CONFIG_RP2040_I2C0_GPIO, true, false);  /* Pull up */
+  rp2040_gpio_set_pulls(CONFIG_RP2040_I2C0_GPIO + 1, true, false);
 #endif
 
 #if defined(CONFIG_RP2040_I2C1) &&  CONFIG_RP2040_I2C1_GPIO >= 0
   rp2040_gpio_set_function(CONFIG_RP2040_I2C1_GPIO,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_I2C);  /* SDA */
+                           RP2040_GPIO_FUNC_I2C);       /* SDA */
   rp2040_gpio_set_function(CONFIG_RP2040_I2C1_GPIO + 1,
-                           RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_I2C);  /* SCL */
+                           RP2040_GPIO_FUNC_I2C);       /* SCL */
 
-  rp2040_gpio_set_pulls(CONFIG_RP2040_I2C1_GPIO, false, true); /* Pull down */
-  rp2040_gpio_set_pulls(CONFIG_RP2040_I2C1_GPIO + 1, false, true);
+  rp2040_gpio_set_pulls(CONFIG_RP2040_I2C1_GPIO, true, false);  /* Pull up */
+  rp2040_gpio_set_pulls(CONFIG_RP2040_I2C1_GPIO + 1, true, false);
 #endif
-}
 
-/****************************************************************************
- * Name: rp2040_boardinitialize
- *
- * Description:
- *
- ****************************************************************************/
+  /* Set default SPI pin */
 
-void rp2040_boardinitialize(void)
-{
+#if defined(CONFIG_RP2040_SPI0) && CONFIG_RP2040_SPI0_GPIO >= 0
+  rp2040_gpio_set_function(CONFIG_RP2040_SPI0_GPIO,
+                           RP2040_GPIO_FUNC_SPI);       /* RX */
+  rp2040_gpio_set_function(CONFIG_RP2040_SPI0_GPIO + 2,
+                           RP2040_GPIO_FUNC_SPI);       /* SCK */
+  rp2040_gpio_set_function(CONFIG_RP2040_SPI0_GPIO + 3,
+                           RP2040_GPIO_FUNC_SPI);       /* TX */
+
+  /* CSn is controlled by board-specific logic */
+
+  rp2040_gpio_init(CONFIG_RP2040_SPI0_GPIO + 1);        /* CSn */
+  rp2040_gpio_setdir(CONFIG_RP2040_SPI0_GPIO + 1, true);
+  rp2040_gpio_put(CONFIG_RP2040_SPI0_GPIO + 1, true);
+#endif
+
+#if defined(CONFIG_RP2040_SPI1) &&  CONFIG_RP2040_SPI1_GPIO >= 0
+  rp2040_gpio_set_function(CONFIG_RP2040_SPI1_GPIO,
+                           RP2040_GPIO_FUNC_SPI);       /* RX */
+  rp2040_gpio_set_function(CONFIG_RP2040_SPI1_GPIO + 2,
+                           RP2040_GPIO_FUNC_SPI);       /* SCK */
+  rp2040_gpio_set_function(CONFIG_RP2040_SPI1_GPIO + 3,
+                           RP2040_GPIO_FUNC_SPI);       /* TX */
+
+  /* CSn is controlled by board-specific logic */
+
+  rp2040_gpio_init(CONFIG_RP2040_SPI1_GPIO + 1);        /* CSn */
+  rp2040_gpio_setdir(CONFIG_RP2040_SPI1_GPIO + 1, true);
+  rp2040_gpio_put(CONFIG_RP2040_SPI1_GPIO + 1, true);
+#endif
 }
diff --git a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c
index 68e7826..4932312 100644
--- a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c
+++ b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c
@@ -63,6 +63,35 @@ int rp2040_bringup(void)
   #endif
 #endif
 
+#ifdef CONFIG_RP2040_SPI_DRIVER
+  #ifdef CONFIG_RP2040_SPI0
+  ret = board_spidev_initialize(0);
+  if (ret < 0)
+    {
+      _err("ERROR: Failed to initialize SPI0.\n");
+    }
+  #endif
+
+  #ifdef CONFIG_RP2040_SPI1
+  ret = board_spidev_initialize(1);
+  if (ret < 0)
+    {
+      _err("ERROR: Failed to initialize SPI1.\n");
+    }
+  #endif
+#endif
+
+#ifdef CONFIG_RP2040_SPISD
+  /* Mount the SPI-based MMC/SD block driver */
+
+  ret = board_spisd_initialize(0, CONFIG_RP2040_SPISD_SPI_CH);
+  if (ret < 0)
+    {
+      _err("ERROR: Failed to initialize SPI device to MMC/SD: %d\n",
+           ret);
+    }
+#endif
+
 #ifdef CONFIG_FS_PROCFS
   /* Mount the procfs file system */
 
diff --git a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_spi.c b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_spi.c
new file mode 100644
index 0000000..d7866a0
--- /dev/null
+++ b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_spi.c
@@ -0,0 +1,110 @@
+/****************************************************************************
+ * boards/arm/rp2040/raspberrypi-pico/src/rp2040_spi.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/spi/spi.h>
+#include <arch/board/board.h>
+
+#include "arm_arch.h"
+#include "chip.h"
+#include "rp2040_gpio.h"
+#include "hardware/rp2040_spi.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name:  rp2040_spi0/1select and rp2040_spi0/1status
+ *
+ * Description:
+ *   The external functions, rp2040_spi0/1select and rp2040_spi0/1status
+ *   must be provided by board-specific logic.
+ *   They are implementations of the select and status methods of the SPI
+ *   interface defined by struct spi_ops_s (see include/nuttx/spi/spi.h).
+ *   All other methods (including rp2040_spibus_initialize()) are provided by
+ *   common RP2040 logic.  To use this common SPI logic on your board:
+ *
+ *   1. Provide logic in rp2040_boardinitialize() to configure SPI chip
+ *      select pins.
+ *   2. Provide rp2040_spi0/1select() and rp2040_spi0/1status()
+ *      functions in your board-specific logic.
+ *      These functions will perform chip selection and status operations
+ *      using GPIOs in the way your board is configured.
+ *   3. Add a calls to rp2040_spibus_initialize() in your low level
+ *      application initialization logic
+ *   4. The handle returned by rp2040_spibus_initialize() may then be used to
+ *      bind the SPI driver to higher level logic (e.g., calling
+ *      mmcsd_spislotinitialize(), for example, will bind the SPI driver to
+ *      the SPI MMC/SD driver).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RP2040_SPI0
+void rp2040_spi0select(FAR struct spi_dev_s *dev, uint32_t devid,
+                       bool selected)
+{
+  spiinfo("devid: %d CS: %s\n", (int)devid,
+          selected ? "assert" : "de-assert");
+
+  rp2040_gpio_put(CONFIG_RP2040_SPI0_GPIO + 1, !selected);
+}
+
+uint8_t rp2040_spi0status(FAR struct spi_dev_s *dev, uint32_t devid)
+{
+  uint8_t ret = 0;
+
+#  if defined(CONFIG_RP2040_SPISD) && (CONFIG_RP2040_SPISD_SPI_CH == 0)
+  ret = board_spisd_status(dev, devid);
+#  endif
+  return ret;
+}
+#endif
+
+#ifdef CONFIG_RP2040_SPI1
+void rp2040_spi1select(FAR struct spi_dev_s *dev, uint32_t devid,
+                       bool selected)
+{
+  spiinfo("devid: %d CS: %s\n", (int)devid,
+          selected ? "assert" : "de-assert");
+
+  rp2040_gpio_put(CONFIG_RP2040_SPI1_GPIO + 1, !selected);
+}
+
+uint8_t rp2040_spi1status(FAR struct spi_dev_s *dev, uint32_t devid)
+{
+  uint8_t ret = 0;
+
+#  if defined(CONFIG_RP2040_SPISD) && (CONFIG_RP2040_SPISD_SPI_CH == 1)
+  ret = board_spisd_status(dev, devid);
+#  endif
+  return ret;
+}
+#endif