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:
parent
67cdccc1c2
commit
efb286dfdf
3 changed files with 83 additions and 32 deletions
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "udc_common.h"
|
#include "udc_common.h"
|
||||||
#include "udc_dwc2.h"
|
#include "udc_dwc2.h"
|
||||||
#include "udc_dwc2_vendor_quirks.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -22,6 +21,7 @@
|
||||||
|
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
LOG_MODULE_REGISTER(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL);
|
LOG_MODULE_REGISTER(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL);
|
||||||
|
#include "udc_dwc2_vendor_quirks.h"
|
||||||
|
|
||||||
enum dwc2_drv_event_type {
|
enum dwc2_drv_event_type {
|
||||||
/* Trigger next transfer, must not be used for control OUT */
|
/* 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) {
|
(void)dwc2_quirk_irq_clear(dev);
|
||||||
config->quirks->irq_clear(dev);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int udc_dwc2_ep_enqueue(const struct device *dev,
|
static int udc_dwc2_ep_enqueue(const struct device *dev,
|
||||||
|
@ -1523,18 +1521,21 @@ static int udc_dwc2_enable(const struct device *dev)
|
||||||
struct usb_dwc2_reg *const base = dwc2_get_base(dev);
|
struct usb_dwc2_reg *const base = dwc2_get_base(dev);
|
||||||
int err;
|
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);
|
err = udc_dwc2_init_controller(dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call vendor-specific function to enable peripheral */
|
err = dwc2_quirk_post_enable(dev);
|
||||||
if (config->quirks != NULL && config->quirks->pwr_on != NULL) {
|
if (err) {
|
||||||
LOG_DBG("Enable vendor power");
|
LOG_ERR("Quirk post enable failed %d", err);
|
||||||
err = config->quirks->pwr_on(dev);
|
return err;
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable global interrupt */
|
/* Enable global interrupt */
|
||||||
|
@ -1553,6 +1554,7 @@ static int udc_dwc2_disable(const struct device *dev)
|
||||||
const struct udc_dwc2_config *const config = dev->config;
|
const struct udc_dwc2_config *const config = dev->config;
|
||||||
struct usb_dwc2_reg *const base = dwc2_get_base(dev);
|
struct usb_dwc2_reg *const base = dwc2_get_base(dev);
|
||||||
mem_addr_t dctl_reg = (mem_addr_t)&base->dctl;
|
mem_addr_t dctl_reg = (mem_addr_t)&base->dctl;
|
||||||
|
int err;
|
||||||
|
|
||||||
/* Enable soft disconnect */
|
/* Enable soft disconnect */
|
||||||
sys_set_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON);
|
sys_set_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON);
|
||||||
|
@ -1571,20 +1573,23 @@ static int udc_dwc2_disable(const struct device *dev)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = dwc2_quirk_disable(dev);
|
||||||
|
if (err) {
|
||||||
|
LOG_ERR("Quirk disable failed %d", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int udc_dwc2_init(const struct device *dev)
|
static int udc_dwc2_init(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct udc_dwc2_config *const config = dev->config;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (config->quirks != NULL && config->quirks->clk_enable != NULL) {
|
ret = dwc2_quirk_init(dev);
|
||||||
LOG_DBG("Enable vendor clock");
|
if (ret) {
|
||||||
ret = config->quirks->clk_enable(dev);
|
LOG_ERR("Quirk init failed %d", ret);
|
||||||
if (ret) {
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dwc2_init_pinctrl(dev);
|
return dwc2_init_pinctrl(dev);
|
||||||
|
@ -1592,6 +1597,14 @@ static int udc_dwc2_init(const struct device *dev)
|
||||||
|
|
||||||
static int udc_dwc2_shutdown(const struct device *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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,17 @@
|
||||||
|
|
||||||
/* Vendor quirks per driver instance */
|
/* Vendor quirks per driver instance */
|
||||||
struct dwc2_vendor_quirks {
|
struct dwc2_vendor_quirks {
|
||||||
int (*clk_enable)(const struct device *dev);
|
/* Called at the beginning of udc_dwc2_init() */
|
||||||
int (*clk_disable)(const struct device *dev);
|
int (*init)(const struct device *dev);
|
||||||
int (*pwr_on)(const struct device *dev);
|
/* Called on udc_dwc2_enable() before the controller is initialized */
|
||||||
int (*pwr_off)(const struct device *dev);
|
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);
|
int (*irq_clear)(const struct device *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,4 +44,24 @@ struct udc_dwc2_config {
|
||||||
void (*irq_disable_func)(const struct device *dev);
|
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 */
|
#endif /* ZEPHYR_DRIVERS_USB_UDC_DWC2_H */
|
||||||
|
|
|
@ -11,13 +11,13 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <zephyr/device.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)
|
#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 {
|
struct usb_dw_stm32_clk {
|
||||||
const struct device *const dev;
|
const struct device *const dev;
|
||||||
const struct stm32_pclken *const pclken;
|
const struct stm32_pclken *const pclken;
|
||||||
|
@ -26,7 +26,7 @@ struct usb_dw_stm32_clk {
|
||||||
|
|
||||||
#define DT_DRV_COMPAT snps_dwc2
|
#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;
|
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]);
|
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;
|
const struct udc_dwc2_config *const config = dev->config;
|
||||||
mem_addr_t ggpio_reg = (mem_addr_t)&config->base->ggpio;
|
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;
|
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) \
|
#define QUIRK_STM32F4_FSOTG_DEFINE(n) \
|
||||||
static const struct stm32_pclken pclken_##n[] = STM32_DT_INST_CLOCKS(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), \
|
.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 = { \
|
struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \
|
||||||
.clk_enable = clk_enable_stm32f4_fsotg_##n, \
|
.pre_enable = stm32f4_fsotg_enable_clk_##n, \
|
||||||
.pwr_on = pwr_on_stm32f4_fsotg, \
|
.post_enable = stm32f4_fsotg_enable_phy, \
|
||||||
|
.disable = stm32f4_fsotg_disable_phy, \
|
||||||
.irq_clear = NULL, \
|
.irq_clear = NULL, \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue