hsotg->core_params->dma_desc_enable = val;
}
+void dwc2_set_param_dma_desc_fs_enable(struct dwc2_hsotg *hsotg, int val)
+{
+ int valid = 1;
+
+ if (val > 0 && (hsotg->core_params->dma_enable <= 0 ||
+ !hsotg->hw_params.dma_desc_enable))
+ valid = 0;
+ if (val < 0)
+ valid = 0;
+
+ if (!valid) {
+ if (val >= 0)
+ dev_err(hsotg->dev,
+ "%d invalid for dma_desc_fs_enable parameter. Check HW configuration.\n",
+ val);
+ val = (hsotg->core_params->dma_enable > 0 &&
+ hsotg->hw_params.dma_desc_enable);
+ }
+
+ hsotg->core_params->dma_desc_fs_enable = val;
+ dev_dbg(hsotg->dev, "Setting dma_desc_fs_enable to %d\n", val);
+}
+
void dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg,
int val)
{
dwc2_set_param_otg_cap(hsotg, params->otg_cap);
dwc2_set_param_dma_enable(hsotg, params->dma_enable);
dwc2_set_param_dma_desc_enable(hsotg, params->dma_desc_enable);
+ dwc2_set_param_dma_desc_fs_enable(hsotg, params->dma_desc_fs_enable);
dwc2_set_param_host_support_fs_ls_low_power(hsotg,
params->host_support_fs_ls_low_power);
dwc2_set_param_enable_dynamic_fifo(hsotg,
* value for this if none is specified.
* 0 - Address DMA
* 1 - Descriptor DMA (default, if available)
+ * @dma_desc_fs_enable: When DMA mode is enabled, specifies whether to use
+ * address DMA mode or descriptor DMA mode for accessing
+ * the data FIFOs in Full Speed mode only. The driver
+ * will automatically detect the value for this if none is
+ * specified.
+ * 0 - Address DMA
+ * 1 - Descriptor DMA in FS (default, if available)
* @speed: Specifies the maximum speed of operation in host and
* device mode. The actual speed depends on the speed of
* the attached device and the value of phy_type.
int otg_ver;
int dma_enable;
int dma_desc_enable;
+ int dma_desc_fs_enable;
int speed;
int enable_dynamic_fifo;
int en_multiple_tx_fifo;
unsigned op_mode:3;
unsigned arch:2;
unsigned dma_desc_enable:1;
+ unsigned dma_desc_fs_enable:1;
unsigned enable_dynamic_fifo:1;
unsigned en_multiple_tx_fifo:1;
unsigned host_rx_fifo_size:16;
u16 frame_number;
u16 periodic_qh_count;
bool bus_suspended;
+ bool new_connection;
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
#define FRAME_NUM_ARRAY_SIZE 1000
*/
extern void dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val);
+/*
+ * When DMA mode is enabled specifies whether to use
+ * address DMA or DMA Descritor mode with full speed devices
+ * for accessing the data FIFOs in host mode.
+ * 0 - address DMA
+ * 1 - FS DMA Descriptor(default, if available)
+ */
+extern void dwc2_set_param_dma_desc_fs_enable(struct dwc2_hsotg *hsotg,
+ int val);
+
/*
* Specifies the maximum speed of operation in host and device mode.
* The actual speed depends on the speed of the attached device and
port_status |= USB_PORT_STAT_TEST;
/* USB_PORT_FEAT_INDICATOR unsupported always 0 */
+ if (hsotg->core_params->dma_desc_fs_enable) {
+ /*
+ * Enable descriptor DMA only if a full speed
+ * device is connected.
+ */
+ if (hsotg->new_connection &&
+ ((port_status &
+ (USB_PORT_STAT_CONNECTION |
+ USB_PORT_STAT_HIGH_SPEED |
+ USB_PORT_STAT_LOW_SPEED)) ==
+ USB_PORT_STAT_CONNECTION)) {
+ u32 hcfg;
+
+ dev_info(hsotg->dev, "Enabling descriptor DMA mode\n");
+ hsotg->core_params->dma_desc_enable = 1;
+ hcfg = dwc2_readl(hsotg->regs + HCFG);
+ hcfg |= HCFG_DESCDMA;
+ dwc2_writel(hcfg, hsotg->regs + HCFG);
+ hsotg->new_connection = false;
+ }
+ }
+
dev_vdbg(hsotg->dev, "port_status=%08x\n", port_status);
*(__le32 *)buf = cpu_to_le32(port_status);
break;
" --Port Interrupt HPRT0=0x%08x Port Enable Changed (now %d)--\n",
hprt0, !!(hprt0 & HPRT0_ENA));
hprt0_modify |= HPRT0_ENACHG;
- if (hprt0 & HPRT0_ENA)
+ if (hprt0 & HPRT0_ENA) {
+ hsotg->new_connection = true;
dwc2_hprt0_enable(hsotg, hprt0, &hprt0_modify);
- else
+ } else {
hsotg->flags.b.port_enable_change = 1;
+ if (hsotg->core_params->dma_desc_fs_enable) {
+ u32 hcfg;
+
+ hsotg->core_params->dma_desc_enable = 0;
+ hsotg->new_connection = false;
+ hcfg = dwc2_readl(hsotg->regs + HCFG);
+ hcfg &= ~HCFG_DESCDMA;
+ dwc2_writel(hcfg, hsotg->regs + HCFG);
+ }
+ }
}
/* Overcurrent Change Interrupt */
*/
void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{
- if (hsotg->core_params->dma_desc_enable > 0) {
+ if (qh->desc_list) {
dwc2_hcd_qh_free_ddma(hsotg, qh);
} else {
/* kfree(NULL) is safe */
.otg_ver = 0, /* 1.3 */
.dma_enable = 1,
.dma_desc_enable = 0,
+ .dma_desc_fs_enable = 0,
.speed = 0, /* High Speed */
.enable_dynamic_fifo = 1,
.en_multiple_tx_fifo = 1,
.otg_ver = -1,
.dma_enable = -1,
.dma_desc_enable = 0,
+ .dma_desc_fs_enable = 0,
.speed = -1,
.enable_dynamic_fifo = 1,
.en_multiple_tx_fifo = -1,
/*
* Disable descriptor dma mode by default as the HW can support
* it, but does not support it for SPLIT transactions.
+ * Disable it for FS devices as well.
*/
defparams.dma_desc_enable = 0;
+ defparams.dma_desc_fs_enable = 0;
}
hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL);