summaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r--drivers/usb/dwc2/core.c42
-rw-r--r--drivers/usb/dwc2/core.h8
-rw-r--r--drivers/usb/dwc2/core_intr.c26
-rw-r--r--drivers/usb/dwc2/debugfs.c1
-rw-r--r--drivers/usb/dwc2/gadget.c28
-rw-r--r--drivers/usb/dwc2/hcd.c10
-rw-r--r--drivers/usb/dwc2/hcd_queue.c52
-rw-r--r--drivers/usb/dwc2/hw.h14
-rw-r--r--drivers/usb/dwc2/params.c43
9 files changed, 176 insertions, 48 deletions
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 5635e4d7ec..9919ab725d 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -249,6 +249,11 @@ void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup,
dwc2_writel(hsotg, gpwrdn, GPWRDN);
udelay(10);
+ /* Reset ULPI latch */
+ gpwrdn = dwc2_readl(hsotg, GPWRDN);
+ gpwrdn &= ~GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY;
+ dwc2_writel(hsotg, gpwrdn, GPWRDN);
+
/* Disable PMU interrupt */
gpwrdn = dwc2_readl(hsotg, GPWRDN);
gpwrdn &= ~GPWRDN_PMUINTSEL;
@@ -975,6 +980,41 @@ void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
dwc2_writel(hsotg, hcfg, HCFG);
}
+static void dwc2_set_clock_switch_timer(struct dwc2_hsotg *hsotg)
+{
+ u32 grstctl, gsnpsid, val = 0;
+
+ gsnpsid = dwc2_readl(hsotg, GSNPSID);
+
+ /*
+ * Applicable only to HSOTG core v5.00a or higher.
+ * Not applicable to HS/FS IOT devices.
+ */
+ if ((gsnpsid & ~DWC2_CORE_REV_MASK) != DWC2_OTG_ID ||
+ gsnpsid < DWC2_CORE_REV_5_00a)
+ return;
+
+ if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI &&
+ hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED) ||
+ (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
+ hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED) ||
+ (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED &&
+ hsotg->hw_params.fs_phy_type != GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED)) {
+ val = GRSTCTL_CLOCK_SWITH_TIMER_VALUE_DIS;
+ }
+
+ if (hsotg->params.speed == DWC2_SPEED_PARAM_LOW &&
+ hsotg->hw_params.hs_phy_type != GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED &&
+ hsotg->hw_params.fs_phy_type != GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED) {
+ val = GRSTCTL_CLOCK_SWITH_TIMER_VALUE_147;
+ }
+
+ grstctl = dwc2_readl(hsotg, GRSTCTL);
+ grstctl &= ~GRSTCTL_CLOCK_SWITH_TIMER_MASK;
+ grstctl |= GRSTCTL_CLOCK_SWITH_TIMER(val);
+ dwc2_writel(hsotg, grstctl, GRSTCTL);
+}
+
static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
{
u32 usbcfg, ggpio, i2cctl;
@@ -992,6 +1032,8 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
usbcfg |= GUSBCFG_PHYSEL;
dwc2_writel(hsotg, usbcfg, GUSBCFG);
+ dwc2_set_clock_switch_timer(hsotg);
+
/* Reset after a PHY select */
retval = dwc2_core_reset(hsotg, false);
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index a141f83aba..2bd74f3033 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -288,6 +288,11 @@ enum dwc2_ep0_state {
* core has been configured to work at either data path
* width.
* 8 or 16 (default 16 if available)
+ * @eusb2_disc: Specifies whether eUSB2 PHY disconnect support flow
+ * applicable or no. Applicable in device mode of HSOTG
+ * and HS IOT cores v5.00 or higher.
+ * 0 - eUSB2 PHY disconnect support flow not applicable
+ * 1 - eUSB2 PHY disconnect support flow applicable
* @phy_ulpi_ddr: Specifies whether the ULPI operates at double or single
* data rate. This parameter is only applicable if phy_type
* is ULPI.
@@ -442,6 +447,7 @@ struct dwc2_core_params {
#define DWC2_SPEED_PARAM_LOW 2
u8 phy_utmi_width;
+ bool eusb2_disc;
bool phy_ulpi_ddr;
bool phy_ulpi_ext_vbus;
bool enable_dynamic_fifo;
@@ -1110,8 +1116,10 @@ struct dwc2_hsotg {
#define DWC2_CORE_REV_3_10a 0x4f54310a
#define DWC2_CORE_REV_4_00a 0x4f54400a
#define DWC2_CORE_REV_4_20a 0x4f54420a
+#define DWC2_CORE_REV_5_00a 0x4f54500a
#define DWC2_FS_IOT_REV_1_00a 0x5531100a
#define DWC2_HS_IOT_REV_1_00a 0x5532100a
+#define DWC2_HS_IOT_REV_5_00a 0x5532500a
#define DWC2_CORE_REV_MASK 0x0000ffff
/* DWC OTG HW Core ID */
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 26d752a4c3..7d3e641806 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -84,6 +84,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
u32 gotgint;
u32 gotgctl;
u32 gintmsk;
+ u32 pcgctl;
gotgint = dwc2_readl(hsotg, GOTGINT);
gotgctl = dwc2_readl(hsotg, GOTGCTL);
@@ -96,8 +97,22 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
dwc2_op_state_str(hsotg));
gotgctl = dwc2_readl(hsotg, GOTGCTL);
- if (dwc2_is_device_mode(hsotg))
+ if (dwc2_is_device_mode(hsotg)) {
+ if (hsotg->params.eusb2_disc) {
+ /* Clear the Gate hclk. */
+ pcgctl = dwc2_readl(hsotg, PCGCTL);
+ pcgctl &= ~PCGCTL_GATEHCLK;
+ dwc2_writel(hsotg, pcgctl, PCGCTL);
+ udelay(5);
+
+ /* Clear Phy Clock bit. */
+ pcgctl = dwc2_readl(hsotg, PCGCTL);
+ pcgctl &= ~PCGCTL_STOPPCLK;
+ dwc2_writel(hsotg, pcgctl, PCGCTL);
+ udelay(5);
+ }
dwc2_hsotg_disconnect(hsotg);
+ }
if (hsotg->op_state == OTG_STATE_B_HOST) {
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
@@ -117,7 +132,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
* disconnected
*/
/* Reset to a clean state */
- hsotg->lx_state = DWC2_L0;
+ hsotg->lx_state = DWC2_L3;
}
gotgctl = dwc2_readl(hsotg, GOTGCTL);
@@ -286,7 +301,7 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
hsotg->lx_state);
if (dwc2_is_device_mode(hsotg)) {
- if (hsotg->lx_state == DWC2_L2) {
+ if (hsotg->lx_state != DWC2_L0) {
if (hsotg->in_ppd) {
ret = dwc2_exit_partial_power_down(hsotg, 0,
true);
@@ -714,6 +729,11 @@ static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg,
gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+ /* Reset ULPI latch */
+ gpwrdn = dwc2_readl(hsotg, GPWRDN);
+ gpwrdn &= ~GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY;
+ dwc2_writel(hsotg, gpwrdn, GPWRDN);
+
/* De-assert Wakeup Logic */
gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
gpwrdn_tmp &= ~GPWRDN_PMUACTV;
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c
index 1d72ece9cf..7c82ab5904 100644
--- a/drivers/usb/dwc2/debugfs.c
+++ b/drivers/usb/dwc2/debugfs.c
@@ -686,6 +686,7 @@ static int params_show(struct seq_file *seq, void *v)
print_param(seq, p, host_channels);
print_param(seq, p, phy_type);
print_param(seq, p, phy_utmi_width);
+ print_param(seq, p, eusb2_disc);
print_param(seq, p, phy_ulpi_ddr);
print_param(seq, p, phy_ulpi_ext_vbus);
print_param(seq, p, i2c_enable);
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index b2f6da5b65..74ac79abd8 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3424,8 +3424,11 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
dwc2_hsotg_init_fifo(hsotg);
- if (!is_usb_reset)
+ if (!is_usb_reset) {
dwc2_set_bit(hsotg, DCTL, DCTL_SFTDISCON);
+ if (hsotg->params.eusb2_disc)
+ dwc2_set_bit(hsotg, GOTGCTL, GOTGCTL_EUSB2_DISC_SUPP);
+ }
dcfg |= DCFG_EPMISCNT(1);
@@ -5316,6 +5319,8 @@ void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg)
int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg)
{
u32 gpwrdn;
+ u32 gusbcfg;
+ u32 pcgcctl;
int ret = 0;
/* Change to L2(suspend) state */
@@ -5335,6 +5340,22 @@ int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg)
}
gpwrdn = GPWRDN_PWRDNRSTN;
+ udelay(10);
+ gusbcfg = dwc2_readl(hsotg, GUSBCFG);
+ if (gusbcfg & GUSBCFG_ULPI_UTMI_SEL) {
+ /* ULPI interface */
+ gpwrdn |= GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY;
+ }
+ dwc2_writel(hsotg, gpwrdn, GPWRDN);
+ udelay(10);
+
+ /* Suspend the Phy Clock */
+ pcgcctl = dwc2_readl(hsotg, PCGCTL);
+ pcgcctl |= PCGCTL_STOPPCLK;
+ dwc2_writel(hsotg, pcgcctl, PCGCTL);
+ udelay(10);
+
+ gpwrdn = dwc2_readl(hsotg, GPWRDN);
gpwrdn |= GPWRDN_PMUACTV;
dwc2_writel(hsotg, gpwrdn, GPWRDN);
udelay(10);
@@ -5435,6 +5456,11 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
if (reset)
dwc2_clear_bit(hsotg, DCFG, DCFG_DEVADDR_MASK);
+ /* Reset ULPI latch */
+ gpwrdn = dwc2_readl(hsotg, GPWRDN);
+ gpwrdn &= ~GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY;
+ dwc2_writel(hsotg, gpwrdn, GPWRDN);
+
/* De-assert Wakeup Logic */
gpwrdn = dwc2_readl(hsotg, GPWRDN);
gpwrdn &= ~GPWRDN_PMUACTV;
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index dd5b1c5691..cb54390e7d 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -5525,6 +5525,11 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg)
gusbcfg = dwc2_readl(hsotg, GUSBCFG);
if (gusbcfg & GUSBCFG_ULPI_UTMI_SEL) {
/* ULPI interface */
+ udelay(10);
+ gpwrdn = dwc2_readl(hsotg, GPWRDN);
+ gpwrdn |= GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY;
+ dwc2_writel(hsotg, gpwrdn, GPWRDN);
+ udelay(10);
/* Suspend the Phy Clock */
pcgcctl = dwc2_readl(hsotg, PCGCTL);
pcgcctl |= PCGCTL_STOPPCLK;
@@ -5631,6 +5636,11 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
dwc2_writel(hsotg, gr->gusbcfg, GUSBCFG);
dwc2_writel(hsotg, hr->hcfg, HCFG);
+ /* Reset ULPI latch */
+ gpwrdn = dwc2_readl(hsotg, GPWRDN);
+ gpwrdn &= ~GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY;
+ dwc2_writel(hsotg, gpwrdn, GPWRDN);
+
/* De-assert Wakeup Logic */
if (!(rem_wakeup && hsotg->hw_params.snpsid >= DWC2_CORE_REV_4_30a)) {
gpwrdn = dwc2_readl(hsotg, GPWRDN);
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 0d4495c6b9..238c6fd50e 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -16,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
+#include <linux/seq_buf.h>
#include <linux/slab.h>
#include <linux/usb.h>
@@ -360,41 +361,6 @@ static unsigned long *dwc2_get_ls_map(struct dwc2_hsotg *hsotg,
#ifdef DWC2_PRINT_SCHEDULE
/*
- * cat_printf() - A printf() + strcat() helper
- *
- * This is useful for concatenating a bunch of strings where each string is
- * constructed using printf.
- *
- * @buf: The destination buffer; will be updated to point after the printed
- * data.
- * @size: The number of bytes in the buffer (includes space for '\0').
- * @fmt: The format for printf.
- * @...: The args for printf.
- */
-static __printf(3, 4)
-void cat_printf(char **buf, size_t *size, const char *fmt, ...)
-{
- va_list args;
- int i;
-
- if (*size == 0)
- return;
-
- va_start(args, fmt);
- i = vsnprintf(*buf, *size, fmt, args);
- va_end(args);
-
- if (i >= *size) {
- (*buf)[*size - 1] = '\0';
- *buf += *size;
- *size = 0;
- } else {
- *buf += i;
- *size -= i;
- }
-}
-
-/*
* pmap_print() - Print the given periodic map
*
* Will attempt to print out the periodic schedule.
@@ -416,9 +382,7 @@ static void pmap_print(unsigned long *map, int bits_per_period,
int period;
for (period = 0; period < periods_in_map; period++) {
- char tmp[64];
- char *buf = tmp;
- size_t buf_size = sizeof(tmp);
+ DECLARE_SEQ_BUF(buf, 64);
int period_start = period * bits_per_period;
int period_end = period_start + bits_per_period;
int start = 0;
@@ -442,19 +406,19 @@ static void pmap_print(unsigned long *map, int bits_per_period,
continue;
if (!printed)
- cat_printf(&buf, &buf_size, "%s %d: ",
- period_name, period);
+ seq_buf_printf(&buf, "%s %d: ",
+ period_name, period);
else
- cat_printf(&buf, &buf_size, ", ");
+ seq_buf_puts(&buf, ", ");
printed = true;
- cat_printf(&buf, &buf_size, "%d %s -%3d %s", start,
- units, start + count - 1, units);
+ seq_buf_printf(&buf, "%d %s -%3d %s", start,
+ units, start + count - 1, units);
count = 0;
}
if (printed)
- print_fn(tmp, print_data);
+ print_fn(seq_buf_str(&buf), print_data);
}
}
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
index 12f8c7f86d..fe8c87a2f8 100644
--- a/drivers/usb/dwc2/hw.h
+++ b/drivers/usb/dwc2/hw.h
@@ -11,6 +11,7 @@
#define HSOTG_REG(x) (x)
#define GOTGCTL HSOTG_REG(0x000)
+#define GOTGCTL_EUSB2_DISC_SUPP BIT(28)
#define GOTGCTL_CHIRPEN BIT(27)
#define GOTGCTL_MULT_VALID_BC_MASK (0x1f << 22)
#define GOTGCTL_MULT_VALID_BC_SHIFT 22
@@ -98,6 +99,17 @@
#define GRSTCTL_AHBIDLE BIT(31)
#define GRSTCTL_DMAREQ BIT(30)
#define GRSTCTL_CSFTRST_DONE BIT(29)
+#define GRSTCTL_CLOCK_SWITH_TIMER_MASK (0x7 << 11)
+#define GRSTCTL_CLOCK_SWITH_TIMER_SHIFT 11
+#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_19 0x0
+#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_15 0x1
+#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_147 0x2
+#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_50 0x3
+#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_100 0x4
+#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_125 0x5
+#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_200 0x6
+#define GRSTCTL_CLOCK_SWITH_TIMER_VALUE_DIS 0x7
+#define GRSTCTL_CLOCK_SWITH_TIMER(_x) ((_x) << 11)
#define GRSTCTL_TXFNUM_MASK (0x1f << 6)
#define GRSTCTL_TXFNUM_SHIFT 6
#define GRSTCTL_TXFNUM_LIMIT 0x1f
@@ -332,6 +344,8 @@
#define GLPMCFG_LPMCAP BIT(0)
#define GPWRDN HSOTG_REG(0x0058)
+
+#define GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY BIT(29)
#define GPWRDN_MULT_VAL_ID_BC_MASK (0x1f << 24)
#define GPWRDN_MULT_VAL_ID_BC_SHIFT 24
#define GPWRDN_ADP_INT BIT(23)
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index eb677c3cfd..5a1500d0bd 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -201,6 +201,25 @@ static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg)
p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT;
}
+static void dwc2_set_cv1800_params(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_core_params *p = &hsotg->params;
+
+ p->otg_caps.hnp_support = false;
+ p->otg_caps.srp_support = false;
+ p->host_dma = false;
+ p->g_dma = false;
+ p->speed = DWC2_SPEED_PARAM_HIGH;
+ p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI;
+ p->phy_utmi_width = 16;
+ p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT;
+ p->lpm = false;
+ p->lpm_clock_gating = false;
+ p->besl = false;
+ p->hird_threshold_en = false;
+ p->power_down = DWC2_POWER_DOWN_PARAM_NONE;
+}
+
static void dwc2_set_stm32f4x9_fsotg_params(struct dwc2_hsotg *hsotg)
{
struct dwc2_core_params *p = &hsotg->params;
@@ -295,6 +314,8 @@ const struct of_device_id dwc2_of_match_table[] = {
.data = dwc2_set_amlogic_a1_params },
{ .compatible = "amcc,dwc-otg", .data = dwc2_set_amcc_params },
{ .compatible = "apm,apm82181-dwc-otg", .data = dwc2_set_amcc_params },
+ { .compatible = "sophgo,cv1800-usb",
+ .data = dwc2_set_cv1800_params },
{ .compatible = "st,stm32f4x9-fsotg",
.data = dwc2_set_stm32f4x9_fsotg_params },
{ .compatible = "st,stm32f4x9-hsotg" },
@@ -475,6 +496,7 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg)
dwc2_set_param_lpm(hsotg);
p->phy_ulpi_ddr = false;
p->phy_ulpi_ext_vbus = false;
+ p->eusb2_disc = false;
p->enable_dynamic_fifo = hw->enable_dynamic_fifo;
p->en_multiple_tx_fifo = hw->en_multiple_tx_fifo;
@@ -737,6 +759,25 @@ static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg)
}
}
+static void dwc2_check_param_eusb2_disc(struct dwc2_hsotg *hsotg)
+{
+ u32 gsnpsid;
+
+ if (!hsotg->params.eusb2_disc)
+ return;
+ gsnpsid = dwc2_readl(hsotg, GSNPSID);
+ /*
+ * eusb2_disc not supported by FS IOT devices.
+ * For other cores, it supported starting from version 5.00a
+ */
+ if ((gsnpsid & ~DWC2_CORE_REV_MASK) == DWC2_FS_IOT_ID ||
+ (gsnpsid & DWC2_CORE_REV_MASK) <
+ (DWC2_CORE_REV_5_00a & DWC2_CORE_REV_MASK)) {
+ hsotg->params.eusb2_disc = false;
+ return;
+ }
+}
+
#define CHECK_RANGE(_param, _min, _max, _def) do { \
if ((int)(hsotg->params._param) < (_min) || \
(hsotg->params._param) > (_max)) { \
@@ -765,6 +806,8 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg)
dwc2_check_param_speed(hsotg);
dwc2_check_param_phy_utmi_width(hsotg);
dwc2_check_param_power_down(hsotg);
+ dwc2_check_param_eusb2_disc(hsotg);
+
CHECK_BOOL(enable_dynamic_fifo, hw->enable_dynamic_fifo);
CHECK_BOOL(en_multiple_tx_fifo, hw->en_multiple_tx_fifo);
CHECK_BOOL(i2c_enable, hw->i2c_enable);