xref: /rk3399_rockchip-uboot/drivers/usb/host/ohci-generic.c (revision 155d9f65d3bf78cc7113475110c129dc0dbbdae1)
1fee331f6SAlexey Brodkin /*
2fee331f6SAlexey Brodkin  * Copyright (C) 2015 Alexey Brodkin <abrodkin@synopsys.com>
3fee331f6SAlexey Brodkin  *
4fee331f6SAlexey Brodkin  * SPDX-License-Identifier:	GPL-2.0+
5fee331f6SAlexey Brodkin  */
6fee331f6SAlexey Brodkin 
7fee331f6SAlexey Brodkin #include <common.h>
8*155d9f65SPatrice Chotard #include <clk.h>
9fee331f6SAlexey Brodkin #include <dm.h>
10*155d9f65SPatrice Chotard #include <dm/ofnode.h>
11fee331f6SAlexey Brodkin #include "ohci.h"
12fee331f6SAlexey Brodkin 
13fee331f6SAlexey Brodkin #if !defined(CONFIG_USB_OHCI_NEW)
14fee331f6SAlexey Brodkin # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
15fee331f6SAlexey Brodkin #endif
16fee331f6SAlexey Brodkin 
17fee331f6SAlexey Brodkin struct generic_ohci {
18fee331f6SAlexey Brodkin 	ohci_t ohci;
19*155d9f65SPatrice Chotard 	struct clk *clocks;	/* clock list */
20*155d9f65SPatrice Chotard 	int clock_count;	/* number of clock in clock list */
21fee331f6SAlexey Brodkin };
22fee331f6SAlexey Brodkin 
23fee331f6SAlexey Brodkin static int ohci_usb_probe(struct udevice *dev)
24fee331f6SAlexey Brodkin {
25a821c4afSSimon Glass 	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
26*155d9f65SPatrice Chotard 	struct generic_ohci *priv = dev_get_priv(dev);
27*155d9f65SPatrice Chotard 	int i, err, ret, clock_nb;
28fee331f6SAlexey Brodkin 
29*155d9f65SPatrice Chotard 	err = 0;
30*155d9f65SPatrice Chotard 	priv->clock_count = 0;
31*155d9f65SPatrice Chotard 	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
32*155d9f65SPatrice Chotard 	if (clock_nb > 0) {
33*155d9f65SPatrice Chotard 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
34*155d9f65SPatrice Chotard 					    GFP_KERNEL);
35*155d9f65SPatrice Chotard 		if (!priv->clocks)
36*155d9f65SPatrice Chotard 			return -ENOMEM;
37*155d9f65SPatrice Chotard 
38*155d9f65SPatrice Chotard 		for (i = 0; i < clock_nb; i++) {
39*155d9f65SPatrice Chotard 			err = clk_get_by_index(dev, i, &priv->clocks[i]);
40*155d9f65SPatrice Chotard 			if (err < 0)
41*155d9f65SPatrice Chotard 				break;
42*155d9f65SPatrice Chotard 
43*155d9f65SPatrice Chotard 			err = clk_enable(&priv->clocks[i]);
44*155d9f65SPatrice Chotard 			if (err) {
45*155d9f65SPatrice Chotard 				error("failed to enable clock %d\n", i);
46*155d9f65SPatrice Chotard 				clk_free(&priv->clocks[i]);
47*155d9f65SPatrice Chotard 				goto clk_err;
48*155d9f65SPatrice Chotard 			}
49*155d9f65SPatrice Chotard 			priv->clock_count++;
50*155d9f65SPatrice Chotard 		}
51*155d9f65SPatrice Chotard 	} else if (clock_nb != -ENOENT) {
52*155d9f65SPatrice Chotard 		error("failed to get clock phandle(%d)\n", clock_nb);
53*155d9f65SPatrice Chotard 		return clock_nb;
54*155d9f65SPatrice Chotard 	}
55*155d9f65SPatrice Chotard 
56*155d9f65SPatrice Chotard 	err = ohci_register(dev, regs);
57*155d9f65SPatrice Chotard 	if (err)
58*155d9f65SPatrice Chotard 		goto clk_err;
59*155d9f65SPatrice Chotard 
60*155d9f65SPatrice Chotard 	return 0;
61*155d9f65SPatrice Chotard 
62*155d9f65SPatrice Chotard clk_err:
63*155d9f65SPatrice Chotard 	ret = clk_release_all(priv->clocks, priv->clock_count);
64*155d9f65SPatrice Chotard 	if (ret)
65*155d9f65SPatrice Chotard 		error("failed to disable all clocks\n");
66*155d9f65SPatrice Chotard 
67*155d9f65SPatrice Chotard 	return err;
68fee331f6SAlexey Brodkin }
69fee331f6SAlexey Brodkin 
70fee331f6SAlexey Brodkin static int ohci_usb_remove(struct udevice *dev)
71fee331f6SAlexey Brodkin {
72*155d9f65SPatrice Chotard 	struct generic_ohci *priv = dev_get_priv(dev);
73*155d9f65SPatrice Chotard 	int ret;
74*155d9f65SPatrice Chotard 
75*155d9f65SPatrice Chotard 	ret = ohci_deregister(dev);
76*155d9f65SPatrice Chotard 	if (ret)
77*155d9f65SPatrice Chotard 		return ret;
78*155d9f65SPatrice Chotard 
79*155d9f65SPatrice Chotard 	return clk_release_all(priv->clocks, priv->clock_count);
80fee331f6SAlexey Brodkin }
81fee331f6SAlexey Brodkin 
82fee331f6SAlexey Brodkin static const struct udevice_id ohci_usb_ids[] = {
83fee331f6SAlexey Brodkin 	{ .compatible = "generic-ohci" },
84fee331f6SAlexey Brodkin 	{ }
85fee331f6SAlexey Brodkin };
86fee331f6SAlexey Brodkin 
87fee331f6SAlexey Brodkin U_BOOT_DRIVER(ohci_generic) = {
88fee331f6SAlexey Brodkin 	.name	= "ohci_generic",
89fee331f6SAlexey Brodkin 	.id	= UCLASS_USB,
90fee331f6SAlexey Brodkin 	.of_match = ohci_usb_ids,
91fee331f6SAlexey Brodkin 	.probe = ohci_usb_probe,
92fee331f6SAlexey Brodkin 	.remove = ohci_usb_remove,
93fee331f6SAlexey Brodkin 	.ops	= &ohci_usb_ops,
94fee331f6SAlexey Brodkin 	.priv_auto_alloc_size = sizeof(struct generic_ohci),
95fee331f6SAlexey Brodkin 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
96fee331f6SAlexey Brodkin };
97