1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * dwc3-of-simple.c - OF glue layer for simple integrations
4  *
5  * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com
6  *
7  * Author: Felipe Balbi <balbi@ti.com>
8  *
9  * Copyright (C) 2018 BayLibre, SAS
10  * Author: Neil Armstrong <narmstron@baylibre.com>
11  */
12 
13 #include <common.h>
14 #include <dm.h>
15 #include <fdtdec.h>
16 #include <reset.h>
17 #include <clk.h>
18 
19 struct dwc3_of_simple {
20 	struct clk_bulk		clks;
21 	struct reset_ctl_bulk	resets;
22 };
23 
24 static int dwc3_of_simple_reset_init(struct udevice *dev,
25 				     struct dwc3_of_simple *simple)
26 {
27 	int ret;
28 
29 	ret = reset_get_bulk(dev, &simple->resets);
30 	if (ret == -ENOTSUPP)
31 		return 0;
32 	else if (ret)
33 		return ret;
34 
35 	ret = reset_deassert_bulk(&simple->resets);
36 	if (ret) {
37 		reset_release_bulk(&simple->resets);
38 		return ret;
39 	}
40 
41 	return 0;
42 }
43 
44 static int dwc3_of_simple_clk_init(struct udevice *dev,
45 				   struct dwc3_of_simple *simple)
46 {
47 	int ret;
48 
49 	ret = clk_get_bulk(dev, &simple->clks);
50 	if (ret == -ENOSYS)
51 		return 0;
52 	if (ret)
53 		return ret;
54 
55 #if CONFIG_IS_ENABLED(CLK)
56 	ret = clk_enable_bulk(&simple->clks);
57 	if (ret) {
58 		clk_release_bulk(&simple->clks);
59 		return ret;
60 	}
61 #endif
62 
63 	return 0;
64 }
65 
66 static int dwc3_of_simple_probe(struct udevice *dev)
67 {
68 	struct dwc3_of_simple *simple = dev_get_platdata(dev);
69 	int ret;
70 
71 	ret = dwc3_of_simple_clk_init(dev, simple);
72 	if (ret)
73 		return ret;
74 
75 	ret = dwc3_of_simple_reset_init(dev, simple);
76 	if (ret)
77 		return ret;
78 
79 	return 0;
80 }
81 
82 static int dwc3_of_simple_remove(struct udevice *dev)
83 {
84 	struct dwc3_of_simple *simple = dev_get_platdata(dev);
85 
86 	reset_release_bulk(&simple->resets);
87 
88 	clk_release_bulk(&simple->clks);
89 
90 	return dm_scan_fdt_dev(dev);
91 }
92 
93 static const struct udevice_id dwc3_of_simple_ids[] = {
94 	{ .compatible = "amlogic,meson-gxl-dwc3" },
95 	{ .compatible = "ti,dwc3" },
96 	{ }
97 };
98 
99 U_BOOT_DRIVER(dwc3_of_simple) = {
100 	.name = "dwc3-of-simple",
101 	.id = UCLASS_SIMPLE_BUS,
102 	.of_match = dwc3_of_simple_ids,
103 	.probe = dwc3_of_simple_probe,
104 	.remove = dwc3_of_simple_remove,
105 	.platdata_auto_alloc_size = sizeof(struct dwc3_of_simple),
106 	.flags = DM_FLAG_ALLOC_PRIV_DMA,
107 };
108