xref: /rk3399_rockchip-uboot/drivers/usb/host/ohci-generic.c (revision 8a51b4b3dac35a18acca2538efe2c2979aa56417)
1 /*
2  * Copyright (C) 2015 Alexey Brodkin <abrodkin@synopsys.com>
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <clk.h>
9 #include <dm.h>
10 #include <dm/ofnode.h>
11 #include <reset.h>
12 #include "ohci.h"
13 
14 #if !defined(CONFIG_USB_OHCI_NEW)
15 # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
16 #endif
17 
18 struct generic_ohci {
19 	ohci_t ohci;
20 	struct clk *clocks;	/* clock list */
21 	struct reset_ctl *resets; /* reset list */
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_usb_probe(struct udevice *dev)
27 {
28 	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
29 	struct generic_ohci *priv = dev_get_priv(dev);
30 	int i, err, ret, clock_nb, reset_nb;
31 
32 	err = 0;
33 	priv->clock_count = 0;
34 	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
35 	if (clock_nb > 0) {
36 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
37 					    GFP_KERNEL);
38 		if (!priv->clocks)
39 			return -ENOMEM;
40 
41 		for (i = 0; i < clock_nb; i++) {
42 			err = clk_get_by_index(dev, i, &priv->clocks[i]);
43 			if (err < 0)
44 				break;
45 
46 			err = clk_enable(&priv->clocks[i]);
47 			if (err) {
48 				error("failed to enable clock %d\n", i);
49 				clk_free(&priv->clocks[i]);
50 				goto clk_err;
51 			}
52 			priv->clock_count++;
53 		}
54 	} else if (clock_nb != -ENOENT) {
55 		error("failed to get clock phandle(%d)\n", clock_nb);
56 		return clock_nb;
57 	}
58 
59 	priv->reset_count = 0;
60 	reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells");
61 	if (reset_nb > 0) {
62 		priv->resets = devm_kcalloc(dev, reset_nb,
63 					    sizeof(struct reset_ctl),
64 					    GFP_KERNEL);
65 		if (!priv->resets)
66 			return -ENOMEM;
67 
68 		for (i = 0; i < reset_nb; i++) {
69 			err = reset_get_by_index(dev, i, &priv->resets[i]);
70 			if (err < 0)
71 				break;
72 
73 			err = reset_deassert(&priv->resets[i]);
74 			if (err) {
75 				error("failed to deassert reset %d\n", i);
76 				reset_free(&priv->resets[i]);
77 				goto reset_err;
78 			}
79 			priv->reset_count++;
80 		}
81 	} else if (reset_nb != -ENOENT) {
82 		error("failed to get reset phandle(%d)\n", reset_nb);
83 		goto clk_err;
84 	}
85 
86 	err = ohci_register(dev, regs);
87 	if (err)
88 		goto reset_err;
89 
90 	return 0;
91 
92 reset_err:
93 	ret = reset_release_all(priv->resets, priv->reset_count);
94 	if (ret)
95 		error("failed to assert all resets\n");
96 clk_err:
97 	ret = clk_release_all(priv->clocks, priv->clock_count);
98 	if (ret)
99 		error("failed to disable all clocks\n");
100 
101 	return err;
102 }
103 
104 static int ohci_usb_remove(struct udevice *dev)
105 {
106 	struct generic_ohci *priv = dev_get_priv(dev);
107 	int ret;
108 
109 	ret = ohci_deregister(dev);
110 	if (ret)
111 		return ret;
112 
113 	ret = reset_release_all(priv->resets, priv->reset_count);
114 	if (ret)
115 		return ret;
116 
117 	return clk_release_all(priv->clocks, priv->clock_count);
118 }
119 
120 static const struct udevice_id ohci_usb_ids[] = {
121 	{ .compatible = "generic-ohci" },
122 	{ }
123 };
124 
125 U_BOOT_DRIVER(ohci_generic) = {
126 	.name	= "ohci_generic",
127 	.id	= UCLASS_USB,
128 	.of_match = ohci_usb_ids,
129 	.probe = ohci_usb_probe,
130 	.remove = ohci_usb_remove,
131 	.ops	= &ohci_usb_ops,
132 	.priv_auto_alloc_size = sizeof(struct generic_ohci),
133 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
134 };
135