Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: dwc2: add otg_rev and otg_caps information for gadget driver

Currently the dwc2 doesn't fill in the 'otg_caps' of usb_gadget structure.
When registering a gadget device (e.g. via configfs), the
usb_otg_descriptor_init() checks the 'otg_caps' and 'otg_rev'. It defaults
to HNP and SRP bmAttributes if unspecified. There may be a mismatch with
what's being set in dwc2 params structure. This result in the descriptors
to be miss-configured in this case.

So replace 'otg_cap' bit field by 'otg_caps' structure, so hnp, srp and
otg_rev' can be configured directly in the params.
It's then provided to the gadget struct. These parameters can be tuned
for each platform. In case it's not set, it will default to current
behavior.

Also add option to setup these from the device tree by calling
of_usb_update_otg_caps(). This provides support for standard properties
such as "otg-rev", "hnp-disable" and "srp-disable" (see usb-drd.yaml).

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
Link: https://lore.kernel.org/r/1634133425-25670-4-git-send-email-fabrice.gasnier@foss.st.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Fabrice Gasnier and committed by
Greg Kroah-Hartman
f5c8a6cb 924e2b40

+57 -52
+9 -10
drivers/usb/dwc2/core.h
··· 238 238 /** 239 239 * struct dwc2_core_params - Parameters for configuring the core 240 240 * 241 - * @otg_cap: Specifies the OTG capabilities. 242 - * 0 - HNP and SRP capable 243 - * 1 - SRP Only capable 244 - * 2 - No HNP/SRP capable (always available) 245 - * Defaults to best available option (0, 1, then 2) 241 + * @otg_caps: Specifies the OTG capabilities. OTG caps from the platform parameters, 242 + * used to setup the: 243 + * - HNP and SRP capable 244 + * - SRP Only capable 245 + * - No HNP/SRP capable (always available) 246 + * Defaults to best available option 247 + * - OTG revision number the device is compliant with, in binary-coded 248 + * decimal (i.e. 2.0 is 0200H). (see struct usb_otg_caps) 246 249 * @host_dma: Specifies whether to use slave or DMA mode for accessing 247 250 * the data FIFOs. The driver will automatically detect the 248 251 * value for this parameter if none is specified. ··· 456 453 * default described above. 457 454 */ 458 455 struct dwc2_core_params { 459 - u8 otg_cap; 460 - #define DWC2_CAP_PARAM_HNP_SRP_CAPABLE 0 461 - #define DWC2_CAP_PARAM_SRP_ONLY_CAPABLE 1 462 - #define DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE 2 463 - 456 + struct usb_otg_caps otg_caps; 464 457 u8 phy_type; 465 458 #define DWC2_PHY_TYPE_PARAM_FS 0 466 459 #define DWC2_PHY_TYPE_PARAM_UTMI 1
+3 -1
drivers/usb/dwc2/debugfs.c
··· 670 670 struct dwc2_core_params *p = &hsotg->params; 671 671 int i; 672 672 673 - print_param(seq, p, otg_cap); 673 + print_param(seq, p, otg_caps.hnp_support); 674 + print_param(seq, p, otg_caps.srp_support); 675 + print_param(seq, p, otg_caps.otg_rev); 674 676 print_param(seq, p, dma_desc_enable); 675 677 print_param(seq, p, dma_desc_fs_enable); 676 678 print_param(seq, p, speed);
+1
drivers/usb/dwc2/gadget.c
··· 4966 4966 hsotg->gadget.max_speed = USB_SPEED_HIGH; 4967 4967 hsotg->gadget.ops = &dwc2_hsotg_gadget_ops; 4968 4968 hsotg->gadget.name = dev_name(dev); 4969 + hsotg->gadget.otg_caps = &hsotg->params.otg_caps; 4969 4970 hsotg->remote_wakeup_allowed = 0; 4970 4971 4971 4972 if (hsotg->params.lpm)
+4 -8
drivers/usb/dwc2/hcd.c
··· 138 138 139 139 switch (hsotg->hw_params.op_mode) { 140 140 case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: 141 - if (hsotg->params.otg_cap == 142 - DWC2_CAP_PARAM_HNP_SRP_CAPABLE) 141 + if (hsotg->params.otg_caps.hnp_support && 142 + hsotg->params.otg_caps.srp_support) 143 143 usbcfg |= GUSBCFG_HNPCAP; 144 - if (hsotg->params.otg_cap != 145 - DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE) 146 - usbcfg |= GUSBCFG_SRPCAP; 147 - break; 144 + fallthrough; 148 145 149 146 case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: 150 147 case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: 151 148 case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST: 152 - if (hsotg->params.otg_cap != 153 - DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE) 149 + if (hsotg->params.otg_caps.srp_support) 154 150 usbcfg |= GUSBCFG_SRPCAP; 155 151 break; 156 152
+40 -33
drivers/usb/dwc2/params.c
··· 36 36 #include <linux/kernel.h> 37 37 #include <linux/module.h> 38 38 #include <linux/of_device.h> 39 + #include <linux/usb/of.h> 39 40 40 41 #include "core.h" 41 42 ··· 54 53 { 55 54 struct dwc2_core_params *p = &hsotg->params; 56 55 57 - p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; 56 + p->otg_caps.hnp_support = false; 57 + p->otg_caps.srp_support = false; 58 58 p->speed = DWC2_SPEED_PARAM_HIGH; 59 59 p->host_rx_fifo_size = 512; 60 60 p->host_nperio_tx_fifo_size = 512; ··· 86 84 { 87 85 struct dwc2_core_params *p = &hsotg->params; 88 86 89 - p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; 87 + p->otg_caps.hnp_support = false; 88 + p->otg_caps.srp_support = false; 90 89 p->host_rx_fifo_size = 525; 91 90 p->host_nperio_tx_fifo_size = 128; 92 91 p->host_perio_tx_fifo_size = 256; ··· 100 97 { 101 98 struct dwc2_core_params *p = &hsotg->params; 102 99 103 - p->otg_cap = 2; 100 + p->otg_caps.hnp_support = false; 101 + p->otg_caps.srp_support = false; 104 102 p->host_rx_fifo_size = 288; 105 103 p->host_nperio_tx_fifo_size = 128; 106 104 p->host_perio_tx_fifo_size = 96; ··· 115 111 { 116 112 struct dwc2_core_params *p = &hsotg->params; 117 113 118 - p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; 114 + p->otg_caps.hnp_support = false; 115 + p->otg_caps.srp_support = false; 119 116 p->speed = DWC2_SPEED_PARAM_HIGH; 120 117 p->host_rx_fifo_size = 512; 121 118 p->host_nperio_tx_fifo_size = 500; ··· 149 144 { 150 145 struct dwc2_core_params *p = &hsotg->params; 151 146 152 - p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; 147 + p->otg_caps.hnp_support = false; 148 + p->otg_caps.srp_support = false; 153 149 p->speed = DWC2_SPEED_PARAM_FULL; 154 150 p->host_rx_fifo_size = 128; 155 151 p->host_nperio_tx_fifo_size = 96; ··· 174 168 { 175 169 struct dwc2_core_params *p = &hsotg->params; 176 170 177 - p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; 171 + p->otg_caps.hnp_support = false; 172 + p->otg_caps.srp_support = false; 178 173 p->speed = DWC2_SPEED_PARAM_FULL; 179 174 p->host_rx_fifo_size = 128; 180 175 p->host_nperio_tx_fifo_size = 96; ··· 195 188 { 196 189 struct dwc2_core_params *p = &hsotg->params; 197 190 198 - p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; 191 + p->otg_caps.hnp_support = false; 192 + p->otg_caps.srp_support = false; 199 193 p->activate_stm_id_vb_detection = !device_property_read_bool(hsotg->dev, "usb-role-switch"); 200 194 p->host_rx_fifo_size = 440; 201 195 p->host_nperio_tx_fifo_size = 256; ··· 249 241 250 242 static void dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg) 251 243 { 252 - u8 val; 253 - 254 244 switch (hsotg->hw_params.op_mode) { 255 245 case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: 256 - val = DWC2_CAP_PARAM_HNP_SRP_CAPABLE; 246 + hsotg->params.otg_caps.hnp_support = true; 247 + hsotg->params.otg_caps.srp_support = true; 257 248 break; 258 249 case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: 259 250 case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: 260 251 case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST: 261 - val = DWC2_CAP_PARAM_SRP_ONLY_CAPABLE; 252 + hsotg->params.otg_caps.hnp_support = false; 253 + hsotg->params.otg_caps.srp_support = true; 262 254 break; 263 255 default: 264 - val = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; 256 + hsotg->params.otg_caps.hnp_support = false; 257 + hsotg->params.otg_caps.srp_support = false; 265 258 break; 266 259 } 267 - 268 - hsotg->params.otg_cap = val; 269 260 } 270 261 271 262 static void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg) ··· 470 463 &p->g_tx_fifo_size[1], 471 464 num); 472 465 } 466 + 467 + of_usb_update_otg_caps(hsotg->dev->of_node, &p->otg_caps); 473 468 } 474 469 475 470 if (of_find_property(hsotg->dev->of_node, "disable-over-current", NULL)) ··· 482 473 { 483 474 int valid = 1; 484 475 485 - switch (hsotg->params.otg_cap) { 486 - case DWC2_CAP_PARAM_HNP_SRP_CAPABLE: 476 + if (hsotg->params.otg_caps.hnp_support && hsotg->params.otg_caps.srp_support) { 477 + /* check HNP && SRP capable */ 487 478 if (hsotg->hw_params.op_mode != GHWCFG2_OP_MODE_HNP_SRP_CAPABLE) 488 479 valid = 0; 489 - break; 490 - case DWC2_CAP_PARAM_SRP_ONLY_CAPABLE: 491 - switch (hsotg->hw_params.op_mode) { 492 - case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: 493 - case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: 494 - case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: 495 - case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST: 496 - break; 497 - default: 498 - valid = 0; 499 - break; 480 + } else if (!hsotg->params.otg_caps.hnp_support) { 481 + /* check SRP only capable */ 482 + if (hsotg->params.otg_caps.srp_support) { 483 + switch (hsotg->hw_params.op_mode) { 484 + case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: 485 + case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: 486 + case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: 487 + case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST: 488 + break; 489 + default: 490 + valid = 0; 491 + break; 492 + } 500 493 } 501 - break; 502 - case DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE: 503 - /* always valid */ 504 - break; 505 - default: 494 + /* else: NO HNP && NO SRP capable: always valid */ 495 + } else { 506 496 valid = 0; 507 - break; 508 497 } 509 498 510 499 if (!valid)