From 8c2c5a1ff713fe9e2c70748174e92208bda68bae Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Mon, 18 Nov 2024 15:47:05 +0900 Subject: [PATCH 1/3] drivers: gpio: rpi_pico: Add support for RP2350B As the RP2350B has more than 32 GPIO pins, we changed the configuration so that it is split into two ports. To do this, we created a `raspberrypi,pico-gpio-port` node and moved the previous `raspberrypi,pico-gpio-port` functions to it. This became a child node of `raspberrypi,pico-gpio-port`, and `raspberrypi,pico-gpio-port` will remain a gpio mapper. Signed-off-by: TOKITA Hiroshi --- boards/raspberrypi/rpi_pico2/rpi_pico2.dtsi | 2 +- doc/releases/migration-guide-4.2.rst | 12 + drivers/gpio/Kconfig.rpi_pico | 2 +- drivers/gpio/gpio_rpi_pico.c | 259 +++++++++++++----- dts/arm/raspberrypi/rpi_pico/rp2040.dtsi | 21 +- dts/arm/raspberrypi/rpi_pico/rp2350.dtsi | 29 +- .../gpio/raspberrypi,pico-gpio-port.yaml | 19 ++ dts/bindings/gpio/raspberrypi,pico-gpio.yaml | 15 +- 8 files changed, 275 insertions(+), 84 deletions(-) create mode 100644 dts/bindings/gpio/raspberrypi,pico-gpio-port.yaml diff --git a/boards/raspberrypi/rpi_pico2/rpi_pico2.dtsi b/boards/raspberrypi/rpi_pico2/rpi_pico2.dtsi index 9c61122ee37c..522413c94f1a 100644 --- a/boards/raspberrypi/rpi_pico2/rpi_pico2.dtsi +++ b/boards/raspberrypi/rpi_pico2/rpi_pico2.dtsi @@ -97,7 +97,7 @@ pinctrl-names = "default"; }; -&gpio0 { +gpio0_lo: &gpio0 { status = "okay"; }; diff --git a/doc/releases/migration-guide-4.2.rst b/doc/releases/migration-guide-4.2.rst index fbd8d34ede52..d21d352ec35b 100644 --- a/doc/releases/migration-guide-4.2.rst +++ b/doc/releases/migration-guide-4.2.rst @@ -35,9 +35,21 @@ Boards Device Drivers and Devicetree ***************************** +Ethernet +======== + * Removed Kconfig option ``ETH_STM32_HAL_MII`` (:github:`86074`). PHY interface type is now selected via the ``phy-connection-type`` property in the device tree. +GPIO +==== + +* To support the RP2350B, which has many pins, the RaspberryPi-GPIO configuration has + been changed. The previous role of :dtcompatible:`raspberrypi,rpi-gpio` has been migrated to + :dtcompatible:`raspberrypi,rpi-gpio-port`, and :dtcompatible:`raspberrypi,rpi-gpio` is + now left as a placeholder and mapper. + The labels have also been changed along, so no changes are necessary for regular use. + Bluetooth ********* diff --git a/drivers/gpio/Kconfig.rpi_pico b/drivers/gpio/Kconfig.rpi_pico index 64370be497c0..8d75fea44729 100644 --- a/drivers/gpio/Kconfig.rpi_pico +++ b/drivers/gpio/Kconfig.rpi_pico @@ -3,7 +3,7 @@ config GPIO_RPI_PICO default y - depends on DT_HAS_RASPBERRYPI_PICO_GPIO_ENABLED + depends on DT_HAS_RASPBERRYPI_PICO_GPIO_PORT_ENABLED select PICOSDK_USE_GPIO select PINCTRL bool "Raspberry Pi Pico GPIO driver" diff --git a/drivers/gpio/gpio_rpi_pico.c b/drivers/gpio/gpio_rpi_pico.c index 2e2e592eee82..198820f9244e 100644 --- a/drivers/gpio/gpio_rpi_pico.c +++ b/drivers/gpio/gpio_rpi_pico.c @@ -16,28 +16,115 @@ #include -#define DT_DRV_COMPAT raspberrypi_pico_gpio +#define DT_DRV_COMPAT raspberrypi_pico_gpio_port #define ALL_EVENTS (GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE \ | GPIO_IRQ_LEVEL_LOW | GPIO_IRQ_LEVEL_HIGH) +#define GPIO_RPI_PINS_PER_PORT 32 + +#define ADDR_IS_ZERO(n, x) (DT_INST_REG_ADDR(n) == 0) | +#define ADDR_IS_NON_ZERO(n, x) (DT_INST_REG_ADDR(n) != 0) | +#define GPIO_RPI_LO_AVAILABLE (DT_INST_FOREACH_STATUS_OKAY_VARGS(ADDR_IS_ZERO) 0) +#define GPIO_RPI_HI_AVAILABLE (DT_INST_FOREACH_STATUS_OKAY_VARGS(ADDR_IS_NON_ZERO) 0) + +#if GPIO_RPI_HI_AVAILABLE +#define PORT_NO(port) ((((struct gpio_rpi_config *)port->config)->high_dev != NULL) ? 0 : 1) +#else +#define PORT_NO(port) ((int)port & 0) /* generate zero and suppress unused warning */ +#endif + struct gpio_rpi_config { struct gpio_driver_config common; void (*bank_config_func)(void); +#if GPIO_RPI_HI_AVAILABLE + const struct device *high_dev; +#endif }; struct gpio_rpi_data { struct gpio_driver_data common; sys_slist_t callbacks; - uint32_t int_enabled_mask; uint32_t single_ended_mask; uint32_t open_drain_mask; }; +static inline void gpio_set_dir_out_masked_n(uint n, uint32_t mask) +{ + if (!n) { + gpio_set_dir_out_masked(mask); + } else if (n == 1) { +#if PICO_USE_GPIO_COPROCESSOR + gpioc_hi_oe_set(mask); +#else + sio_hw->gpio_hi_oe_set = mask; +#endif + } +} + +static inline void gpio_set_dir_in_masked_n(uint n, uint32_t mask) +{ + if (!n) { + gpio_set_dir_in_masked(mask); + } else if (n == 1) { +#if PICO_USE_GPIO_COPROCESSOR + gpioc_hi_oe_clr(mask); +#else + sio_hw->gpio_hi_oe_clr = mask; +#endif + } +} + +static inline void gpio_set_dir_masked_n(uint n, uint32_t mask, uint32_t value) +{ + if (!n) { + gpio_set_dir_masked(mask, value); + } else if (n == 1) { +#if PICO_USE_GPIO_COPROCESSOR + gpioc_hi_oe_xor((gpioc_hi_oe_get() ^ value) & mask); +#else + sio_hw->gpio_oe_togl = (sio_hw->gpio_hi_oe ^ value) & mask; +#endif + } +} + +static inline uint32_t gpio_get_all_n(uint n) +{ + if (!n) { + return gpio_get_all(); + } else if (n == 1) { +#if PICO_USE_GPIO_COPROCESSOR + return gpioc_hi_in_get(); +#else + return sio_hw->gpio_hi_in; +#endif + } + + return 0; +} + +static inline void gpio_toggle_dir_masked_n(uint n, uint32_t mask) +{ + if (!n) { +#if PICO_USE_GPIO_COPROCESSOR + gpioc_lo_oe_xor(mask); +#else + sio_hw->gpio_oe_togl = mask; +#endif + } else if (n == 1) { +#if PICO_USE_GPIO_COPROCESSOR + gpioc_hi_oe_xor(mask); +#else + sio_hw->gpio_hi_oe_togl = mask; +#endif + } +} + static int gpio_rpi_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) { + const int offset = GPIO_RPI_PINS_PER_PORT * PORT_NO(dev); struct gpio_rpi_data *data = dev->data; if (flags == GPIO_DISCONNECTED) { @@ -51,17 +138,15 @@ static int gpio_rpi_configure(const struct device *dev, return 0; } - gpio_set_pulls(pin, - (flags & GPIO_PULL_UP) != 0U, - (flags & GPIO_PULL_DOWN) != 0U); + gpio_set_pulls(pin + offset, (flags & GPIO_PULL_UP) != 0U, (flags & GPIO_PULL_DOWN) != 0U); /* Avoid gpio_init, since that also clears previously set direction/high/low */ - gpio_set_function(pin, GPIO_FUNC_SIO); + gpio_set_function(pin + offset, GPIO_FUNC_SIO); if (flags & GPIO_INPUT) { - gpio_set_dir(pin, GPIO_IN); + gpio_set_dir(pin + offset, GPIO_IN); } else { - gpio_set_input_enabled(pin, false); + gpio_set_input_enabled(pin + offset, false); } if (flags & GPIO_OUTPUT) { @@ -75,21 +160,21 @@ static int gpio_rpi_configure(const struct device *dev, */ if (flags & GPIO_LINE_OPEN_DRAIN) { data->open_drain_mask |= BIT(pin); - gpio_put(pin, 0); - gpio_set_dir(pin, flags & GPIO_OUTPUT_INIT_LOW); + gpio_put(pin + offset, 0); + gpio_set_dir(pin + offset, flags & GPIO_OUTPUT_INIT_LOW); } else { data->open_drain_mask &= ~(BIT(pin)); - gpio_put(pin, 1); - gpio_set_dir(pin, flags & GPIO_OUTPUT_INIT_HIGH); + gpio_put(pin + offset, 1); + gpio_set_dir(pin + offset, flags & GPIO_OUTPUT_INIT_HIGH); } } else { data->single_ended_mask &= ~(BIT(pin)); if (flags & GPIO_OUTPUT_INIT_HIGH) { - gpio_put(pin, 1); + gpio_put(pin + offset, 1); } else if (flags & GPIO_OUTPUT_INIT_LOW) { - gpio_put(pin, 0); + gpio_put(pin + offset, 0); } - gpio_set_dir(pin, GPIO_OUT); + gpio_set_dir(pin + offset, GPIO_OUT); } } @@ -99,20 +184,21 @@ static int gpio_rpi_configure(const struct device *dev, #ifdef CONFIG_GPIO_GET_CONFIG static int gpio_rpi_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *flags) { + const int offset = GPIO_RPI_PINS_PER_PORT * PORT_NO(dev); struct gpio_rpi_data *data = dev->data; *flags = 0; /* RP2xxxx supports Bus Keeper mode where both pull-up and pull-down are enabled. */ - if (gpio_is_pulled_up(pin)) { + if (gpio_is_pulled_up(pin + offset)) { *flags |= GPIO_PULL_UP; } - if (gpio_is_pulled_down(pin)) { + if (gpio_is_pulled_down(pin + offset)) { *flags |= GPIO_PULL_DOWN; } - if (gpio_get_dir(pin)) { - *flags |= gpio_get_out_level(pin) ? GPIO_OUTPUT_HIGH : GPIO_OUTPUT_LOW; + if (gpio_get_dir(pin + offset)) { + *flags |= gpio_get_out_level(pin + offset) ? GPIO_OUTPUT_HIGH : GPIO_OUTPUT_LOW; if (data->single_ended_mask & BIT(pin)) { *flags |= data->open_drain_mask & BIT(pin) ? GPIO_OPEN_DRAIN : GPIO_PUSH_PULL; @@ -127,9 +213,10 @@ static int gpio_rpi_get_config(const struct device *dev, gpio_pin_t pin, gpio_fl } #endif -static int gpio_rpi_port_get_raw(const struct device *dev, uint32_t *value) +static int gpio_rpi_port_get_raw(const struct device *port, uint32_t *value) { - *value = gpio_get_all(); + *value = gpio_get_all_n(PORT_NO(port)); + return 0; } @@ -137,12 +224,16 @@ static int gpio_rpi_port_set_masked_raw(const struct device *port, uint32_t mask, uint32_t value) { struct gpio_rpi_data *data = port->data; + /* First handle push-pull pins: */ - gpio_put_masked(mask & ~data->single_ended_mask, value); + gpio_put_masked_n(PORT_NO(port), mask & ~data->single_ended_mask, value); /* Then handle open-drain pins: */ - gpio_set_dir_masked(mask & data->single_ended_mask & data->open_drain_mask, ~value); + gpio_set_dir_masked_n(PORT_NO(port), mask & data->single_ended_mask & data->open_drain_mask, + ~value); /* Then handle open-source pins: */ - gpio_set_dir_masked(mask & data->single_ended_mask & ~data->open_drain_mask, value); + gpio_set_dir_masked_n(PORT_NO(port), + mask & data->single_ended_mask & ~data->open_drain_mask, value); + return 0; } @@ -150,12 +241,16 @@ static int gpio_rpi_port_set_bits_raw(const struct device *port, uint32_t pins) { struct gpio_rpi_data *data = port->data; + /* First handle push-pull pins: */ - gpio_set_mask(pins & ~data->single_ended_mask); + gpio_set_mask_n(PORT_NO(port), pins & ~data->single_ended_mask); /* Then handle open-drain pins: */ - gpio_set_dir_in_masked(pins & data->single_ended_mask & data->open_drain_mask); + gpio_set_dir_in_masked_n(PORT_NO(port), + pins & data->single_ended_mask & data->open_drain_mask); /* Then handle open-source pins: */ - gpio_set_dir_out_masked(pins & data->single_ended_mask & ~data->open_drain_mask); + gpio_set_dir_out_masked_n(PORT_NO(port), + pins & data->single_ended_mask & ~data->open_drain_mask); + return 0; } @@ -163,12 +258,16 @@ static int gpio_rpi_port_clear_bits_raw(const struct device *port, uint32_t pins) { struct gpio_rpi_data *data = port->data; + /* First handle push-pull pins: */ - gpio_clr_mask(pins & ~data->single_ended_mask); + gpio_clr_mask_n(PORT_NO(port), pins & ~data->single_ended_mask); /* Then handle open-drain pins: */ - gpio_set_dir_out_masked(pins & data->single_ended_mask & data->open_drain_mask); + gpio_set_dir_out_masked_n(PORT_NO(port), + pins & data->single_ended_mask & data->open_drain_mask); /* Then handle open-source pins: */ - gpio_set_dir_in_masked(pins & data->single_ended_mask & ~data->open_drain_mask); + gpio_set_dir_in_masked_n(PORT_NO(port), + pins & data->single_ended_mask & ~data->open_drain_mask); + return 0; } @@ -176,13 +275,12 @@ static int gpio_rpi_port_toggle_bits(const struct device *port, uint32_t pins) { struct gpio_rpi_data *data = port->data; + /* First handle push-pull pins: */ - gpio_xor_mask(pins & ~data->single_ended_mask); + gpio_xor_mask_n(PORT_NO(port), pins & ~data->single_ended_mask); /* Then handle single-ended pins: */ - /* (unfortunately there's no pico-sdk api call that can be used for this, - * but it's possible by accessing the registers directly) - */ - sio_hw->gpio_oe_togl = (pins & data->single_ended_mask); + gpio_toggle_dir_masked_n(PORT_NO(port), pins & data->single_ended_mask); + return 0; } @@ -191,10 +289,10 @@ static int gpio_rpi_pin_interrupt_configure(const struct device *dev, enum gpio_int_mode mode, enum gpio_int_trig trig) { - struct gpio_rpi_data *data = dev->data; + const int offset = GPIO_RPI_PINS_PER_PORT * PORT_NO(dev); uint32_t events = 0; - gpio_set_irq_enabled(pin, ALL_EVENTS, false); + gpio_set_irq_enabled(pin + offset, ALL_EVENTS, false); if (mode != GPIO_INT_DISABLE) { if (mode & GPIO_INT_EDGE) { if (trig & GPIO_INT_LOW_0) { @@ -211,9 +309,9 @@ static int gpio_rpi_pin_interrupt_configure(const struct device *dev, events |= GPIO_IRQ_LEVEL_HIGH; } } - gpio_set_irq_enabled(pin, events, true); + gpio_set_irq_enabled(pin + offset, events, true); } - WRITE_BIT(data->int_enabled_mask, pin, mode != GPIO_INT_DISABLE); + return 0; } @@ -296,6 +394,18 @@ static void gpio_rpi_isr(const struct device *dev) events = (*status_reg >> 4 * (pin % 8)) & ALL_EVENTS; if (events) { gpio_acknowledge_irq(pin, ALL_EVENTS); + +#if GPIO_RPI_HI_AVAILABLE + if (pin >= GPIO_RPI_PINS_PER_PORT) { + const struct gpio_rpi_config *config = dev->config; + struct gpio_rpi_data *high_data = config->high_dev->data; + + gpio_fire_callbacks(&high_data->callbacks, config->high_dev, + BIT(pin - GPIO_RPI_PINS_PER_PORT)); + continue; + } +#endif + gpio_fire_callbacks(&data->callbacks, dev, BIT(pin)); } } @@ -305,31 +415,56 @@ static int gpio_rpi_bank_init(const struct device *dev) { const struct gpio_rpi_config *config = dev->config; - config->bank_config_func(); + if (config->bank_config_func != NULL) { + config->bank_config_func(); + } + return 0; } -#define GPIO_RPI_INIT(idx) \ - static void bank_##idx##_config_func(void) \ - { \ - IRQ_CONNECT(DT_INST_IRQN(idx), DT_INST_IRQ(idx, priority), \ - gpio_rpi_isr, DEVICE_DT_INST_GET(idx), 0); \ - irq_enable(DT_INST_IRQN(idx)); \ - } \ - static const struct gpio_rpi_config gpio_rpi_##idx##_config = { \ - .bank_config_func = bank_##idx##_config_func, \ - .common = \ - { \ - .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(idx), \ - } \ - }; \ - \ - static struct gpio_rpi_data gpio_rpi_##idx##_data; \ - \ - DEVICE_DT_INST_DEFINE(idx, gpio_rpi_bank_init, NULL, \ - &gpio_rpi_##idx##_data, \ - &gpio_rpi_##idx##_config, \ - POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \ - &gpio_rpi_driver_api); +#define GPIO_REG_0U 1 +#define IS_GPIO_RPI_LO_NODE(n) UTIL_CAT(GPIO_REG_, DT_REG_ADDR(n)) + +#define DEVICE_IF_GPIO_RPI_HI_NODE(n) COND_CODE_1(IS_GPIO_RPI_LO_NODE(n), (), (DEVICE_DT_GET(n))) + +#define FIND_GPIO_RPI_HI_DEVICE(n) \ + COND_CODE_1(UTIL_CAT(GPIO_REG_, DT_REG_ADDR(n)), \ + (DT_FOREACH_CHILD(DT_PARENT(n), DEVICE_IF_GPIO_RPI_HI_NODE)), (NULL)) + +#if GPIO_RPI_HI_AVAILABLE +#define GPIO_RPI_INIT_HIGH_DEV(idx) .high_dev = FIND_GPIO_RPI_HI_DEVICE(DT_DRV_INST(idx)), +#else +#define GPIO_RPI_INIT_HIGH_DEV(idx) +#endif + +#define GPIO_RPI_INIT(idx) \ + BUILD_ASSERT(DT_CHILD_NUM(DT_INST_PARENT(idx)) > 0 && \ + DT_CHILD_NUM(DT_INST_PARENT(idx)) <= 2, \ + "raspberrypi,pico-gpio node must have one or two child node."); \ + BUILD_ASSERT(GPIO_RPI_LO_AVAILABLE, \ + "raspberrypi,pico-gpio node must have reg=0 child node."); \ + IF_ENABLED(IS_GPIO_RPI_LO_NODE(DT_DRV_INST(idx)), ( \ + static void bank_##idx##_config_func(void) \ + { \ + IRQ_CONNECT(DT_IRQN(DT_INST_PARENT(idx)), \ + DT_IRQ(DT_INST_PARENT(idx), priority), \ + gpio_rpi_isr, DEVICE_DT_INST_GET(idx), 0); \ + irq_enable(DT_IRQN(DT_INST_PARENT(idx))); \ + } \ + )) \ + static const struct gpio_rpi_config gpio_rpi_##idx##_config = { \ + .common = { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(idx), \ + }, \ + IF_ENABLED(IS_GPIO_RPI_LO_NODE(DT_DRV_INST(idx)), ( \ + .bank_config_func = bank_##idx##_config_func, \ + )) \ + GPIO_RPI_INIT_HIGH_DEV(idx) \ + }; \ + static struct gpio_rpi_data gpio_rpi_##idx##_data; \ + \ + DEVICE_DT_INST_DEFINE(idx, gpio_rpi_bank_init, NULL, &gpio_rpi_##idx##_data, \ + &gpio_rpi_##idx##_config, POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_rpi_driver_api); DT_INST_FOREACH_STATUS_OKAY(GPIO_RPI_INIT) diff --git a/dts/arm/raspberrypi/rpi_pico/rp2040.dtsi b/dts/arm/raspberrypi/rpi_pico/rp2040.dtsi index 6398674e0e02..9c20584c710e 100644 --- a/dts/arm/raspberrypi/rpi_pico/rp2040.dtsi +++ b/dts/arm/raspberrypi/rpi_pico/rp2040.dtsi @@ -238,14 +238,27 @@ "gpin0", "gpin1"; }; - gpio0: gpio@40014000 { + gpio0_map: gpio@40014000 { compatible = "raspberrypi,pico-gpio"; reg = <0x40014000 DT_SIZE_K(4)>; interrupts = <13 RPI_PICO_DEFAULT_IRQ_PRIORITY>; - gpio-controller; + + gpio-map-mask = <0xffffffe0 0xffffffc0>; + gpio-map-pass-thru = <0x1f 0x3f>; + gpio-map = <0x0 0x0 &gpio0 0x0 0x0>; + #gpio-cells = <2>; - status = "disabled"; - ngpios = <30>; + #address-cells = <1>; + #size-cells = <0>; + + gpio0: gpio-port@0 { + compatible = "raspberrypi,pico-gpio-port"; + reg = <0x0>; + status = "disabled"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <30>; + }; }; uart0: uart@40034000 { diff --git a/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi b/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi index 687cafc19aad..4ddf435a7bca 100644 --- a/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi +++ b/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi @@ -235,13 +235,36 @@ "gpin0", "gpin1"; }; - gpio0: gpio@40028000 { + gpio0_map: gpio@40028000 { compatible = "raspberrypi,pico-gpio"; reg = <0x40028000 DT_SIZE_K(4)>; interrupts = <21 RPI_PICO_DEFAULT_IRQ_PRIORITY>; - gpio-controller; + + gpio-map-mask = <0xffffffe0 0xffffffc0>; + gpio-map-pass-thru = <0x1f 0x3f>; + gpio-map = <0x00 0x0 &gpio0 0x0 0x0 + 0x20 0x0 &gpio0_hi 0x0 0x0>; #gpio-cells = <2>; - status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + gpio0: gpio-port@0 { + compatible = "raspberrypi,pico-gpio-port"; + reg = <0x0>; + status = "disabled"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + }; + + gpio0_hi: gpio-port@1 { + compatible = "raspberrypi,pico-gpio-port"; + reg = <0x1>; + status = "disabled"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + }; }; uart0: uart@40070000 { diff --git a/dts/bindings/gpio/raspberrypi,pico-gpio-port.yaml b/dts/bindings/gpio/raspberrypi,pico-gpio-port.yaml new file mode 100644 index 000000000000..fb4c9e4e737f --- /dev/null +++ b/dts/bindings/gpio/raspberrypi,pico-gpio-port.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2021, Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +description: Raspberry Pi Pico GPIO Port + +compatible: "raspberrypi,pico-gpio-port" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/raspberrypi,pico-gpio.yaml b/dts/bindings/gpio/raspberrypi,pico-gpio.yaml index 89afb5084b57..dc441964a7bc 100644 --- a/dts/bindings/gpio/raspberrypi,pico-gpio.yaml +++ b/dts/bindings/gpio/raspberrypi,pico-gpio.yaml @@ -1,19 +1,8 @@ -# Copyright (c) 2021, Yonatan Schachter +# Copyright (c) 2024 TOKITA Hiroshi # SPDX-License-Identifier: Apache-2.0 description: Raspberry Pi Pico GPIO compatible: "raspberrypi,pico-gpio" -include: [gpio-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#gpio-cells": - const: 2 - -gpio-cells: - - pin - - flags +include: [gpio-nexus.yaml, base.yaml] From dd3c9d2867307485cb4e69869df4e3698a29c666 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Mon, 2 Sep 2024 21:54:34 +0900 Subject: [PATCH 2/3] soc: raspberrypi: rp2350: Add initial support for the RP2350B RP2350B is a rich IO variant in the RP2350 series. Signed-off-by: TOKITA Hiroshi --- dts/arm/raspberrypi/rpi_pico/rp2350b.dtsi | 13 +++++++++++++ soc/raspberrypi/rpi_pico/rp2350/Kconfig | 9 +++++++++ soc/raspberrypi/rpi_pico/rp2350/Kconfig.soc | 11 +++++++++++ soc/raspberrypi/rpi_pico/soc.yml | 3 +++ 4 files changed, 36 insertions(+) create mode 100644 dts/arm/raspberrypi/rpi_pico/rp2350b.dtsi diff --git a/dts/arm/raspberrypi/rpi_pico/rp2350b.dtsi b/dts/arm/raspberrypi/rpi_pico/rp2350b.dtsi new file mode 100644 index 000000000000..55b67427237d --- /dev/null +++ b/dts/arm/raspberrypi/rpi_pico/rp2350b.dtsi @@ -0,0 +1,13 @@ +#include + +&gpio0 { + ngpios = <32>; +}; + +&gpio0_hi { + ngpios = <16>; +}; + +&die_temp { + io-channels = <&adc 8>; +}; diff --git a/soc/raspberrypi/rpi_pico/rp2350/Kconfig b/soc/raspberrypi/rpi_pico/rp2350/Kconfig index 2de28a5dd56f..28553021e2cb 100644 --- a/soc/raspberrypi/rpi_pico/rp2350/Kconfig +++ b/soc/raspberrypi/rpi_pico/rp2350/Kconfig @@ -18,6 +18,15 @@ config SOC_RP2350A_M33 select CPU_HAS_ARM_MPU select CPU_HAS_ARM_SAU +config SOC_RP2350B_M33 + select ARM + select ARM_TRUSTZONE_M + select CPU_CORTEX_M_HAS_SYSTICK + select CPU_CORTEX_M_HAS_VTOR + select CPU_CORTEX_M33 + select CPU_HAS_ARM_MPU + select CPU_HAS_ARM_SAU + config RP2_REQUIRES_IMAGE_DEFINITION_BLOCK bool default y diff --git a/soc/raspberrypi/rpi_pico/rp2350/Kconfig.soc b/soc/raspberrypi/rpi_pico/rp2350/Kconfig.soc index 19012bb5648a..069bc56cfbf3 100644 --- a/soc/raspberrypi/rpi_pico/rp2350/Kconfig.soc +++ b/soc/raspberrypi/rpi_pico/rp2350/Kconfig.soc @@ -20,5 +20,16 @@ config SOC_RP2350A_M33 help Use the RP2350A with a Cortex-M33 core in both 'sockets'. +config SOC_RP2350B + bool + select SOC_SERIES_RP2350 + +config SOC_RP2350B_M33 + bool + select SOC_RP2350B + help + Use the RP2350B with a Cortex-M33 core in both 'sockets'. + config SOC default "rp2350a" if SOC_RP2350A + default "rp2350b" if SOC_RP2350B diff --git a/soc/raspberrypi/rpi_pico/soc.yml b/soc/raspberrypi/rpi_pico/soc.yml index 32039c209440..fac2f36cd969 100644 --- a/soc/raspberrypi/rpi_pico/soc.yml +++ b/soc/raspberrypi/rpi_pico/soc.yml @@ -9,3 +9,6 @@ family: - name: rp2350a cpuclusters: - name: m33 + - name: rp2350b + cpuclusters: + - name: m33 From 3977e2a8f597a4153791be4b183d27e5d697c954 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Thu, 22 Aug 2024 20:27:29 +0900 Subject: [PATCH 3/3] boards: pimoroni: pico_plus2: Add Pimoroni Pico Plus2 board Pinoroni Pico Plus2 is an RP2350B based board that has more rich I/O, RAM, and Flash than the original Raspberry Pi Pico2. Signed-off-by: TOKITA Hiroshi --- boards/pimoroni/index.rst | 10 + boards/pimoroni/pico_plus2/Kconfig.defconfig | 9 + boards/pimoroni/pico_plus2/Kconfig.pico_plus2 | 5 + boards/pimoroni/pico_plus2/board.cmake | 14 ++ boards/pimoroni/pico_plus2/board.yml | 6 + .../pico_plus2/doc/img/pico_plus2.webp | Bin 0 -> 29568 bytes boards/pimoroni/pico_plus2/doc/index.rst | 59 ++++++ .../pico_plus2/pico_plus2-pinctrl.dtsi | 51 +++++ boards/pimoroni/pico_plus2/pico_plus2.dtsi | 178 ++++++++++++++++++ .../pico_plus2/pico_plus2_rp2350b_m33.dts | 22 +++ .../pico_plus2/pico_plus2_rp2350b_m33.yaml | 20 ++ .../pico_plus2_rp2350b_m33_defconfig | 14 ++ .../pimoroni/pico_plus2/support/openocd.cfg | 11 ++ dts/bindings/vendor-prefixes.txt | 1 + .../boards/pico_plus2_rp2350b_m33.overlay | 24 +++ samples/drivers/counter/alarm/src/main.c | 4 + .../pwm/boards/pico_plus2_rp2350b_m33.overlay | 15 ++ .../boards/pico_plus2_rp2350b_m33.conf | 1 + .../boards/pico_plus2_rp2350b_m33.overlay | 9 + .../boards/pico_plus2_rp2350b_m33.overlay | 33 ++++ .../boards/pico_plus2_rp2350b_m33.overlay | 9 + .../boards/pico_plus2_rp2350b_m33.overlay | 8 + .../boards/pico_plus2_rp2350b_m33.conf | 1 + .../boards/pico_plus2_rp2350b_m33.overlay | 8 + .../boards/pico_plus2_rp2350b_m33.conf | 1 + .../spi/spi_loopback/socs/rp2040.overlay | 7 + .../spi/spi_loopback/socs/rp2350b_m33.overlay | 7 + tests/drivers/spi/spi_loopback/testcase.yaml | 20 +- 28 files changed, 542 insertions(+), 5 deletions(-) create mode 100644 boards/pimoroni/index.rst create mode 100644 boards/pimoroni/pico_plus2/Kconfig.defconfig create mode 100644 boards/pimoroni/pico_plus2/Kconfig.pico_plus2 create mode 100644 boards/pimoroni/pico_plus2/board.cmake create mode 100644 boards/pimoroni/pico_plus2/board.yml create mode 100644 boards/pimoroni/pico_plus2/doc/img/pico_plus2.webp create mode 100644 boards/pimoroni/pico_plus2/doc/index.rst create mode 100644 boards/pimoroni/pico_plus2/pico_plus2-pinctrl.dtsi create mode 100644 boards/pimoroni/pico_plus2/pico_plus2.dtsi create mode 100644 boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33.dts create mode 100644 boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33.yaml create mode 100644 boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33_defconfig create mode 100644 boards/pimoroni/pico_plus2/support/openocd.cfg create mode 100644 samples/drivers/adc/adc_dt/boards/pico_plus2_rp2350b_m33.overlay create mode 100644 samples/drivers/led/pwm/boards/pico_plus2_rp2350b_m33.overlay create mode 100644 samples/sensor/die_temp_polling/boards/pico_plus2_rp2350b_m33.conf create mode 100644 samples/sensor/die_temp_polling/boards/pico_plus2_rp2350b_m33.overlay create mode 100644 tests/drivers/adc/adc_api/boards/pico_plus2_rp2350b_m33.overlay create mode 100644 tests/drivers/dma/loop_transfer/boards/pico_plus2_rp2350b_m33.overlay create mode 100644 tests/drivers/gpio/gpio_api_1pin/boards/pico_plus2_rp2350b_m33.overlay create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/pico_plus2_rp2350b_m33.conf create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/pico_plus2_rp2350b_m33.overlay create mode 100644 tests/drivers/spi/spi_loopback/boards/pico_plus2_rp2350b_m33.conf create mode 100644 tests/drivers/spi/spi_loopback/socs/rp2040.overlay create mode 100644 tests/drivers/spi/spi_loopback/socs/rp2350b_m33.overlay diff --git a/boards/pimoroni/index.rst b/boards/pimoroni/index.rst new file mode 100644 index 000000000000..3867af38c3ca --- /dev/null +++ b/boards/pimoroni/index.rst @@ -0,0 +1,10 @@ +.. _boards-pimoroni: + +Pimoroni Ltd. +############# + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/boards/pimoroni/pico_plus2/Kconfig.defconfig b/boards/pimoroni/pico_plus2/Kconfig.defconfig new file mode 100644 index 000000000000..35cdf9270546 --- /dev/null +++ b/boards/pimoroni/pico_plus2/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2024 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_PICO_PLUS2 + +config USB_SELF_POWERED + default n + +endif # BOARD_PICO_PLUS2 diff --git a/boards/pimoroni/pico_plus2/Kconfig.pico_plus2 b/boards/pimoroni/pico_plus2/Kconfig.pico_plus2 new file mode 100644 index 000000000000..cd30fda60aea --- /dev/null +++ b/boards/pimoroni/pico_plus2/Kconfig.pico_plus2 @@ -0,0 +1,5 @@ +# Copyright (c) 2024 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_PICO_PLUS2 + select SOC_RP2350B_M33 if BOARD_PICO_PLUS2_RP2350B_M33 diff --git a/boards/pimoroni/pico_plus2/board.cmake b/boards/pimoroni/pico_plus2/board.cmake new file mode 100644 index 000000000000..6de42450d892 --- /dev/null +++ b/boards/pimoroni/pico_plus2/board.cmake @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/rp2350.cfg]") + +# The adapter speed is expected to be set by interface configuration. +# The Raspberry Pi's OpenOCD fork doesn't, so match their documentation at +# https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html#debugging-with-swd +board_runner_args(openocd --cmd-pre-init "set_adapter_speed_if_not_set 5000") + +board_runner_args(uf2 "--board-id=RP2350") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/uf2.board.cmake) diff --git a/boards/pimoroni/pico_plus2/board.yml b/boards/pimoroni/pico_plus2/board.yml new file mode 100644 index 000000000000..71acca8e80e8 --- /dev/null +++ b/boards/pimoroni/pico_plus2/board.yml @@ -0,0 +1,6 @@ +board: + name: pico_plus2 + full_name: Pimoroni Pico Plus2 + vendor: pimoroni + socs: + - name: rp2350b diff --git a/boards/pimoroni/pico_plus2/doc/img/pico_plus2.webp b/boards/pimoroni/pico_plus2/doc/img/pico_plus2.webp new file mode 100644 index 0000000000000000000000000000000000000000..4d4967b6a58d90b2322826e8e29a95b8fc91ba2c GIT binary patch literal 29568 zcmb5UQ;=xevaVaUZQHhO+qP}nwr$%OW!rYuDBEY=6Fc^r>*3yr+n@SNkCr`K=AU1- zmP(RhVjj)_0P3Pb3Tg@*1UCP?J5U4V0#e-o-2n0B$`#5~QB;%`w_s*8AV-?p9k?}u zi|1^7;;-Mn@4M3a;~H%J*w^~m|CIJO+Ixp-U6U8)XZWN3ybj~D_LKimzlyKt)B6T~ zn_k9ms2}_Wy!3yE2mG@6?>s}loPF`W;^9xz@8*xZ2Y<8w>^5ReL2rox1PRJbw~ zCIqCym8mcxAQdi8h6w?waAhit3rK}4Q(;0tDqNZh69Q7<{=a>aVnBGwzDIuX(cHOt zgQx$Q*>4&^w1tTnN9_87XL0>si@@#(NhNPw1P;*>OP%g+<6#78#?C3G-!M@iT}#IB z1?NkmluTd1#I4H(LhLQB&YghtE!e~38#w7fMgPlK;Kz@IknvN3LFi7$>LNZ*NiWyX z#t6`9YoX}LSXkz$=F+?DEE}YStFD;D!Tu5gy2pK&qvyl`KhH_K8X{i24&c6DNHf&I67+e z#Ho?qmcTFP^JAz9chGLhT45eSoD&R9sKu^%xLTV(;uB!*BhUP7>S8bp} zg<_jL8@Ptd!M~j;!uIyrx$;T@k6+ArNmx_J=fTBsU!{%N{G=dh#SDLJ5=q|d<;3_9 z8+0XwT6?W5bIsUU3$p%(V|T{ADNcQR;(&L+p*PU` z?+CFM*XXNBh-tXWAqj=Rim?dj<|uzrwpy!p#Of2G>WEWdS3H5gr9`SX-U{X6)geMJAwQUS-3bH^3Au=FRIsl5$bFo!8fkS`Rzg1#&+?N@aD z-;@t~7rF>7(CO}<`l#ddz!#%Zaf+MK7ygpUd&Sz|zN{ootH~q>vyJ(%FO$$jgJ8KE zei$n$?Mn4(xac9AT@EVCpd^=_tHf zVBO5qB424y{ewOf$Oxtfz&F?OJ?9ZgEIJ?tp0yV;ulg%OqXninBAmGL;(HAKmCZsx zv>@M;5vhu7<5C0bYFz*XR)sI2TG-UW$Vvc*TukIy&eS8s@9G5!x4BM2uJHb=WcWtgAv@SJp=C8ade=D5wh{KfiXAFv-G zzuNcOO$%a>E)Gf@FwWHnIpcB5BLnXFB(BHN1LXdoT%DhnNnh-Oz5t0nsObN$IQ9dt zg{u(pEtfjlt51R5U2q{2ojxN%#IXobJ6JqUZ~^CLsP0cT*PybiI_$1P5NtmjhoQ)b zYzw7Hc%Hr3llQ1**MDbBblTe;|^7&LF5+N((*4AHb-g%5z9z24iQO= zpVllacO&p$wS^56-U!eb>|cq1pnpNPCG9 z8T#0Y=sTm9KEg|Rj3juteEIj|OdAh2Kd9(Gbq)Xb)TnY~nH5&Rc>$#pVi@ry?*3kX z_Wt151Q{=wx0R^s3+yu708Zh~>1n>1{-t|Z&@m@SYqQA}>}x-oO?ROG2wTpjSZx7R zAoA@byERKWFZ;2YaV{sYB>OIhHY4UqZ?E)!J@-##4f`PG+OgT=4^1c$sbaOKGXz#k z+vL75)8&?-@E753n1*(LWg6kDrl!&f)46|<@Cer&eiE;s4a|vS6d3 zMuUDPzZ1@gW^9G5@9lMjUCuDPrA~MSPZsDS7pClB($# z@fufU#1V}V#_XvN6>{Fo#8-yYsdBds=7J1rol2JHJAu$ir6g*^Z!mHGF0VbHthk7f zpYwNaq_E_hcgQb$KDPVBe`801hf@3_l;Tzn3{y+RD!$AB3t8*b4LUx8sXcoDP8W{Q z%3&-H5K3M|k&{{}BQ{hj>of-eCblRL+V5#4zY(ykmK{s0>$oHRj?EaaovG&s;(s*M zR2cu)PKX*%!{p?!y6I+$f93+DoBi{V*Fb)84?#H)z%beFr#v~KUwgiGSS?TLaXbkx znnqU_cZMfzn0%$QX8}Ma<4<-E)t%Mb*Q5hr!2d|)|D_{{F53pJ!w>V%@N_BLCNj9J zWnzAuV?_@XamRiLdWt7ew##=4FBM63tKvUYa$QdOnUEGznHe|&w34aGa}MLSV%h>M zN#!t^7rX6dYbDGH%C<-WO^Nd>(OVS{b(1b=b*?)X%-Ww+$WhF@|+(WVyf ze8tVhpZ-2$Wl~TDxHfuO%E|bP`q(e~XKlp4ljZ1xivO}4z+KTw?0O3fH%>%ZGxRZn zIntT_!yJc5Jd5J^4lFd{(egqfym8lPki7Pfs&voKJPlk;r^#g%q-pP2@tW-G)11b) zxXI$L*Z3mSyZ6Sw0X2D`n z~f)@2mP%r2zTeKr1_Iq=} z3H#LqaZ?(LH~+unoDEx#uTYNc6u(3b>fw+=`bxfq4TF<)tL2Bn!xM$WyIHEvB7)H_ zvg86*^A3yI;e$tD5fV=4a!(J!4Xqx?9JMz8x#sVy3Z-s+Vp7*GvBygxQ%PikUWDV_ zl6h_@V#{XUii!-pjAqocxYd8)KKS=Z=8H)Q!hT2o^p(c2+G;>73B}HMQOm0_+QIn8McF>fOoZ&-PHun59 zus03tqqYrWPB-S2K7b90om2Z4mX_~d)CS)h8S;IWc~>|^*d1&@EbRe)XA`&7Mwx8G z1lJ}%k%YHx2urLLX%yU=@kP5gN7=t%Tf3dkT;S1;1iSwm{(rKW6%734A(wexb6FgxS5vfo?^QRVxG_ zzUQ?N|Ekkcs8>60FYmSKB*@3tE1MYTrh=qJd0vMv^W=@cyh!q%JN(sQ6O=E`{-Q@xE z{PXmG)3z)1!d_#nxiGBxE^#rM+|Bo5^aq&gy}qv&u!E@WtRs_M3pDzqhgrR;zauF6 z8Bf98W#}`A{e<%Pl=h7x!FkjM0I(Kf{a!S6=_BV>X1S*2a;H=v=qxqbe>GnIp9SVz z4YwC-h7~9E-6x*L*H#c$C`?Jvqa$I+cytrlDwPmkgXC9?i-_>;lE zjjHEZ)HiBK0;HE#Y!p>Wn!O0KKh5(bq(j#uN;s<1FLFeha?Tb}uZeC(@hevU)sKd# z$W!S7nj6|`ZHfl<<@?Hk54w&<*&2<2*O@DH{n2yhhPNmCz($occz2txkqog*^3)Y) z5d$T*o@9!QNRwr_UmF0o!`bm>Nj8R5j4WvXJT1HR0l}p?x^`YJkZ~r9Sa_lT7Y!JH zK}-s%=2uyD8yFK|8(|3~2ar9dd7t~@<%V#y1+ZXpH+itfK(i(fgd@u3MB{^@rK}~6 zulvNikZsNLH#>h1f}pJ$W6cCPp=Yv3qU%j=y`@^G?%OQ=FL3`q zRRlaxVrFTxe!P70hz}L3fs9C^bc8lxl(ULnURPSb$cG*)+1Wv@dz!Pg$Mw#`G4To~Ex8@nrH;;O}1(c&mZ0f#6kDxwgdR78~7 z{F&glx2V7wh0XUbH-!M6b885izGzSij@_T;>imZ6AwwJAl%xgXUn|p zp{0^k=}f7_?JZc~!xj-(<4qG7U~VOBZ79OKT=M66>x4F?llk077wD~phJgNjhduD5 zJSg)>8*Uko2wbGI(u$Cz%N_b63Mw%Yj9%WK8WGYlKI%11|T%c>ig>xM4T{7zpLfr?WyGe=KteL zN4?%&MD_Zrg5V0Ean9CKHM{@liVQtlCiq)CQ3RHS`Qg=?(nDDqMB{Lgx{^(Pc6W={m)h3E`zR*|=^GBhwEr znCe&CrOB}|aXp{ZkcJ6kRu8|q;0Vc)uPk!y;@S4Y)qXc}q%VgNXvytx-wuYZn4Upl zum~Z{dkGSAThhwBZBf&EJ=c!S3jN8kkmF22wKuKP<7^SB7s2R_Db+{==2f6iN5ds3 zu58Rldip38%&dN*TjkL$#{gLjxtC}$HW5#`%31W_X({dR2dDAysqa4grd?Jx%Ujgh z82}zq)FAhO-($;r55Nt2ds~*v7DX!#REze#mVdxl+TqxgzDDOBR`mS;*Y)+f1 zXLJ>5Cc)+=s})=2n8(dyokM2NTDW3{y9c82Z47(3s(42n7#q{Wk+6+_e6$SfLB2l2qJMcVVp0aav6fn5t1znZO&KpJcCrM0q8k-yqd3Oq0mTf zlar%ol~e-Wt`5M$1PGMk`4_-!I0)=sW`c6zPpQM78L01*dxS^XM$BrhKc6>C-H4F% zN5JQ?CX;6(w<*bBzt5Gcy@t%bL>t%iCJW>2Eeg3#-2=Nwf-L-r1F8P~h|Di&_tS9N zyZ7hB!JqoLGV@$BvpTgr>k(b;DUF5j?n%cD$DO2`Rh&aO(UCFRA(ZM$#G+PDAhYS+ zW1nGS<+4t}2cR(G;klxS^fI($3L-%2(h?cI1yQ*N5fj! z90|Z0Q5Qg2T*-0Xy#0Q6!PSOYJ?cwis8R42C46u|{rFGI(JbwrKI8l9vEzSFq@Cqv zUH0_rS|u>91OfpJV)*!qS)ua7!6Q^PC$v!*xmG2*oSNa|2|G%}s~A*(m4;hd!9;KH zKyTl~_ekmhJPtRPv$YQ3@~38jK4Anr>81hBjYce$`N-Qjqr2MsCRQq&@FsEnU=Di% z?AaeKsMIulNg=lPq~`c&IqQf|&^eRVTsFo2A+~K`T0CPrcI9%l0X65KHt(ON7ocFe zvmj53Tj$LXO#j5|aDP5cq~rZX1WVKt0CUayU(+Z}fIk#|hU8Ssk0m(;ni-vyh#OsF zj?4;M6_%n6%Delwe#vf8c8B}GDa=_hmZ4$2S#2eMNEBXD2J~#+H7fP(V)V{|TIWy- z&tuppqGfq{^ax(N*)!{fQ6vKy?!NVuaAP1<h8d}8frp>KZ$i$2=glg-~H+=xeWHtZj?OxSKEl$`024oZ9b3-Dg z)1sCjmkdxf&d71Rh`$~1`h9ij?Pg(rrCSuV51GY-XA5Q8I7v~%X7&^~9}+0V`AF`u zr<&bkDPH^c1#t1&;1uG1D@}0e$7Z>3HT4i*YLZxM$%aSU(v*I;Io4mV*jS>7aT0cN z?$AI`>+qIhM`8cXmQ4x!_Ch+^oS*YUTEwi8SSpmWzYgvPuzwFtw7slvcVHnvU;}Y# zT(q!0k*5s(oSlfZqXvlAKIVub%!|#w*Qk!!tb#y>8d494Nfj>Q9BzRG08BB#ym>$v zqn7k|^j7hAxQW)Jsxt#{{MuRPaB`aCWvsp+b)^t(lPS^I?p6TR=p)mVQZ^>=T<{dd z(~Q4fWY?zmg^uytuK_IqZfY%iQOPu&fTb-7+WAQ*Ua{GvQZ>f-YfUWls zPI@@64Jzb_-SdH?FW0#U1)U3odW>R_w4&F5 zwbfiFuy&$Jyc``C3;da!rIqFlZBaEpkoe_mlwei+Ng|kq9k`cg$%%rcpmyqdNmV-5JBk8OeOK%0;qlII@L@*M7&nd7$KtAD&?wGFE79pzVO zbrIn_pW(Bin$P>IBs~431)G*fHU>Rm-=Lx zL$!|?%W04T?M7WqG(=R^oiSs8i>gU@Sy1=ZS_-%DQ>bLwPaF+I52$ZXfERh*@@5k@EGm z`en_2jSP|nRq*2r;-$*zmR&!jLoC|Dh`C0!do|i|1FG^wyk+2%vWF<_(}Yaq6Li-| zR~!6WTlV>PpBXe_0O2*h>?x1=#0>6;vX_|CGPJh|DwaMj1PmBR_U~;Je@g3Qtl3uZ z9AmKX5&MGO3VsxG8XnG>eoR&5Fl)B(k&5|nE}4XFL0G4pz;bS9=m5aj%)@*Y zq+e9zOOKwSdNZ4(D( zUFOJlTMF0`-b``u)6$!DkI(fK0x0Z`R321BiN z%)fCm$UxBFKWZ6@b+dSF&O^nXqM{c-8n!e>iKhWf3Q*OZ zM|&2&!t77l^IKXF8G*5d$WpdJ9o<5N3Ik2t{iunv*Kb-H`-_X*ACIzG_P>8EQl zXw}KdeBCJ?ogj~b;ml_Ju55$*U;GWtj(Sv%MusQW$Oj*nN;5-m#b92E*w-8W7L?o( z%CL+s{|Z!AmQ(EZ9sBnka4!G=*$&PIUISZq%H&Ge0@IuV9>b?AkCmD=)7Nnet}gl( zxc3>iYRqR@!%CwvZYxFrwp!Z$5o`E~I)nU3$9r*6Y7mF9XxY4Q85)2=8hJ4Xp~meP zY<2=r+iApUfD?dC_@g}{d79EXYxCUJ$ne#ql z=6SG(A5q>s)_C_%`~){2XoSP?VIEfKt|2`{$mNam!SN##=p2%uUB0LwQ=aFn(9>AR z8(8QUyYboM7^REH3ILzrb~e7K8fTWj-^I& zPGRA>VsSPT?YrK8qSpGBmlK(Xw~ZTAjI333qMqjTi`L*Hya2~u;%Gerqz%;^kPfAP zbUzDUe1Fy|s5%7t+_UAN{5r9*CZTocTqD~EC9~WHz%*othhOLs5X@!p8fp+zCLS;o zXT?CEo6Vt=6=012_{IIFyE?CxDe#@@*}`|uk^UC;I38>p0pk$YSM8H%L#*313Z1ls z2%svA)LL@vY;MA1>sT8T>b(l!)Vc=?yy5pz-LVs-5<0{UruPdS5{^nd{vu8`AC&Q( z*_Y042Dcg*wgs)ETW@w(oOnTB84YJ^nzCYTg>4Q8R7yK;&Oiy<#~ zv4mTRV&cl9|6`kBs)|H`#UC@D*mL)J2ea0umdw&qr0LUj!>;H zyoXGi4K<|B^|v_)CqqssLD7}s*2myr#Q84;n8-AP2(q+Uot672#Z4WbC|6M6aquMegB4I$bPrr|wH-CIn!@~=o zo4s1IPIP5sn(65>?{oP03B7tn>t1qg#@8g<4sg$TR6IKv#VMi87W%WL&p~ZHV$>dP*|_=~WXIRlOP|F20=|e1rmS zyxZO#W7>Avc;ZsK!0bzN2L&#C^Zf~}`h}8~8Mb;_+gUo78FZ(XhBz*)4Gr9k3J$?s z7u7vBLp_0Ueo}sOlHefOIBDG?kgv`2=)5->37O_Y>j5zcch>4j-m2|X^y?$PHd$!# z4H@~eLo;WH=NwLZi8AzO@y2qWmQ4^0ESCCL5W7PLcO8#2zw>YCD1D7FQW=;nAc5DU zh(hq4F$J9W>jAOF^Wqxl$}vr3A{&X_Hxf$#Aenn3S=-qR4z)cpH9V!95mS{Nb7VG(Z;cK;_os8&EB<6+Z=~7XU0Q%6f?Fka9Ezt4!0eTJ&tXXm?>Q@)$VArgo@&aN zI2$;n-mx{Er~_K(O7y@5QJ&ar8z_)`{XRkeL=OK`rJ-iN;a%oDko}s_w1or8P$XRG zz=D-uP(>(}!nundn-y4AkR%-l0rmC$!rUCb6j5IA(^L4zQ8KU{>s?#Zv7*y9Y*pws zPqbK(`zc(BG&_urn9@XxjF)r^QS*;M#J25nsB@B2U&Cb*BvctAm8pFkNGYD zehNkNVv;joBhAZf_Z_dLyrLyoGXf0!G5z z7ml(U&1?P{ZEA4Z8*m*mHfln54+FNWLKgd%Z5U9)u-if3!H#NH$t(h-n`@FxTcDaA zBf>$S{r4kDz|D1l1hO%IJtWuFs-j08>vSa@kw16Sv#G;A-wSH4GIK*TWdjyGKXhn z`M8Q4O~oON;!oHund*2yLRR%glE%0{8_(Q)+F!w9)<`@rn-PbEW+NN5D=@d10rH!~ z2s%?}22*+LY$FqHdkwS8f`m-Y7oBT+YVF|cG}4pY2h#UvWVydCKm*+D2Vj7|QBvB| z0GP*e8~{0n5n=)5@B5wfwAGM~U(M}e?@!WMG5h3Rt?yfriNI0UzI@Rt$LBRy%Kr`Q$GkC_i~=I5wEERC~@Cy%f;bUPvpAhAh`s;dvdj-v^Jdo z9EpdXhh{(>AM^Wdyts0JaHSV{rJGMhi6iW*=-6^~7^n{H_0bgkJrMA) zVIm1Ag3OZR=I7f>ti;P*7n{wGhzX#Ml;Mz@*ZF$dhj2+pk-)U(S`iX8g=b=bJR(5k zV;&jIX0!wWwFq3`uz1WDuX>{gF-+$Xo|?E4bZ@K!+qrf{@(Q(u(URt@?Di!?OasO{ zA+28YhB9R#zcX%+YZ#Iy>A+*D8ca9Ht`Qaiu)QB){kQUD^ zckK5c_=wZTq)rayFB;;4&qdAOU%dR;0d|Oqw>ZeY*|egpM3wG9M*Z<-yLdA(rW*K@ zO<*qK7%SuZ7`2uJRey}R%Pp$NRVUpCfcBSS(xO^nd)C)Ef+W*@h*N_Bz!wVo0D< zveS!UoZ~pQ0Og+25M?PUTz=qK?$8t`@L^Yy@uGSzYdp(%pqvB(oKH_bt=Ch;6zZ(| zy>jIjyYwTBA_Xwjkk^&bl5)KiSkTc)>)yY z*dPcu5-%ft<`ww&6fouss<6Iu|1|Dz===6;ZkX_MYp1GVuo2GzN`4?1xb#wqK)GJ1 znIe8H{zZf_3}Df-$-=A!|Mj&`Dxc%^(cI*xnRi+6GN-PGHwKN}&IQR%G zf!1J>+zOSAHSkyX6NW&#VV=(v@UIODh9HC$MrZU1P;oHXiuk`(;IE?`@Vu9#c3+c2 zWQ@O#U!UCsCoJpKY8N*yHx$#f=el*nMr5$8;vPBE^37vKW*}4``JBLi&7f3MSn+;YXWbt0RfER*Ai%oEJzdvQN01jN3YKv^c zqQyrYfGx+!mh)L0yD0+N1xz(Z>Vr6M?nIfjP}qcsLGMq?yta%$9-{4SRPG5O>iPjk zi#ag)A$37%2lXM;UznWyR8{drvWU1&i>CA`MszB#6^TQzdsN~E8D1pFpQb~I(N>&? zebzDc4AUynW5JuOMp7d)QbaRccme7Cya6_W%X#`?)w5|Td#bGp*A_tG-NXL&*o0!H z!o#HdzvSFm;|z(QXKeNm<1C(KPjb}Li}|EGQAjKACw;8v3jOmXE;Ck*dpRR+VX08fn+iPC@TQMjvtVrRm~kvw}yD$*PmM(mgLU4ct}0-|@UfR?o1; zmoCG{t~@MXvLAGgA+uV=W<>JB1+xw2g|p-gA0wK>Qqz*x+3^M?uVG+h`(Wt{nMB`? zU5>QLL6IP+RV0tzP+oCe$dnkd-{aLtGZWDrt@959!U+c!Ni~TTnDK+ell1XUQU2@wai6^5q8EC*%A>^TlETOeu0ZSW{tdPciLW4i2M)C?q~dVQ+j1%^~hycI}l&8yu;%u&ugsg+)BJu zi(&R5cUUp}C$mK2kp^T+aQcL(emzFrdc{5vU80tA1x#i;V#>0EC+u~aamITW4)0uN zRT#Suqf4E%Av~PwE=0%Ad*KpPa4L9~{_xdv>wA3N4S0Gd9(3PLgvjgXclqN3IUO2Tp8qK^~aMX5ZwM?L>Feu8N0;Hgd<;jk!5_ zQ#;sN2qsTQhxeF>I{;v%)?bYaeSG|aMFpc5Lfiw&cV6+(ZIM*Ln8eoObWnss z9Var2hqDB7%X*@&kLtqIebB%v?P#FaH~9_NuN_Mwc8aGCD`(!{7{@A=RN7#OATSnu zTrZ7go;`$GgIg$%DnmJ!hJR0s}=m^^5q{p5Ia*RVGGdpVjSI*0>QZSBiGoSu0| z*a5o^)v1YiYttsx`!HwN-p~10I_7y*^kuYyWo>)E zy{~4B=+fgeI=y$dBr$iPyAotii=SQ8Lmzj)JPyBotS~hx&r3N7TC%52?{W|$cW`*N zk}%GzA(GxBI?)*yIp<3Gn5XTAkKrK+AwDWZ1#lmDSo7h~q z5?c?t2yaRA&OCbx1$1_}l|yg!x`Y&lbS$M;6`igoIKazxv{J1xlEw+xp2+O2k;C{f zGm?pFTv1snu_1u*7lr+_osPM`%VZ@uBA^~Izzj!)zlcp6Lj~KS`O$dGl#TC=js z(V~-!kBYx$N(=W~c8~^Th48WDahy62%4=Jd1E#6n#SQbzrnkksjk4%eDAv%D?orQH~2h z%&D7??*Y9+nJ8>ugSX%30L9H2HUXM>)@NN_b%yrJp>-y#z*&!n*)O7eN6BZvj|i)(M!FC!&E>dZgNiKP))9D(Mgrc&@4l?YlY(8z-)rv zel&Ef01Ms1plz~`SAbit*+j@eyV~0ya6}vHq?wm|&RI_!c(ey#FSS_j2^?iv)O#_K z3fH_ET*!=mOY=U@3!-NU^}jUT(&&-Pd88e6Nn0mXPimp>4ctnLZ#AVv>w%c%lEdb~ zgekxTWp-Wg(YR2AOtYyTRK`~tBWYA<25a+FgjyK<%ij7`lzTlK$gCc`{4F)BhiQjO zk)gR#WvDFHQi0i6_f2_)jOiiZlw&Udz$!Q>^EIN8rulULPEqL~eEd3>bcYHP4JqW9 z97%H6HtLCEnTzRJBO1Dyoy1?TKJdI1oy;8ATP57~U#8t~u&mzv7AGxw&Ddi}8wsj4 zElk~=9orP%{om)mh5bLiw7Ld0NZviE@%MNRQ8fevP- zT#_Sla!@OJ;_^QIQOr|5^!|^?=VwWj4iiAZXz^B zuy+wtbJDLJ9iQ?o^t2+j@0HQujgAE5dMl+d(m;Quz`m8qmg1*JQc8q}+d8+9ezadl zZ5l@$#UkTW9Op=}M+4=6mDq3-knEgp2jo*KB+;zy&9vSg0$fa$nabgKjQp$FZRP6Qv0iCs>U99%A1AN%QFS!z0T z0K76cH<~0W5!bu%#g(H^_E5&WRRmiZoSLjn#A&b5w@z{yAvD~OoNwCWYj?8Ke;*hG zPWIZyQXhZ#uYof&0xoIo*E^ri{!+j43OP44iEjT{_zenxbkARCQvHGbQC3Fte7$E? z7)(}GEfrM*G{BB~L#MuzGP%d@>%fvZ6*V3x^g>r#B=bn9YRQ6Zo?c9(zku}UL-6h* zQ?U(j-@+*RBsE_fj^K$TWwiA8MfbC27!SiYH?DuMr&cD(=%q6t;R&<(6og{Jzho(D2Rd}BJZgcSE9kRpnm|?!t(1Ll{2u3#zW#z@Mb(gtf=F2Hw;@x39>Z!{w8b9*a=cq8B zmWuu8J=2p zyy38t-e=tk4feMg-@Cbpx(m?Ml(E#nR`PjDxk{Oy!5|f-Cl1KTurq!#!QSaXp*oE$ zRZnr_P0H(ZqMyhtW}k+{A?|)o&hlvKKvmkxE=H=OV6q1y?HkElaUcAEjaoS=s)ES* zo*xUOcQc*f;5HTx+Vr%DT=P_%@zZ!}*NMRl2 z)?E)J407WGp9CmRB=3ao$@@ov^jU=!><<#Rb#;vp{{E2kW~;J$nQ_O__nKo#v*)J9 zRv9rYqe$y0PJO?ceBRg zhA7dD&x1sqlsh30M%4jz)-0LpCkzxtNsPDUqjt5FmcU=}scR?){fvHOPnJ{nZQlLO z@V|z}MS;#oo(snwRcz+(Z%RFZh&e?V_;5v$V~ig=D@&qZ_^{_txS?#O8jS5!llURX zNub_Vm|GU3%5mBQyT#CkLx8^LVUHc|*Qbl+%nEa_R@iVXIQ2}x*obOLwW`kH?g_GK zTXHcQ_}pr?GwZD=#v^y3zL}3N!TL}aV|y3IpPTuFmXISeaxQ#fWGpACQ$eo7sVEmI zFN9ve-+gbI0~xCTVj!K5A%rX)RVrqL>~b)VC&bpH>OOC3 zqDhTMC*&4}G%m;f765&BnI4CMsgeU&FSi@Sq)1o;zqC(!X$p=oe0pB))6- zi%OVam#aB~lXAOR#HSa9uoKzv!_U2+T(S|ZvL|yMt%qffU9rGW`BHxr2Gr~EFf6Pz z){TutF6R=%={WWHzM30TBc6^stbWArTQK75b>`|w>_l^=$d^49saHwvlrV~r#0ev9 zIKjZ)HRiQ{T&lnS1f1u-=9^aCug1mEMprbR0xrT;zFKfr_^=mkn1oY zNdv3Bx}nd90dFZCy}DqryP39C5KhahBM3U4^G)hFtM#);lXMjs7S+9Nr#qp62B&@O zTO%T~Mg!d8L{GjM(oLJex!hHrD*6&q!=I21VWS&RJHhfY_d%=P3RPRYv=kISyk7CZ zBbcR)`Vb>P75~`^>3VQ5FcJBD6Sy)w(Hi&`5v-=68g0ukN_?hhn+}ec2Z?^D=Z9jC-XKZ7BuLtsye2{z`n@hZ2 zCm)h_VZIiTqN=_~L|y*dG;zl3d?y)5fBu2JPzbZ&+{I*xc2vqBi~!@L@8=Ky_=K^lq z>nDk*VtrmU%@l7V&t@^~eb6JZkw^XES$!4~R z=XfMaehJ^hi*~Td9up|zXUb3tIw2&l9@1(eGIXUBZPib|eSXKJ#zdbY-yc%S0PO4h z5`i=j0ZJ?+a0q9R@H!An5hU;sL<~sjBH=xE#+@6TYF~eE;e}+0nxLAr2LkerwH_7- zkSVYJH%nV5K=%(o7t2$2a{$PBov;q(mi*k=732azb>jx|KEQOS_I;Z@^KnfN4X~&w z&7;wF=rzZ6UWd&qXo~Szjr-JhpDsOw85#ixKTe{fqV51QXlR*waN` zk5xNkl?)(S&O{H=C_secm6C6cpY&%to~ajqod+rP>+98h2U}IxZjPb)$G#D$Xp$V5 z_FeJ4HW~+%yK9I+pjSqCLQT5Ab>51ZJbY*%Ek#o?=qg9Qz7o}WO33E(Qv=Q@2Idfx zG@le<{4l9Y@colNgu79fLYJ7^^NGxj%v~>D)>a1X37T8rdD#uV#G`E|Cr2t8YQXwu z3QW{Rm*33bE|zD+Z@)>vSL-25N$a|+WTjtcI6#%Xm)V=nMS9p%?BjsfCXy5O@1ye< zCb}Q29C6Wk53_npNjTEuly&63)k1qtpxUFul21Ec(m&(DhNqs5^PF+~zc^>gixh7W z9;H(~mW{ra&VypgP;8koFiCm(8dL)h-H4wB1IQ$v_8Yoo)r$MA$LxptO`AeQHlT2# zD2OR88M1G4XWgrgHn_+Q`@$Slh+u3(t=hg41pwl9 zaTzkCY^cFGyJ^I=myj<+oRN&2!xw&0V5!6;kzZ?K-xNkgu>_T}iiJp_{}S%w{8=>9 zpRTsZ4ZKDG0LUeoPL6!%8}1jOc8alAM~zCvXGeXYDD}GQx^l1R$fC3p?@>Wq{?20N z(Sid}^=7`Ir!4%Ch}Z9B*XhE%$oe_im(zT3!s;cjA=>AfuYe-e^V6v~gNEZqzTpVO zTFDo|=y1MWS{B}`;oD_$#rrWyKm(7=g*7WlH%9R_B`C}tOW`zhy)15d=bSm8(Ewa5 z)?R;kQfEw0T59l#T^)rZA4Y09IQAM|0_3*v&h`3U6fOYDGy0)-zTn}lRV&yp70$*Fv~^h{@zegTtr*On_cHe z!tzRmpMQn4*zdK0@G$$7P$yb`H1orcWu}|o$T&Y7g5Om>P9A0Yi&l4Kx7Q}Vdp$_M zG^~NB0@xvschIN&iM~tyn=nJaw0(*-U+31O)7$DI4OIG71g=}3>SXVOU$ zz{|d6@7aa7&{`2@9wzC#m5RjUg@h48>l6JTf5OLZTfCGQ8a}U4gRfZ;qx+Iy9BBLH zuI&WDWfjJGsfZ?2Q1-T`k;K%(?H1QIW&Sd>MC46doNtXoZbe%2Nu9^#3HFCk8#YJn z-QO_KAq$NC_rEE`Y4^TIfbR2+u3`DbN5)|UB44jTPy0>uSMsMm_&JZ^Ku1!=sA*(V zb2gatbZ#9|hn)o~Bo4m?#xtHbuYr$jR zJ=Gd8pqDubCgM)Bo__A1cUxxZ*bZpD=-L*@%G?WmSI2rorbP^-a|KxNX7wKshDq`e z8+Wz2663=hdk|2A8*~R%oc+FbE>j+&#a~lM3PPs15``=XU>;s;MnsWOPGS%bM`3ku z|E<#N7<9?-9X5`cXmph)4*!HGl#`~|6$<9VJZ?4La>;eR9&e&G0>{P#U5A<3g#LPz zgF+D0mwG#$AIUoNJ90SxCNKNw*`6rNnYJ0`{Y&lIw7ivQZwc0{z?Vq_pL80k3v^d8 zL#saSXP8&g855#&UrQk7YEE=X+t!p%H(gpE^$jrEId%(B<`s%>wQ9YwKCd(!t>t_THk;l&mU z3a(y60tX5J;DaE+{fDu4iwc1_02ixmiPXt+-~`@8NlX8RAt6D$8T+IV5S>F0b;_Fi zIBYEe8F%oQjIUK42cNEwBm?jzJs1>43Pu75fV@-_5>8Jho(mqf#iYt^;fvNAATD#5 za^WuPfR@DR+OdqbxdFZtA5N;7LR3WUuk@g11;j_3k0CJj>s8zAHmkgdfpga=8W!Tf z6cqKX3MHG(p}9qT@Z9&vv+cp0{$SqybZpmJAO|THmg;3xZT@@E7wh#HQ|qG5QmayW zFoCmiXf0&c1x#<$v$B%Lf~qjv=gVp!FkQyQ&x;L=(* z&Of7PEeuA`8yQqY{S6`ntmJJUzGeG+x#*9Q$;tIS@nGP;vLgj400Lw)?8up;yLT8q zG_@aw{^qQoMHv@`9)yeb@HDo(ub(=rwPZx^3E0U$8jiU=S7*l`7ExT<>}$6?TJE&{ zdWL?aK3wBX-)6#5(MfU1UB5)CHg~NdHT3@{ZZVP0T#{00*Y9n%A1mVf2-*51O|Q0m zndo5V3Y(DSD}VqH-eH|VoSJ~qQ77U}FiW>fUA4zyt7P7HZZkdfFkPJXoTsXThhSb4XV%2}3ru@0`iHXe5Y`G@x#>yDof{i`1#))$ zx(fJpCvPL~+eDjhIG>91cE3Sf^FW*D9HgEP?2^_nojWDKUzO(DzEd^SX|T~WnMZ<# zVd*bJ<@^ugHF)Ru+iN(5a=Phw_O2J`QI+OV0VBQw(bFdJ+JWT)hOY(sX3q=a$RZ@IX$wpuEW%?(+4jwpRYQ3lR)5z4k6hJT30 zKkn0yh8sr2Ds8Jv^@swkbeLJFnO!LaiSdUXt9e7w9D`!{$SpH~0rlNFNr0e3oA41~ z*Y;d;bcW_%tg>Cy@2VkCsqU_L%b>fqR@#@zJ@S-&8200lOB^7~_BgR!3#{}jw<*bB?N0M5#)txwfu{R2#G zIXAQQq}mrMhUk)J447Fqz=dlL<^%BE-AT)Ada6i9@Fq-n80e|y#(=3Oe>k!w%|TO- zXaPP8adF}sx4%(2IorUjJtli&_HldnZ8_nyEQ|tlviV2T1~0VgCTV7Iav}um(id@n z{mT}@@t6K0<=1LK(kYexiJc=JC}%m%nzeixOohwP)YPdd<#jn9pICMT9SAm=qoP;m zV8CyU2=ABUq{0B&RvUYwlfv=^Vt}{HLbl|lpwX;*wZUWeD><1ACC&?jX=$#IpAUc?1F_}nDB#plh zGJ!S27ParPv15BUGl;T`;IWw?!Adxqeb;RKG~Tg#n)}bD{wj2J;?0I;`i|%KS5?kG}3Hqu(j%RbmuZt%uX2}LR@w{V245uAO zYz0AMl@2t%{yRx&lyl#PX+VI|#d_g2_n<1qD36X195-`v4@>(x2=5vCa(G~S^hlAQ zFeb5|93EXV#*?m`Ck*^d&1d#M7&A@0H<}Usl&ix?gw4WXz&aV57c-85v$-l<+3O9s zGme*QU{5hY*9%7bLfAxjIa(q*dVtlD^~T~YmksdF&QG2i<*QGappHl94BnVTh?8-1 zj|Cbd59@jpSR2JnK!g_>Mk_@f=qU8X7ZcS}OzOq7Z54!L$YQk)jk$e0KHmZ36Ri%l ztVAx)mFr;&GSNJq+*^8?`{Mc39mlcgY4;9R7%<1H_sPtbg5|@ZbbN-+^ycW$Uc&B0mPTy1YTnxHpt7THTlcXj2;6?@&3z z<2z1JhkeQjl_XA4vxa~eNnUQGbN-l(R$03t6iMA5Uk+r>$M>Ym1U4$DGw>GdcB3m> z*v$te52OS3ae2jzm+-;z|v&?nKfwyVJGFh+S^6tFzzsTD5^~q3y$UzTKU%H zV*0)fR&ZdcCtyDQK03!xUfP%aQGr)dbVhPu3>DoNu2%wmk=-a- zK-D(1Y^cTb-o2!YVGxuG47&}+n3b9FePlmxT`ELk5BTP2YeQ~Pc`qwz8$ z=8NX6?^!p%xvS|}z%V9+{b0ER}|z^l0>I-8t-B0oXbD&tOVEul*Y70X~!1|LC< z7{yKf5$OIFYZauhvp@llwmVO5@tEbSMFhWDq*8#SH|Zx?ki2SaQg(9~ZMfLD96uN* z0p+i)aPb2epEh7GO(~)u_w^}d#xafa;ETTf{{1qn>EH5*==Sw*Q-cSuj8Ha{IK`BK zm|tVxRf9YFxqJ+nF+x2gH2I<|TpdO(53U{LX=tdn9yf z&SnkJ&Ub+%J<9HI;^oE{&C+1{ENZF44rP8*4VF>aiULLfRE@}>>5t$)AOPmZ)yrWp zCK-$-rRl4b%SvB)joYw>;Br4*&~aUADrk5ltcfijk~S`rxqb(T0$5CiytM<|xbD%D zzsx?1F`F{0VHaqf$kC8{ebwuw*N7snxx|_dm~2jQc_Yq48EakXdPr$zDUJSB?AXwO zvBV~BO5(6F&LIMPFGydeHZ<5$m!!2~H$Ef#KSqnv%r~jzwM^xcY~AT@S*%=OF_V*w zC7ZmT*gw-`ZowDzxF$b$`a03*s)8C-Vf1QcpMDm%Ou#7+_4uqDEH>@3KiF| z(=Z@pmODd^K4mjCb2EotG zit!6zv?=zwPZ(qh{zXY}cP<2bA?x;ThLdmV9hABSpZn$)`3CzU+Tx-Zg~r`smCfKt zJjV-QfqC@-I;th`oSK(z()0nFPYqQZN9nXI=C;Fg3V0#%-~b1(JP20ejUsx-TM4xM zUsIS>Z1X1=9C@-r}#w0ii2KNS^X8;pHs1c^oT&X*VP;*_w)odmhNv%nj-gO^r%Dn%|HmmgW zr>&^#ql21UB=^`?5cT^Q2;8M_O!Kev15matOw>G0GC&IJ%1z1c;82amgI2- z+8rO-6qW3nS@Ll9Mj`#e5i~lw#Z=LLXq%mSl?uT%`R4Gb%Sfg>4q%MWgw*ryc&}MB zBK15dZCX}d2jfUpAa_joQXy zCB83#`LlEC1@tEALb|(z&y_x;rr_X>>gQtrbtOr2dVCqe!?*>E+|p>O;H3c7mMd<} zbkiN)!K``OazT^^tI#Abi+Ewq<*YYnye z7m29Es*NOKS=C8e*rzh(xvP_cgV{ggjcuD!(Yk@ROCV8;@my54x<%aDm14A?Z@|^F z1v_b`2K9z*%REF<+zrm2=fZn+VdGn;p#*+S1KXx+f=sY2d1iJ}JBTHu&alQ8#3Pws zg@rZ8(e z6$Exo0E85_Y=GoUMG-$g(8V~#1wrM$ya=qs3&@8bK!|TyEtu==-nfJwumaOBZALrN zJE$(!EN6^)+Fk9w*~<8~^HR{!xPZDpCR;eKdzbfcf35EesrwUM@QyG=Jdu#rA z5p!S>uA*Z$Z(z^>U)9>+nvT8Jb`>j2AtwTXD1R`)v=+6-xHyO6p4S#}jQeLW)Ez*w zqK&9r$nPzd0R>F{plp5lY`ns@I3_%v6>E-8P5B%A5&>--&UTOeWu7!Pos45Lq<$>q zs;O6Ck3si*jFvSaD2LgqQ8(n5yYiIHW-JNCFN_oX0KCc?Nem3=u~`eIhBQjrz8{(< zli$0TNsi~P__&#FPA((i6cR+Q!{P6nS3vsJR?Zts3TwfHvezznLWvJ;^uuqoCJu9$ z)t&c?%vf{dWTWbDmdANN(Xy_?@ggEMzyS7d-r*H7tDsJ@TI=ZPxcz-ihu^^al@*R3 zQ6^s+vdrBs{wn(hBkkhR<8(SycsFn%OE#WUP43-1>N%OTHyHZZ%pt~snL~!-BeV>?h7z5T4buU~ds(%{cyrMy8n2l9$=SDnkl4dX1c;iXzA|^mevx&_n!B*| zL(_jkfIq!wt__(C1%aTk-S0BrItvEFJ)PuX`ha|8td}2rf0yY**y|~lAS{Z3h7xaH z2gAwBdKQNZzA8_Ef#VOKEpZ?t`E`eA=?*s*(EUTFUt-Sfhu7n9|Cg9xNix;u&0kKW zb0`_{3Uy4t+va@01mW+x^s09Q|C<8l3JPLQS!@|OYEm*^;l!z2@lWiA!Zv6=!<{Ns zlRa=cYc3Tk(5cI@lAnFQ%;TV2)W!T2|g0Q&FI)Mqom!7_&LY7I>G-fdkw3UY*D7%S#^5-96a}U4j9;bBLMc*z9(Iq zu06BtpW_4yU-IRLaag8n0^GW5E{d1q_H_{`mt-S7e5(_lf&6avfCjxQWAB@)2}Ui2 zrWG}_y^hY=&ABwXll@hMPhlm95 >N`HO6>d-VpT3@dFKV6L=k1y^rh)4FX7!zk z+bbC�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 + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + + group2 { + pinmux = ; + input-enable; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + input-enable; + input-schmitt-enable; + }; + }; + + spi0_default: spi0_default { + group1 { + pinmux = , , ; + }; + + group2 { + pinmux = ; + input-enable; + }; + }; + + pwm_ch4b_default: pwm_ch4b_default { + group1 { + pinmux = ; + }; + }; + + adc_default: adc_default { + group1 { + pinmux = , , , ; + input-enable; + }; + }; +}; diff --git a/boards/pimoroni/pico_plus2/pico_plus2.dtsi b/boards/pimoroni/pico_plus2/pico_plus2.dtsi new file mode 100644 index 000000000000..f77ae33e0421 --- /dev/null +++ b/boards/pimoroni/pico_plus2/pico_plus2.dtsi @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2024 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include "pico_plus2-pinctrl.dtsi" + +/ { + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,code-partition = &code_partition; + }; + + aliases { + watchdog0 = &wdt0; + led0 = &led0; + pwm-led0 = &pwm_led0; + sw0 = &user_sw; + }; + + leds { + compatible = "gpio-leds"; + + led0: led_0 { + gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; + label = "LED"; + }; + }; + + pwm_leds { + compatible = "pwm-leds"; + status = "disabled"; + + pwm_led0: pwm_led_0 { + pwms = <&pwm 9 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + label = "PWM_LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + + user_sw: user_sw { + gpios = <&gpio0_hi 13 (GPIO_ACTIVE_LOW)>; + zephyr,code = ; + }; + }; + + pico_header: connector { + compatible = "raspberrypi,pico-header"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 0 0>, /* GP0 */ + <1 0 &gpio0 1 0>, /* GP1 */ + <2 0 &gpio0 2 0>, /* GP2 */ + <3 0 &gpio0 3 0>, /* GP3 */ + <4 0 &gpio0 4 0>, /* GP4 */ + <5 0 &gpio0 5 0>, /* GP5 */ + <6 0 &gpio0 6 0>, /* GP6 */ + <7 0 &gpio0 7 0>, /* GP7 */ + <8 0 &gpio0 8 0>, /* GP8 */ + <9 0 &gpio0 9 0>, /* GP9 */ + <10 0 &gpio0 10 0>, /* GP10 */ + <11 0 &gpio0 11 0>, /* GP11 */ + <12 0 &gpio0 12 0>, /* GP12 */ + <13 0 &gpio0 13 0>, /* GP13 */ + <14 0 &gpio0 14 0>, /* GP14 */ + <15 0 &gpio0 15 0>, /* GP15 */ + <16 0 &gpio0 16 0>, /* GP16 */ + <17 0 &gpio0 17 0>, /* GP17 */ + <18 0 &gpio0 18 0>, /* GP18 */ + <19 0 &gpio0 19 0>, /* GP19 */ + <20 0 &gpio0 20 0>, /* GP20 */ + <21 0 &gpio0 21 0>, /* GP21 */ + <22 0 &gpio0 22 0>, /* GP22 */ + <26 0 &gpio0 26 0>, /* GP26 */ + <27 0 &gpio0 27 0>, /* GP27 */ + <28 0 &gpio0 28 0>; /* GP28 */ + }; +}; + +&flash0 { + reg = <0x10000000 DT_SIZE_M(16)>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserved memory for an image definition block. The block is much + * smaller than 256 bytes, but in practice the linker places the vector + * table at a much larger alignment offset. + */ + image_def: partition@0 { + label = "image_def"; + reg = <0x00000000 0x100>; + read-only; + }; + + /* + * Usable flash. Starts at 0x100, after the image definition block. + * The partition size is 16MB minus the 0x100 bytes taken by the + * image definition. + */ + code_partition: partition@100 { + label = "code-partition"; + reg = <0x100 (DT_SIZE_M(16) - 0x100)>; + read-only; + }; + }; +}; + +&uart0 { + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +gpio0_lo: &gpio0 { + status = "okay"; +}; + +&gpio0_hi { + status = "okay"; +}; + +&spi0 { + clock-frequency = ; + pinctrl-0 = <&spi0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c0 { + clock-frequency = ; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&adc { + pinctrl-0 = <&adc_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&pwm { + pinctrl-0 = <&pwm_ch4b_default>; + pinctrl-names = "default"; + divider-int-0 = <255>; +}; + +&timer0 { + status = "okay"; +}; + +zephyr_udc0: &usbd { + status = "okay"; +}; + + +pico_spi: &spi0 {}; +pico_i2c0: &i2c0 {}; +pico_i2c1: &i2c1 {}; +pico_serial: &uart0 {}; +stemma_qt_i2c: &i2c0 {}; diff --git a/boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33.dts b/boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33.dts new file mode 100644 index 000000000000..425c2237f735 --- /dev/null +++ b/boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +/* The build system assumes that there's a cpucluster-specific file. + * + * This file provides composition of the device tree: + * 1. The common features of the SoC + * 2. Core-specific configuration. + * 3. Board-specific configuration. + */ +#include +#include + +/* there's nothing specific to the Cortex-M33 cores vs the (not yet + * implemented) Hazard3 cores. + */ +#include "pico_plus2.dtsi" diff --git a/boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33.yaml b/boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33.yaml new file mode 100644 index 000000000000..c4a91adfac8c --- /dev/null +++ b/boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33.yaml @@ -0,0 +1,20 @@ +identifier: pico_plus2/rp2350b/m33 +name: Pimoroni Pico Plus 2 (Cortex-M33) +type: mcu +arch: arm +flash: 16384 +ram: 8192 +toolchain: + - zephyr + - gnuarmemb +supported: + - adc + - clock + - counter + - dma + - gpio + - hwinfo + - i2c + - pwm + - spi + - uart diff --git a/boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33_defconfig b/boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33_defconfig new file mode 100644 index 000000000000..8bd68e351139 --- /dev/null +++ b/boards/pimoroni/pico_plus2/pico_plus2_rp2350b_m33_defconfig @@ -0,0 +1,14 @@ +# This configuration is orthogonal to whether the Cortex-M33 or Hazard3 cores +# are in use, but Zephyr does not support providing a qualifier-agnostic +# _defconfig file. +CONFIG_BUILD_OUTPUT_HEX=y +CONFIG_BUILD_OUTPUT_UF2=y +CONFIG_CLOCK_CONTROL=y +CONFIG_CONSOLE=y +CONFIG_GPIO=y +CONFIG_RESET=y +CONFIG_SERIAL=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=150000000 +CONFIG_UART_CONSOLE=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_USE_DT_CODE_PARTITION=y diff --git a/boards/pimoroni/pico_plus2/support/openocd.cfg b/boards/pimoroni/pico_plus2/support/openocd.cfg new file mode 100644 index 000000000000..82666bb53314 --- /dev/null +++ b/boards/pimoroni/pico_plus2/support/openocd.cfg @@ -0,0 +1,11 @@ +# Copyright (c) 2024 TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +# Checking and set 'adapter speed'. +# Set the adaptor speed, if unset, and given as an argument. +proc set_adapter_speed_if_not_set { speed } { + puts "checking adapter speed..." + if { [catch {adapter speed} ret] } { + adapter speed $speed + } +} diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index 8243f706f1ed..373c06b35893 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -513,6 +513,7 @@ phicomm PHICOMM Co., Ltd. phosense Beijing Phosense Electronic Technology Co., Ltd. phytec PHYTEC picochip Picochip Ltd +pimoroni Pimoroni Ltd. pine64 Pine64 pineriver Shenzhen PineRiver Designs Co., Ltd. pixart PixArt Imaging Inc. diff --git a/samples/drivers/adc/adc_dt/boards/pico_plus2_rp2350b_m33.overlay b/samples/drivers/adc/adc_dt/boards/pico_plus2_rp2350b_m33.overlay new file mode 100644 index 000000000000..abf2d227844b --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/pico_plus2_rp2350b_m33.overlay @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 TOKITA Hiroshi + */ + +/ { + zephyr,user { + io-channels = <&adc 0>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/counter/alarm/src/main.c b/samples/drivers/counter/alarm/src/main.c index d7f577e72c7e..4e86116b2cc1 100644 --- a/samples/drivers/counter/alarm/src/main.c +++ b/samples/drivers/counter/alarm/src/main.c @@ -54,7 +54,11 @@ struct counter_alarm_cfg alarm_cfg; #elif defined(CONFIG_COUNTER_SNPS_DW) #define TIMER DT_NODELABEL(timer0) #elif defined(CONFIG_COUNTER_TIMER_RPI_PICO) +#ifdef CONFIG_SOC_SERIES_RP2040 #define TIMER DT_NODELABEL(timer) +#elif CONFIG_SOC_SERIES_RP2350 +#define TIMER DT_NODELABEL(timer0) +#endif #elif defined(CONFIG_COUNTER_TIMER_MAX32) #define TIMER DT_NODELABEL(counter0) #elif defined(CONFIG_COUNTER_RA_AGT) diff --git a/samples/drivers/led/pwm/boards/pico_plus2_rp2350b_m33.overlay b/samples/drivers/led/pwm/boards/pico_plus2_rp2350b_m33.overlay new file mode 100644 index 000000000000..565dcd6fbbab --- /dev/null +++ b/samples/drivers/led/pwm/boards/pico_plus2_rp2350b_m33.overlay @@ -0,0 +1,15 @@ +/ { + leds { + status = "disabled"; + }; + + pwm_leds { + status = "okay"; + }; +}; + +&pwm { + status = "okay"; + divider-frac-4 = <15>; + divider-int-4 = <255>; +}; diff --git a/samples/sensor/die_temp_polling/boards/pico_plus2_rp2350b_m33.conf b/samples/sensor/die_temp_polling/boards/pico_plus2_rp2350b_m33.conf new file mode 100644 index 000000000000..488a81dca520 --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/pico_plus2_rp2350b_m33.conf @@ -0,0 +1 @@ +CONFIG_ADC=y diff --git a/samples/sensor/die_temp_polling/boards/pico_plus2_rp2350b_m33.overlay b/samples/sensor/die_temp_polling/boards/pico_plus2_rp2350b_m33.overlay new file mode 100644 index 000000000000..38f5ece1c98a --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/pico_plus2_rp2350b_m33.overlay @@ -0,0 +1,9 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 TOKITA Hiroshi + */ + +&die_temp { + status = "okay"; +}; diff --git a/tests/drivers/adc/adc_api/boards/pico_plus2_rp2350b_m33.overlay b/tests/drivers/adc/adc_api/boards/pico_plus2_rp2350b_m33.overlay new file mode 100644 index 000000000000..1de395543efa --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/pico_plus2_rp2350b_m33.overlay @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 TOKITA Hiroshi + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>; + }; +}; + +&adc { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/tests/drivers/dma/loop_transfer/boards/pico_plus2_rp2350b_m33.overlay b/tests/drivers/dma/loop_transfer/boards/pico_plus2_rp2350b_m33.overlay new file mode 100644 index 000000000000..35ee84e3c4ea --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/pico_plus2_rp2350b_m33.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Tokita, Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +tst_dma0: &dma { + status = "okay"; +}; diff --git a/tests/drivers/gpio/gpio_api_1pin/boards/pico_plus2_rp2350b_m33.overlay b/tests/drivers/gpio/gpio_api_1pin/boards/pico_plus2_rp2350b_m33.overlay new file mode 100644 index 000000000000..32d95560343d --- /dev/null +++ b/tests/drivers/gpio/gpio_api_1pin/boards/pico_plus2_rp2350b_m33.overlay @@ -0,0 +1,8 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 TOKITA Hiroshi + */ + +/* Pico Plus2 is pin-compatible with the RPi-Pico2, so reuse. */ +#include "rpi_pico2_rp2350a_m33.overlay" diff --git a/tests/drivers/gpio/gpio_basic_api/boards/pico_plus2_rp2350b_m33.conf b/tests/drivers/gpio/gpio_basic_api/boards/pico_plus2_rp2350b_m33.conf new file mode 100644 index 000000000000..b9d02cf11d5d --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/pico_plus2_rp2350b_m33.conf @@ -0,0 +1 @@ +CONFIG_SKIP_PULL_TEST=y diff --git a/tests/drivers/gpio/gpio_basic_api/boards/pico_plus2_rp2350b_m33.overlay b/tests/drivers/gpio/gpio_basic_api/boards/pico_plus2_rp2350b_m33.overlay new file mode 100644 index 000000000000..3938f695d9d1 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/pico_plus2_rp2350b_m33.overlay @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2024 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Pico Plus2 is pin-compatible with the RPi-Pico, so reuse. */ +#include "rpi_pico.overlay" diff --git a/tests/drivers/spi/spi_loopback/boards/pico_plus2_rp2350b_m33.conf b/tests/drivers/spi/spi_loopback/boards/pico_plus2_rp2350b_m33.conf new file mode 100644 index 000000000000..53e8607eb619 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/pico_plus2_rp2350b_m33.conf @@ -0,0 +1 @@ +CONFIG_SPI_PL022_DMA=y diff --git a/tests/drivers/spi/spi_loopback/socs/rp2040.overlay b/tests/drivers/spi/spi_loopback/socs/rp2040.overlay new file mode 100644 index 000000000000..99b39fca98a2 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/socs/rp2040.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2022 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include diff --git a/tests/drivers/spi/spi_loopback/socs/rp2350b_m33.overlay b/tests/drivers/spi/spi_loopback/socs/rp2350b_m33.overlay new file mode 100644 index 000000000000..1d38b504b427 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/socs/rp2350b_m33.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include diff --git a/tests/drivers/spi/spi_loopback/testcase.yaml b/tests/drivers/spi/spi_loopback/testcase.yaml index 4bf13f43fac1..3fe2b8278cf4 100644 --- a/tests/drivers/spi/spi_loopback/testcase.yaml +++ b/tests/drivers/spi/spi_loopback/testcase.yaml @@ -173,35 +173,45 @@ tests: extra_configs: - CONFIG_SPI_PL022_INTERRUPT=y - CONFIG_SPI_PL022_DMA=n - platform_allow: rpi_pico + platform_allow: + - rpi_pico + - pico_plus2/rp2350b/m33 drivers.spi.pl022_spi_dma.loopback: extra_args: DTC_OVERLAY_FILE="boards/rpi_pico_pl022_dma.overlay" extra_configs: - CONFIG_SPI_PL022_INTERRUPT=n - CONFIG_SPI_PL022_DMA=y - CONFIG_DMA=y - platform_allow: rpi_pico + platform_allow: + - rpi_pico + - pico_plus2/rp2350b/m33 drivers.spi.pl022_spi_dma_and_interrupt.loopback: extra_args: DTC_OVERLAY_FILE="boards/rpi_pico_pl022_dma.overlay" extra_configs: - CONFIG_SPI_PL022_INTERRUPT=y - CONFIG_SPI_PL022_DMA=y - CONFIG_DMA=y - platform_allow: rpi_pico + platform_allow: + - rpi_pico + - pico_plus2/rp2350b/m33 drivers.spi.pl022_spi_dma_no_dma_props.loopback: extra_args: DTC_OVERLAY_FILE="boards/rpi_pico_pl022.overlay" extra_configs: - CONFIG_SPI_PL022_INTERRUPT=n - CONFIG_SPI_PL022_DMA=y - CONFIG_DMA=y - platform_allow: rpi_pico + platform_allow: + - rpi_pico + - pico_plus2/rp2350b/m33 drivers.spi.pl022_spi_dma_and_interrupt_no_dma_props.loopback: extra_args: DTC_OVERLAY_FILE="boards/rpi_pico_pl022.overlay" extra_configs: - CONFIG_SPI_PL022_INTERRUPT=y - CONFIG_SPI_PL022_DMA=y - CONFIG_DMA=y - platform_allow: rpi_pico + platform_allow: + - rpi_pico + - pico_plus2/rp2350b/m33 drivers.spi.pio_spi.loopback: extra_args: - DTC_OVERLAY_FILE="boards/rpi_pico_pio.overlay"