Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2015 Alexey Brodkin <abrodkin@synopsys.com> */ #include <clk.h> #include <dm.h> #include <log.h> #include <dm/device_compat.h> #include <dm/devres.h> #include <dm/ofnode.h> #include <generic-phy.h> #include <reset.h> #include "ohci.h" struct generic_ohci { ohci_t ohci; struct clk_bulk clocks; /* clock list */ struct reset_ctl_bulk resets; /* reset list */ struct phy phy; }; static int ohci_usb_probe(struct udevice *dev) { struct ohci_regs *regs = dev_read_addr_ptr(dev); struct generic_ohci *priv = dev_get_priv(dev); int err, ret; ret = clk_get_bulk(dev, &priv->clocks); if (ret && ret != -ENOENT) { dev_err(dev, "Failed to get clocks (ret=%d)\n", ret); return ret; } err = clk_enable_bulk(&priv->clocks); if (err) { dev_err(dev, "Failed to enable clocks (err=%d)\n", err); goto clk_err; } err = reset_get_bulk(dev, &priv->resets); if (err && err != -ENOENT) { dev_err(dev, "failed to get resets (err=%d)\n", err); goto clk_err; } err = reset_deassert_bulk(&priv->resets); if (err) { dev_err(dev, "failed to deassert resets (err=%d)\n", err); goto reset_err; } err = generic_setup_phy(dev, &priv->phy, 0, PHY_MODE_USB_HOST, 0); if (err) goto reset_err; err = ohci_register(dev, regs); if (err) goto phy_err; return 0; phy_err: ret = generic_shutdown_phy(&priv->phy); if (ret) dev_err(dev, "failed to shutdown usb phy\n"); reset_err: ret = reset_release_bulk(&priv->resets); if (ret) dev_err(dev, "failed to release resets (ret=%d)\n", ret); clk_err: ret = clk_release_bulk(&priv->clocks); if (ret) dev_err(dev, "failed to release clocks (ret=%d)\n", ret); return err; } 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; ret = generic_shutdown_phy(&priv->phy); if (ret) return ret; ret = reset_release_bulk(&priv->resets); if (ret) return ret; return clk_release_bulk(&priv->clocks); } static const struct udevice_id ohci_usb_ids[] = { { .compatible = "generic-ohci" }, { } }; U_BOOT_DRIVER(ohci_generic) = { .name = "ohci_generic", .id = UCLASS_USB, .of_match = ohci_usb_ids, .probe = ohci_usb_probe, .remove = ohci_usb_remove, .ops = &ohci_usb_ops, .priv_auto = sizeof(struct generic_ohci), .flags = DM_FLAG_ALLOC_PRIV_DMA, }; |