]>
Commit | Line | Data |
---|---|---|
89c1e2da SW |
1 | /* |
2 | * Copyright (c) 2016, NVIDIA CORPORATION. | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0 | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <dm.h> | |
9 | #include <fdtdec.h> | |
10 | #include <reset.h> | |
11 | #include <reset-uclass.h> | |
12 | ||
13 | DECLARE_GLOBAL_DATA_PTR; | |
14 | ||
15 | static inline struct reset_ops *reset_dev_ops(struct udevice *dev) | |
16 | { | |
17 | return (struct reset_ops *)dev->driver->ops; | |
18 | } | |
19 | ||
20 | static int reset_of_xlate_default(struct reset_ctl *reset_ctl, | |
21 | struct fdtdec_phandle_args *args) | |
22 | { | |
23 | debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); | |
24 | ||
25 | if (args->args_count != 1) { | |
26 | debug("Invaild args_count: %d\n", args->args_count); | |
27 | return -EINVAL; | |
28 | } | |
29 | ||
30 | reset_ctl->id = args->args[0]; | |
31 | ||
32 | return 0; | |
33 | } | |
34 | ||
35 | int reset_get_by_index(struct udevice *dev, int index, | |
36 | struct reset_ctl *reset_ctl) | |
37 | { | |
38 | struct fdtdec_phandle_args args; | |
39 | int ret; | |
40 | struct udevice *dev_reset; | |
41 | struct reset_ops *ops; | |
42 | ||
43 | debug("%s(dev=%p, index=%d, reset_ctl=%p)\n", __func__, dev, index, | |
44 | reset_ctl); | |
45 | ||
e160f7d4 | 46 | ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), |
89c1e2da SW |
47 | "resets", "#reset-cells", 0, |
48 | index, &args); | |
49 | if (ret) { | |
50 | debug("%s: fdtdec_parse_phandle_with_args failed: %d\n", | |
51 | __func__, ret); | |
52 | return ret; | |
53 | } | |
54 | ||
55 | ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node, | |
56 | &dev_reset); | |
57 | if (ret) { | |
58 | debug("%s: uclass_get_device_by_of_offset failed: %d\n", | |
59 | __func__, ret); | |
60 | return ret; | |
61 | } | |
62 | ops = reset_dev_ops(dev_reset); | |
63 | ||
64 | reset_ctl->dev = dev_reset; | |
65 | if (ops->of_xlate) | |
66 | ret = ops->of_xlate(reset_ctl, &args); | |
67 | else | |
68 | ret = reset_of_xlate_default(reset_ctl, &args); | |
69 | if (ret) { | |
70 | debug("of_xlate() failed: %d\n", ret); | |
71 | return ret; | |
72 | } | |
73 | ||
74 | ret = ops->request(reset_ctl); | |
75 | if (ret) { | |
76 | debug("ops->request() failed: %d\n", ret); | |
77 | return ret; | |
78 | } | |
79 | ||
80 | return 0; | |
81 | } | |
82 | ||
83 | int reset_get_by_name(struct udevice *dev, const char *name, | |
84 | struct reset_ctl *reset_ctl) | |
85 | { | |
86 | int index; | |
87 | ||
88 | debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name, | |
89 | reset_ctl); | |
90 | ||
e160f7d4 | 91 | index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev), |
b02e4044 | 92 | "reset-names", name); |
89c1e2da | 93 | if (index < 0) { |
b02e4044 | 94 | debug("fdt_stringlist_search() failed: %d\n", index); |
89c1e2da SW |
95 | return index; |
96 | } | |
97 | ||
98 | return reset_get_by_index(dev, index, reset_ctl); | |
99 | } | |
100 | ||
101 | int reset_free(struct reset_ctl *reset_ctl) | |
102 | { | |
103 | struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); | |
104 | ||
105 | debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); | |
106 | ||
107 | return ops->free(reset_ctl); | |
108 | } | |
109 | ||
110 | int reset_assert(struct reset_ctl *reset_ctl) | |
111 | { | |
112 | struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); | |
113 | ||
114 | debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); | |
115 | ||
116 | return ops->rst_assert(reset_ctl); | |
117 | } | |
118 | ||
119 | int reset_deassert(struct reset_ctl *reset_ctl) | |
120 | { | |
121 | struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); | |
122 | ||
123 | debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); | |
124 | ||
125 | return ops->rst_deassert(reset_ctl); | |
126 | } | |
127 | ||
128 | UCLASS_DRIVER(reset) = { | |
129 | .id = UCLASS_RESET, | |
130 | .name = "reset", | |
131 | }; |