static int ohci_usb_remove(struct udevice *dev) { struct generic_ohci *priv = dev_get_priv(dev); int ret; ret = ohci_deregister(dev); if (ret) return ret; if (generic_phy_valid(&priv->phy)) { ret = generic_phy_exit(&priv->phy); if (ret) return ret; } ret = reset_release_all(priv->resets, priv->reset_count); if (ret) return ret; return clk_release_all(priv->clocks, priv->clock_count); }
static int ohci_usb_probe(struct udevice *dev) { struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev); struct generic_ohci *priv = dev_get_priv(dev); int i, err, ret, clock_nb, reset_nb; err = 0; priv->clock_count = 0; clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); if (clock_nb > 0) { priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), GFP_KERNEL); if (!priv->clocks) return -ENOMEM; for (i = 0; i < clock_nb; i++) { err = clk_get_by_index(dev, i, &priv->clocks[i]); if (err < 0) break; err = clk_enable(&priv->clocks[i]); if (err) { pr_err("failed to enable clock %d\n", i); clk_free(&priv->clocks[i]); goto clk_err; } priv->clock_count++; } } else if (clock_nb != -ENOENT) { pr_err("failed to get clock phandle(%d)\n", clock_nb); return clock_nb; } priv->reset_count = 0; reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells"); if (reset_nb > 0) { priv->resets = devm_kcalloc(dev, reset_nb, sizeof(struct reset_ctl), GFP_KERNEL); if (!priv->resets) return -ENOMEM; for (i = 0; i < reset_nb; i++) { err = reset_get_by_index(dev, i, &priv->resets[i]); if (err < 0) break; err = reset_deassert(&priv->resets[i]); if (err) { pr_err("failed to deassert reset %d\n", i); reset_free(&priv->resets[i]); goto reset_err; } priv->reset_count++; } } else if (reset_nb != -ENOENT) { pr_err("failed to get reset phandle(%d)\n", reset_nb); goto clk_err; } err = generic_phy_get_by_index(dev, 0, &priv->phy); if (err) { if (err != -ENOENT) { pr_err("failed to get usb phy\n"); goto reset_err; } } else { err = generic_phy_init(&priv->phy); if (err) { pr_err("failed to init usb phy\n"); goto reset_err; } } err = ohci_register(dev, regs); if (err) goto phy_err; return 0; phy_err: if (generic_phy_valid(&priv->phy)) { ret = generic_phy_exit(&priv->phy); if (ret) pr_err("failed to release phy\n"); } reset_err: ret = reset_release_all(priv->resets, priv->reset_count); if (ret) pr_err("failed to assert all resets\n"); clk_err: ret = clk_release_all(priv->clocks, priv->clock_count); if (ret) pr_err("failed to disable all clocks\n"); return err; }
int board_usb_init(int index, enum usb_init_type init) { struct fdtdec_phandle_args args; struct udevice *dev; const void *blob = gd->fdt_blob; struct clk clk; struct phy phy; int node; int phy_provider; int ret; /* find the usb otg node */ node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); if (node < 0) { debug("Not found usb_otg device\n"); return -ENODEV; } if (!fdtdec_get_is_enabled(blob, node)) { debug("stm32 usbotg is disabled in the device tree\n"); return -ENODEV; } /* Enable clock */ ret = fdtdec_parse_phandle_with_args(blob, node, "clocks", "#clock-cells", 0, 0, &args); if (ret) { debug("usbotg has no clocks defined in the device tree\n"); return ret; } ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev); if (ret) return ret; if (args.args_count != 1) { debug("Can't find clock ID in the device tree\n"); return -ENODATA; } clk.dev = dev; clk.id = args.args[0]; ret = clk_enable(&clk); if (ret) { debug("Failed to enable usbotg clock\n"); return ret; } /* Reset */ ret = fdtdec_parse_phandle_with_args(blob, node, "resets", "#reset-cells", 0, 0, &args); if (ret) { debug("usbotg has no resets defined in the device tree\n"); goto clk_err; } ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node, &dev); if (ret || args.args_count != 1) goto clk_err; usbotg_reset.dev = dev; usbotg_reset.id = args.args[0]; reset_assert(&usbotg_reset); udelay(2); reset_deassert(&usbotg_reset); /* Get USB PHY */ ret = fdtdec_parse_phandle_with_args(blob, node, "phys", "#phy-cells", 0, 0, &args); if (!ret) { phy_provider = fdt_parent_offset(blob, args.node); ret = uclass_get_device_by_of_offset(UCLASS_PHY, phy_provider, &dev); if (ret) goto clk_err; phy.dev = dev; phy.id = fdtdec_get_uint(blob, args.node, "reg", -1); ret = generic_phy_power_on(&phy); if (ret) { debug("unable to power on the phy\n"); goto clk_err; } ret = generic_phy_init(&phy); if (ret) { debug("failed to init usb phy\n"); goto phy_power_err; } } /* Parse and store data needed for gadget */ stm32mp_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); if (stm32mp_otg_data.regs_otg == FDT_ADDR_T_NONE) { debug("usbotg: can't get base address\n"); ret = -ENODATA; goto phy_init_err; } stm32mp_otg_data.rx_fifo_sz = fdtdec_get_int(blob, node, "g-rx-fifo-size", 0); stm32mp_otg_data.np_tx_fifo_sz = fdtdec_get_int(blob, node, "g-np-tx-fifo-size", 0); stm32mp_otg_data.tx_fifo_sz = fdtdec_get_int(blob, node, "g-tx-fifo-size", 0); /* Enable voltage level detector */ if (!(fdtdec_parse_phandle_with_args(blob, node, "usb33d-supply", NULL, 0, 0, &args))) { if (!uclass_get_device_by_of_offset(UCLASS_REGULATOR, args.node, &dev)) { ret = regulator_set_enable(dev, true); if (ret) { debug("Failed to enable usb33d\n"); goto phy_init_err; } } } /* Enable vbus sensing */ setbits_le32(stm32mp_otg_data.regs_otg + STM32MP_GGPIO, STM32MP_GGPIO_VBUS_SENSING); return dwc2_udc_probe(&stm32mp_otg_data); phy_init_err: generic_phy_exit(&phy); phy_power_err: generic_phy_power_off(&phy); clk_err: clk_disable(&clk); return ret; }
static int ehci_usb_probe(struct udevice *dev) { struct generic_ehci *priv = dev_get_priv(dev); struct ehci_hccr *hccr; struct ehci_hcor *hcor; int i, err, ret, clock_nb, reset_nb; err = 0; priv->clock_count = 0; clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks", "#clock-cells"); if (clock_nb > 0) { priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), GFP_KERNEL); if (!priv->clocks) return -ENOMEM; for (i = 0; i < clock_nb; i++) { err = clk_get_by_index(dev, i, &priv->clocks[i]); if (err < 0) break; err = clk_enable(&priv->clocks[i]); if (err) { pr_err("failed to enable clock %d\n", i); clk_free(&priv->clocks[i]); goto clk_err; } priv->clock_count++; } } else { if (clock_nb != -ENOENT) { pr_err("failed to get clock phandle(%d)\n", clock_nb); return clock_nb; } } priv->reset_count = 0; reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets", "#reset-cells"); if (reset_nb > 0) { priv->resets = devm_kcalloc(dev, reset_nb, sizeof(struct reset_ctl), GFP_KERNEL); if (!priv->resets) return -ENOMEM; for (i = 0; i < reset_nb; i++) { err = reset_get_by_index(dev, i, &priv->resets[i]); if (err < 0) break; if (reset_deassert(&priv->resets[i])) { pr_err("failed to deassert reset %d\n", i); reset_free(&priv->resets[i]); goto reset_err; } priv->reset_count++; } } else { if (reset_nb != -ENOENT) { pr_err("failed to get reset phandle(%d)\n", reset_nb); goto clk_err; } } err = generic_phy_get_by_index(dev, 0, &priv->phy); if (err) { if (err != -ENOENT) { pr_err("failed to get usb phy\n"); goto reset_err; } } else { err = generic_phy_init(&priv->phy); if (err) { pr_err("failed to init usb phy\n"); goto reset_err; } } hccr = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE); hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); if (err) goto phy_err; return 0; phy_err: if (generic_phy_valid(&priv->phy)) { ret = generic_phy_exit(&priv->phy); if (ret) pr_err("failed to release phy\n"); } reset_err: ret = reset_release_all(priv->resets, priv->reset_count); if (ret) pr_err("failed to assert all resets\n"); clk_err: ret = clk_release_all(priv->clocks, priv->clock_count); if (ret) pr_err("failed to disable all clocks\n"); return err; }