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

Configure Feed

Select the types of activity you want to include in your feed.

usb: dwc3: dwc3-octeon: Avoid half-initialized controller state

Power gpio configuration is done from the middle of
dwc3_octeon_clocks_start leaving hardware in half-initialized
state if it fails. As that indicates dwc3_octeon_clocks_start
does more than just initialize the clocks rename it appropriately
and verify power gpio configuration in advance at the beginning
of device probe.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/ZMd/oMRx8ze22/kK@lenoch
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Ladislav Michl and committed by
Greg Kroah-Hartman
c6110163 23f87bca

+43 -47
+43 -47
drivers/usb/dwc3/dwc3-octeon.c
··· 192 192 void __iomem *base; 193 193 }; 194 194 195 + #define DWC3_GPIO_POWER_NONE (-1) 196 + 195 197 #ifdef CONFIG_CAVIUM_OCTEON_SOC 196 198 #include <asm/octeon/octeon.h> 197 199 static inline uint64_t dwc3_octeon_readq(void __iomem *addr) ··· 260 258 return div; 261 259 } 262 260 263 - static int dwc3_octeon_config_power(struct device *dev, void __iomem *base) 264 - { 265 - uint32_t gpio_pwr[3]; 266 - int gpio, len, power_active_low; 267 - struct device_node *node = dev->of_node; 268 - u64 val; 269 - void __iomem *uctl_host_cfg_reg = base + USBDRD_UCTL_HOST_CFG; 270 - 271 - if (of_find_property(node, "power", &len) != NULL) { 272 - if (len == 12) { 273 - of_property_read_u32_array(node, "power", gpio_pwr, 3); 274 - power_active_low = gpio_pwr[2] & 0x01; 275 - gpio = gpio_pwr[1]; 276 - } else if (len == 8) { 277 - of_property_read_u32_array(node, "power", gpio_pwr, 2); 278 - power_active_low = 0; 279 - gpio = gpio_pwr[1]; 280 - } else { 281 - dev_err(dev, "invalid power configuration\n"); 282 - return -EINVAL; 283 - } 284 - dwc3_octeon_config_gpio(((u64)base >> 24) & 1, gpio); 285 - 286 - /* Enable XHCI power control and set if active high or low. */ 287 - val = dwc3_octeon_readq(uctl_host_cfg_reg); 288 - val |= USBDRD_UCTL_HOST_PPC_EN; 289 - if (power_active_low) 290 - val &= ~USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN; 291 - else 292 - val |= USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN; 293 - dwc3_octeon_writeq(uctl_host_cfg_reg, val); 294 - } else { 295 - /* Disable XHCI power control and set if active high. */ 296 - val = dwc3_octeon_readq(uctl_host_cfg_reg); 297 - val &= ~USBDRD_UCTL_HOST_PPC_EN; 298 - val &= ~USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN; 299 - dwc3_octeon_writeq(uctl_host_cfg_reg, val); 300 - dev_info(dev, "power control disabled\n"); 301 - } 302 - return 0; 303 - } 304 - 305 - static int dwc3_octeon_clocks_start(struct dwc3_octeon *octeon) 261 + static int dwc3_octeon_setup(struct dwc3_octeon *octeon, 262 + int power_gpio, int power_active_low) 306 263 { 307 264 int i, div, mpll_mul, ref_clk_fsel, ref_clk_sel = 2; 308 265 u32 clock_rate; 309 266 u64 val; 310 267 struct device *dev = octeon->dev; 311 268 void __iomem *uctl_ctl_reg = octeon->base + USBDRD_UCTL_CTL; 269 + void __iomem *uctl_host_cfg_reg = octeon->base + USBDRD_UCTL_HOST_CFG; 312 270 313 271 if (dev->of_node) { 314 272 const char *ss_clock_type; ··· 416 454 udelay(10); 417 455 418 456 /* Step 8c: Setup power control. */ 419 - if (dwc3_octeon_config_power(dev, octeon->base)) 420 - return -EINVAL; 457 + val = dwc3_octeon_readq(uctl_host_cfg_reg); 458 + val |= USBDRD_UCTL_HOST_PPC_EN; 459 + if (power_gpio == DWC3_GPIO_POWER_NONE) { 460 + val &= ~USBDRD_UCTL_HOST_PPC_EN; 461 + } else { 462 + val |= USBDRD_UCTL_HOST_PPC_EN; 463 + dwc3_octeon_config_gpio(((__force uintptr_t)octeon->base >> 24) & 1, 464 + power_gpio); 465 + dev_dbg(dev, "power control is using gpio%d\n", power_gpio); 466 + } 467 + if (power_active_low) 468 + val &= ~USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN; 469 + else 470 + val |= USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN; 471 + dwc3_octeon_writeq(uctl_host_cfg_reg, val); 421 472 422 473 /* Step 8d: Deassert UAHC reset signal. */ 423 474 val = dwc3_octeon_readq(uctl_ctl_reg); ··· 483 508 struct device *dev = &pdev->dev; 484 509 struct device_node *node = dev->of_node; 485 510 struct dwc3_octeon *octeon; 486 - int err; 511 + int power_active_low, power_gpio; 512 + int err, len; 513 + 514 + power_gpio = DWC3_GPIO_POWER_NONE; 515 + power_active_low = 0; 516 + if (of_find_property(node, "power", &len)) { 517 + u32 gpio_pwr[3]; 518 + 519 + switch (len) { 520 + case 8: 521 + of_property_read_u32_array(node, "power", gpio_pwr, 2); 522 + break; 523 + case 12: 524 + of_property_read_u32_array(node, "power", gpio_pwr, 3); 525 + power_active_low = gpio_pwr[2] & 0x01; 526 + break; 527 + default: 528 + dev_err(dev, "invalid power configuration\n"); 529 + return -EINVAL; 530 + } 531 + power_gpio = gpio_pwr[1]; 532 + } 487 533 488 534 octeon = devm_kzalloc(dev, sizeof(*octeon), GFP_KERNEL); 489 535 if (!octeon) ··· 515 519 if (IS_ERR(octeon->base)) 516 520 return PTR_ERR(octeon->base); 517 521 518 - err = dwc3_octeon_clocks_start(octeon); 522 + err = dwc3_octeon_setup(octeon, power_gpio, power_active_low); 519 523 if (err) 520 524 return err; 521 525