Skip to content

Commit 9035073

Browse files
Bartosz GolaszewskipH5
authored andcommitted
reset: convert reset core to using firmware nodes
With everything else now in place, we can convert the remaining parts of the reset subsystem to becoming fwnode-agnostic - meaning it will work with all kinds of firmware nodes, not only devicetree. To that end: extend struct reset_controller_dev with fields taking information relevant for using firmware nodes (which mirrors what we already do for OF-nodes) and limit using of_ APIs only to where it's absolutely necessary (mostly around the of_xlate callback). For backward compatibility of existing drivers we still support OF-nodes but firmware nodes become the preferred method. Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
1 parent ba8dbbb commit 9035073

2 files changed

Lines changed: 112 additions & 68 deletions

File tree

drivers/reset/core.c

Lines changed: 100 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,13 @@ struct reset_control_array {
8181

8282
/**
8383
* struct reset_gpio_lookup - lookup key for ad-hoc created reset-gpio devices
84-
* @of_args: phandle to the reset controller with all the args like GPIO number
84+
* @ref_args: Reference to the reset controller with all the args like GPIO number
8585
* @swnode: Software node containing the reference to the GPIO provider
8686
* @list: list entry for the reset_gpio_lookup_list
8787
* @adev: Auxiliary device representing the reset controller
8888
*/
8989
struct reset_gpio_lookup {
90-
struct of_phandle_args of_args;
90+
struct fwnode_reference_args ref_args;
9191
struct fwnode_handle *swnode;
9292
struct list_head list;
9393
struct auxiliary_device adev;
@@ -98,24 +98,24 @@ static const char *rcdev_name(struct reset_controller_dev *rcdev)
9898
if (rcdev->dev)
9999
return dev_name(rcdev->dev);
100100

101-
if (rcdev->of_node)
102-
return rcdev->of_node->full_name;
101+
if (rcdev->fwnode)
102+
return fwnode_get_name(rcdev->fwnode);
103103

104104
return NULL;
105105
}
106106

107107
/**
108-
* of_reset_simple_xlate - translate reset_spec to the reset line number
108+
* fwnode_reset_simple_xlate - translate reset_spec to the reset line number
109109
* @rcdev: a pointer to the reset controller device
110-
* @reset_spec: reset line specifier as found in the device tree
110+
* @reset_spec: reset line specifier as found in firmware
111111
*
112-
* This static translation function is used by default if of_xlate in
113-
* :c:type:`reset_controller_dev` is not set. It is useful for all reset
114-
* controllers with 1:1 mapping, where reset lines can be indexed by number
115-
* without gaps.
112+
* This static translation function is used by default if neither fwnode_xlate
113+
* not of_xlate in :c:type:`reset_controller_dev` is not set. It is useful for
114+
* all reset controllers with 1:1 mapping, where reset lines can be indexed by
115+
* number without gaps.
116116
*/
117-
static int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
118-
const struct of_phandle_args *reset_spec)
117+
static int fwnode_reset_simple_xlate(struct reset_controller_dev *rcdev,
118+
const struct fwnode_reference_args *reset_spec)
119119
{
120120
if (reset_spec->args[0] >= rcdev->nr_resets)
121121
return -EINVAL;
@@ -129,9 +129,23 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
129129
*/
130130
int reset_controller_register(struct reset_controller_dev *rcdev)
131131
{
132-
if (!rcdev->of_xlate) {
133-
rcdev->of_reset_n_cells = 1;
134-
rcdev->of_xlate = of_reset_simple_xlate;
132+
if ((rcdev->of_node && rcdev->fwnode) || (rcdev->of_xlate && rcdev->fwnode_xlate))
133+
return -EINVAL;
134+
135+
if (!rcdev->of_node && !rcdev->fwnode) {
136+
rcdev->fwnode = dev_fwnode(rcdev->dev);
137+
if (!rcdev->fwnode)
138+
return -EINVAL;
139+
}
140+
141+
if (rcdev->of_node) {
142+
rcdev->fwnode = of_fwnode_handle(rcdev->of_node);
143+
rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells;
144+
}
145+
146+
if (rcdev->fwnode && !rcdev->fwnode_xlate) {
147+
rcdev->fwnode_reset_n_cells = 1;
148+
rcdev->fwnode_xlate = fwnode_reset_simple_xlate;
135149
}
136150

137151
INIT_LIST_HEAD(&rcdev->reset_control_head);
@@ -931,7 +945,7 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev,
931945
adev->id = id;
932946
adev->name = "gpio";
933947
adev->dev.parent = parent;
934-
adev->dev.platform_data = &rgpio_dev->of_args;
948+
adev->dev.platform_data = &rgpio_dev->ref_args;
935949
adev->dev.release = reset_gpio_aux_device_release;
936950
device_set_node(&adev->dev, rgpio_dev->swnode);
937951

@@ -951,18 +965,18 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev,
951965
return 0;
952966
}
953967

954-
static void reset_gpio_add_devlink(struct device_node *np,
968+
static void reset_gpio_add_devlink(struct fwnode_handle *fwnode,
955969
struct reset_gpio_lookup *rgpio_dev)
956970
{
957971
struct device *consumer;
958972

959973
/*
960-
* We must use get_dev_from_fwnode() and not of_find_device_by_node()
974+
* We must use get_dev_from_fwnode() and not ref_find_device_by_node()
961975
* because the latter only considers the platform bus while we want to
962976
* get consumers of any kind that can be associated with firmware
963977
* nodes: auxiliary, soundwire, etc.
964978
*/
965-
consumer = get_dev_from_fwnode(of_fwnode_handle(np));
979+
consumer = get_dev_from_fwnode(fwnode);
966980
if (consumer) {
967981
if (!device_link_add(consumer, &rgpio_dev->adev.dev,
968982
DL_FLAG_AUTOREMOVE_CONSUMER))
@@ -982,15 +996,23 @@ static void reset_gpio_add_devlink(struct device_node *np,
982996
*/
983997
}
984998

999+
/* TODO: move it out into drivers/base/ */
1000+
static bool fwnode_reference_args_equal(const struct fwnode_reference_args *left,
1001+
const struct fwnode_reference_args *right)
1002+
{
1003+
return left->fwnode == right->fwnode && left->nargs == right->nargs &&
1004+
!memcmp(left->args, right->args, sizeof(left->args[0]) * left->nargs);
1005+
}
1006+
9851007
/*
9861008
* @np: OF-node associated with the consumer
987-
* @args: phandle to the GPIO provider with all the args like GPIO number
1009+
* @args: Reference to the GPIO provider with all the args like GPIO number
9881010
*/
989-
static int __reset_add_reset_gpio_device(struct device_node *np,
990-
const struct of_phandle_args *args)
1011+
static int __reset_add_reset_gpio_device(struct fwnode_handle *fwnode,
1012+
const struct fwnode_reference_args *args)
9911013
{
9921014
struct property_entry properties[3] = { };
993-
unsigned int offset, of_flags, lflags;
1015+
unsigned int offset, flags, lflags;
9941016
struct reset_gpio_lookup *rgpio_dev;
9951017
struct device *parent;
9961018
int ret, prop = 0;
@@ -1001,7 +1023,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
10011023
* args[1]: GPIO flags
10021024
* TODO: Handle other cases.
10031025
*/
1004-
if (args->args_count != 2)
1026+
if (args->nargs != 2)
10051027
return -ENOENT;
10061028

10071029
/*
@@ -1012,7 +1034,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
10121034
lockdep_assert_not_held(&reset_list_mutex);
10131035

10141036
offset = args->args[0];
1015-
of_flags = args->args[1];
1037+
flags = args->args[1];
10161038

10171039
/*
10181040
* Later we map GPIO flags between OF and Linux, however not all
@@ -1022,33 +1044,31 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
10221044
* FIXME: Find a better way of translating OF flags to GPIO lookup
10231045
* flags.
10241046
*/
1025-
if (of_flags > GPIO_ACTIVE_LOW) {
1047+
if (flags > GPIO_ACTIVE_LOW) {
10261048
pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
1027-
of_flags, offset);
1049+
flags, offset);
10281050
return -EINVAL;
10291051
}
10301052

10311053
struct gpio_device *gdev __free(gpio_device_put) =
1032-
gpio_device_find_by_fwnode(of_fwnode_handle(args->np));
1054+
gpio_device_find_by_fwnode(args->fwnode);
10331055
if (!gdev)
10341056
return -EPROBE_DEFER;
10351057

10361058
guard(mutex)(&reset_gpio_lookup_mutex);
10371059

10381060
list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) {
1039-
if (args->np == rgpio_dev->of_args.np) {
1040-
if (of_phandle_args_equal(args, &rgpio_dev->of_args)) {
1041-
/*
1042-
* Already on the list, create the device link
1043-
* and stop here.
1044-
*/
1045-
reset_gpio_add_devlink(np, rgpio_dev);
1046-
return 0;
1047-
}
1061+
if (fwnode_reference_args_equal(args, &rgpio_dev->ref_args)) {
1062+
/*
1063+
* Already on the list, create the device link
1064+
* and stop here.
1065+
*/
1066+
reset_gpio_add_devlink(fwnode, rgpio_dev);
1067+
return 0;
10481068
}
10491069
}
10501070

1051-
lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW);
1071+
lflags = GPIO_PERSISTENT | (flags & GPIO_ACTIVE_LOW);
10521072
parent = gpio_device_to_device(gdev);
10531073
properties[prop++] = PROPERTY_ENTRY_STRING("compatible", "reset-gpio");
10541074
properties[prop++] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags);
@@ -1058,43 +1078,43 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
10581078
if (!rgpio_dev)
10591079
return -ENOMEM;
10601080

1061-
rgpio_dev->of_args = *args;
1081+
rgpio_dev->ref_args = *args;
10621082
/*
1063-
* We keep the device_node reference, but of_args.np is put at the end
1064-
* of __fwnode_reset_control_get(), so get it one more time.
1083+
* We keep the fwnode_handle reference, but ref_args.fwnode is put at
1084+
* the end of __fwnode_reset_control_get(), so get it one more time.
10651085
* Hold reference as long as rgpio_dev memory is valid.
10661086
*/
1067-
of_node_get(rgpio_dev->of_args.np);
1087+
fwnode_handle_get(rgpio_dev->ref_args.fwnode);
10681088

10691089
rgpio_dev->swnode = fwnode_create_software_node(properties, NULL);
10701090
if (IS_ERR(rgpio_dev->swnode)) {
10711091
ret = PTR_ERR(rgpio_dev->swnode);
1072-
goto err_put_of_node;
1092+
goto err_put_fwnode;
10731093
}
10741094

10751095
ret = reset_create_gpio_aux_device(rgpio_dev, parent);
10761096
if (ret)
10771097
goto err_del_swnode;
10781098

1079-
reset_gpio_add_devlink(np, rgpio_dev);
1099+
reset_gpio_add_devlink(fwnode, rgpio_dev);
10801100
list_add(&rgpio_dev->list, &reset_gpio_lookup_list);
10811101

10821102
return 0;
10831103

10841104
err_del_swnode:
10851105
fwnode_remove_software_node(rgpio_dev->swnode);
1086-
err_put_of_node:
1087-
of_node_put(rgpio_dev->of_args.np);
1106+
err_put_fwnode:
1107+
fwnode_handle_put(rgpio_dev->ref_args.fwnode);
10881108
kfree(rgpio_dev);
10891109

10901110
return ret;
10911111
}
10921112

1093-
static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_args *args,
1094-
bool gpio_fallback)
1113+
static struct reset_controller_dev *
1114+
__reset_find_rcdev(const struct fwnode_reference_args *args, bool gpio_fallback)
10951115
{
1116+
struct fwnode_reference_args *rc_args;
10961117
struct reset_controller_dev *rcdev;
1097-
struct of_phandle_args *rc_args;
10981118

10991119
lockdep_assert_held(&reset_list_mutex);
11001120

@@ -1103,10 +1123,10 @@ static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_a
11031123
device_is_compatible(rcdev->dev, "reset-gpio")) {
11041124
rc_args = dev_get_platdata(rcdev->dev);
11051125

1106-
if (of_phandle_args_equal(args, rc_args))
1126+
if (fwnode_reference_args_equal(args, rc_args))
11071127
return rcdev;
11081128
} else {
1109-
if (args->np == rcdev->of_node)
1129+
if (args->fwnode == rcdev->fwnode)
11101130
return rcdev;
11111131
}
11121132
}
@@ -1120,27 +1140,26 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
11201140
{
11211141
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
11221142
bool gpio_fallback = false;
1123-
struct device_node *node = to_of_node(fwnode);
11241143
struct reset_control *rstc = ERR_PTR(-EINVAL);
11251144
struct reset_controller_dev *rcdev;
1126-
struct of_phandle_args args;
1127-
int rstc_id;
1145+
struct fwnode_reference_args args;
1146+
struct of_phandle_args of_args;
1147+
int rstc_id = -EINVAL;
11281148
int ret;
11291149

11301150
if (!fwnode)
11311151
return ERR_PTR(-EINVAL);
11321152

11331153
if (id) {
1134-
index = of_property_match_string(node,
1135-
"reset-names", id);
1154+
index = fwnode_property_match_string(fwnode, "reset-names", id);
11361155
if (index == -EILSEQ)
11371156
return ERR_PTR(index);
11381157
if (index < 0)
11391158
return optional ? NULL : ERR_PTR(-ENOENT);
11401159
}
11411160

1142-
ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
1143-
index, &args);
1161+
ret = fwnode_property_get_reference_args(fwnode, "resets", "#reset-cells",
1162+
0, index, &args);
11441163
if (ret == -EINVAL)
11451164
return ERR_PTR(ret);
11461165
if (ret) {
@@ -1151,16 +1170,16 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
11511170
* There can be only one reset-gpio for regular devices, so
11521171
* don't bother with the "reset-gpios" phandle index.
11531172
*/
1154-
ret = of_parse_phandle_with_args(node, "reset-gpios", "#gpio-cells",
1155-
0, &args);
1173+
ret = fwnode_property_get_reference_args(fwnode, "reset-gpios",
1174+
"#gpio-cells", 0, 0, &args);
11561175
if (ret)
11571176
return optional ? NULL : ERR_PTR(ret);
11581177

11591178
gpio_fallback = true;
11601179

1161-
ret = __reset_add_reset_gpio_device(node, &args);
1180+
ret = __reset_add_reset_gpio_device(fwnode, &args);
11621181
if (ret) {
1163-
of_node_put(args.np);
1182+
fwnode_handle_put(args.fwnode);
11641183
return ERR_PTR(ret);
11651184
}
11661185
}
@@ -1173,15 +1192,30 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
11731192
goto out_put;
11741193
}
11751194

1176-
if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) {
1195+
if (WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) {
11771196
rstc = ERR_PTR(-EINVAL);
11781197
goto out_put;
11791198
}
11801199

1181-
rstc_id = rcdev->of_xlate(rcdev, &args);
1200+
if (rcdev->of_xlate && is_of_node(fwnode)) {
1201+
ret = of_parse_phandle_with_args(to_of_node(fwnode),
1202+
gpio_fallback ? "reset-gpios" : "resets",
1203+
gpio_fallback ? "#gpio-cells" : "#reset-cells",
1204+
gpio_fallback ? 0 : index,
1205+
&of_args);
1206+
if (ret) {
1207+
rstc = ERR_PTR(ret);
1208+
goto out_put;
1209+
}
1210+
1211+
rstc_id = rcdev->of_xlate(rcdev, &of_args);
1212+
of_node_put(of_args.np);
1213+
} else if (rcdev->fwnode_xlate) {
1214+
rstc_id = rcdev->fwnode_xlate(rcdev, &args);
1215+
}
11821216
if (rstc_id < 0) {
11831217
rstc = ERR_PTR(rstc_id);
1184-
goto out_put;
1218+
goto out_put;
11851219
}
11861220

11871221
flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL;
@@ -1190,7 +1224,7 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
11901224
rstc = __reset_control_get_internal(rcdev, rstc_id, flags);
11911225

11921226
out_put:
1193-
of_node_put(args.np);
1227+
fwnode_handle_put(args.fwnode);
11941228

11951229
return rstc;
11961230
}

0 commit comments

Comments
 (0)