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