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