diff options
-rw-r--r-- | drivers/usb/dwc2/core.c | 14 | ||||
-rw-r--r-- | drivers/usb/dwc2/core.h | 4 | ||||
-rw-r--r-- | drivers/usb/dwc2/gadget.c | 12 | ||||
-rw-r--r-- | drivers/usb/dwc2/hcd.c | 5 | ||||
-rw-r--r-- | drivers/usb/dwc2/hw.h | 5 | ||||
-rw-r--r-- | drivers/usb/dwc2/params.c | 3 |
6 files changed, 41 insertions, 2 deletions
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index e85f2d230da4..204506f92620 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -498,6 +498,20 @@ int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg) return 0; } +/* + * dwc2_enable_acg - enable active clock gating feature + */ +void dwc2_enable_acg(struct dwc2_hsotg *hsotg) +{ + if (hsotg->params.acg_enable) { + u32 pcgcctl1 = dwc2_readl(hsotg->regs + PCGCCTL1); + + dev_dbg(hsotg->dev, "Enabling Active Clock Gating\n"); + pcgcctl1 |= PCGCCTL1_GATEEN; + dwc2_writel(pcgcctl1, hsotg->regs + PCGCCTL1); + } +} + /** * dwc2_dump_host_registers() - Prints the host registers * diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index db5c02bd4420..a7033b9f20f5 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -479,6 +479,7 @@ struct dwc2_core_params { bool enable_dynamic_fifo; bool en_multiple_tx_fifo; bool i2c_enable; + bool acg_enable; bool ulpi_fs_ls; bool ts_dline; bool reload_ctl; @@ -587,6 +588,7 @@ struct dwc2_hw_params { unsigned hs_phy_type:2; unsigned fs_phy_type:2; unsigned i2c_enable:1; + unsigned acg_enable:1; unsigned num_dev_ep:4; unsigned num_dev_in_eps : 4; unsigned num_dev_perio_in_ep:4; @@ -1115,6 +1117,8 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg); void dwc2_enable_global_interrupts(struct dwc2_hsotg *hcd); void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd); +void dwc2_enable_acg(struct dwc2_hsotg *hsotg); + /* This function should be called on every hardware interrupt. */ irqreturn_t dwc2_handle_common_intr(int irq, void *dev); diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 481684385bfe..47b098380f10 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -4346,6 +4346,8 @@ static int dwc2_hsotg_pullup(struct usb_gadget *gadget, int is_on) if (is_on) { hsotg->enabled = 1; dwc2_hsotg_core_init_disconnected(hsotg, false); + /* Enable ACG feature in device mode,if supported */ + dwc2_enable_acg(hsotg); dwc2_hsotg_core_connect(hsotg); } else { dwc2_hsotg_core_disconnect(hsotg); @@ -4378,8 +4380,11 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget *gadget, int is_active) hsotg->op_state = OTG_STATE_B_PERIPHERAL; dwc2_hsotg_core_init_disconnected(hsotg, false); - if (hsotg->enabled) + if (hsotg->enabled) { + /* Enable ACG feature in device mode,if supported */ + dwc2_enable_acg(hsotg); dwc2_hsotg_core_connect(hsotg); + } } else { dwc2_hsotg_core_disconnect(hsotg); dwc2_hsotg_disconnect(hsotg); @@ -4744,8 +4749,11 @@ int dwc2_hsotg_resume(struct dwc2_hsotg *hsotg) spin_lock_irqsave(&hsotg->lock, flags); dwc2_hsotg_core_init_disconnected(hsotg, false); - if (hsotg->enabled) + if (hsotg->enabled) { + /* Enable ACG feature in device mode,if supported */ + dwc2_enable_acg(hsotg); dwc2_hsotg_core_connect(hsotg); + } spin_unlock_irqrestore(&hsotg->lock, flags); } diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 6f7f9c73b596..edcc9058274a 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2436,6 +2436,9 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg) } } + /* Enable ACG feature in host mode, if supported */ + dwc2_enable_acg(hsotg); + /* Turn on the vbus power */ dev_dbg(hsotg->dev, "Init: Port Power? op_state=%d\n", hsotg->op_state); if (hsotg->op_state == OTG_STATE_A_HOST) { @@ -3302,6 +3305,8 @@ static void dwc2_conn_id_status_change(struct work_struct *work) spin_lock_irqsave(&hsotg->lock, flags); dwc2_hsotg_core_init_disconnected(hsotg, false); spin_unlock_irqrestore(&hsotg->lock, flags); + /* Enable ACG feature in device mode,if supported */ + dwc2_enable_acg(hsotg); dwc2_hsotg_core_connect(hsotg); } else { host: diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h index 43a3fb00f14f..bfb85519af32 100644 --- a/drivers/usb/dwc2/hw.h +++ b/drivers/usb/dwc2/hw.h @@ -310,6 +310,7 @@ #define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14) #define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14 +#define GHWCFG4_ACG_SUPPORTED BIT(12) #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2 @@ -645,6 +646,10 @@ #define PCGCTL_GATEHCLK BIT(1) #define PCGCTL_STOPPCLK BIT(0) +#define PCGCCTL1 HSOTG_REG(0xe04) +#define PCGCCTL1_TIMER (0x3 << 1) +#define PCGCCTL1_GATEEN BIT(0) + #define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000)) /* Host Mode Registers */ diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 430325510812..f0f877c4528d 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -272,6 +272,7 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg) p->enable_dynamic_fifo = hw->enable_dynamic_fifo; p->en_multiple_tx_fifo = hw->en_multiple_tx_fifo; p->i2c_enable = hw->i2c_enable; + p->acg_enable = hw->acg_enable; p->ulpi_fs_ls = false; p->ts_dline = false; p->reload_ctl = (hw->snpsid >= DWC2_CORE_REV_2_92a); @@ -526,6 +527,7 @@ static void dwc2_check_params(struct dwc2_hsotg *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); + CHECK_BOOL(acg_enable, hw->acg_enable); CHECK_BOOL(reload_ctl, (hsotg->hw_params.snpsid > DWC2_CORE_REV_2_92a)); CHECK_RANGE(max_packet_count, 15, hw->max_packet_count, @@ -716,6 +718,7 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ); hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >> GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT; + hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED); /* fifo sizes */ hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >> |