usb: dwc2: host: enable descriptor dma for fs devices

As descriptor dma mode does not support split transfers, it can't be
enabled for high speed devices. Add a core parameter to enable it for
full speed devices.

Ensure frame list and descriptor list are correctly freed during
disconnect.

Acked-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@intel.com>
Signed-off-by: Gregory Herrero <gregory.herrero@intel.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
Mian Yousaf Kaukab 2015-11-20 11:49:28 +01:00 committed by Felipe Balbi
parent 75f5c434c3
commit fbb9e22b15
6 changed files with 84 additions and 3 deletions

View File

@ -2485,6 +2485,29 @@ void dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val)
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)
{
@ -3016,6 +3039,7 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
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,

View File

@ -246,6 +246,13 @@ enum dwc2_ep0_state {
* 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.
@ -375,6 +382,7 @@ struct dwc2_core_params {
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;
@ -456,6 +464,7 @@ struct dwc2_hw_params {
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;
@ -770,6 +779,7 @@ struct dwc2_hsotg {
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
@ -941,6 +951,16 @@ extern void dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val);
*/
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

View File

@ -1734,6 +1734,28 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
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;

View File

@ -372,10 +372,21 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg)
" --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 */

View File

@ -232,7 +232,7 @@ struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
*/
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 */

View File

@ -59,6 +59,7 @@ static const struct dwc2_core_params params_bcm2835 = {
.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,
@ -89,6 +90,7 @@ static const struct dwc2_core_params params_rk3066 = {
.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,
@ -348,8 +350,10 @@ static int dwc2_driver_probe(struct platform_device *dev)
/*
* 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);