drivers: udc: mcux: move isr context codes to work context
Move the transfer process codes to work context becuase it lock the mutex, move bus reset process codes too because it calls some common udc apis (they may add mutex lock in future). Signed-off-by: Mark Wang <yichang.wang@nxp.com>
This commit is contained in:
parent
b9a3edc43a
commit
f378de7e46
3 changed files with 247 additions and 137 deletions
|
@ -7,6 +7,7 @@ config UDC_NXP_EHCI
|
|||
depends on DT_HAS_NXP_EHCI_ENABLED
|
||||
select NOCACHE_MEMORY if HAS_MCUX_CACHE && CPU_HAS_DCACHE
|
||||
imply UDC_BUF_FORCE_NOCACHE
|
||||
imply UDC_WORKQUEUE
|
||||
help
|
||||
NXP MCUX USB Device Controller Driver for EHCI.
|
||||
|
||||
|
@ -14,5 +15,14 @@ config UDC_NXP_IP3511
|
|||
bool "NXP MCUX USB IP3511 Device controller driver"
|
||||
default y
|
||||
depends on DT_HAS_NXP_LPCIP3511_ENABLED
|
||||
imply UDC_WORKQUEUE
|
||||
help
|
||||
NXP MCUX USB Device Controller Driver for KHCI.
|
||||
NXP MCUX USB Device Controller Driver for IP3511.
|
||||
|
||||
config UDC_NXP_EVENT_COUNT
|
||||
int "Number or blocks in event slab"
|
||||
depends on UDC_NXP_EHCI || UDC_NXP_IP3511
|
||||
range 4 16
|
||||
default 4
|
||||
help
|
||||
Number of blocks in slab for internal controller events.
|
||||
|
|
|
@ -49,9 +49,31 @@ struct udc_mcux_config {
|
|||
struct udc_mcux_data {
|
||||
const struct device *dev;
|
||||
usb_device_struct_t mcux_device;
|
||||
struct k_work work;
|
||||
struct k_fifo fifo;
|
||||
uint8_t controller_id; /* 0xFF is invalid value */
|
||||
};
|
||||
|
||||
/* Structure for driver's events */
|
||||
struct udc_mcux_event {
|
||||
sys_snode_t node;
|
||||
const struct device *dev;
|
||||
usb_device_callback_message_struct_t mcux_msg;
|
||||
};
|
||||
|
||||
K_MEM_SLAB_DEFINE(udc_event_slab, sizeof(struct udc_mcux_event),
|
||||
CONFIG_UDC_NXP_EVENT_COUNT, sizeof(void *));
|
||||
|
||||
static int udc_mcux_lock(const struct device *dev)
|
||||
{
|
||||
return udc_lock_internal(dev, K_FOREVER);
|
||||
}
|
||||
|
||||
static int udc_mcux_unlock(const struct device *dev)
|
||||
{
|
||||
return udc_unlock_internal(dev);
|
||||
}
|
||||
|
||||
static int udc_mcux_control(const struct device *dev, usb_device_control_type_t command,
|
||||
void *param)
|
||||
{
|
||||
|
@ -81,7 +103,6 @@ static int udc_mcux_ep_feed(const struct device *dev,
|
|||
usb_status_t status = kStatus_USB_Success;
|
||||
uint8_t *data;
|
||||
uint32_t len;
|
||||
unsigned int key;
|
||||
usb_device_endpoint_status_struct_t ep_status;
|
||||
|
||||
ep_status.endpointAddress = cfg->addr;
|
||||
|
@ -90,10 +111,10 @@ static int udc_mcux_ep_feed(const struct device *dev,
|
|||
return -EACCES; /* stalled */
|
||||
}
|
||||
|
||||
key = irq_lock();
|
||||
udc_mcux_lock(dev);
|
||||
if (!udc_ep_is_busy(dev, cfg->addr)) {
|
||||
udc_ep_set_busy(dev, cfg->addr, true);
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(cfg->addr)) {
|
||||
len = net_buf_tailroom(buf);
|
||||
|
@ -107,13 +128,13 @@ static int udc_mcux_ep_feed(const struct device *dev,
|
|||
cfg->addr, data, len);
|
||||
}
|
||||
|
||||
key = irq_lock();
|
||||
udc_mcux_lock(dev);
|
||||
if (status != kStatus_USB_Success) {
|
||||
udc_ep_set_busy(dev, cfg->addr, false);
|
||||
}
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
} else {
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -303,13 +324,12 @@ static int udc_mcux_handler_out(const struct device *dev, uint8_t ep,
|
|||
{
|
||||
int err;
|
||||
struct net_buf *buf;
|
||||
unsigned int key;
|
||||
|
||||
buf = udc_buf_get(dev, ep);
|
||||
|
||||
key = irq_lock();
|
||||
udc_mcux_lock(dev);
|
||||
udc_ep_set_busy(dev, ep, false);
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
|
||||
if (buf == NULL) {
|
||||
udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS);
|
||||
|
@ -357,7 +377,6 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep,
|
|||
{
|
||||
int err;
|
||||
struct net_buf *buf;
|
||||
unsigned int key;
|
||||
|
||||
buf = udc_buf_peek(dev, ep);
|
||||
if (buf == NULL) {
|
||||
|
@ -371,9 +390,9 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep,
|
|||
|
||||
buf = udc_buf_get(dev, ep);
|
||||
|
||||
key = irq_lock();
|
||||
udc_mcux_lock(dev);
|
||||
udc_ep_set_busy(dev, ep, false);
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
|
||||
if (buf == NULL) {
|
||||
udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS);
|
||||
|
@ -388,16 +407,95 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep,
|
|||
return err;
|
||||
}
|
||||
|
||||
static void udc_mcux_event_submit(const struct device *dev,
|
||||
const usb_device_callback_message_struct_t *mcux_msg)
|
||||
{
|
||||
struct udc_mcux_data *priv = udc_get_private(dev);
|
||||
struct udc_mcux_event *ev;
|
||||
int ret;
|
||||
|
||||
ret = k_mem_slab_alloc(&udc_event_slab, (void **)&ev, K_NO_WAIT);
|
||||
if (ret) {
|
||||
udc_submit_event(dev, UDC_EVT_ERROR, ret);
|
||||
LOG_ERR("Failed to allocate slab");
|
||||
return;
|
||||
}
|
||||
|
||||
ev->dev = dev;
|
||||
ev->mcux_msg = *mcux_msg;
|
||||
k_fifo_put(&priv->fifo, ev);
|
||||
k_work_submit_to_queue(udc_get_work_q(), &priv->work);
|
||||
}
|
||||
|
||||
static void udc_mcux_work_handler(struct k_work *item)
|
||||
{
|
||||
struct udc_mcux_event *ev;
|
||||
struct udc_mcux_data *priv;
|
||||
usb_device_callback_message_struct_t *mcux_msg;
|
||||
int err;
|
||||
uint8_t ep;
|
||||
|
||||
priv = CONTAINER_OF(item, struct udc_mcux_data, work);
|
||||
while ((ev = k_fifo_get(&priv->fifo, K_NO_WAIT)) != NULL) {
|
||||
mcux_msg = &ev->mcux_msg;
|
||||
|
||||
if (mcux_msg->code == kUSB_DeviceNotifyBusReset) {
|
||||
struct udc_ep_config *cfg;
|
||||
|
||||
udc_mcux_control(ev->dev, kUSB_DeviceControlSetDefaultStatus, NULL);
|
||||
cfg = udc_get_ep_cfg(ev->dev, USB_CONTROL_EP_OUT);
|
||||
if (cfg->stat.enabled) {
|
||||
udc_ep_disable_internal(ev->dev, USB_CONTROL_EP_OUT);
|
||||
}
|
||||
cfg = udc_get_ep_cfg(ev->dev, USB_CONTROL_EP_IN);
|
||||
if (cfg->stat.enabled) {
|
||||
udc_ep_disable_internal(ev->dev, USB_CONTROL_EP_IN);
|
||||
}
|
||||
if (udc_ep_enable_internal(ev->dev, USB_CONTROL_EP_OUT,
|
||||
USB_EP_TYPE_CONTROL,
|
||||
USB_MCUX_EP0_SIZE, 0)) {
|
||||
LOG_ERR("Failed to enable control endpoint");
|
||||
}
|
||||
|
||||
if (udc_ep_enable_internal(ev->dev, USB_CONTROL_EP_IN,
|
||||
USB_EP_TYPE_CONTROL,
|
||||
USB_MCUX_EP0_SIZE, 0)) {
|
||||
LOG_ERR("Failed to enable control endpoint");
|
||||
}
|
||||
udc_submit_event(ev->dev, UDC_EVT_RESET, 0);
|
||||
} else {
|
||||
ep = mcux_msg->code;
|
||||
|
||||
if (mcux_msg->isSetup) {
|
||||
struct usb_setup_packet *setup =
|
||||
(struct usb_setup_packet *)mcux_msg->buffer;
|
||||
|
||||
err = udc_mcux_handler_setup(ev->dev, setup);
|
||||
} else if (USB_EP_DIR_IS_IN(ep)) {
|
||||
err = udc_mcux_handler_in(ev->dev, ep, mcux_msg->buffer,
|
||||
mcux_msg->length);
|
||||
} else {
|
||||
err = udc_mcux_handler_out(ev->dev, ep, mcux_msg->buffer,
|
||||
mcux_msg->length);
|
||||
}
|
||||
|
||||
if (unlikely(err)) {
|
||||
udc_submit_event(ev->dev, UDC_EVT_ERROR, err);
|
||||
}
|
||||
}
|
||||
|
||||
k_mem_slab_free(&udc_event_slab, (void *)ev);
|
||||
}
|
||||
}
|
||||
|
||||
/* NXP MCUX controller driver notify transfers/status through this interface */
|
||||
usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
|
||||
{
|
||||
usb_device_callback_message_struct_t *mcux_msg = msg;
|
||||
uint8_t ep;
|
||||
usb_device_notification_t mcux_notify;
|
||||
struct udc_mcux_data *priv;
|
||||
const struct device *dev;
|
||||
usb_status_t mcux_status = kStatus_USB_Success;
|
||||
int err = 0;
|
||||
|
||||
if ((NULL == msg) || (NULL == handle)) {
|
||||
return kStatus_USB_InvalidHandle;
|
||||
|
@ -409,31 +507,7 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
|
|||
|
||||
switch (mcux_notify) {
|
||||
case kUSB_DeviceNotifyBusReset:
|
||||
struct udc_ep_config *cfg;
|
||||
|
||||
udc_mcux_control(dev, kUSB_DeviceControlSetDefaultStatus, NULL);
|
||||
cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT);
|
||||
if (cfg->stat.enabled) {
|
||||
udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT);
|
||||
}
|
||||
cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN);
|
||||
if (cfg->stat.enabled) {
|
||||
udc_ep_disable_internal(dev, USB_CONTROL_EP_IN);
|
||||
}
|
||||
if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT,
|
||||
USB_EP_TYPE_CONTROL,
|
||||
USB_MCUX_EP0_SIZE, 0)) {
|
||||
LOG_ERR("Failed to enable control endpoint");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN,
|
||||
USB_EP_TYPE_CONTROL,
|
||||
USB_MCUX_EP0_SIZE, 0)) {
|
||||
LOG_ERR("Failed to enable control endpoint");
|
||||
return -EIO;
|
||||
}
|
||||
udc_submit_event(dev, UDC_EVT_RESET, 0);
|
||||
udc_mcux_event_submit(dev, mcux_msg);
|
||||
break;
|
||||
case kUSB_DeviceNotifyError:
|
||||
udc_submit_event(dev, UDC_EVT_ERROR, -EIO);
|
||||
|
@ -458,25 +532,10 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
|
|||
udc_submit_event(dev, UDC_EVT_SOF, 0);
|
||||
break;
|
||||
default:
|
||||
ep = mcux_msg->code;
|
||||
if (mcux_msg->isSetup) {
|
||||
struct usb_setup_packet *setup =
|
||||
(struct usb_setup_packet *)mcux_msg->buffer;
|
||||
|
||||
err = udc_mcux_handler_setup(dev, setup);
|
||||
} else if (USB_EP_DIR_IS_IN(ep)) {
|
||||
err = udc_mcux_handler_in(dev, ep, mcux_msg->buffer, mcux_msg->length);
|
||||
} else {
|
||||
err = udc_mcux_handler_out(dev, ep, mcux_msg->buffer, mcux_msg->length);
|
||||
}
|
||||
|
||||
udc_mcux_event_submit(dev, mcux_msg);
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely(err)) {
|
||||
udc_submit_event(dev, UDC_EVT_ERROR, err);
|
||||
mcux_status = kStatus_USB_Error;
|
||||
}
|
||||
return mcux_status;
|
||||
}
|
||||
|
||||
|
@ -532,7 +591,6 @@ static int udc_mcux_ep_dequeue(const struct device *dev,
|
|||
struct udc_ep_config *const cfg)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
unsigned int key;
|
||||
|
||||
cfg->stat.halted = false;
|
||||
buf = udc_buf_get_all(dev, cfg->addr);
|
||||
|
@ -540,9 +598,9 @@ static int udc_mcux_ep_dequeue(const struct device *dev,
|
|||
udc_submit_ep_event(dev, buf, -ECONNABORTED);
|
||||
}
|
||||
|
||||
key = irq_lock();
|
||||
udc_mcux_lock(dev);
|
||||
udc_ep_set_busy(dev, cfg->addr, false);
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -676,16 +734,6 @@ static int udc_mcux_shutdown(const struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int udc_mcux_lock(const struct device *dev)
|
||||
{
|
||||
return udc_lock_internal(dev, K_FOREVER);
|
||||
}
|
||||
|
||||
static int udc_mcux_unlock(const struct device *dev)
|
||||
{
|
||||
return udc_unlock_internal(dev);
|
||||
}
|
||||
|
||||
static inline void udc_mcux_get_hal_driver_id(struct udc_mcux_data *priv,
|
||||
const struct udc_mcux_config *config)
|
||||
{
|
||||
|
@ -723,6 +771,8 @@ static int udc_mcux_driver_preinit(const struct device *dev)
|
|||
}
|
||||
|
||||
k_mutex_init(&data->mutex);
|
||||
k_fifo_init(&priv->fifo);
|
||||
k_work_init(&priv->work, udc_mcux_work_handler);
|
||||
|
||||
for (int i = 0; i < config->num_of_eps; i++) {
|
||||
config->ep_cfg_out[i].caps.out = 1;
|
||||
|
|
|
@ -49,9 +49,31 @@ struct udc_mcux_config {
|
|||
struct udc_mcux_data {
|
||||
const struct device *dev;
|
||||
usb_device_struct_t mcux_device;
|
||||
struct k_work work;
|
||||
struct k_fifo fifo;
|
||||
uint8_t controller_id; /* 0xFF is invalid value */
|
||||
};
|
||||
|
||||
/* Structure for driver's events */
|
||||
struct udc_mcux_event {
|
||||
sys_snode_t node;
|
||||
const struct device *dev;
|
||||
usb_device_callback_message_struct_t mcux_msg;
|
||||
};
|
||||
|
||||
K_MEM_SLAB_DEFINE(udc_event_slab, sizeof(struct udc_mcux_event),
|
||||
CONFIG_UDC_NXP_EVENT_COUNT, sizeof(void *));
|
||||
|
||||
static int udc_mcux_lock(const struct device *dev)
|
||||
{
|
||||
return udc_lock_internal(dev, K_FOREVER);
|
||||
}
|
||||
|
||||
static int udc_mcux_unlock(const struct device *dev)
|
||||
{
|
||||
return udc_unlock_internal(dev);
|
||||
}
|
||||
|
||||
static int udc_mcux_control(const struct device *dev, usb_device_control_type_t command,
|
||||
void *param)
|
||||
{
|
||||
|
@ -81,7 +103,6 @@ static int udc_mcux_ep_feed(const struct device *dev,
|
|||
usb_status_t status = kStatus_USB_Success;
|
||||
uint8_t *data;
|
||||
uint32_t len;
|
||||
unsigned int key;
|
||||
usb_device_endpoint_status_struct_t ep_status;
|
||||
|
||||
ep_status.endpointAddress = cfg->addr;
|
||||
|
@ -90,10 +111,10 @@ static int udc_mcux_ep_feed(const struct device *dev,
|
|||
return -EACCES; /* stalled */
|
||||
}
|
||||
|
||||
key = irq_lock();
|
||||
udc_mcux_lock(dev);
|
||||
if (!udc_ep_is_busy(dev, cfg->addr)) {
|
||||
udc_ep_set_busy(dev, cfg->addr, true);
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(cfg->addr)) {
|
||||
len = net_buf_tailroom(buf);
|
||||
|
@ -107,13 +128,13 @@ static int udc_mcux_ep_feed(const struct device *dev,
|
|||
cfg->addr, data, len);
|
||||
}
|
||||
|
||||
key = irq_lock();
|
||||
udc_mcux_lock(dev);
|
||||
if (status != kStatus_USB_Success) {
|
||||
udc_ep_set_busy(dev, cfg->addr, false);
|
||||
}
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
} else {
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -303,13 +324,12 @@ static int udc_mcux_handler_out(const struct device *dev, uint8_t ep,
|
|||
{
|
||||
int err;
|
||||
struct net_buf *buf;
|
||||
unsigned int key;
|
||||
|
||||
buf = udc_buf_get(dev, ep);
|
||||
|
||||
key = irq_lock();
|
||||
udc_mcux_lock(dev);
|
||||
udc_ep_set_busy(dev, ep, false);
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
|
||||
if (buf == NULL) {
|
||||
udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS);
|
||||
|
@ -357,7 +377,6 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep,
|
|||
{
|
||||
int err;
|
||||
struct net_buf *buf;
|
||||
unsigned int key;
|
||||
|
||||
buf = udc_buf_peek(dev, ep);
|
||||
if (buf == NULL) {
|
||||
|
@ -371,9 +390,9 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep,
|
|||
|
||||
buf = udc_buf_get(dev, ep);
|
||||
|
||||
key = irq_lock();
|
||||
udc_mcux_lock(dev);
|
||||
udc_ep_set_busy(dev, ep, false);
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
|
||||
if (buf == NULL) {
|
||||
udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS);
|
||||
|
@ -388,16 +407,95 @@ static int udc_mcux_handler_in(const struct device *dev, uint8_t ep,
|
|||
return err;
|
||||
}
|
||||
|
||||
static void udc_mcux_event_submit(const struct device *dev,
|
||||
const usb_device_callback_message_struct_t *mcux_msg)
|
||||
{
|
||||
struct udc_mcux_data *priv = udc_get_private(dev);
|
||||
struct udc_mcux_event *ev;
|
||||
int ret;
|
||||
|
||||
ret = k_mem_slab_alloc(&udc_event_slab, (void **)&ev, K_NO_WAIT);
|
||||
if (ret) {
|
||||
udc_submit_event(dev, UDC_EVT_ERROR, ret);
|
||||
LOG_ERR("Failed to allocate slab");
|
||||
return;
|
||||
}
|
||||
|
||||
ev->dev = dev;
|
||||
ev->mcux_msg = *mcux_msg;
|
||||
k_fifo_put(&priv->fifo, ev);
|
||||
k_work_submit_to_queue(udc_get_work_q(), &priv->work);
|
||||
}
|
||||
|
||||
static void udc_mcux_work_handler(struct k_work *item)
|
||||
{
|
||||
struct udc_mcux_event *ev;
|
||||
struct udc_mcux_data *priv;
|
||||
usb_device_callback_message_struct_t *mcux_msg;
|
||||
int err;
|
||||
uint8_t ep;
|
||||
|
||||
priv = CONTAINER_OF(item, struct udc_mcux_data, work);
|
||||
while ((ev = k_fifo_get(&priv->fifo, K_NO_WAIT)) != NULL) {
|
||||
mcux_msg = &ev->mcux_msg;
|
||||
|
||||
if (mcux_msg->code == kUSB_DeviceNotifyBusReset) {
|
||||
struct udc_ep_config *cfg;
|
||||
|
||||
udc_mcux_control(ev->dev, kUSB_DeviceControlSetDefaultStatus, NULL);
|
||||
cfg = udc_get_ep_cfg(ev->dev, USB_CONTROL_EP_OUT);
|
||||
if (cfg->stat.enabled) {
|
||||
udc_ep_disable_internal(ev->dev, USB_CONTROL_EP_OUT);
|
||||
}
|
||||
cfg = udc_get_ep_cfg(ev->dev, USB_CONTROL_EP_IN);
|
||||
if (cfg->stat.enabled) {
|
||||
udc_ep_disable_internal(ev->dev, USB_CONTROL_EP_IN);
|
||||
}
|
||||
if (udc_ep_enable_internal(ev->dev, USB_CONTROL_EP_OUT,
|
||||
USB_EP_TYPE_CONTROL,
|
||||
USB_MCUX_EP0_SIZE, 0)) {
|
||||
LOG_ERR("Failed to enable control endpoint");
|
||||
}
|
||||
|
||||
if (udc_ep_enable_internal(ev->dev, USB_CONTROL_EP_IN,
|
||||
USB_EP_TYPE_CONTROL,
|
||||
USB_MCUX_EP0_SIZE, 0)) {
|
||||
LOG_ERR("Failed to enable control endpoint");
|
||||
}
|
||||
udc_submit_event(ev->dev, UDC_EVT_RESET, 0);
|
||||
} else {
|
||||
ep = mcux_msg->code;
|
||||
|
||||
if (mcux_msg->isSetup) {
|
||||
struct usb_setup_packet *setup =
|
||||
(struct usb_setup_packet *)mcux_msg->buffer;
|
||||
|
||||
err = udc_mcux_handler_setup(ev->dev, setup);
|
||||
} else if (USB_EP_DIR_IS_IN(ep)) {
|
||||
err = udc_mcux_handler_in(ev->dev, ep, mcux_msg->buffer,
|
||||
mcux_msg->length);
|
||||
} else {
|
||||
err = udc_mcux_handler_out(ev->dev, ep, mcux_msg->buffer,
|
||||
mcux_msg->length);
|
||||
}
|
||||
|
||||
if (unlikely(err)) {
|
||||
udc_submit_event(ev->dev, UDC_EVT_ERROR, err);
|
||||
}
|
||||
}
|
||||
|
||||
k_mem_slab_free(&udc_event_slab, (void *)ev);
|
||||
}
|
||||
}
|
||||
|
||||
/* NXP MCUX controller driver notify transfers/status through this interface */
|
||||
usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
|
||||
{
|
||||
usb_device_callback_message_struct_t *mcux_msg = msg;
|
||||
uint8_t ep;
|
||||
usb_device_notification_t mcux_notify;
|
||||
struct udc_mcux_data *priv;
|
||||
const struct device *dev;
|
||||
usb_status_t mcux_status = kStatus_USB_Success;
|
||||
int err = 0;
|
||||
|
||||
if ((NULL == msg) || (NULL == handle)) {
|
||||
return kStatus_USB_InvalidHandle;
|
||||
|
@ -409,31 +507,7 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
|
|||
|
||||
switch (mcux_notify) {
|
||||
case kUSB_DeviceNotifyBusReset:
|
||||
struct udc_ep_config *cfg;
|
||||
|
||||
udc_mcux_control(dev, kUSB_DeviceControlSetDefaultStatus, NULL);
|
||||
cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT);
|
||||
if (cfg->stat.enabled) {
|
||||
udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT);
|
||||
}
|
||||
cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN);
|
||||
if (cfg->stat.enabled) {
|
||||
udc_ep_disable_internal(dev, USB_CONTROL_EP_IN);
|
||||
}
|
||||
if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT,
|
||||
USB_EP_TYPE_CONTROL,
|
||||
USB_MCUX_EP0_SIZE, 0)) {
|
||||
LOG_ERR("Failed to enable control endpoint");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN,
|
||||
USB_EP_TYPE_CONTROL,
|
||||
USB_MCUX_EP0_SIZE, 0)) {
|
||||
LOG_ERR("Failed to enable control endpoint");
|
||||
return -EIO;
|
||||
}
|
||||
udc_submit_event(dev, UDC_EVT_RESET, 0);
|
||||
udc_mcux_event_submit(dev, mcux_msg);
|
||||
break;
|
||||
case kUSB_DeviceNotifyError:
|
||||
udc_submit_event(dev, UDC_EVT_ERROR, -EIO);
|
||||
|
@ -458,25 +532,10 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
|
|||
udc_submit_event(dev, UDC_EVT_SOF, 0);
|
||||
break;
|
||||
default:
|
||||
ep = mcux_msg->code;
|
||||
if (mcux_msg->isSetup) {
|
||||
struct usb_setup_packet *setup =
|
||||
(struct usb_setup_packet *)mcux_msg->buffer;
|
||||
|
||||
err = udc_mcux_handler_setup(dev, setup);
|
||||
} else if (USB_EP_DIR_IS_IN(ep)) {
|
||||
err = udc_mcux_handler_in(dev, ep, mcux_msg->buffer, mcux_msg->length);
|
||||
} else {
|
||||
err = udc_mcux_handler_out(dev, ep, mcux_msg->buffer, mcux_msg->length);
|
||||
}
|
||||
|
||||
udc_mcux_event_submit(dev, mcux_msg);
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely(err)) {
|
||||
udc_submit_event(dev, UDC_EVT_ERROR, err);
|
||||
mcux_status = kStatus_USB_Error;
|
||||
}
|
||||
return mcux_status;
|
||||
}
|
||||
|
||||
|
@ -532,7 +591,6 @@ static int udc_mcux_ep_dequeue(const struct device *dev,
|
|||
struct udc_ep_config *const cfg)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
unsigned int key;
|
||||
|
||||
cfg->stat.halted = false;
|
||||
buf = udc_buf_get_all(dev, cfg->addr);
|
||||
|
@ -540,9 +598,9 @@ static int udc_mcux_ep_dequeue(const struct device *dev,
|
|||
udc_submit_ep_event(dev, buf, -ECONNABORTED);
|
||||
}
|
||||
|
||||
key = irq_lock();
|
||||
udc_mcux_lock(dev);
|
||||
udc_ep_set_busy(dev, cfg->addr, false);
|
||||
irq_unlock(key);
|
||||
udc_mcux_unlock(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -676,16 +734,6 @@ static int udc_mcux_shutdown(const struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int udc_mcux_lock(const struct device *dev)
|
||||
{
|
||||
return udc_lock_internal(dev, K_FOREVER);
|
||||
}
|
||||
|
||||
static int udc_mcux_unlock(const struct device *dev)
|
||||
{
|
||||
return udc_unlock_internal(dev);
|
||||
}
|
||||
|
||||
static inline void udc_mcux_get_hal_driver_id(struct udc_mcux_data *priv,
|
||||
const struct udc_mcux_config *config)
|
||||
{
|
||||
|
@ -737,6 +785,8 @@ static int udc_mcux_driver_preinit(const struct device *dev)
|
|||
}
|
||||
|
||||
k_mutex_init(&data->mutex);
|
||||
k_fifo_init(&priv->fifo);
|
||||
k_work_init(&priv->work, udc_mcux_work_handler);
|
||||
|
||||
for (int i = 0; i < config->num_of_eps; i++) {
|
||||
config->ep_cfg_out[i].caps.out = 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue