drivers: udc_dwc2: rework vendor quirks

Rework and rename vendor quirks to better reflect where they intended to
be called. Number of quirks probably not final and will be trimmed
later.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
This commit is contained in:
Johann Fischer 2024-05-14 14:10:30 +02:00 committed by Fabio Baltieri
commit efb286dfdf
3 changed files with 83 additions and 32 deletions

View file

@ -6,7 +6,6 @@
#include "udc_common.h"
#include "udc_dwc2.h"
#include "udc_dwc2_vendor_quirks.h"
#include <string.h>
#include <stdio.h>
@ -22,6 +21,7 @@
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL);
#include "udc_dwc2_vendor_quirks.h"
enum dwc2_drv_event_type {
/* Trigger next transfer, must not be used for control OUT */
@ -904,9 +904,7 @@ static void udc_dwc2_isr_handler(const struct device *dev)
}
}
if (config->quirks != NULL && config->quirks->irq_clear != NULL) {
config->quirks->irq_clear(dev);
}
(void)dwc2_quirk_irq_clear(dev);
}
static int udc_dwc2_ep_enqueue(const struct device *dev,
@ -1523,19 +1521,22 @@ static int udc_dwc2_enable(const struct device *dev)
struct usb_dwc2_reg *const base = dwc2_get_base(dev);
int err;
err = dwc2_quirk_pre_enable(dev);
if (err) {
LOG_ERR("Quirk pre enable failed %d", err);
return err;
}
err = udc_dwc2_init_controller(dev);
if (err) {
return err;
}
/* Call vendor-specific function to enable peripheral */
if (config->quirks != NULL && config->quirks->pwr_on != NULL) {
LOG_DBG("Enable vendor power");
err = config->quirks->pwr_on(dev);
err = dwc2_quirk_post_enable(dev);
if (err) {
LOG_ERR("Quirk post enable failed %d", err);
return err;
}
}
/* Enable global interrupt */
sys_set_bits((mem_addr_t)&base->gahbcfg, USB_DWC2_GAHBCFG_GLBINTRMASK);
@ -1553,6 +1554,7 @@ static int udc_dwc2_disable(const struct device *dev)
const struct udc_dwc2_config *const config = dev->config;
struct usb_dwc2_reg *const base = dwc2_get_base(dev);
mem_addr_t dctl_reg = (mem_addr_t)&base->dctl;
int err;
/* Enable soft disconnect */
sys_set_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON);
@ -1571,27 +1573,38 @@ static int udc_dwc2_disable(const struct device *dev)
return -EIO;
}
err = dwc2_quirk_disable(dev);
if (err) {
LOG_ERR("Quirk disable failed %d", err);
return err;
}
return 0;
}
static int udc_dwc2_init(const struct device *dev)
{
const struct udc_dwc2_config *const config = dev->config;
int ret;
if (config->quirks != NULL && config->quirks->clk_enable != NULL) {
LOG_DBG("Enable vendor clock");
ret = config->quirks->clk_enable(dev);
ret = dwc2_quirk_init(dev);
if (ret) {
LOG_ERR("Quirk init failed %d", ret);
return ret;
}
}
return dwc2_init_pinctrl(dev);
}
static int udc_dwc2_shutdown(const struct device *dev)
{
int ret;
ret = dwc2_quirk_shutdown(dev);
if (ret) {
LOG_ERR("Quirk shutdown failed %d", ret);
return ret;
}
return 0;
}

View file

@ -14,10 +14,17 @@
/* Vendor quirks per driver instance */
struct dwc2_vendor_quirks {
int (*clk_enable)(const struct device *dev);
int (*clk_disable)(const struct device *dev);
int (*pwr_on)(const struct device *dev);
int (*pwr_off)(const struct device *dev);
/* Called at the beginning of udc_dwc2_init() */
int (*init)(const struct device *dev);
/* Called on udc_dwc2_enable() before the controller is initialized */
int (*pre_enable)(const struct device *dev);
/* Called on udc_dwc2_enable() after the controller is initialized */
int (*post_enable)(const struct device *dev);
/* Called at the end of udc_dwc2_disable() */
int (*disable)(const struct device *dev);
/* Called at the end of udc_dwc2_shutdown() */
int (*shutdown)(const struct device *dev);
/* Called at the end of IRQ handling */
int (*irq_clear)(const struct device *dev);
};
@ -37,4 +44,24 @@ struct udc_dwc2_config {
void (*irq_disable_func)(const struct device *dev);
};
#define DWC2_QUIRK_FUNC_DEFINE(fname) \
static inline int dwc2_quirk_##fname(const struct device *dev) \
{ \
const struct udc_dwc2_config *const config = dev->config; \
struct dwc2_vendor_quirks *quirks = config->quirks; \
\
if (quirks != NULL && config->quirks->fname != NULL) { \
return quirks->fname(dev); \
} \
\
return 0; \
}
DWC2_QUIRK_FUNC_DEFINE(init)
DWC2_QUIRK_FUNC_DEFINE(pre_enable)
DWC2_QUIRK_FUNC_DEFINE(post_enable)
DWC2_QUIRK_FUNC_DEFINE(disable)
DWC2_QUIRK_FUNC_DEFINE(shutdown)
DWC2_QUIRK_FUNC_DEFINE(irq_clear)
#endif /* ZEPHYR_DRIVERS_USB_UDC_DWC2_H */

View file

@ -11,13 +11,13 @@
#include <stdint.h>
#include <zephyr/device.h>
#include <zephyr/sys/sys_io.h>
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
#include <usb_dwc2_hw.h>
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_fsotg)
#include <zephyr/sys/sys_io.h>
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
#include <usb_dwc2_hw.h>
struct usb_dw_stm32_clk {
const struct device *const dev;
const struct stm32_pclken *const pclken;
@ -26,7 +26,7 @@ struct usb_dw_stm32_clk {
#define DT_DRV_COMPAT snps_dwc2
static inline int clk_enable_stm32f4_fsotg(const struct usb_dw_stm32_clk *const clk)
static inline int stm32f4_fsotg_enable_clk(const struct usb_dw_stm32_clk *const clk)
{
int ret;
@ -59,7 +59,7 @@ static inline int clk_enable_stm32f4_fsotg(const struct usb_dw_stm32_clk *const
return clock_control_on(clk->dev, (void *)&clk->pclken[0]);
}
static inline int pwr_on_stm32f4_fsotg(const struct device *dev)
static inline int stm32f4_fsotg_enable_phy(const struct device *dev)
{
const struct udc_dwc2_config *const config = dev->config;
mem_addr_t ggpio_reg = (mem_addr_t)&config->base->ggpio;
@ -69,6 +69,16 @@ static inline int pwr_on_stm32f4_fsotg(const struct device *dev)
return 0;
}
static inline int stm32f4_fsotg_disable_phy(const struct device *dev)
{
const struct udc_dwc2_config *const config = dev->config;
mem_addr_t ggpio_reg = (mem_addr_t)&config->base->ggpio;
sys_clear_bits(ggpio_reg, USB_DWC2_GGPIO_STM32_PWRDWN | USB_DWC2_GGPIO_STM32_VBDEN);
return 0;
}
#define QUIRK_STM32F4_FSOTG_DEFINE(n) \
static const struct stm32_pclken pclken_##n[] = STM32_DT_INST_CLOCKS(n);\
\
@ -78,14 +88,15 @@ static inline int pwr_on_stm32f4_fsotg(const struct device *dev)
.pclken_len = DT_INST_NUM_CLOCKS(n), \
}; \
\
static int clk_enable_stm32f4_fsotg_##n(const struct device *dev) \
static int stm32f4_fsotg_enable_clk_##n(const struct device *dev) \
{ \
return clk_enable_stm32f4_fsotg(&stm32f4_clk_##n); \
return stm32f4_fsotg_enable_clk(&stm32f4_clk_##n); \
} \
\
struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \
.clk_enable = clk_enable_stm32f4_fsotg_##n, \
.pwr_on = pwr_on_stm32f4_fsotg, \
.pre_enable = stm32f4_fsotg_enable_clk_##n, \
.post_enable = stm32f4_fsotg_enable_phy, \
.disable = stm32f4_fsotg_disable_phy, \
.irq_clear = NULL, \
};