xref: /linux/drivers/bus/stm32_firewall.c (revision 5643c6b2c8308b206cb01cbfd0e6ac80f9f1bc9a)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
4  */
5 
6 #include <linux/bitfield.h>
7 #include <linux/bits.h>
8 #include <linux/bus/stm32_firewall.h>
9 #include <linux/bus/stm32_firewall_device.h>
10 #include <linux/device.h>
11 #include <linux/err.h>
12 #include <linux/init.h>
13 #include <linux/io.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/of.h>
17 #include <linux/of_platform.h>
18 #include <linux/platform_device.h>
19 #include <linux/types.h>
20 #include <linux/slab.h>
21 
22 /* Corresponds to STM32_FIREWALL_MAX_EXTRA_ARGS + firewall ID */
23 #define STM32_FIREWALL_MAX_ARGS		(STM32_FIREWALL_MAX_EXTRA_ARGS + 1)
24 
25 static LIST_HEAD(firewall_controller_list);
26 static DEFINE_MUTEX(firewall_controller_list_lock);
27 
28 /* Firewall device API */
29 
30 int stm32_firewall_get_firewall(struct device_node *np, struct stm32_firewall *firewall,
31 				unsigned int nb_firewall)
32 {
33 	struct stm32_firewall_controller *ctrl;
34 	struct of_phandle_iterator it;
35 	unsigned int i, j = 0;
36 	int err;
37 
38 	if (!firewall || !nb_firewall)
39 		return -EINVAL;
40 
41 	/* Parse property with phandle parsed out */
42 	of_for_each_phandle(&it, err, np, "access-controllers", "#access-controller-cells", 0) {
43 		struct of_phandle_args provider_args;
44 		struct device_node *provider = it.node;
45 		const char *fw_entry;
46 		bool match = false;
47 
48 		if (err) {
49 			pr_err("Unable to get access-controllers property for node %s\n, err: %d",
50 			       np->full_name, err);
51 			of_node_put(provider);
52 			return err;
53 		}
54 
55 		if (j >= nb_firewall) {
56 			pr_err("Too many firewall controllers");
57 			of_node_put(provider);
58 			return -EINVAL;
59 		}
60 
61 		provider_args.args_count = of_phandle_iterator_args(&it, provider_args.args,
62 								    STM32_FIREWALL_MAX_ARGS);
63 
64 		/* Check if the parsed phandle corresponds to a registered firewall controller */
65 		mutex_lock(&firewall_controller_list_lock);
66 		list_for_each_entry(ctrl, &firewall_controller_list, entry) {
67 			if (ctrl->dev->of_node->phandle == it.phandle) {
68 				match = true;
69 				firewall[j].firewall_ctrl = ctrl;
70 				break;
71 			}
72 		}
73 		mutex_unlock(&firewall_controller_list_lock);
74 
75 		if (!match) {
76 			firewall[j].firewall_ctrl = NULL;
77 			pr_err("No firewall controller registered for %s\n", np->full_name);
78 			of_node_put(provider);
79 			return -ENODEV;
80 		}
81 
82 		err = of_property_read_string_index(np, "access-controller-names", j, &fw_entry);
83 		if (err == 0)
84 			firewall[j].entry = fw_entry;
85 
86 		/* Handle the case when there are no arguments given along with the phandle */
87 		if (provider_args.args_count < 0 ||
88 		    provider_args.args_count > STM32_FIREWALL_MAX_ARGS) {
89 			of_node_put(provider);
90 			return -EINVAL;
91 		} else if (provider_args.args_count == 0) {
92 			firewall[j].extra_args_size = 0;
93 			firewall[j].firewall_id = U32_MAX;
94 			j++;
95 			continue;
96 		}
97 
98 		/* The firewall ID is always the first argument */
99 		firewall[j].firewall_id = provider_args.args[0];
100 
101 		/* Extra args start at the second argument */
102 		for (i = 0; i < provider_args.args_count - 1; i++)
103 			firewall[j].extra_args[i] = provider_args.args[i + 1];
104 
105 		/* Remove the firewall ID arg that is not an extra argument */
106 		firewall[j].extra_args_size = provider_args.args_count - 1;
107 
108 		j++;
109 	}
110 
111 	return 0;
112 }
113 EXPORT_SYMBOL_GPL(stm32_firewall_get_firewall);
114 
115 int stm32_firewall_grant_access(struct stm32_firewall *firewall)
116 {
117 	struct stm32_firewall_controller *firewall_controller;
118 
119 	if (!firewall || firewall->firewall_id == U32_MAX)
120 		return -EINVAL;
121 
122 	firewall_controller = firewall->firewall_ctrl;
123 
124 	if (!firewall_controller)
125 		return -ENODEV;
126 
127 	return firewall_controller->grant_access(firewall_controller, firewall->firewall_id);
128 }
129 EXPORT_SYMBOL_GPL(stm32_firewall_grant_access);
130 
131 int stm32_firewall_grant_access_by_id(struct stm32_firewall *firewall, u32 subsystem_id)
132 {
133 	struct stm32_firewall_controller *firewall_controller;
134 
135 	if (!firewall || subsystem_id == U32_MAX || firewall->firewall_id == U32_MAX)
136 		return -EINVAL;
137 
138 	firewall_controller = firewall->firewall_ctrl;
139 
140 	if (!firewall_controller)
141 		return -ENODEV;
142 
143 	return firewall_controller->grant_access(firewall_controller, subsystem_id);
144 }
145 EXPORT_SYMBOL_GPL(stm32_firewall_grant_access_by_id);
146 
147 void stm32_firewall_release_access(struct stm32_firewall *firewall)
148 {
149 	struct stm32_firewall_controller *firewall_controller;
150 
151 	if (!firewall || firewall->firewall_id == U32_MAX) {
152 		pr_debug("Incorrect arguments when releasing a firewall access\n");
153 		return;
154 	}
155 
156 	firewall_controller = firewall->firewall_ctrl;
157 
158 	if (!firewall_controller) {
159 		pr_debug("No firewall controller to release\n");
160 		return;
161 	}
162 
163 	firewall_controller->release_access(firewall_controller, firewall->firewall_id);
164 }
165 EXPORT_SYMBOL_GPL(stm32_firewall_release_access);
166 
167 void stm32_firewall_release_access_by_id(struct stm32_firewall *firewall, u32 subsystem_id)
168 {
169 	struct stm32_firewall_controller *firewall_controller;
170 
171 	if (!firewall || subsystem_id == U32_MAX || firewall->firewall_id == U32_MAX) {
172 		pr_debug("Incorrect arguments when releasing a firewall access");
173 		return;
174 	}
175 
176 	firewall_controller = firewall->firewall_ctrl;
177 
178 	if (!firewall_controller) {
179 		pr_debug("No firewall controller to release");
180 		return;
181 	}
182 
183 	firewall_controller->release_access(firewall_controller, subsystem_id);
184 }
185 EXPORT_SYMBOL_GPL(stm32_firewall_release_access_by_id);
186 
187 int stm32_firewall_get_grant_all_access(struct device *dev, struct stm32_firewall **firewall,
188 					int *nb_firewall)
189 {
190 	struct stm32_firewall *loc_firewall;
191 	int err;
192 	int i;
193 
194 	*nb_firewall = of_count_phandle_with_args(dev->of_node, "access-controllers",
195 						  "#access-controller-cells");
196 	if (*nb_firewall < 0)
197 		return *nb_firewall;
198 
199 	if (!*nb_firewall) {
200 		*firewall = NULL;
201 		return 0;
202 	}
203 
204 	loc_firewall = devm_kcalloc(dev, *nb_firewall, sizeof(*loc_firewall), GFP_KERNEL);
205 	if (!loc_firewall)
206 		return -ENOMEM;
207 
208 	/* Get stm32 firewall information */
209 	err = stm32_firewall_get_firewall(dev->of_node, loc_firewall, *nb_firewall);
210 	if (err)
211 		return err;
212 
213 	for (i = 0; i < *nb_firewall; i++) {
214 		err = stm32_firewall_grant_access(&loc_firewall[i]);
215 		if (err) {
216 			while (i--)
217 				stm32_firewall_release_access(&loc_firewall[i]);
218 
219 			return err;
220 		}
221 	}
222 
223 	*firewall = loc_firewall;
224 
225 	return 0;
226 }
227 EXPORT_SYMBOL_GPL(stm32_firewall_get_grant_all_access);
228 
229 /* Firewall controller API */
230 
231 int stm32_firewall_controller_register(struct stm32_firewall_controller *firewall_controller)
232 {
233 	struct stm32_firewall_controller *ctrl;
234 
235 	if (!firewall_controller)
236 		return -ENODEV;
237 
238 	pr_info("Registering %s firewall controller\n", firewall_controller->name);
239 
240 	mutex_lock(&firewall_controller_list_lock);
241 	list_for_each_entry(ctrl, &firewall_controller_list, entry) {
242 		if (ctrl == firewall_controller) {
243 			pr_debug("%s firewall controller already registered\n",
244 				 firewall_controller->name);
245 			mutex_unlock(&firewall_controller_list_lock);
246 			return 0;
247 		}
248 	}
249 	list_add_tail(&firewall_controller->entry, &firewall_controller_list);
250 	mutex_unlock(&firewall_controller_list_lock);
251 
252 	return 0;
253 }
254 EXPORT_SYMBOL_GPL(stm32_firewall_controller_register);
255 
256 void stm32_firewall_controller_unregister(struct stm32_firewall_controller *firewall_controller)
257 {
258 	struct stm32_firewall_controller *ctrl;
259 	bool controller_removed = false;
260 
261 	if (!firewall_controller) {
262 		pr_debug("Null reference while unregistering firewall controller\n");
263 		return;
264 	}
265 
266 	mutex_lock(&firewall_controller_list_lock);
267 	list_for_each_entry(ctrl, &firewall_controller_list, entry) {
268 		if (ctrl == firewall_controller) {
269 			controller_removed = true;
270 			list_del_init(&ctrl->entry);
271 			break;
272 		}
273 	}
274 	mutex_unlock(&firewall_controller_list_lock);
275 
276 	if (!controller_removed)
277 		pr_debug("There was no firewall controller named %s to unregister\n",
278 			 firewall_controller->name);
279 }
280 EXPORT_SYMBOL_GPL(stm32_firewall_controller_unregister);
281 
282 int stm32_firewall_populate_bus(struct stm32_firewall_controller *firewall_controller)
283 {
284 	struct stm32_firewall *firewalls;
285 	struct device *parent;
286 	unsigned int i;
287 	int len;
288 	int err;
289 
290 	parent = firewall_controller->dev;
291 
292 	dev_dbg(parent, "Populating %s system bus\n", dev_name(firewall_controller->dev));
293 
294 	for_each_available_child_of_node_scoped(dev_of_node(parent), child) {
295 		/* The access-controllers property is mandatory for firewall bus devices */
296 		len = of_count_phandle_with_args(child, "access-controllers",
297 						 "#access-controller-cells");
298 		if (len <= 0)
299 			return -EINVAL;
300 
301 		firewalls = kzalloc_objs(*firewalls, len);
302 		if (!firewalls)
303 			return -ENOMEM;
304 
305 		err = stm32_firewall_get_firewall(child, firewalls, (unsigned int)len);
306 		if (err) {
307 			kfree(firewalls);
308 			return err;
309 		}
310 
311 		for (i = 0; i < len; i++) {
312 			if (firewall_controller->grant_access(firewalls[i].firewall_ctrl,
313 							      firewalls[i].firewall_id)) {
314 				/*
315 				 * Peripheral access not allowed or not defined.
316 				 * Mark the node as populated so platform bus won't probe it
317 				 */
318 				of_detach_node(child);
319 				dev_err(parent, "%s: Device driver will not be probed\n",
320 					child->full_name);
321 			}
322 		}
323 
324 		kfree(firewalls);
325 	}
326 
327 	return 0;
328 }
329 EXPORT_SYMBOL_GPL(stm32_firewall_populate_bus);
330