xref: /linux/arch/sh/drivers/platform_early.c (revision d723091c8c3e076bb53d52ec3d5a801d49f30caf)
1 // SPDX--License-Identifier: GPL-2.0
2 
3 #include <asm/platform_early.h>
4 #include <linux/mod_devicetable.h>
5 #include <linux/pm.h>
6 
7 static __initdata LIST_HEAD(sh_early_platform_driver_list);
8 static __initdata LIST_HEAD(sh_early_platform_device_list);
9 
10 static const struct platform_device_id *
platform_match_id(const struct platform_device_id * id,struct platform_device * pdev)11 platform_match_id(const struct platform_device_id *id,
12 		  struct platform_device *pdev)
13 {
14 	while (id->name[0]) {
15 		if (strcmp(pdev->name, id->name) == 0) {
16 			pdev->id_entry = id;
17 			return id;
18 		}
19 		id++;
20 	}
21 	return NULL;
22 }
23 
platform_match(struct device * dev,struct device_driver * drv)24 static int platform_match(struct device *dev, struct device_driver *drv)
25 {
26 	struct platform_device *pdev = to_platform_device(dev);
27 	struct platform_driver *pdrv = to_platform_driver(drv);
28 
29 	/* Then try to match against the id table */
30 	if (pdrv->id_table)
31 		return platform_match_id(pdrv->id_table, pdev) != NULL;
32 
33 	/* fall-back to driver name match */
34 	return (strcmp(pdev->name, drv->name) == 0);
35 }
36 
37 #ifdef CONFIG_PM
device_pm_init_common(struct device * dev)38 static void device_pm_init_common(struct device *dev)
39 {
40 	if (!dev->power.early_init) {
41 		spin_lock_init(&dev->power.lock);
42 		dev->power.qos = NULL;
43 		dev->power.early_init = true;
44 	}
45 }
46 
pm_runtime_early_init(struct device * dev)47 static void pm_runtime_early_init(struct device *dev)
48 {
49 	dev->power.disable_depth = 1;
50 	device_pm_init_common(dev);
51 }
52 #else
pm_runtime_early_init(struct device * dev)53 static void pm_runtime_early_init(struct device *dev) {}
54 #endif
55 
56 /**
57  * sh_early_platform_driver_register - register early platform driver
58  * @epdrv: sh_early_platform driver structure
59  * @buf: string passed from early_param()
60  *
61  * Helper function for sh_early_platform_init() / sh_early_platform_init_buffer()
62  */
sh_early_platform_driver_register(struct sh_early_platform_driver * epdrv,char * buf)63 int __init sh_early_platform_driver_register(struct sh_early_platform_driver *epdrv,
64 					  char *buf)
65 {
66 	char *tmp;
67 	int n;
68 
69 	/* Simply add the driver to the end of the global list.
70 	 * Drivers will by default be put on the list in compiled-in order.
71 	 */
72 	if (!epdrv->list.next) {
73 		INIT_LIST_HEAD(&epdrv->list);
74 		list_add_tail(&epdrv->list, &sh_early_platform_driver_list);
75 	}
76 
77 	/* If the user has specified device then make sure the driver
78 	 * gets prioritized. The driver of the last device specified on
79 	 * command line will be put first on the list.
80 	 */
81 	n = strlen(epdrv->pdrv->driver.name);
82 	if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
83 		list_move(&epdrv->list, &sh_early_platform_driver_list);
84 
85 		/* Allow passing parameters after device name */
86 		if (buf[n] == '\0' || buf[n] == ',')
87 			epdrv->requested_id = -1;
88 		else {
89 			epdrv->requested_id = simple_strtoul(&buf[n + 1],
90 							     &tmp, 10);
91 
92 			if (buf[n] != '.' || (tmp == &buf[n + 1])) {
93 				epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
94 				n = 0;
95 			} else
96 				n += strcspn(&buf[n + 1], ",") + 1;
97 		}
98 
99 		if (buf[n] == ',')
100 			n++;
101 
102 		if (epdrv->bufsize) {
103 			memcpy(epdrv->buffer, &buf[n],
104 			       min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1));
105 			epdrv->buffer[epdrv->bufsize - 1] = '\0';
106 		}
107 	}
108 
109 	return 0;
110 }
111 
112 /**
113  * sh_early_platform_add_devices - adds a number of early platform devices
114  * @devs: array of early platform devices to add
115  * @num: number of early platform devices in array
116  *
117  * Used by early architecture code to register early platform devices and
118  * their platform data.
119  */
sh_early_platform_add_devices(struct platform_device ** devs,int num)120 void __init sh_early_platform_add_devices(struct platform_device **devs, int num)
121 {
122 	struct device *dev;
123 	int i;
124 
125 	/* simply add the devices to list */
126 	for (i = 0; i < num; i++) {
127 		dev = &devs[i]->dev;
128 
129 		if (!dev->devres_head.next) {
130 			pm_runtime_early_init(dev);
131 			INIT_LIST_HEAD(&dev->devres_head);
132 			list_add_tail(&dev->devres_head,
133 				      &sh_early_platform_device_list);
134 		}
135 	}
136 }
137 
138 /**
139  * sh_early_platform_driver_register_all - register early platform drivers
140  * @class_str: string to identify early platform driver class
141  *
142  * Used by architecture code to register all early platform drivers
143  * for a certain class. If omitted then only early platform drivers
144  * with matching kernel command line class parameters will be registered.
145  */
sh_early_platform_driver_register_all(char * class_str)146 void __init sh_early_platform_driver_register_all(char *class_str)
147 {
148 	/* The "class_str" parameter may or may not be present on the kernel
149 	 * command line. If it is present then there may be more than one
150 	 * matching parameter.
151 	 *
152 	 * Since we register our early platform drivers using early_param()
153 	 * we need to make sure that they also get registered in the case
154 	 * when the parameter is missing from the kernel command line.
155 	 *
156 	 * We use parse_early_options() to make sure the early_param() gets
157 	 * called at least once. The early_param() may be called more than
158 	 * once since the name of the preferred device may be specified on
159 	 * the kernel command line. sh_early_platform_driver_register() handles
160 	 * this case for us.
161 	 */
162 	parse_early_options(class_str);
163 }
164 
165 /**
166  * sh_early_platform_match - find early platform device matching driver
167  * @epdrv: early platform driver structure
168  * @id: id to match against
169  */
170 static struct platform_device * __init
sh_early_platform_match(struct sh_early_platform_driver * epdrv,int id)171 sh_early_platform_match(struct sh_early_platform_driver *epdrv, int id)
172 {
173 	struct platform_device *pd;
174 
175 	list_for_each_entry(pd, &sh_early_platform_device_list, dev.devres_head)
176 		if (platform_match(&pd->dev, &epdrv->pdrv->driver))
177 			if (pd->id == id)
178 				return pd;
179 
180 	return NULL;
181 }
182 
183 /**
184  * sh_early_platform_left - check if early platform driver has matching devices
185  * @epdrv: early platform driver structure
186  * @id: return true if id or above exists
187  */
sh_early_platform_left(struct sh_early_platform_driver * epdrv,int id)188 static int __init sh_early_platform_left(struct sh_early_platform_driver *epdrv,
189 				       int id)
190 {
191 	struct platform_device *pd;
192 
193 	list_for_each_entry(pd, &sh_early_platform_device_list, dev.devres_head)
194 		if (platform_match(&pd->dev, &epdrv->pdrv->driver))
195 			if (pd->id >= id)
196 				return 1;
197 
198 	return 0;
199 }
200 
201 /**
202  * sh_early_platform_driver_probe_id - probe drivers matching class_str and id
203  * @class_str: string to identify early platform driver class
204  * @id: id to match against
205  * @nr_probe: number of platform devices to successfully probe before exiting
206  */
sh_early_platform_driver_probe_id(char * class_str,int id,int nr_probe)207 static int __init sh_early_platform_driver_probe_id(char *class_str,
208 						 int id,
209 						 int nr_probe)
210 {
211 	struct sh_early_platform_driver *epdrv;
212 	struct platform_device *match;
213 	int match_id;
214 	int n = 0;
215 	int left = 0;
216 
217 	list_for_each_entry(epdrv, &sh_early_platform_driver_list, list) {
218 		/* only use drivers matching our class_str */
219 		if (strcmp(class_str, epdrv->class_str))
220 			continue;
221 
222 		if (id == -2) {
223 			match_id = epdrv->requested_id;
224 			left = 1;
225 
226 		} else {
227 			match_id = id;
228 			left += sh_early_platform_left(epdrv, id);
229 
230 			/* skip requested id */
231 			switch (epdrv->requested_id) {
232 			case EARLY_PLATFORM_ID_ERROR:
233 			case EARLY_PLATFORM_ID_UNSET:
234 				break;
235 			default:
236 				if (epdrv->requested_id == id)
237 					match_id = EARLY_PLATFORM_ID_UNSET;
238 			}
239 		}
240 
241 		switch (match_id) {
242 		case EARLY_PLATFORM_ID_ERROR:
243 			pr_warn("%s: unable to parse %s parameter\n",
244 				class_str, epdrv->pdrv->driver.name);
245 			fallthrough;
246 		case EARLY_PLATFORM_ID_UNSET:
247 			match = NULL;
248 			break;
249 		default:
250 			match = sh_early_platform_match(epdrv, match_id);
251 		}
252 
253 		if (match) {
254 			/*
255 			 * Set up a sensible init_name to enable
256 			 * dev_name() and others to be used before the
257 			 * rest of the driver core is initialized.
258 			 */
259 			if (!match->dev.init_name && slab_is_available()) {
260 				if (match->id != -1)
261 					match->dev.init_name =
262 						kasprintf(GFP_KERNEL, "%s.%d",
263 							  match->name,
264 							  match->id);
265 				else
266 					match->dev.init_name =
267 						kasprintf(GFP_KERNEL, "%s",
268 							  match->name);
269 
270 				if (!match->dev.init_name)
271 					return -ENOMEM;
272 			}
273 
274 			if (epdrv->pdrv->probe(match))
275 				pr_warn("%s: unable to probe %s early.\n",
276 					class_str, match->name);
277 			else
278 				n++;
279 		}
280 
281 		if (n >= nr_probe)
282 			break;
283 	}
284 
285 	if (left)
286 		return n;
287 	else
288 		return -ENODEV;
289 }
290 
291 /**
292  * sh_early_platform_driver_probe - probe a class of registered drivers
293  * @class_str: string to identify early platform driver class
294  * @nr_probe: number of platform devices to successfully probe before exiting
295  * @user_only: only probe user specified early platform devices
296  *
297  * Used by architecture code to probe registered early platform drivers
298  * within a certain class. For probe to happen a registered early platform
299  * device matching a registered early platform driver is needed.
300  */
sh_early_platform_driver_probe(char * class_str,int nr_probe,int user_only)301 int __init sh_early_platform_driver_probe(char *class_str,
302 				       int nr_probe,
303 				       int user_only)
304 {
305 	int k, n, i;
306 
307 	n = 0;
308 	for (i = -2; n < nr_probe; i++) {
309 		k = sh_early_platform_driver_probe_id(class_str, i, nr_probe - n);
310 
311 		if (k < 0)
312 			break;
313 
314 		n += k;
315 
316 		if (user_only)
317 			break;
318 	}
319 
320 	return n;
321 }
322 
323 /**
324  * early_platform_cleanup - clean up early platform code
325  */
early_platform_cleanup(void)326 void __init early_platform_cleanup(void)
327 {
328 	struct platform_device *pd, *pd2;
329 
330 	/* clean up the devres list used to chain devices */
331 	list_for_each_entry_safe(pd, pd2, &sh_early_platform_device_list,
332 				 dev.devres_head) {
333 		list_del(&pd->dev.devres_head);
334 		memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head));
335 	}
336 }
337