diff --git a/drivers/usb/device/usb_dc_it82xx2.c b/drivers/usb/device/usb_dc_it82xx2.c index d0b59f15e75..b0dad074a80 100644 --- a/drivers/usb/device/usb_dc_it82xx2.c +++ b/drivers/usb/device/usb_dc_it82xx2.c @@ -81,8 +81,12 @@ enum it82xx2_transaction_types { #define DC_CONNECT_TO_HOST BIT(6) /* internal pull-up */ /* ENDPOINT[3..0]_CONTROL_REG */ -#define ENDPOINT_EN BIT(0) -#define EP_SEND_STALL BIT(3) +#define ENDPOINT_ENABLE_BIT BIT(0) +#define ENDPOINT_READY_BIT BIT(1) +#define ENDPOINT_OUTDATA_SEQ_BIT BIT(2) +#define ENDPOINT_SEND_STALL_BIT BIT(3) +#define ENDPOINT_ISO_ENABLE_BIT BIT(4) +#define ENDPOINT_DIRECTION_BIT BIT(5) enum it82xx2_ep_status { EP_INIT = 0, @@ -417,14 +421,11 @@ static int it82xx2_usb_extend_ep_ctrl(uint8_t ep, enum it82xx2_ep_ctrl ctrl, boo } break; case EP_READY_ENABLE: - unsigned int key; int idx = ((ep_idx - 4) % 3) + 1; - key = irq_lock(); (enable) ? (ext_ctrl[idx].epn_ext_ctrl2 |= BIT((ep_idx - 4) / 3)) : (ext_ctrl[idx].epn_ext_ctrl2 &= ~BIT((ep_idx - 4) / 3)); ep_regs[ep_fifo].ep_ctrl.fields.ready_bit = enable; - irq_unlock(key); break; default: LOG_ERR("Unknown control type 0x%x", ctrl); @@ -438,51 +439,72 @@ static int it82xx2_usb_ep_ctrl(uint8_t ep, enum it82xx2_ep_ctrl ctrl, bool enabl { struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + uint8_t ep_ctrl_value; uint8_t ep_idx = USB_EP_GET_IDX(ep); if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { return -EINVAL; } + ep_ctrl_value = ep_regs[ep_idx].ep_ctrl.value & ~ENDPOINT_READY_BIT; + switch (ctrl) { case EP_IN_DIRECTION_SET: - ep_regs[ep_idx].ep_ctrl.fields.direction_bit = enable; + if (enable) { + ep_ctrl_value |= ENDPOINT_DIRECTION_BIT; + } else { + ep_ctrl_value &= ~ENDPOINT_DIRECTION_BIT; + } break; case EP_STALL_SEND: - ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit = enable; + if (enable) { + ep_ctrl_value |= ENDPOINT_SEND_STALL_BIT; + } else { + ep_ctrl_value &= ~ENDPOINT_SEND_STALL_BIT; + } break; case EP_STALL_CHECK: return ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit; case EP_IOS_ENABLE: - ep_regs[ep_idx].ep_ctrl.fields.iso_enable_bit = enable; + if (enable) { + ep_ctrl_value |= ENDPOINT_ISO_ENABLE_BIT; + } else { + ep_ctrl_value &= ~ENDPOINT_ISO_ENABLE_BIT; + } break; case EP_ENABLE: - ep_regs[ep_idx].ep_ctrl.fields.enable_bit = enable; + if (enable) { + ep_ctrl_value |= ENDPOINT_ENABLE_BIT; + } else { + ep_ctrl_value &= ~ENDPOINT_ENABLE_BIT; + } break; case EP_READY_ENABLE: - unsigned int key; - - key = irq_lock(); - ep_regs[ep_idx].ep_ctrl.fields.ready_bit = enable; - irq_unlock(key); + if (enable) { + ep_ctrl_value |= ENDPOINT_READY_BIT; + } else { + ep_ctrl_value &= ~ENDPOINT_READY_BIT; + } break; case EP_DATA_SEQ_1: - ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = enable; + if (enable) { + ep_ctrl_value |= ENDPOINT_OUTDATA_SEQ_BIT; + } else { + ep_ctrl_value &= ~ENDPOINT_OUTDATA_SEQ_BIT; + } break; case EP_DATA_SEQ_TOGGLE: if (!enable) { break; } - if (ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit) { - ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = 0; - } else { - ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = 1; - } + ep_ctrl_value ^= ENDPOINT_OUTDATA_SEQ_BIT; break; default: LOG_ERR("Unknown control type 0x%x", ctrl); return -EINVAL; } + + ep_regs[ep_idx].ep_ctrl.value = ep_ctrl_value; return 0; } @@ -490,12 +512,15 @@ static int it82xx2_usb_set_ep_ctrl(uint8_t ep, enum it82xx2_ep_ctrl ctrl, bool e { uint8_t ep_idx = USB_EP_GET_IDX(ep); int ret = 0; + unsigned int key; + key = irq_lock(); if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { ret = it82xx2_usb_extend_ep_ctrl(ep, ctrl, enable); } else { ret = it82xx2_usb_ep_ctrl(ep, ctrl, enable); } + irq_unlock(key); return ret; } @@ -548,7 +573,7 @@ static bool it82xx2_check_setup_following_out(void) ff_regs[EP0].ep_rx_fifo_dcnt_lsb == SETUP_DATA_CNT)); } -static inline void it82xx2_handler_setup(uint8_t fifo_idx, uint8_t ep_ctrl) +static inline void it82xx2_handler_setup(uint8_t fifo_idx) { struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; @@ -556,8 +581,8 @@ static inline void it82xx2_handler_setup(uint8_t fifo_idx, uint8_t ep_ctrl) uint8_t ep_idx = fifo_idx; /* wrong trans */ - if (ep_ctrl & EP_SEND_STALL) { - ep_regs[fifo_idx].ep_ctrl.fields.send_stall_bit = 0; + if (ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit) { + it82xx2_usb_set_ep_ctrl(fifo_idx, EP_STALL_SEND, false); udata0.st_state = STALL_SEND; ff_regs[fifo_idx].ep_rx_fifo_ctrl = FIFO_FORCE_EMPTY; LOG_DBG("Clear Stall Bit & RX FIFO"); @@ -596,14 +621,14 @@ static inline void it82xx2_handler_setup(uint8_t fifo_idx, uint8_t ep_ctrl) } } -static inline void it82xx2_handler_in(const uint8_t ep_idx, const uint8_t ep_ctrl) +static inline void it82xx2_handler_in(const uint8_t ep_idx) { struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; if (ep_idx == 0) { - if (ep_ctrl & EP_SEND_STALL) { - ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit = 0; + if (ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit) { + it82xx2_usb_set_ep_ctrl(ep_idx, EP_STALL_SEND, false); udata0.st_state = STALL_SEND; LOG_DBG("Clear Stall Bit"); return; @@ -657,9 +682,6 @@ static inline void it82xx2_handler_in(const uint8_t ep_idx, const uint8_t ep_ctr static inline void it82xx2_handler_out(const uint8_t ep_idx) { - struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); - struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; - if (ep_idx == 0) { /* ep0 wrong enter check */ if (udata0.st_state >= STATUS_ST) { @@ -688,7 +710,7 @@ static inline void it82xx2_handler_out(const uint8_t ep_idx) udata0.last_token = udata0.now_token; udata0.now_token = SETUP_TOKEN; udata0.st_state = SETUP_ST; - ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = 1; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_DATA_SEQ_1, true); udata0.ep_data[ep_idx].cb_out(ep_idx | USB_EP_DIR_OUT, USB_DC_EP_SETUP); if (udata0.no_data_ctrl) { @@ -799,12 +821,10 @@ static bool it82xx2_usb_fake_token(const uint8_t ep_idx, uint8_t *token_type) static void it82xx2_usb_dc_trans_done(void) { struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); - struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; struct epn_ext_ctrl_regs *epn_ext_ctrl = usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; for (uint8_t fifo_idx = 0; fifo_idx < 4; fifo_idx++) { - uint8_t ep_ctrl = ep_regs[fifo_idx].ep_ctrl.value; uint8_t ep_idx, token_type; if (fifo_idx == 0) { @@ -819,10 +839,10 @@ static void it82xx2_usb_dc_trans_done(void) if (!it82xx2_usb_fake_token(ep_idx, &token_type)) { switch (token_type) { case DC_SETUP_TRANS: - it82xx2_handler_setup(fifo_idx, ep_ctrl); + it82xx2_handler_setup(fifo_idx); break; case DC_IN_TRANS: - it82xx2_handler_in(ep_idx, ep_ctrl); + it82xx2_handler_in(ep_idx); break; case DC_OUTDATA_TRANS: it82xx2_handler_out(ep_idx); @@ -1001,7 +1021,7 @@ int usb_dc_reset(void) } } - ep_regs[0].ep_ctrl.value = ENDPOINT_EN; + ep_regs[0].ep_ctrl.value = ENDPOINT_ENABLE_BIT; usb_regs->dc_address = DC_ADDR_NULL; udata0.addr = DC_ADDR_NULL; usb_regs->dc_interrupt_status = DC_NAK_SENT_INT | DC_SOF_RECEIVED; @@ -1093,9 +1113,7 @@ int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data *const cfg) it82xx2_usb_set_ep_ctrl(ep_idx, EP_IN_DIRECTION_SET, in); if (in) { - if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { - it82xx2_usb_extend_ep_ctrl(ep_idx, EP_DATA_SEQ_1, false); - } + it82xx2_usb_set_ep_ctrl(ep_idx, EP_DATA_SEQ_1, false); udata0.ep_data[ep_idx].ep_status = EP_CONFIG_IN; } else { udata0.ep_data[ep_idx].ep_status = EP_CONFIG_OUT; @@ -1215,7 +1233,7 @@ int usb_dc_ep_set_stall(const uint8_t ep) } if (idx < 198) { - ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit = 0; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_STALL_SEND, false); } udata0.no_data_ctrl = false; @@ -1432,7 +1450,7 @@ int usb_dc_ep_read(uint8_t ep, uint8_t *buf, uint32_t max_data_len, ff_regs[0].ep_tx_fifo_ctrl = FIFO_FORCE_EMPTY; if (buf[6] != 0 || buf[7] != 0) { /* set status IN after data OUT */ - ep_regs[0].ep_ctrl.fields.outdata_sequence_bit = 1; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_DATA_SEQ_1, true); it82xx2_usb_set_ep_ctrl(ep_idx, EP_READY_ENABLE, true); } else { /* no_data_ctrl status */