Skip to content

Commit d936e66

Browse files
jysnpsFelipe Balbi
authored andcommitted
usb: dwc2: Check core parameters
Check that core parameters have valid values and adjust them if they aren't. Signed-off-by: John Youn <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent 57b8e23 commit d936e66

File tree

1 file changed

+185
-0
lines changed

1 file changed

+185
-0
lines changed

drivers/usb/dwc2/params.c

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,189 @@ static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg)
377377
}
378378
}
379379

380+
static void dwc2_check_param_otg_cap(struct dwc2_hsotg *hsotg)
381+
{
382+
int valid = 1;
383+
384+
switch (hsotg->params.otg_cap) {
385+
case DWC2_CAP_PARAM_HNP_SRP_CAPABLE:
386+
if (hsotg->hw_params.op_mode != GHWCFG2_OP_MODE_HNP_SRP_CAPABLE)
387+
valid = 0;
388+
break;
389+
case DWC2_CAP_PARAM_SRP_ONLY_CAPABLE:
390+
switch (hsotg->hw_params.op_mode) {
391+
case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
392+
case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE:
393+
case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE:
394+
case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST:
395+
break;
396+
default:
397+
valid = 0;
398+
break;
399+
}
400+
break;
401+
case DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE:
402+
/* always valid */
403+
break;
404+
default:
405+
valid = 0;
406+
break;
407+
}
408+
409+
if (!valid)
410+
dwc2_set_param_otg_cap(hsotg);
411+
}
412+
413+
static void dwc2_check_param_phy_type(struct dwc2_hsotg *hsotg)
414+
{
415+
int valid = 0;
416+
u32 hs_phy_type;
417+
u32 fs_phy_type;
418+
419+
hs_phy_type = hsotg->hw_params.hs_phy_type;
420+
fs_phy_type = hsotg->hw_params.fs_phy_type;
421+
422+
switch (hsotg->params.phy_type) {
423+
case DWC2_PHY_TYPE_PARAM_FS:
424+
if (fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED)
425+
valid = 1;
426+
break;
427+
case DWC2_PHY_TYPE_PARAM_UTMI:
428+
if ((hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI) ||
429+
(hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI))
430+
valid = 1;
431+
break;
432+
case DWC2_PHY_TYPE_PARAM_ULPI:
433+
if ((hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI) ||
434+
(hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI))
435+
valid = 1;
436+
break;
437+
default:
438+
break;
439+
}
440+
441+
if (!valid)
442+
dwc2_set_param_phy_type(hsotg);
443+
}
444+
445+
static void dwc2_check_param_speed(struct dwc2_hsotg *hsotg)
446+
{
447+
int valid = 1;
448+
int phy_type = hsotg->params.phy_type;
449+
int speed = hsotg->params.speed;
450+
451+
switch (speed) {
452+
case DWC2_SPEED_PARAM_HIGH:
453+
if ((hsotg->params.speed == DWC2_SPEED_PARAM_HIGH) &&
454+
(phy_type == DWC2_PHY_TYPE_PARAM_FS))
455+
valid = 0;
456+
break;
457+
case DWC2_SPEED_PARAM_FULL:
458+
case DWC2_SPEED_PARAM_LOW:
459+
break;
460+
default:
461+
valid = 0;
462+
break;
463+
}
464+
465+
if (!valid)
466+
dwc2_set_param_speed(hsotg);
467+
}
468+
469+
static void dwc2_check_param_phy_utmi_width(struct dwc2_hsotg *hsotg)
470+
{
471+
int valid = 0;
472+
int param = hsotg->params.phy_utmi_width;
473+
int width = hsotg->hw_params.utmi_phy_data_width;
474+
475+
switch (width) {
476+
case GHWCFG4_UTMI_PHY_DATA_WIDTH_8:
477+
valid = (param == 8);
478+
break;
479+
case GHWCFG4_UTMI_PHY_DATA_WIDTH_16:
480+
valid = (param == 16);
481+
break;
482+
case GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16:
483+
valid = (param == 8 || param == 16);
484+
break;
485+
}
486+
487+
if (!valid)
488+
dwc2_set_param_phy_utmi_width(hsotg);
489+
}
490+
491+
#define CHECK_RANGE(_param, _min, _max, _def) do { \
492+
if ((hsotg->params._param) < (_min) || \
493+
(hsotg->params._param) > (_max)) { \
494+
dev_warn(hsotg->dev, "%s: Invalid parameter %s=%d\n", \
495+
__func__, #_param, hsotg->params._param); \
496+
hsotg->params._param = (_def); \
497+
} \
498+
} while (0)
499+
500+
#define CHECK_BOOL(_param, _check) do { \
501+
if (hsotg->params._param && !(_check)) { \
502+
dev_warn(hsotg->dev, "%s: Invalid parameter %s=%d\n", \
503+
__func__, #_param, hsotg->params._param); \
504+
hsotg->params._param = false; \
505+
} \
506+
} while (0)
507+
508+
static void dwc2_check_params(struct dwc2_hsotg *hsotg)
509+
{
510+
struct dwc2_hw_params *hw = &hsotg->hw_params;
511+
struct dwc2_core_params *p = &hsotg->params;
512+
bool dma_capable = !(hw->arch == GHWCFG2_SLAVE_ONLY_ARCH);
513+
514+
dwc2_check_param_otg_cap(hsotg);
515+
dwc2_check_param_phy_type(hsotg);
516+
dwc2_check_param_speed(hsotg);
517+
dwc2_check_param_phy_utmi_width(hsotg);
518+
CHECK_BOOL(enable_dynamic_fifo, hw->enable_dynamic_fifo);
519+
CHECK_BOOL(en_multiple_tx_fifo, hw->en_multiple_tx_fifo);
520+
CHECK_BOOL(i2c_enable, hw->i2c_enable);
521+
CHECK_BOOL(reload_ctl, (hsotg->hw_params.snpsid > DWC2_CORE_REV_2_92a));
522+
CHECK_RANGE(max_packet_count,
523+
15, hw->max_packet_count,
524+
hw->max_packet_count);
525+
CHECK_RANGE(max_transfer_size,
526+
2047, hw->max_transfer_size,
527+
hw->max_transfer_size);
528+
529+
if ((hsotg->dr_mode == USB_DR_MODE_HOST) ||
530+
(hsotg->dr_mode == USB_DR_MODE_OTG)) {
531+
CHECK_BOOL(host_dma, dma_capable);
532+
CHECK_BOOL(dma_desc_enable, p->host_dma);
533+
CHECK_BOOL(dma_desc_fs_enable, p->dma_desc_enable);
534+
CHECK_BOOL(host_ls_low_power_phy_clk,
535+
p->phy_type == DWC2_PHY_TYPE_PARAM_FS);
536+
CHECK_RANGE(host_channels,
537+
1, hw->host_channels,
538+
hw->host_channels);
539+
CHECK_RANGE(host_rx_fifo_size,
540+
16, hw->rx_fifo_size,
541+
hw->rx_fifo_size);
542+
CHECK_RANGE(host_nperio_tx_fifo_size,
543+
16, hw->host_nperio_tx_fifo_size,
544+
hw->host_nperio_tx_fifo_size);
545+
CHECK_RANGE(host_perio_tx_fifo_size,
546+
16, hw->host_perio_tx_fifo_size,
547+
hw->host_perio_tx_fifo_size);
548+
}
549+
550+
if ((hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) ||
551+
(hsotg->dr_mode == USB_DR_MODE_OTG)) {
552+
CHECK_BOOL(g_dma, dma_capable);
553+
CHECK_BOOL(g_dma_desc, (p->g_dma && hw->dma_desc_enable));
554+
CHECK_RANGE(g_rx_fifo_size,
555+
16, hw->rx_fifo_size,
556+
hw->rx_fifo_size);
557+
CHECK_RANGE(g_np_tx_fifo_size,
558+
16, hw->dev_nperio_tx_fifo_size,
559+
hw->dev_nperio_tx_fifo_size);
560+
}
561+
}
562+
380563
/*
381564
* Gets host hardware parameters. Forces host mode if not currently in
382565
* host mode. Should be called immediately after a core soft reset in
@@ -591,5 +774,7 @@ int dwc2_init_params(struct dwc2_hsotg *hsotg)
591774
dwc2_set_default_params(hsotg);
592775
dwc2_get_device_properties(hsotg);
593776

777+
dwc2_check_params(hsotg);
778+
594779
return 0;
595780
}

0 commit comments

Comments
 (0)