Skip to content

Commit f701357

Browse files
jfischer-nokartben
authored andcommitted
drivers: udc_rpi_pico: support VBUS state change detection
Support VBUS state change detection and enable/disable DP pull-up according to VBUS state when pinctrl property is provided. It brings the similar functionality introduced in commit 4c0317f ("drivers: usb_dc_rpi_pico: Implemented vbus detection handling") for the legacy device controller driver. Signed-off-by: Johann Fischer <[email protected]>
1 parent 06232bb commit f701357

File tree

2 files changed

+70
-8
lines changed

2 files changed

+70
-8
lines changed

drivers/usb/udc/Kconfig.rpi_pico

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ config UDC_RPI_PICO
77
depends on DT_HAS_RASPBERRYPI_PICO_USBD_ENABLED
88
select SYS_MEM_BLOCKS
99
select EVENTS
10+
imply PINCTRL
1011
help
1112
Driver for an Raspberry PI Pico USB device controller.
1213

drivers/usb/udc/udc_rpi_pico.c

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <zephyr/kernel.h>
1818
#include <zephyr/sys/mem_blocks.h>
1919
#include <zephyr/drivers/usb/udc.h>
20+
#include <zephyr/drivers/pinctrl.h>
2021
#include <zephyr/drivers/clock_control.h>
2122

2223
#include <zephyr/logging/log.h>
@@ -33,6 +34,7 @@ struct rpi_pico_config {
3334
void (*irq_enable_func)(const struct device *dev);
3435
void (*irq_disable_func)(const struct device *dev);
3536
const struct device *clk_dev;
37+
struct pinctrl_dev_config *const pcfg;
3638
clock_control_subsys_t clk_sys;
3739
};
3840

@@ -105,6 +107,19 @@ static void ALWAYS_INLINE rpi_pico_bit_clr(const mm_reg_t reg, const uint32_t bi
105107
sys_write32(bit, REG_ALIAS_CLR_BITS | reg);
106108
}
107109

110+
111+
static void sie_dp_pullup(const struct device *dev, const bool enable)
112+
{
113+
const struct rpi_pico_config *config = dev->config;
114+
usb_hw_t *base = config->base;
115+
116+
if (enable) {
117+
rpi_pico_bit_set((mm_reg_t)&base->sie_ctrl, USB_SIE_CTRL_PULLUP_EN_BITS);
118+
} else {
119+
rpi_pico_bit_clr((mm_reg_t)&base->sie_ctrl, USB_SIE_CTRL_PULLUP_EN_BITS);
120+
}
121+
}
122+
108123
static void ALWAYS_INLINE sie_status_clr(const struct device *dev, const uint32_t bit)
109124
{
110125
const struct rpi_pico_config *config = dev->config;
@@ -639,6 +654,7 @@ static void rpi_pico_handle_buff_status(const struct device *dev)
639654
static void rpi_pico_isr_handler(const struct device *dev)
640655
{
641656
const struct rpi_pico_config *config = dev->config;
657+
const struct pinctrl_dev_config *const pcfg = config->pcfg;
642658
struct rpi_pico_data *priv = udc_get_private(dev);
643659
usb_hw_t *base = config->base;
644660
uint32_t status = base->ints;
@@ -652,15 +668,35 @@ static void rpi_pico_isr_handler(const struct device *dev)
652668
if (status & USB_INTS_DEV_CONN_DIS_BITS) {
653669
uint32_t sie_status;
654670

671+
sie_status = sys_read32((mm_reg_t)&base->sie_status);
672+
LOG_DBG("CONNECTED bit %u, VBUS_DETECTED bit %u",
673+
(bool)(sie_status & USB_SIE_STATUS_CONNECTED_BITS),
674+
(bool)(sie_status & USB_SIE_STATUS_VBUS_DETECTED_BITS));
675+
676+
if (pcfg != NULL && !(sie_status & USB_SIE_STATUS_CONNECTED_BITS) &&
677+
!(sie_status & USB_SIE_STATUS_VBUS_DETECTED_BITS)) {
678+
sie_dp_pullup(dev, false);
679+
udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0);
680+
}
681+
655682
handled |= USB_INTS_DEV_CONN_DIS_BITS;
656683
sie_status_clr(dev, USB_SIE_STATUS_CONNECTED_BITS);
684+
}
685+
686+
if (status & USB_INTS_VBUS_DETECT_BITS) {
687+
uint32_t sie_status;
657688

658689
sie_status = sys_read32((mm_reg_t)&base->sie_status);
659-
if (sie_status & USB_SIE_STATUS_CONNECTED_BITS) {
690+
LOG_DBG("VBUS_DETECTED bit %u",
691+
(bool)(sie_status & USB_SIE_STATUS_VBUS_DETECTED_BITS));
692+
693+
if (pcfg != NULL && (sie_status & USB_SIE_STATUS_VBUS_DETECTED_BITS)) {
694+
sie_dp_pullup(dev, true);
660695
udc_submit_event(dev, UDC_EVT_VBUS_READY, 0);
661-
} else {
662-
udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0);
663696
}
697+
698+
handled |= USB_INTS_VBUS_DETECT_BITS;
699+
sie_status_clr(dev, USB_SIE_STATUS_VBUS_DETECTED_BITS);
664700
}
665701

666702
if ((status & (USB_INTS_BUFF_STATUS_BITS | USB_INTS_SETUP_REQ_BITS)) &&
@@ -943,6 +979,7 @@ static int udc_rpi_pico_host_wakeup(const struct device *dev)
943979
static int udc_rpi_pico_enable(const struct device *dev)
944980
{
945981
const struct rpi_pico_config *config = dev->config;
982+
const struct pinctrl_dev_config *const pcfg = config->pcfg;
946983
usb_device_dpram_t *dpram = config->dpram;
947984
usb_hw_t *base = config->base;
948985

@@ -958,9 +995,11 @@ static int udc_rpi_pico_enable(const struct device *dev)
958995
sys_write32(USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS,
959996
(mm_reg_t)&base->muxing);
960997

961-
/* Force VBUS detect so the device thinks it is plugged into a host */
962-
sys_write32(USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS,
963-
(mm_reg_t)&base->pwr);
998+
if (pcfg == NULL) {
999+
/* Force VBUS detect so the device thinks it is plugged into a host */
1000+
sys_write32(USB_USB_PWR_VBUS_DETECT_BITS |
1001+
USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS, (mm_reg_t)&base->pwr);
1002+
}
9641003

9651004
/* Enable an interrupt per EP0 transaction */
9661005
sys_write32(USB_SIE_CTRL_EP0_INT_1BUF_BITS, (mm_reg_t)&base->sie_ctrl);
@@ -981,8 +1020,10 @@ static int udc_rpi_pico_enable(const struct device *dev)
9811020
USB_INTE_BUFF_STATUS_BITS,
9821021
(mm_reg_t)&base->inte);
9831022

984-
/* Present full speed device by enabling pull up on DP */
985-
rpi_pico_bit_set((mm_reg_t)&base->sie_ctrl, USB_SIE_CTRL_PULLUP_EN_BITS);
1023+
if (sys_read32((mm_reg_t)&base->sie_status) & USB_SIE_STATUS_VBUS_DETECTED_BITS) {
1024+
/* Present full speed device by enabling pull up on DP */
1025+
sie_dp_pullup(dev, true);
1026+
}
9861027

9871028
/* Enable the USB controller in device mode. */
9881029
sys_write32(USB_MAIN_CTRL_CONTROLLER_EN_BITS, (mm_reg_t)&base->main_ctrl);
@@ -1007,6 +1048,8 @@ static int udc_rpi_pico_disable(const struct device *dev)
10071048
static int udc_rpi_pico_init(const struct device *dev)
10081049
{
10091050
const struct rpi_pico_config *config = dev->config;
1051+
const struct pinctrl_dev_config *const pcfg = config->pcfg;
1052+
int err;
10101053

10111054
if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT,
10121055
USB_EP_TYPE_CONTROL, 64, 0)) {
@@ -1020,6 +1063,14 @@ static int udc_rpi_pico_init(const struct device *dev)
10201063
return -EIO;
10211064
}
10221065

1066+
if (pcfg != NULL) {
1067+
err = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT);
1068+
if (err) {
1069+
LOG_ERR("Failed to apply default pinctrl state (%d)", err);
1070+
return err;
1071+
}
1072+
}
1073+
10231074
return clock_control_on(config->clk_dev, config->clk_sys);
10241075
}
10251076

@@ -1132,7 +1183,16 @@ static const struct udc_api udc_rpi_pico_api = {
11321183

11331184
#define DT_DRV_COMPAT raspberrypi_pico_usbd
11341185

1186+
#define UDC_RPI_PICO_PINCTRL_DT_INST_DEFINE(n) \
1187+
COND_CODE_1(DT_INST_PINCTRL_HAS_NAME(n, default), \
1188+
(PINCTRL_DT_INST_DEFINE(n)), ())
1189+
1190+
#define UDC_RPI_PICO_PINCTRL_DT_INST_DEV_CONFIG_GET(n) \
1191+
COND_CODE_1(DT_INST_PINCTRL_HAS_NAME(n, default), \
1192+
((void *)PINCTRL_DT_INST_DEV_CONFIG_GET(n)), (NULL))
1193+
11351194
#define UDC_RPI_PICO_DEVICE_DEFINE(n) \
1195+
UDC_RPI_PICO_PINCTRL_DT_INST_DEFINE(n); \
11361196
K_THREAD_STACK_DEFINE(udc_rpi_pico_stack_##n, CONFIG_UDC_RPI_PICO_STACK_SIZE); \
11371197
\
11381198
SYS_MEM_BLOCKS_DEFINE_STATIC_WITH_EXT_BUF(rpi_pico_mb_##n, \
@@ -1190,6 +1250,7 @@ static const struct udc_api udc_rpi_pico_api = {
11901250
.make_thread = udc_rpi_pico_make_thread_##n, \
11911251
.irq_enable_func = udc_rpi_pico_irq_enable_func_##n, \
11921252
.irq_disable_func = udc_rpi_pico_irq_disable_func_##n, \
1253+
.pcfg = UDC_RPI_PICO_PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
11931254
.clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
11941255
.clk_sys = (void *)DT_INST_PHA_BY_IDX(n, clocks, 0, clk_id), \
11951256
}; \

0 commit comments

Comments
 (0)