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