Skip to content

Commit a2c5861

Browse files
jfischer-nokartben
authored andcommitted
drivers: udc_rpi_pico: fix set/clear endpoint halt
For the IN endpoint, we only need to set/reset the STALL bit in the endpoint control register. To set halt on the OUT endpoint, the AVAILABLE bit must also be set, which is similar to starting a new transfer, but first any transfer in progress must be canceled. Signed-off-by: Johann Fischer <[email protected]>
1 parent e98e774 commit a2c5861

File tree

1 file changed

+66
-25
lines changed

1 file changed

+66
-25
lines changed

drivers/usb/udc/udc_rpi_pico.c

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ static int rpi_pico_prep_rx(const struct device *dev,
239239
struct net_buf *const buf, struct udc_ep_config *const cfg)
240240
{
241241
struct rpi_pico_ep_data *const ep_data = get_ep_data(dev, cfg->addr);
242+
unsigned int lock_key;
242243
uint32_t buf_ctrl;
243244

244245
buf_ctrl = read_buf_ctrl_reg(dev, cfg->addr);
@@ -250,6 +251,8 @@ static int rpi_pico_prep_rx(const struct device *dev,
250251
LOG_DBG("Prepare RX ep 0x%02x len %u pid: %u",
251252
cfg->addr, net_buf_tailroom(buf), ep_data->next_pid);
252253

254+
lock_key = irq_lock();
255+
253256
buf_ctrl = cfg->mps;
254257
buf_ctrl |= ep_data->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
255258
ep_data->next_pid ^= 1U;
@@ -264,13 +267,16 @@ static int rpi_pico_prep_rx(const struct device *dev,
264267
arch_nop();
265268
write_buf_ctrl_reg(dev, cfg->addr, buf_ctrl | USB_BUF_CTRL_AVAIL);
266269

270+
irq_unlock(lock_key);
271+
267272
return 0;
268273
}
269274

270275
static int rpi_pico_prep_tx(const struct device *dev,
271276
struct net_buf *const buf, struct udc_ep_config *const cfg)
272277
{
273278
struct rpi_pico_ep_data *const ep_data = get_ep_data(dev, cfg->addr);
279+
unsigned int lock_key;
274280
uint32_t buf_ctrl;
275281
size_t len;
276282

@@ -280,6 +286,8 @@ static int rpi_pico_prep_tx(const struct device *dev,
280286
return -EBUSY;
281287
}
282288

289+
lock_key = irq_lock();
290+
283291
len = MIN(cfg->mps, buf->len);
284292
memcpy(ep_data->buf, buf->data, len);
285293

@@ -301,6 +309,8 @@ static int rpi_pico_prep_tx(const struct device *dev,
301309
arch_nop();
302310
write_buf_ctrl_reg(dev, cfg->addr, buf_ctrl | USB_BUF_CTRL_AVAIL);
303311

312+
irq_unlock(lock_key);
313+
304314
return 0;
305315
}
306316

@@ -466,6 +476,10 @@ static void rpi_pico_handle_xfer_next(const struct device *dev,
466476
}
467477

468478
if (USB_EP_DIR_IS_OUT(cfg->addr)) {
479+
if (cfg->stat.halted) {
480+
return;
481+
}
482+
469483
err = rpi_pico_prep_rx(dev, buf, cfg);
470484
} else {
471485
err = rpi_pico_prep_tx(dev, buf, cfg);
@@ -742,9 +756,13 @@ static void rpi_pico_isr_handler(const struct device *dev)
742756
if (status & USB_INTS_ERROR_DATA_SEQ_BITS) {
743757
handled |= USB_INTS_ERROR_DATA_SEQ_BITS;
744758
sie_status_clr(dev, USB_SIE_STATUS_DATA_SEQ_ERROR_BITS);
745-
746-
LOG_ERR("Data Sequence Error");
747-
udc_submit_event(dev, UDC_EVT_ERROR, -EINVAL);
759+
/*
760+
* This can be triggered before the STALL handshake response
761+
* to the OUT DATAx. Handling IRQ_ON_STALL to fix the expected
762+
* DATA PID is too much overhead since the endpoint is halted
763+
* anyway.
764+
*/
765+
LOG_WRN("Data Sequence Error");
748766
}
749767

750768
if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) {
@@ -904,21 +922,39 @@ static int udc_rpi_pico_ep_set_halt(const struct device *dev,
904922
const struct rpi_pico_config *config = dev->config;
905923
mem_addr_t buf_ctrl_reg = get_buf_ctrl_reg(dev, cfg->addr);
906924
usb_hw_t *base = config->base;
925+
unsigned int lock_key;
926+
uint32_t bits;
907927

928+
lock_key = irq_lock();
908929
if (USB_EP_GET_IDX(cfg->addr) == 0) {
909-
uint32_t bit = USB_EP_DIR_IS_OUT(cfg->addr) ?
910-
USB_EP_STALL_ARM_EP0_OUT_BITS : USB_EP_STALL_ARM_EP0_IN_BITS;
930+
bits = USB_EP_DIR_IS_OUT(cfg->addr) ?
931+
USB_EP_STALL_ARM_EP0_OUT_BITS : USB_EP_STALL_ARM_EP0_IN_BITS;
932+
rpi_pico_bit_set((mm_reg_t)&base->ep_stall_arm, bits);
933+
}
911934

912-
rpi_pico_bit_set((mm_reg_t)&base->ep_stall_arm, bit);
935+
if (USB_EP_DIR_IS_OUT(cfg->addr)) {
936+
/*
937+
* Cancel any transfer in progress. The available bit must be
938+
* set for the controller to respond to OUT DATAx with a STALL
939+
* handshake.
940+
*/
941+
rpi_pico_ep_cancel(dev, cfg->addr);
942+
bits = USB_BUF_CTRL_STALL | USB_BUF_CTRL_AVAIL;
943+
} else {
944+
/* Only STALL bit needs to be set here. */
945+
bits = USB_BUF_CTRL_STALL;
913946
}
914947

915-
rpi_pico_bit_set(buf_ctrl_reg, USB_BUF_CTRL_STALL);
948+
rpi_pico_bit_set(buf_ctrl_reg, bits);
916949

917-
LOG_INF("Set halt ep 0x%02x", cfg->addr);
918950
if (USB_EP_GET_IDX(cfg->addr) != 0) {
919951
cfg->stat.halted = true;
920952
}
921953

954+
irq_unlock(lock_key);
955+
LOG_DBG("Set halt ep 0x%02x buf_ctrl 0x%08x busy %u",
956+
cfg->addr, sys_read32(buf_ctrl_reg), udc_ep_is_busy(cfg));
957+
922958
return 0;
923959
}
924960

@@ -928,28 +964,33 @@ static int udc_rpi_pico_ep_clear_halt(const struct device *dev,
928964
struct rpi_pico_ep_data *const ep_data = get_ep_data(dev, cfg->addr);
929965
struct rpi_pico_data *priv = udc_get_private(dev);
930966
mem_addr_t buf_ctrl_reg = get_buf_ctrl_reg(dev, cfg->addr);
967+
unsigned int lock_key;
931968

932-
if (USB_EP_GET_IDX(cfg->addr) != 0) {
933-
ep_data->next_pid = 0;
934-
rpi_pico_bit_clr(buf_ctrl_reg, USB_BUF_CTRL_DATA1_PID);
935-
/*
936-
* By default, clk_sys runs at 125MHz, wait 3 nop instructions
937-
* before clearing the CTRL_STALL bit. See 4.1.2.5.4.
938-
*/
939-
arch_nop();
940-
arch_nop();
941-
arch_nop();
942-
rpi_pico_bit_clr(buf_ctrl_reg, USB_BUF_CTRL_STALL);
969+
if (USB_EP_GET_IDX(cfg->addr) == 0) {
970+
return 0;
971+
}
943972

944-
if (udc_buf_peek(cfg)) {
945-
k_event_post(&priv->xfer_new, udc_ep_to_bmsk(cfg->addr));
946-
k_event_post(&priv->events, BIT(RPI_PICO_EVT_XFER_NEW));
947-
}
973+
lock_key = irq_lock();
974+
if (USB_EP_DIR_IS_OUT(cfg->addr)) {
975+
/* Cancel responds with a STALL handshake.*/
976+
rpi_pico_ep_cancel(dev, cfg->addr);
977+
} else {
978+
rpi_pico_bit_clr(buf_ctrl_reg, USB_BUF_CTRL_STALL);
948979
}
949980

981+
ep_data->next_pid = 0;
950982
cfg->stat.halted = false;
951-
LOG_INF("Clear halt ep 0x%02x buf_ctrl 0x%08x",
952-
cfg->addr, sys_read32(buf_ctrl_reg));
983+
irq_unlock(lock_key);
984+
985+
if (udc_ep_is_busy(cfg)) {
986+
rpi_pico_handle_xfer_next(dev, cfg);
987+
} else if (udc_buf_peek(cfg)) {
988+
k_event_post(&priv->xfer_new, udc_ep_to_bmsk(cfg->addr));
989+
k_event_post(&priv->events, BIT(RPI_PICO_EVT_XFER_NEW));
990+
}
991+
992+
LOG_DBG("Clear halt ep 0x%02x buf_ctrl 0x%08x busy %u",
993+
cfg->addr, sys_read32(buf_ctrl_reg), udc_ep_is_busy(cfg));
953994

954995
return 0;
955996
}

0 commit comments

Comments
 (0)