xref: /rk3399_rockchip-uboot/drivers/usb/host/ehci-generic.c (revision a1cee8e808042e2597d162b1687fdb470634271e)
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/ofnode.h>
10 #include <reset.h>
11 #include <asm/io.h>
12 #include <dm.h>
13 #include "ehci.h"
14 
15 /*
16  * Even though here we don't explicitly use "struct ehci_ctrl"
17  * ehci_register() expects it to be the first thing that resides in
18  * device's private data.
19  */
20 struct generic_ehci {
21 	struct ehci_ctrl ctrl;
22 	struct clk *clocks;
23 	struct reset_ctl *resets;
24 	int clock_count;
25 	int reset_count;
26 };
27 
28 static int ehci_usb_probe(struct udevice *dev)
29 {
30 	struct generic_ehci *priv = dev_get_priv(dev);
31 	struct ehci_hccr *hccr;
32 	struct ehci_hcor *hcor;
33 	int i, err, ret, clock_nb, reset_nb;
34 
35 	err = 0;
36 	priv->clock_count = 0;
37 	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
38 						  "#clock-cells");
39 	if (clock_nb > 0) {
40 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
41 					    GFP_KERNEL);
42 		if (!priv->clocks)
43 			return -ENOMEM;
44 
45 		for (i = 0; i < clock_nb; i++) {
46 			err = clk_get_by_index(dev, i, &priv->clocks[i]);
47 
48 			if (err < 0)
49 				break;
50 			err = clk_enable(&priv->clocks[i]);
51 			if (err) {
52 				error("failed to enable clock %d\n", i);
53 				clk_free(&priv->clocks[i]);
54 				goto clk_err;
55 			}
56 			priv->clock_count++;
57 		}
58 	} else {
59 		if (clock_nb != -ENOENT) {
60 			error("failed to get clock phandle(%d)\n", clock_nb);
61 			return clock_nb;
62 		}
63 	}
64 
65 	priv->reset_count = 0;
66 	reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
67 						  "#reset-cells");
68 	if (reset_nb > 0) {
69 		priv->resets = devm_kcalloc(dev, reset_nb,
70 					    sizeof(struct reset_ctl),
71 					    GFP_KERNEL);
72 		if (!priv->resets)
73 			return -ENOMEM;
74 
75 		for (i = 0; i < reset_nb; i++) {
76 			err = reset_get_by_index(dev, i, &priv->resets[i]);
77 			if (err < 0)
78 				break;
79 
80 			if (reset_deassert(&priv->resets[i])) {
81 				error("failed to deassert reset %d\n", i);
82 				reset_free(&priv->resets[i]);
83 				goto reset_err;
84 			}
85 			priv->reset_count++;
86 		}
87 	} else {
88 		if (reset_nb != -ENOENT) {
89 			error("failed to get reset phandle(%d)\n", reset_nb);
90 			goto clk_err;
91 		}
92 	}
93 
94 	hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
95 	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
96 				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
97 
98 	err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
99 	if (err)
100 		goto reset_err;
101 
102 	return 0;
103 
104 reset_err:
105 	ret = reset_release_all(priv->resets, priv->reset_count);
106 	if (ret)
107 		error("failed to assert all resets\n");
108 clk_err:
109 	ret = clk_release_all(priv->clocks, priv->clock_count);
110 	if (ret)
111 		error("failed to disable all clocks\n");
112 
113 	return err;
114 }
115 
116 static int ehci_usb_remove(struct udevice *dev)
117 {
118 	struct generic_ehci *priv = dev_get_priv(dev);
119 	int ret;
120 
121 	ret = ehci_deregister(dev);
122 	if (ret)
123 		return ret;
124 
125 	ret =  reset_release_all(priv->resets, priv->reset_count);
126 	if (ret)
127 		return ret;
128 
129 	return clk_release_all(priv->clocks, priv->clock_count);
130 }
131 
132 static const struct udevice_id ehci_usb_ids[] = {
133 	{ .compatible = "generic-ehci" },
134 	{ }
135 };
136 
137 U_BOOT_DRIVER(ehci_generic) = {
138 	.name	= "ehci_generic",
139 	.id	= UCLASS_USB,
140 	.of_match = ehci_usb_ids,
141 	.probe = ehci_usb_probe,
142 	.remove = ehci_usb_remove,
143 	.ops	= &ehci_usb_ops,
144 	.priv_auto_alloc_size = sizeof(struct generic_ehci),
145 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
146 };
147