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 - https://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 <reset.h>
16#include <clk.h>
17
18struct dwc3_of_simple {
19	struct clk_bulk		clks;
20	struct reset_ctl_bulk	resets;
21};
22
23static int dwc3_of_simple_reset_init(struct udevice *dev,
24				     struct dwc3_of_simple *simple)
25{
26	int ret;
27
28	ret = reset_get_bulk(dev, &simple->resets);
29	if (ret == -ENOTSUPP)
30		return 0;
31	else if (ret)
32		return ret;
33
34	ret = reset_deassert_bulk(&simple->resets);
35	if (ret) {
36		reset_release_bulk(&simple->resets);
37		return ret;
38	}
39
40	return 0;
41}
42
43static int dwc3_of_simple_clk_init(struct udevice *dev,
44				   struct dwc3_of_simple *simple)
45{
46	int ret;
47
48	ret = clk_get_bulk(dev, &simple->clks);
49	if (ret == -ENOSYS)
50		return 0;
51	if (ret)
52		return ret;
53
54#if CONFIG_IS_ENABLED(CLK)
55	ret = clk_enable_bulk(&simple->clks);
56	if (ret) {
57		clk_release_bulk(&simple->clks);
58		return ret;
59	}
60#endif
61
62	return 0;
63}
64
65static int dwc3_of_simple_probe(struct udevice *dev)
66{
67	struct dwc3_of_simple *simple = dev_get_plat(dev);
68	int ret;
69
70	ret = dwc3_of_simple_clk_init(dev, simple);
71	if (ret)
72		return ret;
73
74	ret = dwc3_of_simple_reset_init(dev, simple);
75	if (ret)
76		return ret;
77
78	return 0;
79}
80
81static int dwc3_of_simple_remove(struct udevice *dev)
82{
83	struct dwc3_of_simple *simple = dev_get_plat(dev);
84
85	reset_release_bulk(&simple->resets);
86
87	clk_release_bulk(&simple->clks);
88
89	return dm_scan_fdt_dev(dev);
90}
91
92static const struct udevice_id dwc3_of_simple_ids[] = {
93	{ .compatible = "amlogic,meson-gxl-dwc3" },
94	{ .compatible = "rockchip,rk3399-dwc3" },
95	{ .compatible = "ti,dwc3" },
96	{ }
97};
98
99U_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	.plat_auto	= sizeof(struct dwc3_of_simple),
106	.flags = DM_FLAG_ALLOC_PRIV_DMA,
107};
108