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