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