xref: /rk3399_rockchip-uboot/drivers/usb/host/ehci-generic.c (revision f5439a16d8c42b2b85b577a0e7b6572bf20583c5)
190fbb282SAlexey Brodkin /*
290fbb282SAlexey Brodkin  * Copyright (C) 2015 Alexey Brodkin <abrodkin@synopsys.com>
390fbb282SAlexey Brodkin  *
490fbb282SAlexey Brodkin  * SPDX-License-Identifier:	GPL-2.0+
590fbb282SAlexey Brodkin  */
690fbb282SAlexey Brodkin 
790fbb282SAlexey Brodkin #include <common.h>
84feefdcfSMasahiro Yamada #include <clk.h>
9a1cee8e8SPatrice Chotard #include <dm/ofnode.h>
100d0ba1a7SPatrice Chotard #include <generic-phy.h>
118824cfc1SMasahiro Yamada #include <reset.h>
12643cacb6SMarek Vasut #include <asm/io.h>
1390fbb282SAlexey Brodkin #include <dm.h>
1490fbb282SAlexey Brodkin #include "ehci.h"
1590fbb282SAlexey Brodkin 
1690fbb282SAlexey Brodkin /*
1790fbb282SAlexey Brodkin  * Even though here we don't explicitly use "struct ehci_ctrl"
1890fbb282SAlexey Brodkin  * ehci_register() expects it to be the first thing that resides in
1990fbb282SAlexey Brodkin  * device's private data.
2090fbb282SAlexey Brodkin  */
2190fbb282SAlexey Brodkin struct generic_ehci {
2290fbb282SAlexey Brodkin 	struct ehci_ctrl ctrl;
23a1cee8e8SPatrice Chotard 	struct clk *clocks;
24a1cee8e8SPatrice Chotard 	struct reset_ctl *resets;
250d0ba1a7SPatrice Chotard 	struct phy phy;
26a1cee8e8SPatrice Chotard 	int clock_count;
27a1cee8e8SPatrice Chotard 	int reset_count;
2890fbb282SAlexey Brodkin };
2990fbb282SAlexey Brodkin 
3090fbb282SAlexey Brodkin static int ehci_usb_probe(struct udevice *dev)
3190fbb282SAlexey Brodkin {
32a1cee8e8SPatrice Chotard 	struct generic_ehci *priv = dev_get_priv(dev);
33643cacb6SMarek Vasut 	struct ehci_hccr *hccr;
3490fbb282SAlexey Brodkin 	struct ehci_hcor *hcor;
35a1cee8e8SPatrice Chotard 	int i, err, ret, clock_nb, reset_nb;
364feefdcfSMasahiro Yamada 
37a1cee8e8SPatrice Chotard 	err = 0;
38a1cee8e8SPatrice Chotard 	priv->clock_count = 0;
39a1cee8e8SPatrice Chotard 	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
40a1cee8e8SPatrice Chotard 						  "#clock-cells");
41a1cee8e8SPatrice Chotard 	if (clock_nb > 0) {
42a1cee8e8SPatrice Chotard 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
43a1cee8e8SPatrice Chotard 					    GFP_KERNEL);
44a1cee8e8SPatrice Chotard 		if (!priv->clocks)
45a1cee8e8SPatrice Chotard 			return -ENOMEM;
464feefdcfSMasahiro Yamada 
47a1cee8e8SPatrice Chotard 		for (i = 0; i < clock_nb; i++) {
48a1cee8e8SPatrice Chotard 			err = clk_get_by_index(dev, i, &priv->clocks[i]);
49a1cee8e8SPatrice Chotard 
50a1cee8e8SPatrice Chotard 			if (err < 0)
514feefdcfSMasahiro Yamada 				break;
52a1cee8e8SPatrice Chotard 			err = clk_enable(&priv->clocks[i]);
53b653780cSPatrice Chotard 			if (err) {
54b653780cSPatrice Chotard 				dev_err(dev, "failed to enable clock %d\n", i);
55a1cee8e8SPatrice Chotard 				clk_free(&priv->clocks[i]);
56a1cee8e8SPatrice Chotard 				goto clk_err;
57a1cee8e8SPatrice Chotard 			}
58a1cee8e8SPatrice Chotard 			priv->clock_count++;
59a1cee8e8SPatrice Chotard 		}
60a1cee8e8SPatrice Chotard 	} else {
61a1cee8e8SPatrice Chotard 		if (clock_nb != -ENOENT) {
62b653780cSPatrice Chotard 			dev_err(dev, "failed to get clock phandle(%d)\n",
63b653780cSPatrice Chotard 				clock_nb);
64a1cee8e8SPatrice Chotard 			return clock_nb;
65a1cee8e8SPatrice Chotard 		}
664feefdcfSMasahiro Yamada 	}
6790fbb282SAlexey Brodkin 
68a1cee8e8SPatrice Chotard 	priv->reset_count = 0;
69a1cee8e8SPatrice Chotard 	reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
70a1cee8e8SPatrice Chotard 						  "#reset-cells");
71a1cee8e8SPatrice Chotard 	if (reset_nb > 0) {
72a1cee8e8SPatrice Chotard 		priv->resets = devm_kcalloc(dev, reset_nb,
73a1cee8e8SPatrice Chotard 					    sizeof(struct reset_ctl),
74a1cee8e8SPatrice Chotard 					    GFP_KERNEL);
75a1cee8e8SPatrice Chotard 		if (!priv->resets)
76a1cee8e8SPatrice Chotard 			return -ENOMEM;
778824cfc1SMasahiro Yamada 
78a1cee8e8SPatrice Chotard 		for (i = 0; i < reset_nb; i++) {
79a1cee8e8SPatrice Chotard 			err = reset_get_by_index(dev, i, &priv->resets[i]);
80a1cee8e8SPatrice Chotard 			if (err < 0)
818824cfc1SMasahiro Yamada 				break;
82a1cee8e8SPatrice Chotard 
83a1cee8e8SPatrice Chotard 			if (reset_deassert(&priv->resets[i])) {
84b653780cSPatrice Chotard 				dev_err(dev, "failed to deassert reset %d\n",
85b653780cSPatrice Chotard 					i);
86a1cee8e8SPatrice Chotard 				reset_free(&priv->resets[i]);
87a1cee8e8SPatrice Chotard 				goto reset_err;
88a1cee8e8SPatrice Chotard 			}
89a1cee8e8SPatrice Chotard 			priv->reset_count++;
90a1cee8e8SPatrice Chotard 		}
91a1cee8e8SPatrice Chotard 	} else {
92a1cee8e8SPatrice Chotard 		if (reset_nb != -ENOENT) {
93b653780cSPatrice Chotard 			dev_err(dev, "failed to get reset phandle(%d)\n",
94b653780cSPatrice Chotard 				reset_nb);
95a1cee8e8SPatrice Chotard 			goto clk_err;
96a1cee8e8SPatrice Chotard 		}
978824cfc1SMasahiro Yamada 	}
988824cfc1SMasahiro Yamada 
99*f5439a16SMarek Vasut 	err = ehci_setup_phy(dev, &priv->phy, 0);
100f06fcfdeSPatrice Chotard 	if (err)
1010d0ba1a7SPatrice Chotard 		goto reset_err;
1020d0ba1a7SPatrice Chotard 
10397ff91faSPhilipp Tomsich 	hccr = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE);
10490fbb282SAlexey Brodkin 	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
10590fbb282SAlexey Brodkin 				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
10690fbb282SAlexey Brodkin 
107a1cee8e8SPatrice Chotard 	err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
108a1cee8e8SPatrice Chotard 	if (err)
1090d0ba1a7SPatrice Chotard 		goto phy_err;
110a1cee8e8SPatrice Chotard 
111a1cee8e8SPatrice Chotard 	return 0;
112a1cee8e8SPatrice Chotard 
1130d0ba1a7SPatrice Chotard phy_err:
114*f5439a16SMarek Vasut 	ret = ehci_shutdown_phy(dev, &priv->phy);
1153d54c056SPatrice Chotard 	if (ret)
116f06fcfdeSPatrice Chotard 		dev_err(dev, "failed to shutdown usb phy\n");
1170d0ba1a7SPatrice Chotard 
118a1cee8e8SPatrice Chotard reset_err:
119a1cee8e8SPatrice Chotard 	ret = reset_release_all(priv->resets, priv->reset_count);
120a1cee8e8SPatrice Chotard 	if (ret)
121b653780cSPatrice Chotard 		dev_err(dev, "failed to assert all resets\n");
122a1cee8e8SPatrice Chotard clk_err:
123a1cee8e8SPatrice Chotard 	ret = clk_release_all(priv->clocks, priv->clock_count);
124a1cee8e8SPatrice Chotard 	if (ret)
125b653780cSPatrice Chotard 		dev_err(dev, "failed to disable all clocks\n");
126a1cee8e8SPatrice Chotard 
127a1cee8e8SPatrice Chotard 	return err;
128a1cee8e8SPatrice Chotard }
129a1cee8e8SPatrice Chotard 
130a1cee8e8SPatrice Chotard static int ehci_usb_remove(struct udevice *dev)
131a1cee8e8SPatrice Chotard {
132a1cee8e8SPatrice Chotard 	struct generic_ehci *priv = dev_get_priv(dev);
133a1cee8e8SPatrice Chotard 	int ret;
134a1cee8e8SPatrice Chotard 
135a1cee8e8SPatrice Chotard 	ret = ehci_deregister(dev);
136a1cee8e8SPatrice Chotard 	if (ret)
137a1cee8e8SPatrice Chotard 		return ret;
138a1cee8e8SPatrice Chotard 
139*f5439a16SMarek Vasut 	ret = ehci_shutdown_phy(dev, &priv->phy);
1403d54c056SPatrice Chotard 	if (ret)
1413d54c056SPatrice Chotard 		return ret;
1423d54c056SPatrice Chotard 
143a1cee8e8SPatrice Chotard 	ret =  reset_release_all(priv->resets, priv->reset_count);
144a1cee8e8SPatrice Chotard 	if (ret)
145a1cee8e8SPatrice Chotard 		return ret;
146a1cee8e8SPatrice Chotard 
147a1cee8e8SPatrice Chotard 	return clk_release_all(priv->clocks, priv->clock_count);
14890fbb282SAlexey Brodkin }
14990fbb282SAlexey Brodkin 
15090fbb282SAlexey Brodkin static const struct udevice_id ehci_usb_ids[] = {
15190fbb282SAlexey Brodkin 	{ .compatible = "generic-ehci" },
15290fbb282SAlexey Brodkin 	{ }
15390fbb282SAlexey Brodkin };
15490fbb282SAlexey Brodkin 
15590fbb282SAlexey Brodkin U_BOOT_DRIVER(ehci_generic) = {
15690fbb282SAlexey Brodkin 	.name	= "ehci_generic",
15790fbb282SAlexey Brodkin 	.id	= UCLASS_USB,
15890fbb282SAlexey Brodkin 	.of_match = ehci_usb_ids,
15990fbb282SAlexey Brodkin 	.probe = ehci_usb_probe,
160a1cee8e8SPatrice Chotard 	.remove = ehci_usb_remove,
16190fbb282SAlexey Brodkin 	.ops	= &ehci_usb_ops,
16290fbb282SAlexey Brodkin 	.priv_auto_alloc_size = sizeof(struct generic_ehci),
16390fbb282SAlexey Brodkin 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
16490fbb282SAlexey Brodkin };
165