Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Bartosz Golaszewski and committed by
Philipp Zabel
9035073d ba8dbbb1

+112 -68
+100 -66
drivers/reset/core.c
··· 81 81 82 82 /** 83 83 * 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 85 85 * @swnode: Software node containing the reference to the GPIO provider 86 86 * @list: list entry for the reset_gpio_lookup_list 87 87 * @adev: Auxiliary device representing the reset controller 88 88 */ 89 89 struct reset_gpio_lookup { 90 - struct of_phandle_args of_args; 90 + struct fwnode_reference_args ref_args; 91 91 struct fwnode_handle *swnode; 92 92 struct list_head list; 93 93 struct auxiliary_device adev; ··· 98 98 if (rcdev->dev) 99 99 return dev_name(rcdev->dev); 100 100 101 - if (rcdev->of_node) 102 - return rcdev->of_node->full_name; 101 + if (rcdev->fwnode) 102 + return fwnode_get_name(rcdev->fwnode); 103 103 104 104 return NULL; 105 105 } 106 106 107 107 /** 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 109 109 * @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 111 111 * 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. 116 116 */ 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) 119 119 { 120 120 if (reset_spec->args[0] >= rcdev->nr_resets) 121 121 return -EINVAL; ··· 129 129 */ 130 130 int reset_controller_register(struct reset_controller_dev *rcdev) 131 131 { 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; 135 149 } 136 150 137 151 INIT_LIST_HEAD(&rcdev->reset_control_head); ··· 945 931 adev->id = id; 946 932 adev->name = "gpio"; 947 933 adev->dev.parent = parent; 948 - adev->dev.platform_data = &rgpio_dev->of_args; 934 + adev->dev.platform_data = &rgpio_dev->ref_args; 949 935 adev->dev.release = reset_gpio_aux_device_release; 950 936 device_set_node(&adev->dev, rgpio_dev->swnode); 951 937 ··· 965 951 return 0; 966 952 } 967 953 968 - static void reset_gpio_add_devlink(struct device_node *np, 954 + static void reset_gpio_add_devlink(struct fwnode_handle *fwnode, 969 955 struct reset_gpio_lookup *rgpio_dev) 970 956 { 971 957 struct device *consumer; 972 958 973 959 /* 974 - * We must use get_dev_from_fwnode() and not of_find_device_by_node() 960 + * We must use get_dev_from_fwnode() and not ref_find_device_by_node() 975 961 * because the latter only considers the platform bus while we want to 976 962 * get consumers of any kind that can be associated with firmware 977 963 * nodes: auxiliary, soundwire, etc. 978 964 */ 979 - consumer = get_dev_from_fwnode(of_fwnode_handle(np)); 965 + consumer = get_dev_from_fwnode(fwnode); 980 966 if (consumer) { 981 967 if (!device_link_add(consumer, &rgpio_dev->adev.dev, 982 968 DL_FLAG_AUTOREMOVE_CONSUMER)) ··· 996 982 */ 997 983 } 998 984 985 + /* TODO: move it out into drivers/base/ */ 986 + static bool fwnode_reference_args_equal(const struct fwnode_reference_args *left, 987 + const struct fwnode_reference_args *right) 988 + { 989 + return left->fwnode == right->fwnode && left->nargs == right->nargs && 990 + !memcmp(left->args, right->args, sizeof(left->args[0]) * left->nargs); 991 + } 992 + 999 993 /* 1000 994 * @np: OF-node associated with the consumer 1001 - * @args: phandle to the GPIO provider with all the args like GPIO number 995 + * @args: Reference to the GPIO provider with all the args like GPIO number 1002 996 */ 1003 - static int __reset_add_reset_gpio_device(struct device_node *np, 1004 - const struct of_phandle_args *args) 997 + static int __reset_add_reset_gpio_device(struct fwnode_handle *fwnode, 998 + const struct fwnode_reference_args *args) 1005 999 { 1006 1000 struct property_entry properties[3] = { }; 1007 - unsigned int offset, of_flags, lflags; 1001 + unsigned int offset, flags, lflags; 1008 1002 struct reset_gpio_lookup *rgpio_dev; 1009 1003 struct device *parent; 1010 1004 int ret, prop = 0; ··· 1023 1001 * args[1]: GPIO flags 1024 1002 * TODO: Handle other cases. 1025 1003 */ 1026 - if (args->args_count != 2) 1004 + if (args->nargs != 2) 1027 1005 return -ENOENT; 1028 1006 1029 1007 /* ··· 1034 1012 lockdep_assert_not_held(&reset_list_mutex); 1035 1013 1036 1014 offset = args->args[0]; 1037 - of_flags = args->args[1]; 1015 + flags = args->args[1]; 1038 1016 1039 1017 /* 1040 1018 * Later we map GPIO flags between OF and Linux, however not all ··· 1044 1022 * FIXME: Find a better way of translating OF flags to GPIO lookup 1045 1023 * flags. 1046 1024 */ 1047 - if (of_flags > GPIO_ACTIVE_LOW) { 1025 + if (flags > GPIO_ACTIVE_LOW) { 1048 1026 pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n", 1049 - of_flags, offset); 1027 + flags, offset); 1050 1028 return -EINVAL; 1051 1029 } 1052 1030 1053 1031 struct gpio_device *gdev __free(gpio_device_put) = 1054 - gpio_device_find_by_fwnode(of_fwnode_handle(args->np)); 1032 + gpio_device_find_by_fwnode(args->fwnode); 1055 1033 if (!gdev) 1056 1034 return -EPROBE_DEFER; 1057 1035 1058 1036 guard(mutex)(&reset_gpio_lookup_mutex); 1059 1037 1060 1038 list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) { 1061 - if (args->np == rgpio_dev->of_args.np) { 1062 - if (of_phandle_args_equal(args, &rgpio_dev->of_args)) { 1063 - /* 1064 - * Already on the list, create the device link 1065 - * and stop here. 1066 - */ 1067 - reset_gpio_add_devlink(np, rgpio_dev); 1068 - return 0; 1069 - } 1039 + if (fwnode_reference_args_equal(args, &rgpio_dev->ref_args)) { 1040 + /* 1041 + * Already on the list, create the device link 1042 + * and stop here. 1043 + */ 1044 + reset_gpio_add_devlink(fwnode, rgpio_dev); 1045 + return 0; 1070 1046 } 1071 1047 } 1072 1048 1073 - lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW); 1049 + lflags = GPIO_PERSISTENT | (flags & GPIO_ACTIVE_LOW); 1074 1050 parent = gpio_device_to_device(gdev); 1075 1051 properties[prop++] = PROPERTY_ENTRY_STRING("compatible", "reset-gpio"); 1076 1052 properties[prop++] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags); ··· 1078 1058 if (!rgpio_dev) 1079 1059 return -ENOMEM; 1080 1060 1081 - rgpio_dev->of_args = *args; 1061 + rgpio_dev->ref_args = *args; 1082 1062 /* 1083 - * We keep the device_node reference, but of_args.np is put at the end 1084 - * of __fwnode_reset_control_get(), so get it one more time. 1063 + * We keep the fwnode_handle reference, but ref_args.fwnode is put at 1064 + * the end of __fwnode_reset_control_get(), so get it one more time. 1085 1065 * Hold reference as long as rgpio_dev memory is valid. 1086 1066 */ 1087 - of_node_get(rgpio_dev->of_args.np); 1067 + fwnode_handle_get(rgpio_dev->ref_args.fwnode); 1088 1068 1089 1069 rgpio_dev->swnode = fwnode_create_software_node(properties, NULL); 1090 1070 if (IS_ERR(rgpio_dev->swnode)) { 1091 1071 ret = PTR_ERR(rgpio_dev->swnode); 1092 - goto err_put_of_node; 1072 + goto err_put_fwnode; 1093 1073 } 1094 1074 1095 1075 ret = reset_create_gpio_aux_device(rgpio_dev, parent); 1096 1076 if (ret) 1097 1077 goto err_del_swnode; 1098 1078 1099 - reset_gpio_add_devlink(np, rgpio_dev); 1079 + reset_gpio_add_devlink(fwnode, rgpio_dev); 1100 1080 list_add(&rgpio_dev->list, &reset_gpio_lookup_list); 1101 1081 1102 1082 return 0; 1103 1083 1104 1084 err_del_swnode: 1105 1085 fwnode_remove_software_node(rgpio_dev->swnode); 1106 - err_put_of_node: 1107 - of_node_put(rgpio_dev->of_args.np); 1086 + err_put_fwnode: 1087 + fwnode_handle_put(rgpio_dev->ref_args.fwnode); 1108 1088 kfree(rgpio_dev); 1109 1089 1110 1090 return ret; 1111 1091 } 1112 1092 1113 - static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_args *args, 1114 - bool gpio_fallback) 1093 + static struct reset_controller_dev * 1094 + __reset_find_rcdev(const struct fwnode_reference_args *args, bool gpio_fallback) 1115 1095 { 1096 + struct fwnode_reference_args *rc_args; 1116 1097 struct reset_controller_dev *rcdev; 1117 - struct of_phandle_args *rc_args; 1118 1098 1119 1099 lockdep_assert_held(&reset_list_mutex); 1120 1100 ··· 1123 1103 device_is_compatible(rcdev->dev, "reset-gpio")) { 1124 1104 rc_args = dev_get_platdata(rcdev->dev); 1125 1105 1126 - if (of_phandle_args_equal(args, rc_args)) 1106 + if (fwnode_reference_args_equal(args, rc_args)) 1127 1107 return rcdev; 1128 1108 } else { 1129 - if (args->np == rcdev->of_node) 1109 + if (args->fwnode == rcdev->fwnode) 1130 1110 return rcdev; 1131 1111 } 1132 1112 } ··· 1140 1120 { 1141 1121 bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL; 1142 1122 bool gpio_fallback = false; 1143 - struct device_node *node = to_of_node(fwnode); 1144 1123 struct reset_control *rstc = ERR_PTR(-EINVAL); 1145 1124 struct reset_controller_dev *rcdev; 1146 - struct of_phandle_args args; 1147 - int rstc_id; 1125 + struct fwnode_reference_args args; 1126 + struct of_phandle_args of_args; 1127 + int rstc_id = -EINVAL; 1148 1128 int ret; 1149 1129 1150 1130 if (!fwnode) 1151 1131 return ERR_PTR(-EINVAL); 1152 1132 1153 1133 if (id) { 1154 - index = of_property_match_string(node, 1155 - "reset-names", id); 1134 + index = fwnode_property_match_string(fwnode, "reset-names", id); 1156 1135 if (index == -EILSEQ) 1157 1136 return ERR_PTR(index); 1158 1137 if (index < 0) 1159 1138 return optional ? NULL : ERR_PTR(-ENOENT); 1160 1139 } 1161 1140 1162 - ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", 1163 - index, &args); 1141 + ret = fwnode_property_get_reference_args(fwnode, "resets", "#reset-cells", 1142 + 0, index, &args); 1164 1143 if (ret == -EINVAL) 1165 1144 return ERR_PTR(ret); 1166 1145 if (ret) { ··· 1170 1151 * There can be only one reset-gpio for regular devices, so 1171 1152 * don't bother with the "reset-gpios" phandle index. 1172 1153 */ 1173 - ret = of_parse_phandle_with_args(node, "reset-gpios", "#gpio-cells", 1174 - 0, &args); 1154 + ret = fwnode_property_get_reference_args(fwnode, "reset-gpios", 1155 + "#gpio-cells", 0, 0, &args); 1175 1156 if (ret) 1176 1157 return optional ? NULL : ERR_PTR(ret); 1177 1158 1178 1159 gpio_fallback = true; 1179 1160 1180 - ret = __reset_add_reset_gpio_device(node, &args); 1161 + ret = __reset_add_reset_gpio_device(fwnode, &args); 1181 1162 if (ret) { 1182 - of_node_put(args.np); 1163 + fwnode_handle_put(args.fwnode); 1183 1164 return ERR_PTR(ret); 1184 1165 } 1185 1166 } ··· 1192 1173 goto out_put; 1193 1174 } 1194 1175 1195 - if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) { 1176 + if (WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) { 1196 1177 rstc = ERR_PTR(-EINVAL); 1197 1178 goto out_put; 1198 1179 } 1199 1180 1200 - rstc_id = rcdev->of_xlate(rcdev, &args); 1181 + if (rcdev->of_xlate && is_of_node(fwnode)) { 1182 + ret = of_parse_phandle_with_args(to_of_node(fwnode), 1183 + gpio_fallback ? "reset-gpios" : "resets", 1184 + gpio_fallback ? "#gpio-cells" : "#reset-cells", 1185 + gpio_fallback ? 0 : index, 1186 + &of_args); 1187 + if (ret) { 1188 + rstc = ERR_PTR(ret); 1189 + goto out_put; 1190 + } 1191 + 1192 + rstc_id = rcdev->of_xlate(rcdev, &of_args); 1193 + of_node_put(of_args.np); 1194 + } else if (rcdev->fwnode_xlate) { 1195 + rstc_id = rcdev->fwnode_xlate(rcdev, &args); 1196 + } 1201 1197 if (rstc_id < 0) { 1202 1198 rstc = ERR_PTR(rstc_id); 1203 - goto out_put; 1199 + goto out_put; 1204 1200 } 1205 1201 1206 1202 flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL; ··· 1224 1190 rstc = __reset_control_get_internal(rcdev, rstc_id, flags); 1225 1191 1226 1192 out_put: 1227 - of_node_put(args.np); 1193 + fwnode_handle_put(args.fwnode); 1228 1194 1229 1195 return rstc; 1230 1196 }
+12 -2
include/linux/reset-controller.h
··· 5 5 #include <linux/list.h> 6 6 #include <linux/mutex.h> 7 7 8 + struct fwnode_handle; 9 + struct fwnode_reference_args; 8 10 struct reset_controller_dev; 9 11 10 12 /** ··· 40 38 * @of_node: corresponding device tree node as phandle target 41 39 * @of_reset_n_cells: number of cells in reset line specifiers 42 40 * @of_xlate: translation function to translate from specifier as found in the 43 - * device tree to id as given to the reset control ops, defaults 44 - * to :c:func:`of_reset_simple_xlate`. 41 + * device tree to id as given to the reset control ops 42 + * @fwnode: firmware node associated with this device 43 + * @fwnode_reset_n_cells: number of cells in reset line specifiers 44 + * @fwnode_xlate: translation function to translate from firmware specifier to 45 + * id as given to the reset control ops, defaults to 46 + * :c:func:`fwnode_reset_simple_xlate` 45 47 * @nr_resets: number of reset controls in this reset controller device 46 48 * @lock: protects the reset control list from concurrent access 47 49 */ ··· 59 53 int of_reset_n_cells; 60 54 int (*of_xlate)(struct reset_controller_dev *rcdev, 61 55 const struct of_phandle_args *reset_spec); 56 + struct fwnode_handle *fwnode; 57 + int fwnode_reset_n_cells; 58 + int (*fwnode_xlate)(struct reset_controller_dev *rcdev, 59 + const struct fwnode_reference_args *reset_spec); 62 60 unsigned int nr_resets; 63 61 struct mutex lock; 64 62 };