xref: /OK3568_Linux_fs/u-boot/drivers/usb/host/ohci-generic.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2015 Alexey Brodkin <abrodkin@synopsys.com>
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <asm/io.h>
8 #include <common.h>
9 #include <clk.h>
10 #include <dm.h>
11 #include <dm/ofnode.h>
12 #include <generic-phy.h>
13 #include <reset.h>
14 #include "ohci.h"
15 
16 #if !defined(CONFIG_USB_OHCI_NEW)
17 # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
18 #endif
19 
20 struct generic_ohci {
21 	ohci_t ohci;
22 	struct clk *clocks;	/* clock list */
23 	struct reset_ctl *resets; /* reset list */
24 	struct phy phy;
25 	int clock_count;	/* number of clock in clock list */
26 	int reset_count;	/* number of reset in reset list */
27 };
28 
ohci_setup_phy(struct udevice * dev,int index)29 static int ohci_setup_phy(struct udevice *dev, int index)
30 {
31 	struct generic_ohci *priv = dev_get_priv(dev);
32 	int ret;
33 
34 	ret = generic_phy_get_by_index(dev, index, &priv->phy);
35 	if (ret) {
36 		if (ret != -ENOENT) {
37 			dev_err(dev, "failed to get usb phy\n");
38 			return ret;
39 		}
40 	} else {
41 		ret = generic_phy_init(&priv->phy);
42 		if (ret) {
43 			dev_err(dev, "failed to init usb phy\n");
44 			return ret;
45 		}
46 
47 		ret = generic_phy_power_on(&priv->phy);
48 		if (ret) {
49 			dev_err(dev, "failed to power on usb phy\n");
50 			return generic_phy_exit(&priv->phy);
51 		}
52 	}
53 
54 	return 0;
55 }
56 
ohci_shutdown_phy(struct udevice * dev)57 static int ohci_shutdown_phy(struct udevice *dev)
58 {
59 	struct generic_ohci *priv = dev_get_priv(dev);
60 	int ret = 0;
61 
62 	if (generic_phy_valid(&priv->phy)) {
63 		ret = generic_phy_power_off(&priv->phy);
64 		if (ret) {
65 			dev_err(dev, "failed to power off usb phy\n");
66 			return ret;
67 		}
68 
69 		ret = generic_phy_exit(&priv->phy);
70 		if (ret) {
71 			dev_err(dev, "failed to power off usb phy\n");
72 			return ret;
73 		}
74 	}
75 
76 	return 0;
77 }
78 
ohci_usb_probe(struct udevice * dev)79 static int ohci_usb_probe(struct udevice *dev)
80 {
81 	struct ohci_regs *regs;
82 	struct generic_ohci *priv = dev_get_priv(dev);
83 	int i, err, ret, clock_nb, reset_nb;
84 
85 	err = 0;
86 	priv->clock_count = 0;
87 	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
88 	if (clock_nb > 0) {
89 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
90 					    GFP_KERNEL);
91 		if (!priv->clocks)
92 			return -ENOMEM;
93 
94 		for (i = 0; i < clock_nb; i++) {
95 			err = clk_get_by_index(dev, i, &priv->clocks[i]);
96 			if (err < 0)
97 				break;
98 
99 			err = clk_enable(&priv->clocks[i]);
100 			if (err && err != -ENOSYS) {
101 				dev_err(dev, "failed to enable clock %d\n", i);
102 				clk_free(&priv->clocks[i]);
103 				goto clk_err;
104 			}
105 			priv->clock_count++;
106 		}
107 	} else if (clock_nb != -ENOENT) {
108 		dev_err(dev, "failed to get clock phandle(%d)\n", clock_nb);
109 		return clock_nb;
110 	}
111 
112 	priv->reset_count = 0;
113 	reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells");
114 	if (reset_nb > 0) {
115 		priv->resets = devm_kcalloc(dev, reset_nb,
116 					    sizeof(struct reset_ctl),
117 					    GFP_KERNEL);
118 		if (!priv->resets)
119 			return -ENOMEM;
120 
121 		for (i = 0; i < reset_nb; i++) {
122 			err = reset_get_by_index(dev, i, &priv->resets[i]);
123 			if (err < 0)
124 				break;
125 
126 			err = reset_deassert(&priv->resets[i]);
127 			if (err) {
128 				dev_err(dev, "failed to deassert reset %d\n", i);
129 				reset_free(&priv->resets[i]);
130 				goto reset_err;
131 			}
132 			priv->reset_count++;
133 		}
134 	} else if (reset_nb != -ENOENT) {
135 		dev_err(dev, "failed to get reset phandle(%d)\n", reset_nb);
136 		goto clk_err;
137 	}
138 
139 	err = ohci_setup_phy(dev, 0);
140 	if (err)
141 		goto reset_err;
142 
143 	regs = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE);
144 	err = ohci_register(dev, regs);
145 	if (err)
146 		goto phy_err;
147 
148 	return 0;
149 
150 phy_err:
151 	ret = ohci_shutdown_phy(dev);
152 	if (ret)
153 		dev_err(dev, "failed to shutdown usb phy\n");
154 
155 reset_err:
156 	ret = reset_release_all(priv->resets, priv->reset_count);
157 	if (ret)
158 		dev_err(dev, "failed to assert all resets\n");
159 clk_err:
160 	ret = clk_release_all(priv->clocks, priv->clock_count);
161 	if (ret)
162 		dev_err(dev, "failed to disable all clocks\n");
163 
164 	return err;
165 }
166 
ohci_usb_remove(struct udevice * dev)167 static int ohci_usb_remove(struct udevice *dev)
168 {
169 	struct generic_ohci *priv = dev_get_priv(dev);
170 	int ret;
171 
172 	ret = ohci_deregister(dev);
173 	if (ret)
174 		return ret;
175 
176 	ret = ohci_shutdown_phy(dev);
177 	if (ret)
178 		return ret;
179 
180 	ret = reset_release_all(priv->resets, priv->reset_count);
181 	if (ret)
182 		return ret;
183 
184 	return clk_release_all(priv->clocks, priv->clock_count);
185 }
186 
187 static const struct udevice_id ohci_usb_ids[] = {
188 	{ .compatible = "generic-ohci" },
189 	{ }
190 };
191 
192 U_BOOT_DRIVER(ohci_generic) = {
193 	.name	= "ohci_generic",
194 	.id	= UCLASS_USB,
195 	.of_match = ohci_usb_ids,
196 	.probe = ohci_usb_probe,
197 	.remove = ohci_usb_remove,
198 	.ops	= &ohci_usb_ops,
199 	.priv_auto_alloc_size = sizeof(struct generic_ohci),
200 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
201 };
202