1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2015
4 * Texas Instruments Incorporated - https://www.ti.com/
5 */
6
7#define LOG_CATEGORY UCLASS_REMOTEPROC
8
9#define pr_fmt(fmt) "%s: " fmt, __func__
10#include <common.h>
11#include <elf.h>
12#include <errno.h>
13#include <log.h>
14#include <malloc.h>
15#include <virtio_ring.h>
16#include <fs_loader.h>
17#include <remoteproc.h>
18#include <asm/io.h>
19#include <dm/device-internal.h>
20#include <dm.h>
21#include <dm/uclass.h>
22#include <dm/uclass-internal.h>
23#include <linux/compat.h>
24#include <linux/printk.h>
25
26DECLARE_GLOBAL_DATA_PTR;
27
28struct resource_table {
29	u32 ver;
30	u32 num;
31	u32 reserved[2];
32	u32 offset[0];
33} __packed;
34
35typedef int (*handle_resource_t) (struct udevice *, void *, int offset, int avail);
36
37static struct resource_table *rsc_table;
38
39/**
40 * for_each_remoteproc_device() - iterate through the list of rproc devices
41 * @fn: check function to call per match, if this function returns fail,
42 *	iteration is aborted with the resultant error value
43 * @skip_dev:	Device to skip calling the callback about.
44 * @data:	Data to pass to the callback function
45 *
46 * Return: 0 if none of the callback returned a non 0 result, else returns the
47 * result from the callback function
48 */
49static int for_each_remoteproc_device(int (*fn) (struct udevice *dev,
50					struct dm_rproc_uclass_pdata *uc_pdata,
51					const void *data),
52				      struct udevice *skip_dev,
53				      const void *data)
54{
55	struct udevice *dev;
56	struct dm_rproc_uclass_pdata *uc_pdata;
57	int ret;
58
59	for (ret = uclass_find_first_device(UCLASS_REMOTEPROC, &dev); dev;
60	     ret = uclass_find_next_device(&dev)) {
61		if (ret || dev == skip_dev)
62			continue;
63		uc_pdata = dev_get_uclass_plat(dev);
64		ret = fn(dev, uc_pdata, data);
65		if (ret)
66			return ret;
67	}
68
69	return 0;
70}
71
72/**
73 * _rproc_name_is_unique() - iteration helper to check if rproc name is unique
74 * @dev:	device that we are checking name for
75 * @uc_pdata:	uclass platform data
76 * @data:	compare data (this is the name we want to ensure is unique)
77 *
78 * Return: 0 is there is no match(is unique); if there is a match(we dont
79 * have a unique name), return -EINVAL.
80 */
81static int _rproc_name_is_unique(struct udevice *dev,
82				 struct dm_rproc_uclass_pdata *uc_pdata,
83				 const void *data)
84{
85	const char *check_name = data;
86
87	/* devices not yet populated with data - so skip them */
88	if (!uc_pdata->name || !check_name)
89		return 0;
90
91	/* Return 0 to search further if we dont match */
92	if (strlen(uc_pdata->name) != strlen(check_name))
93		return 0;
94
95	if (!strcmp(uc_pdata->name, check_name))
96		return -EINVAL;
97
98	return 0;
99}
100
101/**
102 * rproc_name_is_unique() - Check if the rproc name is unique
103 * @check_dev:	Device we are attempting to ensure is unique
104 * @check_name:	Name we are trying to ensure is unique.
105 *
106 * Return: true if we have a unique name, false if name is not unique.
107 */
108static bool rproc_name_is_unique(struct udevice *check_dev,
109				 const char *check_name)
110{
111	int ret;
112
113	ret = for_each_remoteproc_device(_rproc_name_is_unique,
114					 check_dev, check_name);
115	return ret ? false : true;
116}
117
118/**
119 * rproc_pre_probe() - Pre probe accessor for the uclass
120 * @dev:	device for which we are preprobing
121 *
122 * Parses and fills up the uclass pdata for use as needed by core and
123 * remote proc drivers.
124 *
125 * Return: 0 if all wernt ok, else appropriate error value.
126 */
127static int rproc_pre_probe(struct udevice *dev)
128{
129	struct dm_rproc_uclass_pdata *uc_pdata;
130	const struct dm_rproc_ops *ops;
131
132	uc_pdata = dev_get_uclass_plat(dev);
133
134	/* See if we need to populate via fdt */
135
136	if (!dev_get_plat(dev)) {
137#if CONFIG_IS_ENABLED(OF_CONTROL)
138		bool tmp;
139		debug("'%s': using fdt\n", dev->name);
140		uc_pdata->name = dev_read_string(dev, "remoteproc-name");
141
142		/* Default is internal memory mapped */
143		uc_pdata->mem_type = RPROC_INTERNAL_MEMORY_MAPPED;
144		tmp = dev_read_bool(dev, "remoteproc-internal-memory-mapped");
145		if (tmp)
146			uc_pdata->mem_type = RPROC_INTERNAL_MEMORY_MAPPED;
147#else
148		/* Nothing much we can do about this, can we? */
149		return -EINVAL;
150#endif
151
152	} else {
153		struct dm_rproc_uclass_pdata *pdata = dev_get_plat(dev);
154
155		debug("'%s': using legacy data\n", dev->name);
156		if (pdata->name)
157			uc_pdata->name = pdata->name;
158		uc_pdata->mem_type = pdata->mem_type;
159		uc_pdata->driver_plat_data = pdata->driver_plat_data;
160	}
161
162	/* Else try using device Name */
163	if (!uc_pdata->name)
164		uc_pdata->name = dev->name;
165	if (!uc_pdata->name) {
166		debug("Unnamed device!");
167		return -EINVAL;
168	}
169
170	if (!rproc_name_is_unique(dev, uc_pdata->name)) {
171		debug("%s duplicate name '%s'\n", dev->name, uc_pdata->name);
172		return -EINVAL;
173	}
174
175	ops = rproc_get_ops(dev);
176	if (!ops) {
177		debug("%s driver has no ops?\n", dev->name);
178		return -EINVAL;
179	}
180
181	if (!ops->load || !ops->start) {
182		debug("%s driver has missing mandatory ops?\n", dev->name);
183		return -EINVAL;
184	}
185
186	return 0;
187}
188
189/**
190 * rproc_post_probe() - post probe accessor for the uclass
191 * @dev:	deivce we finished probing
192 *
193 * initiate init function after the probe is completed. This allows
194 * the remote processor drivers to split up the initializations between
195 * probe and init as needed.
196 *
197 * Return: if the remote proc driver has a init routine, invokes it and
198 * hands over the return value. overall, 0 if all went well, else appropriate
199 * error value.
200 */
201static int rproc_post_probe(struct udevice *dev)
202{
203	const struct dm_rproc_ops *ops;
204
205	ops = rproc_get_ops(dev);
206	if (!ops) {
207		debug("%s driver has no ops?\n", dev->name);
208		return -EINVAL;
209	}
210
211	if (ops->init)
212		return ops->init(dev);
213
214	return 0;
215}
216
217/**
218 * rproc_add_res() - After parsing the resource table add the mappings
219 * @dev:	device we finished probing
220 * @mapping: rproc_mem_entry for the resource
221 *
222 * Return: if the remote proc driver has a add_res routine, invokes it and
223 * hands over the return value. overall, 0 if all went well, else appropriate
224 * error value.
225 */
226static int rproc_add_res(struct udevice *dev, struct rproc_mem_entry *mapping)
227{
228	const struct dm_rproc_ops *ops = rproc_get_ops(dev);
229
230	if (!ops->add_res)
231		return -ENOSYS;
232
233	return ops->add_res(dev, mapping);
234}
235
236/**
237 * rproc_alloc_mem() - After parsing the resource table allocat mem
238 * @dev:	device we finished probing
239 * @len: rproc_mem_entry for the resource
240 * @align: alignment for the resource
241 *
242 * Return: if the remote proc driver has a add_res routine, invokes it and
243 * hands over the return value. overall, 0 if all went well, else appropriate
244 * error value.
245 */
246static void *rproc_alloc_mem(struct udevice *dev, unsigned long len,
247			     unsigned long align)
248{
249	const struct dm_rproc_ops *ops;
250
251	ops = rproc_get_ops(dev);
252	if (!ops) {
253		debug("%s driver has no ops?\n", dev->name);
254		return NULL;
255	}
256
257	if (ops->alloc_mem)
258		return ops->alloc_mem(dev, len, align);
259
260	return NULL;
261}
262
263/**
264 * rproc_config_pagetable() - Configure page table for remote processor
265 * @dev:	device we finished probing
266 * @virt: Virtual address of the resource
267 * @phys: Physical address the resource
268 * @len: length the resource
269 *
270 * Return: if the remote proc driver has a add_res routine, invokes it and
271 * hands over the return value. overall, 0 if all went well, else appropriate
272 * error value.
273 */
274static int rproc_config_pagetable(struct udevice *dev, unsigned int virt,
275				  unsigned int phys, unsigned int len)
276{
277	const struct dm_rproc_ops *ops;
278
279	ops = rproc_get_ops(dev);
280	if (!ops) {
281		debug("%s driver has no ops?\n", dev->name);
282		return -EINVAL;
283	}
284
285	if (ops->config_pagetable)
286		return ops->config_pagetable(dev, virt, phys, len);
287
288	return 0;
289}
290
291UCLASS_DRIVER(rproc) = {
292	.id = UCLASS_REMOTEPROC,
293	.name = "remoteproc",
294	.flags = DM_UC_FLAG_SEQ_ALIAS,
295	.pre_probe = rproc_pre_probe,
296	.post_probe = rproc_post_probe,
297	.per_device_plat_auto	= sizeof(struct dm_rproc_uclass_pdata),
298};
299
300/* Remoteproc subsystem access functions */
301/**
302 * _rproc_probe_dev() - iteration helper to probe a rproc device
303 * @dev:	device to probe
304 * @uc_pdata:	uclass data allocated for the device
305 * @data:	unused
306 *
307 * Return: 0 if all ok, else appropriate error value.
308 */
309static int _rproc_probe_dev(struct udevice *dev,
310			    struct dm_rproc_uclass_pdata *uc_pdata,
311			    const void *data)
312{
313	int ret;
314
315	ret = device_probe(dev);
316
317	if (ret)
318		debug("%s: Failed to initialize - %d\n", dev->name, ret);
319	return ret;
320}
321
322/**
323 * _rproc_dev_is_probed() - check if the device has been probed
324 * @dev:	device to check
325 * @uc_pdata:	unused
326 * @data:	unused
327 *
328 * Return: -EAGAIN if not probed else return 0
329 */
330static int _rproc_dev_is_probed(struct udevice *dev,
331			    struct dm_rproc_uclass_pdata *uc_pdata,
332			    const void *data)
333{
334	if (dev_get_flags(dev) & DM_FLAG_ACTIVATED)
335		return 0;
336
337	return -EAGAIN;
338}
339
340bool rproc_is_initialized(void)
341{
342	int ret = for_each_remoteproc_device(_rproc_dev_is_probed, NULL, NULL);
343	return ret ? false : true;
344}
345
346int rproc_init(void)
347{
348	int ret;
349
350	if (rproc_is_initialized()) {
351		debug("Already initialized\n");
352		return -EINVAL;
353	}
354
355	ret = for_each_remoteproc_device(_rproc_probe_dev, NULL, NULL);
356	return ret;
357}
358
359int rproc_dev_init(int id)
360{
361	struct udevice *dev = NULL;
362	int ret;
363
364	ret = uclass_get_device_by_seq(UCLASS_REMOTEPROC, id, &dev);
365	if (ret) {
366		debug("Unknown remote processor id '%d' requested(%d)\n",
367		      id, ret);
368		return ret;
369	}
370
371	ret = device_probe(dev);
372	if (ret)
373		debug("%s: Failed to initialize - %d\n", dev->name, ret);
374
375	return ret;
376}
377
378int rproc_load(int id, ulong addr, ulong size)
379{
380	struct udevice *dev = NULL;
381	struct dm_rproc_uclass_pdata *uc_pdata;
382	const struct dm_rproc_ops *ops;
383	int ret;
384
385	ret = uclass_get_device_by_seq(UCLASS_REMOTEPROC, id, &dev);
386	if (ret) {
387		debug("Unknown remote processor id '%d' requested(%d)\n",
388		      id, ret);
389		return ret;
390	}
391
392	uc_pdata = dev_get_uclass_plat(dev);
393
394	ops = rproc_get_ops(dev);
395	if (!ops) {
396		debug("%s driver has no ops?\n", dev->name);
397		return -EINVAL;
398	}
399
400	debug("Loading to '%s' from address 0x%08lX size of %lu bytes\n",
401	      uc_pdata->name, addr, size);
402	if (ops->load)
403		return ops->load(dev, addr, size);
404
405	debug("%s: data corruption?? mandatory function is missing!\n",
406	      dev->name);
407
408	return -EINVAL;
409};
410
411/*
412 * Completely internal helper enums..
413 * Keeping this isolated helps this code evolve independent of other
414 * parts..
415 */
416enum rproc_ops {
417	RPROC_START,
418	RPROC_STOP,
419	RPROC_RESET,
420	RPROC_PING,
421	RPROC_RUNNING,
422};
423
424/**
425 * _rproc_ops_wrapper() - wrapper for invoking remote proc driver callback
426 * @id:		id of the remote processor
427 * @op:		one of rproc_ops that indicate what operation to invoke
428 *
429 * Most of the checks and verification for remoteproc operations are more
430 * or less same for almost all operations. This allows us to put a wrapper
431 * and use the common checks to allow the driver to function appropriately.
432 *
433 * Return: 0 if all ok, else appropriate error value.
434 */
435static int _rproc_ops_wrapper(int id, enum rproc_ops op)
436{
437	struct udevice *dev = NULL;
438	struct dm_rproc_uclass_pdata *uc_pdata;
439	const struct dm_rproc_ops *ops;
440	int (*fn)(struct udevice *dev);
441	bool mandatory = false;
442	char *op_str;
443	int ret;
444
445	ret = uclass_get_device_by_seq(UCLASS_REMOTEPROC, id, &dev);
446	if (ret) {
447		debug("Unknown remote processor id '%d' requested(%d)\n",
448		      id, ret);
449		return ret;
450	}
451
452	uc_pdata = dev_get_uclass_plat(dev);
453
454	ops = rproc_get_ops(dev);
455	if (!ops) {
456		debug("%s driver has no ops?\n", dev->name);
457		return -EINVAL;
458	}
459	switch (op) {
460	case RPROC_START:
461		fn = ops->start;
462		mandatory = true;
463		op_str = "Starting";
464		break;
465	case RPROC_STOP:
466		fn = ops->stop;
467		op_str = "Stopping";
468		break;
469	case RPROC_RESET:
470		fn = ops->reset;
471		op_str = "Resetting";
472		break;
473	case RPROC_RUNNING:
474		fn = ops->is_running;
475		op_str = "Checking if running:";
476		break;
477	case RPROC_PING:
478		fn = ops->ping;
479		op_str = "Pinging";
480		break;
481	default:
482		debug("what is '%d' operation??\n", op);
483		return -EINVAL;
484	}
485
486	debug("%s %s...\n", op_str, uc_pdata->name);
487	if (fn)
488		return fn(dev);
489
490	if (mandatory)
491		debug("%s: data corruption?? mandatory function is missing!\n",
492		      dev->name);
493
494	return -ENOSYS;
495}
496
497int rproc_start(int id)
498{
499	return _rproc_ops_wrapper(id, RPROC_START);
500};
501
502int rproc_stop(int id)
503{
504	return _rproc_ops_wrapper(id, RPROC_STOP);
505};
506
507int rproc_reset(int id)
508{
509	return _rproc_ops_wrapper(id, RPROC_RESET);
510};
511
512int rproc_ping(int id)
513{
514	return _rproc_ops_wrapper(id, RPROC_PING);
515};
516
517int rproc_is_running(int id)
518{
519	return _rproc_ops_wrapper(id, RPROC_RUNNING);
520};
521
522
523static int handle_trace(struct udevice *dev, struct fw_rsc_trace *rsc,
524			int offset, int avail)
525{
526	if (sizeof(*rsc) > avail) {
527		debug("trace rsc is truncated\n");
528		return -EINVAL;
529	}
530
531	/*
532	 * make sure reserved bytes are zeroes
533	 */
534	if (rsc->reserved) {
535		debug("trace rsc has non zero reserved bytes\n");
536		return -EINVAL;
537	}
538
539	debug("trace rsc: da 0x%x, len 0x%x\n", rsc->da, rsc->len);
540
541	return 0;
542}
543
544static int handle_devmem(struct udevice *dev, struct fw_rsc_devmem *rsc,
545			 int offset, int avail)
546{
547	struct rproc_mem_entry *mapping;
548
549	if (sizeof(*rsc) > avail) {
550		debug("devmem rsc is truncated\n");
551		return -EINVAL;
552	}
553
554	/*
555	 * make sure reserved bytes are zeroes
556	 */
557	if (rsc->reserved) {
558		debug("devmem rsc has non zero reserved bytes\n");
559		return -EINVAL;
560	}
561
562	debug("devmem rsc: pa 0x%x, da 0x%x, len 0x%x\n",
563	      rsc->pa, rsc->da, rsc->len);
564
565	rproc_config_pagetable(dev, rsc->da, rsc->pa, rsc->len);
566
567	mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
568	if (!mapping)
569		return -ENOMEM;
570
571	/*
572	 * We'll need this info later when we'll want to unmap everything
573	 * (e.g. on shutdown).
574	 *
575	 * We can't trust the remote processor not to change the resource
576	 * table, so we must maintain this info independently.
577	 */
578	mapping->dma = rsc->pa;
579	mapping->da = rsc->da;
580	mapping->len = rsc->len;
581	rproc_add_res(dev, mapping);
582
583	debug("mapped devmem pa 0x%x, da 0x%x, len 0x%x\n",
584	      rsc->pa, rsc->da, rsc->len);
585
586	return 0;
587}
588
589static int handle_carveout(struct udevice *dev, struct fw_rsc_carveout *rsc,
590			   int offset, int avail)
591{
592	struct rproc_mem_entry *mapping;
593
594	if (sizeof(*rsc) > avail) {
595		debug("carveout rsc is truncated\n");
596		return -EINVAL;
597	}
598
599	/*
600	 * make sure reserved bytes are zeroes
601	 */
602	if (rsc->reserved) {
603		debug("carveout rsc has non zero reserved bytes\n");
604		return -EINVAL;
605	}
606
607	debug("carveout rsc: da %x, pa %x, len %x, flags %x\n",
608	      rsc->da, rsc->pa, rsc->len, rsc->flags);
609
610	rsc->pa = (uintptr_t)rproc_alloc_mem(dev, rsc->len, 8);
611	if (!rsc->pa) {
612		debug
613		    ("failed to allocate carveout rsc: da %x, pa %x, len %x, flags %x\n",
614		     rsc->da, rsc->pa, rsc->len, rsc->flags);
615		return -ENOMEM;
616	}
617	rproc_config_pagetable(dev, rsc->da, rsc->pa, rsc->len);
618
619	/*
620	 * Ok, this is non-standard.
621	 *
622	 * Sometimes we can't rely on the generic iommu-based DMA API
623	 * to dynamically allocate the device address and then set the IOMMU
624	 * tables accordingly, because some remote processors might
625	 * _require_ us to use hard coded device addresses that their
626	 * firmware was compiled with.
627	 *
628	 * In this case, we must use the IOMMU API directly and map
629	 * the memory to the device address as expected by the remote
630	 * processor.
631	 *
632	 * Obviously such remote processor devices should not be configured
633	 * to use the iommu-based DMA API: we expect 'dma' to contain the
634	 * physical address in this case.
635	 */
636	mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
637	if (!mapping)
638		return -ENOMEM;
639
640	/*
641	 * We'll need this info later when we'll want to unmap
642	 * everything (e.g. on shutdown).
643	 *
644	 * We can't trust the remote processor not to change the
645	 * resource table, so we must maintain this info independently.
646	 */
647	mapping->dma = rsc->pa;
648	mapping->da = rsc->da;
649	mapping->len = rsc->len;
650	rproc_add_res(dev, mapping);
651
652	debug("carveout mapped 0x%x to 0x%x\n", rsc->da, rsc->pa);
653
654	return 0;
655}
656
657#define RPROC_PAGE_SHIFT 12
658#define RPROC_PAGE_SIZE  BIT(RPROC_PAGE_SHIFT)
659#define RPROC_PAGE_ALIGN(x) (((x) + (RPROC_PAGE_SIZE - 1)) & ~(RPROC_PAGE_SIZE - 1))
660
661static int alloc_vring(struct udevice *dev, struct fw_rsc_vdev *rsc, int i)
662{
663	struct fw_rsc_vdev_vring *vring = &rsc->vring[i];
664	int size;
665	int order;
666	void *pa;
667
668	debug("vdev rsc: vring%d: da %x, qsz %d, align %d\n",
669	      i, vring->da, vring->num, vring->align);
670
671	/*
672	 * verify queue size and vring alignment are sane
673	 */
674	if (!vring->num || !vring->align) {
675		debug("invalid qsz (%d) or alignment (%d)\n", vring->num,
676		      vring->align);
677		return -EINVAL;
678	}
679
680	/*
681	 * actual size of vring (in bytes)
682	 */
683	size = RPROC_PAGE_ALIGN(vring_size(vring->num, vring->align));
684	order = vring->align >> RPROC_PAGE_SHIFT;
685
686	pa = rproc_alloc_mem(dev, size, order);
687	if (!pa) {
688		debug("failed to allocate vring rsc\n");
689		return -ENOMEM;
690	}
691	debug("alloc_mem(%#x, %d): %p\n", size, order, pa);
692	vring->da = (uintptr_t)pa;
693
694	return 0;
695}
696
697static int handle_vdev(struct udevice *dev, struct fw_rsc_vdev *rsc,
698		       int offset, int avail)
699{
700	int i, ret;
701	void *pa;
702
703	/*
704	 * make sure resource isn't truncated
705	 */
706	if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring)
707	    + rsc->config_len > avail) {
708		debug("vdev rsc is truncated\n");
709		return -EINVAL;
710	}
711
712	/*
713	 * make sure reserved bytes are zeroes
714	 */
715	if (rsc->reserved[0] || rsc->reserved[1]) {
716		debug("vdev rsc has non zero reserved bytes\n");
717		return -EINVAL;
718	}
719
720	debug("vdev rsc: id %d, dfeatures %x, cfg len %d, %d vrings\n",
721	      rsc->id, rsc->dfeatures, rsc->config_len, rsc->num_of_vrings);
722
723	/*
724	 * we currently support only two vrings per rvdev
725	 */
726	if (rsc->num_of_vrings > 2) {
727		debug("too many vrings: %d\n", rsc->num_of_vrings);
728		return -EINVAL;
729	}
730
731	/*
732	 * allocate the vrings
733	 */
734	for (i = 0; i < rsc->num_of_vrings; i++) {
735		ret = alloc_vring(dev, rsc, i);
736		if (ret)
737			goto alloc_error;
738	}
739
740	pa = rproc_alloc_mem(dev, RPMSG_TOTAL_BUF_SPACE, 6);
741	if (!pa) {
742		debug("failed to allocate vdev rsc\n");
743		return -ENOMEM;
744	}
745	debug("vring buffer alloc_mem(%#x, 6): %p\n", RPMSG_TOTAL_BUF_SPACE,
746	      pa);
747
748	return 0;
749
750 alloc_error:
751	return ret;
752}
753
754/*
755 * A lookup table for resource handlers. The indices are defined in
756 * enum fw_resource_type.
757 */
758static handle_resource_t loading_handlers[RSC_LAST] = {
759	[RSC_CARVEOUT] = (handle_resource_t)handle_carveout,
760	[RSC_DEVMEM] = (handle_resource_t)handle_devmem,
761	[RSC_TRACE] = (handle_resource_t)handle_trace,
762	[RSC_VDEV] = (handle_resource_t)handle_vdev,
763};
764
765/*
766 * handle firmware resource entries before booting the remote processor
767 */
768static int handle_resources(struct udevice *dev, int len,
769			    handle_resource_t handlers[RSC_LAST])
770{
771	handle_resource_t handler;
772	int ret = 0, i;
773
774	for (i = 0; i < rsc_table->num; i++) {
775		int offset = rsc_table->offset[i];
776		struct fw_rsc_hdr *hdr = (void *)rsc_table + offset;
777		int avail = len - offset - sizeof(*hdr);
778		void *rsc = (void *)hdr + sizeof(*hdr);
779
780		/*
781		 * make sure table isn't truncated
782		 */
783		if (avail < 0) {
784			debug("rsc table is truncated\n");
785			return -EINVAL;
786		}
787
788		debug("rsc: type %d\n", hdr->type);
789
790		if (hdr->type >= RSC_LAST) {
791			debug("unsupported resource %d\n", hdr->type);
792			continue;
793		}
794
795		handler = handlers[hdr->type];
796		if (!handler)
797			continue;
798
799		ret = handler(dev, rsc, offset + sizeof(*hdr), avail);
800		if (ret)
801			break;
802	}
803
804	return ret;
805}
806
807static int
808handle_intmem_to_l3_mapping(struct udevice *dev,
809			    struct rproc_intmem_to_l3_mapping *l3_mapping)
810{
811	u32 i = 0;
812
813	for (i = 0; i < l3_mapping->num_entries; i++) {
814		struct l3_map *curr_map = &l3_mapping->mappings[i];
815		struct rproc_mem_entry *mapping;
816
817		mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
818		if (!mapping)
819			return -ENOMEM;
820
821		mapping->dma = curr_map->l3_addr;
822		mapping->da = curr_map->priv_addr;
823		mapping->len = curr_map->len;
824		rproc_add_res(dev, mapping);
825	}
826
827	return 0;
828}
829
830static Elf32_Shdr *rproc_find_table(unsigned int addr)
831{
832	Elf32_Ehdr *ehdr;	/* Elf header structure pointer */
833	Elf32_Shdr *shdr;	/* Section header structure pointer */
834	Elf32_Shdr sectionheader;
835	int i;
836	u8 *elf_data;
837	char *name_table;
838	struct resource_table *ptable;
839
840	ehdr = (Elf32_Ehdr *)(uintptr_t)addr;
841	elf_data = (u8 *)ehdr;
842	shdr = (Elf32_Shdr *)(elf_data + ehdr->e_shoff);
843	memcpy(&sectionheader, &shdr[ehdr->e_shstrndx], sizeof(sectionheader));
844	name_table = (char *)(elf_data + sectionheader.sh_offset);
845
846	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
847		memcpy(&sectionheader, shdr, sizeof(sectionheader));
848		u32 size = sectionheader.sh_size;
849		u32 offset = sectionheader.sh_offset;
850
851		if (strcmp
852		    (name_table + sectionheader.sh_name, ".resource_table"))
853			continue;
854
855		ptable = (struct resource_table *)(elf_data + offset);
856
857		/*
858		 * make sure table has at least the header
859		 */
860		if (sizeof(struct resource_table) > size) {
861			debug("header-less resource table\n");
862			return NULL;
863		}
864
865		/*
866		 * we don't support any version beyond the first
867		 */
868		if (ptable->ver != 1) {
869			debug("unsupported fw ver: %d\n", ptable->ver);
870			return NULL;
871		}
872
873		/*
874		 * make sure reserved bytes are zeroes
875		 */
876		if (ptable->reserved[0] || ptable->reserved[1]) {
877			debug("non zero reserved bytes\n");
878			return NULL;
879		}
880
881		/*
882		 * make sure the offsets array isn't truncated
883		 */
884		if (ptable->num * sizeof(ptable->offset[0]) +
885		    sizeof(struct resource_table) > size) {
886			debug("resource table incomplete\n");
887			return NULL;
888		}
889
890		return shdr;
891	}
892
893	return NULL;
894}
895
896struct resource_table *rproc_find_resource_table(struct udevice *dev,
897						 unsigned int addr,
898						 int *tablesz)
899{
900	Elf32_Shdr *shdr;
901	Elf32_Shdr sectionheader;
902	struct resource_table *ptable;
903	u8 *elf_data = (u8 *)(uintptr_t)addr;
904
905	shdr = rproc_find_table(addr);
906	if (!shdr) {
907		debug("%s: failed to get resource section header\n", __func__);
908		return NULL;
909	}
910
911	memcpy(&sectionheader, shdr, sizeof(sectionheader));
912	ptable = (struct resource_table *)(elf_data + sectionheader.sh_offset);
913	if (tablesz)
914		*tablesz = sectionheader.sh_size;
915
916	return ptable;
917}
918
919unsigned long rproc_parse_resource_table(struct udevice *dev, struct rproc *cfg)
920{
921	struct resource_table *ptable = NULL;
922	int tablesz;
923	int ret;
924	unsigned long addr;
925
926	addr = cfg->load_addr;
927
928	ptable = rproc_find_resource_table(dev, addr, &tablesz);
929	if (!ptable) {
930		debug("%s : failed to find resource table\n", __func__);
931		return 0;
932	}
933
934	debug("%s : found resource table\n", __func__);
935	rsc_table = kzalloc(tablesz, GFP_KERNEL);
936	if (!rsc_table) {
937		debug("resource table alloc failed!\n");
938		return 0;
939	}
940
941	/*
942	 * Copy the resource table into a local buffer before handling the
943	 * resource table.
944	 */
945	memcpy(rsc_table, ptable, tablesz);
946	if (cfg->intmem_to_l3_mapping)
947		handle_intmem_to_l3_mapping(dev, cfg->intmem_to_l3_mapping);
948	ret = handle_resources(dev, tablesz, loading_handlers);
949	if (ret) {
950		debug("handle_resources failed: %d\n", ret);
951		return 0;
952	}
953
954	/*
955	 * Instead of trying to mimic the kernel flow of copying the
956	 * processed resource table into its post ELF load location in DDR
957	 * copying it into its original location.
958	 */
959	memcpy(ptable, rsc_table, tablesz);
960	free(rsc_table);
961	rsc_table = NULL;
962
963	return 1;
964}
965
966int rproc_set_firmware(struct udevice *rproc_dev, const char *fw_name)
967{
968	struct dm_rproc_uclass_pdata *uc_pdata;
969	int len;
970	char *p;
971
972	if (!rproc_dev || !fw_name)
973		return -EINVAL;
974
975	uc_pdata = dev_get_uclass_plat(rproc_dev);
976	if (!uc_pdata)
977		return -EINVAL;
978
979	len = strcspn(fw_name, "\n");
980	if (!len) {
981		debug("invalid firmware name\n");
982		return -EINVAL;
983	}
984
985	if (uc_pdata->fw_name)
986		free(uc_pdata->fw_name);
987
988	p = strndup(fw_name, len);
989	if (!p)
990		return -ENOMEM;
991
992	uc_pdata->fw_name = p;
993
994	return 0;
995}
996
997#if CONFIG_IS_ENABLED(FS_LOADER)
998int rproc_boot(struct udevice *rproc_dev)
999{
1000	struct dm_rproc_uclass_pdata *uc_pdata;
1001	struct udevice *fs_loader;
1002	int core_id, ret = 0;
1003	char *firmware;
1004	void *addr;
1005
1006	if (!rproc_dev)
1007		return -EINVAL;
1008
1009	uc_pdata = dev_get_uclass_plat(rproc_dev);
1010	if (!uc_pdata)
1011		return -EINVAL;
1012
1013	core_id = dev_seq(rproc_dev);
1014	firmware = uc_pdata->fw_name;
1015	if (!firmware) {
1016		debug("No firmware name set for rproc core %d\n", core_id);
1017		return -EINVAL;
1018	}
1019
1020	/* Initialize all rproc cores */
1021	if (!rproc_is_initialized()) {
1022		ret = rproc_init();
1023		if (ret) {
1024			debug("rproc_init() failed: %d\n", ret);
1025			return ret;
1026		}
1027	}
1028
1029	/* Loading firmware to a given address */
1030	ret = get_fs_loader(&fs_loader);
1031	if (ret) {
1032		debug("could not get fs loader: %d\n", ret);
1033		return ret;
1034	}
1035
1036	if (CONFIG_REMOTEPROC_MAX_FW_SIZE) {
1037		addr = malloc(CONFIG_REMOTEPROC_MAX_FW_SIZE);
1038		if (!addr)
1039			return -ENOMEM;
1040	} else {
1041		debug("CONFIG_REMOTEPROC_MAX_FW_SIZE not defined\n");
1042		return -EINVAL;
1043	}
1044
1045	ret = request_firmware_into_buf(fs_loader, firmware, addr, CONFIG_REMOTEPROC_MAX_FW_SIZE,
1046					0);
1047	if (ret < 0) {
1048		debug("could not request %s: %d\n", firmware, ret);
1049		goto free_buffer;
1050	}
1051
1052	ret = rproc_load(core_id, (ulong)addr, ret);
1053	if (ret) {
1054		debug("failed to load %s to rproc core %d from addr 0x%08lX err %d\n",
1055		      uc_pdata->fw_name, core_id, (ulong)addr, ret);
1056		goto free_buffer;
1057	}
1058
1059	ret = rproc_start(core_id);
1060	if (ret)
1061		debug("failed to start rproc core %d\n", core_id);
1062
1063free_buffer:
1064	free(addr);
1065	return ret;
1066}
1067#endif
1068