Commit fbb9e22b authored by Mian Yousaf Kaukab's avatar Mian Yousaf Kaukab Committed by Felipe Balbi

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: default avatarJohn Youn <johnyoun@synopsys.com>
Signed-off-by: default avatarMian Yousaf Kaukab <yousaf.kaukab@intel.com>
Signed-off-by: default avatarGregory Herrero <gregory.herrero@intel.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 75f5c434
...@@ -2485,6 +2485,29 @@ void dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val) ...@@ -2485,6 +2485,29 @@ void dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val)
hsotg->core_params->dma_desc_enable = 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, void dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg,
int val) int val)
{ {
...@@ -3016,6 +3039,7 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg, ...@@ -3016,6 +3039,7 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
dwc2_set_param_otg_cap(hsotg, params->otg_cap); dwc2_set_param_otg_cap(hsotg, params->otg_cap);
dwc2_set_param_dma_enable(hsotg, params->dma_enable); 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_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, dwc2_set_param_host_support_fs_ls_low_power(hsotg,
params->host_support_fs_ls_low_power); params->host_support_fs_ls_low_power);
dwc2_set_param_enable_dynamic_fifo(hsotg, dwc2_set_param_enable_dynamic_fifo(hsotg,
......
...@@ -246,6 +246,13 @@ enum dwc2_ep0_state { ...@@ -246,6 +246,13 @@ enum dwc2_ep0_state {
* value for this if none is specified. * value for this if none is specified.
* 0 - Address DMA * 0 - Address DMA
* 1 - Descriptor DMA (default, if available) * 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 * @speed: Specifies the maximum speed of operation in host and
* device mode. The actual speed depends on the speed of * device mode. The actual speed depends on the speed of
* the attached device and the value of phy_type. * the attached device and the value of phy_type.
...@@ -375,6 +382,7 @@ struct dwc2_core_params { ...@@ -375,6 +382,7 @@ struct dwc2_core_params {
int otg_ver; int otg_ver;
int dma_enable; int dma_enable;
int dma_desc_enable; int dma_desc_enable;
int dma_desc_fs_enable;
int speed; int speed;
int enable_dynamic_fifo; int enable_dynamic_fifo;
int en_multiple_tx_fifo; int en_multiple_tx_fifo;
...@@ -456,6 +464,7 @@ struct dwc2_hw_params { ...@@ -456,6 +464,7 @@ struct dwc2_hw_params {
unsigned op_mode:3; unsigned op_mode:3;
unsigned arch:2; unsigned arch:2;
unsigned dma_desc_enable:1; unsigned dma_desc_enable:1;
unsigned dma_desc_fs_enable:1;
unsigned enable_dynamic_fifo:1; unsigned enable_dynamic_fifo:1;
unsigned en_multiple_tx_fifo:1; unsigned en_multiple_tx_fifo:1;
unsigned host_rx_fifo_size:16; unsigned host_rx_fifo_size:16;
...@@ -770,6 +779,7 @@ struct dwc2_hsotg { ...@@ -770,6 +779,7 @@ struct dwc2_hsotg {
u16 frame_number; u16 frame_number;
u16 periodic_qh_count; u16 periodic_qh_count;
bool bus_suspended; bool bus_suspended;
bool new_connection;
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
#define FRAME_NUM_ARRAY_SIZE 1000 #define FRAME_NUM_ARRAY_SIZE 1000
...@@ -941,6 +951,16 @@ extern void dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val); ...@@ -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); 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. * Specifies the maximum speed of operation in host and device mode.
* The actual speed depends on the speed of the attached device and * The actual speed depends on the speed of the attached device and
......
...@@ -1734,6 +1734,28 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, ...@@ -1734,6 +1734,28 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
port_status |= USB_PORT_STAT_TEST; port_status |= USB_PORT_STAT_TEST;
/* USB_PORT_FEAT_INDICATOR unsupported always 0 */ /* 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); dev_vdbg(hsotg->dev, "port_status=%08x\n", port_status);
*(__le32 *)buf = cpu_to_le32(port_status); *(__le32 *)buf = cpu_to_le32(port_status);
break; break;
......
...@@ -372,10 +372,21 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg) ...@@ -372,10 +372,21 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg)
" --Port Interrupt HPRT0=0x%08x Port Enable Changed (now %d)--\n", " --Port Interrupt HPRT0=0x%08x Port Enable Changed (now %d)--\n",
hprt0, !!(hprt0 & HPRT0_ENA)); hprt0, !!(hprt0 & HPRT0_ENA));
hprt0_modify |= HPRT0_ENACHG; hprt0_modify |= HPRT0_ENACHG;
if (hprt0 & HPRT0_ENA) if (hprt0 & HPRT0_ENA) {
hsotg->new_connection = true;
dwc2_hprt0_enable(hsotg, hprt0, &hprt0_modify); dwc2_hprt0_enable(hsotg, hprt0, &hprt0_modify);
else } else {
hsotg->flags.b.port_enable_change = 1; 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 */ /* Overcurrent Change Interrupt */
......
...@@ -232,7 +232,7 @@ struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, ...@@ -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) 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); dwc2_hcd_qh_free_ddma(hsotg, qh);
} else { } else {
/* kfree(NULL) is safe */ /* kfree(NULL) is safe */
......
...@@ -59,6 +59,7 @@ static const struct dwc2_core_params params_bcm2835 = { ...@@ -59,6 +59,7 @@ static const struct dwc2_core_params params_bcm2835 = {
.otg_ver = 0, /* 1.3 */ .otg_ver = 0, /* 1.3 */
.dma_enable = 1, .dma_enable = 1,
.dma_desc_enable = 0, .dma_desc_enable = 0,
.dma_desc_fs_enable = 0,
.speed = 0, /* High Speed */ .speed = 0, /* High Speed */
.enable_dynamic_fifo = 1, .enable_dynamic_fifo = 1,
.en_multiple_tx_fifo = 1, .en_multiple_tx_fifo = 1,
...@@ -89,6 +90,7 @@ static const struct dwc2_core_params params_rk3066 = { ...@@ -89,6 +90,7 @@ static const struct dwc2_core_params params_rk3066 = {
.otg_ver = -1, .otg_ver = -1,
.dma_enable = -1, .dma_enable = -1,
.dma_desc_enable = 0, .dma_desc_enable = 0,
.dma_desc_fs_enable = 0,
.speed = -1, .speed = -1,
.enable_dynamic_fifo = 1, .enable_dynamic_fifo = 1,
.en_multiple_tx_fifo = -1, .en_multiple_tx_fifo = -1,
...@@ -348,8 +350,10 @@ static int dwc2_driver_probe(struct platform_device *dev) ...@@ -348,8 +350,10 @@ static int dwc2_driver_probe(struct platform_device *dev)
/* /*
* Disable descriptor dma mode by default as the HW can support * Disable descriptor dma mode by default as the HW can support
* it, but does not support it for SPLIT transactions. * it, but does not support it for SPLIT transactions.
* Disable it for FS devices as well.
*/ */
defparams.dma_desc_enable = 0; defparams.dma_desc_enable = 0;
defparams.dma_desc_fs_enable = 0;
} }
hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL); hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment