1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * PRU-RTU remoteproc driver for various SoCs
4  *
5  * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
6  *	Keerthy <j-keerthy@ti.com>
7  */
8 
9 #include <common.h>
10 #include <dm.h>
11 #include <elf.h>
12 #include <dm/of_access.h>
13 #include <remoteproc.h>
14 #include <errno.h>
15 #include <clk.h>
16 #include <reset.h>
17 #include <regmap.h>
18 #include <syscon.h>
19 #include <asm/io.h>
20 #include <power-domain.h>
21 #include <linux/pruss_driver.h>
22 #include <dm/device_compat.h>
23 
24 /* PRU_ICSS_PRU_CTRL registers */
25 #define PRU_CTRL_CTRL		0x0000
26 #define PRU_CTRL_STS		0x0004
27 #define PRU_CTRL_WAKEUP_EN	0x0008
28 #define PRU_CTRL_CYCLE		0x000C
29 #define PRU_CTRL_STALL		0x0010
30 #define PRU_CTRL_CTBIR0		0x0020
31 #define PRU_CTRL_CTBIR1		0x0024
32 #define PRU_CTRL_CTPPR0		0x0028
33 #define PRU_CTRL_CTPPR1		0x002C
34 
35 /* CTRL register bit-fields */
36 #define CTRL_CTRL_SOFT_RST_N	BIT(0)
37 #define CTRL_CTRL_EN		BIT(1)
38 #define CTRL_CTRL_SLEEPING	BIT(2)
39 #define CTRL_CTRL_CTR_EN	BIT(3)
40 #define CTRL_CTRL_SINGLE_STEP	BIT(8)
41 #define CTRL_CTRL_RUNSTATE	BIT(15)
42 
43 #define RPROC_FLAGS_SHIFT	16
44 #define RPROC_FLAGS_NONE	0
45 #define RPROC_FLAGS_ELF_PHDR	BIT(0 + RPROC_FLAGS_SHIFT)
46 #define RPROC_FLAGS_ELF_SHDR	BIT(1 + RPROC_FLAGS_SHIFT)
47 
48 /**
49  * enum pru_mem - PRU core memory range identifiers
50  */
51 enum pru_mem {
52 	PRU_MEM_IRAM = 0,
53 	PRU_MEM_CTRL,
54 	PRU_MEM_DEBUG,
55 	PRU_MEM_MAX,
56 };
57 
58 struct pru_privdata {
59 	phys_addr_t pru_iram;
60 	phys_addr_t pru_ctrl;
61 	phys_addr_t pru_debug;
62 	fdt_size_t pru_iramsz;
63 	fdt_size_t pru_ctrlsz;
64 	fdt_size_t pru_debugsz;
65 	const char *fw_name;
66 	u32 iram_da;
67 	u32 pdram_da;
68 	u32 sdram_da;
69 	u32 shrdram_da;
70 	u32 bootaddr;
71 	int id;
72 	struct pruss *prusspriv;
73 };
74 
pru_control_read_reg(struct pru_privdata * pru,unsigned int reg)75 static inline u32 pru_control_read_reg(struct pru_privdata *pru, unsigned int reg)
76 {
77 	return readl(pru->pru_ctrl + reg);
78 }
79 
80 static inline
pru_control_write_reg(struct pru_privdata * pru,unsigned int reg,u32 val)81 void pru_control_write_reg(struct pru_privdata *pru, unsigned int reg, u32 val)
82 {
83 	writel(val, pru->pru_ctrl + reg);
84 }
85 
86 static inline
pru_control_set_reg(struct pru_privdata * pru,unsigned int reg,u32 mask,u32 set)87 void pru_control_set_reg(struct pru_privdata *pru, unsigned int reg,
88 			 u32 mask, u32 set)
89 {
90 	u32 val;
91 
92 	val = pru_control_read_reg(pru, reg);
93 	val &= ~mask;
94 	val |= (set & mask);
95 	pru_control_write_reg(pru, reg, val);
96 }
97 
98 /**
99  * pru_rproc_set_ctable() - set the constant table index for the PRU
100  * @rproc: the rproc instance of the PRU
101  * @c: constant table index to set
102  * @addr: physical address to set it to
103  */
pru_rproc_set_ctable(struct pru_privdata * pru,enum pru_ctable_idx c,u32 addr)104 static int pru_rproc_set_ctable(struct pru_privdata *pru, enum pru_ctable_idx c, u32 addr)
105 {
106 	unsigned int reg;
107 	u32 mask, set;
108 	u16 idx;
109 	u16 idx_mask;
110 
111 	/* pointer is 16 bit and index is 8-bit so mask out the rest */
112 	idx_mask = (c >= PRU_C28) ? 0xFFFF : 0xFF;
113 
114 	/* ctable uses bit 8 and upwards only */
115 	idx = (addr >> 8) & idx_mask;
116 
117 	/* configurable ctable (i.e. C24) starts at PRU_CTRL_CTBIR0 */
118 	reg = PRU_CTRL_CTBIR0 + 4 * (c >> 1);
119 	mask = idx_mask << (16 * (c & 1));
120 	set = idx << (16 * (c & 1));
121 
122 	pru_control_set_reg(pru, reg, mask, set);
123 
124 	return 0;
125 }
126 
127 /**
128  * pru_start() - start the pru processor
129  * @dev:	corresponding k3 remote processor device
130  *
131  * Return: 0 if all goes good, else appropriate error message.
132  */
pru_start(struct udevice * dev)133 static int pru_start(struct udevice *dev)
134 {
135 	struct pru_privdata *priv;
136 	int val = 0;
137 
138 	priv = dev_get_priv(dev);
139 
140 	pru_rproc_set_ctable(priv, PRU_C28, 0x100 << 8);
141 
142 	val = CTRL_CTRL_EN | ((priv->bootaddr >> 2) << 16);
143 	writel(val, priv->pru_ctrl + PRU_CTRL_CTRL);
144 
145 	return 0;
146 }
147 
148 /**
149  * pru_stop() - Stop pru processor
150  * @dev:	corresponding k3 remote processor device
151  *
152  * Return: 0 if all goes good, else appropriate error message.
153  */
pru_stop(struct udevice * dev)154 static int pru_stop(struct udevice *dev)
155 {
156 	struct pru_privdata *priv;
157 	int val = 0;
158 
159 	priv = dev_get_priv(dev);
160 
161 	val = readl(priv->pru_ctrl + PRU_CTRL_CTRL);
162 	val &= ~CTRL_CTRL_EN;
163 	writel(val, priv->pru_ctrl + PRU_CTRL_CTRL);
164 
165 	return 0;
166 }
167 
168 /**
169  * pru_init() - Initialize the remote processor
170  * @dev:	rproc device pointer
171  *
172  * Return: 0 if all went ok, else return appropriate error
173  */
pru_init(struct udevice * dev)174 static int pru_init(struct udevice *dev)
175 {
176 	return 0;
177 }
178 
179 /*
180  * Convert PRU device address (data spaces only) to kernel virtual address
181  *
182  * Each PRU has access to all data memories within the PRUSS, accessible at
183  * different ranges. So, look through both its primary and secondary Data
184  * RAMs as well as any shared Data RAM to convert a PRU device address to
185  * kernel virtual address. Data RAM0 is primary Data RAM for PRU0 and Data
186  * RAM1 is primary Data RAM for PRU1.
187  */
pru_d_da_to_pa(struct pru_privdata * priv,u32 da,int len)188 static void *pru_d_da_to_pa(struct pru_privdata *priv, u32 da, int len)
189 {
190 	u32 offset;
191 	void *pa = NULL;
192 	phys_addr_t dram0, dram1, shrdram2;
193 	u32 dram0sz, dram1sz, shrdram2sz;
194 
195 	if (len <= 0)
196 		return NULL;
197 
198 	dram0 = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM0].pa;
199 	dram1 = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM1].pa;
200 	shrdram2 = priv->prusspriv->mem_regions[PRUSS_MEM_SHRD_RAM2].pa;
201 	dram0sz = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM0].size;
202 	dram1sz = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM1].size;
203 	shrdram2sz = priv->prusspriv->mem_regions[PRUSS_MEM_SHRD_RAM2].size;
204 
205 	/* PRU1 has its local RAM addresses reversed */
206 	if (priv->id == 1) {
207 		dram1 = dram0;
208 		dram1sz = dram0sz;
209 
210 		dram0 =  priv->prusspriv->mem_regions[PRUSS_MEM_DRAM1].pa;
211 		dram0sz = priv->prusspriv->mem_regions[PRUSS_MEM_DRAM1].size;
212 	}
213 
214 	if (da >= priv->pdram_da && da + len <= priv->pdram_da + dram0sz) {
215 		offset = da - priv->pdram_da;
216 		pa = (__force void *)(dram0 + offset);
217 	} else if (da >= priv->sdram_da &&
218 		   da + len <= priv->sdram_da + dram1sz) {
219 		offset = da - priv->sdram_da;
220 		pa = (__force void *)(dram1 + offset);
221 	} else if (da >= priv->shrdram_da &&
222 		   da + len <= priv->shrdram_da + shrdram2sz) {
223 		offset = da - priv->shrdram_da;
224 		pa = (__force void *)(shrdram2 + offset);
225 	}
226 
227 	return pa;
228 }
229 
230 /*
231  * Convert PRU device address (instruction space) to kernel virtual address
232  *
233  * A PRU does not have an unified address space. Each PRU has its very own
234  * private Instruction RAM, and its device address is identical to that of
235  * its primary Data RAM device address.
236  */
pru_i_da_to_pa(struct pru_privdata * priv,u32 da,int len)237 static void *pru_i_da_to_pa(struct pru_privdata *priv, u32 da, int len)
238 {
239 	u32 offset;
240 	void *pa = NULL;
241 
242 	if (len <= 0)
243 		return NULL;
244 
245 	if (da >= priv->iram_da &&
246 	    da + len <= priv->iram_da + priv->pru_iramsz) {
247 		offset = da - priv->iram_da;
248 		pa = (__force void *)(priv->pru_iram + offset);
249 	}
250 
251 	return pa;
252 }
253 
254 /* PRU-specific address translator */
pru_da_to_pa(struct pru_privdata * priv,u64 da,int len,u32 flags)255 static void *pru_da_to_pa(struct pru_privdata *priv, u64 da, int len, u32 flags)
256 {
257 	void *pa;
258 	u32 exec_flag;
259 
260 	exec_flag = ((flags & RPROC_FLAGS_ELF_SHDR) ? flags & SHF_EXECINSTR :
261 		     ((flags & RPROC_FLAGS_ELF_PHDR) ? flags & PF_X : 0));
262 
263 	if (exec_flag)
264 		pa = pru_i_da_to_pa(priv, da, len);
265 	else
266 		pa = pru_d_da_to_pa(priv, da, len);
267 
268 	return pa;
269 }
270 
271 /*
272  * Custom memory copy implementation for ICSSG PRU/RTU Cores
273  *
274  * The ICSSG PRU/RTU cores have a memory copying issue with IRAM memories, that
275  * is not seen on previous generation SoCs. The data is reflected properly in
276  * the IRAM memories only for integer (4-byte) copies. Any unaligned copies
277  * result in all the other pre-existing bytes zeroed out within that 4-byte
278  * boundary, thereby resulting in wrong text/code in the IRAMs. Also, the
279  * IRAM memory port interface does not allow any 8-byte copies (as commonly
280  * used by ARM64 memcpy implementation) and throws an exception. The DRAM
281  * memory ports do not show this behavior. Use this custom copying function
282  * to properly load the PRU/RTU firmware images on all memories for simplicity.
283  *
284  * TODO: Improve the function to deal with additional corner cases like
285  * unaligned copy sizes or sub-integer trailing bytes when the need arises.
286  */
pru_rproc_memcpy(void * dest,void * src,size_t count)287 static int pru_rproc_memcpy(void *dest, void *src, size_t count)
288 {
289 	const int *s = src;
290 	int *d = dest;
291 	int size = count / 4;
292 	int *tmp_src = NULL;
293 
294 	/* limited to 4-byte aligned addresses and copy sizes */
295 	if ((long)dest % 4 || count % 4)
296 		return -EINVAL;
297 
298 	/* src offsets in ELF firmware image can be non-aligned */
299 	if ((long)src % 4) {
300 		tmp_src = malloc(count);
301 		if (!tmp_src)
302 			return -ENOMEM;
303 
304 		memcpy(tmp_src, src, count);
305 		s = tmp_src;
306 	}
307 
308 	while (size--)
309 		*d++ = *s++;
310 
311 	kfree(tmp_src);
312 
313 	return 0;
314 }
315 
316 /**
317  * pru_load() - Load pru firmware
318  * @dev:	corresponding k3 remote processor device
319  * @addr:	Address on the RAM from which firmware is to be loaded
320  * @size:	Size of the pru firmware in bytes
321  *
322  * Return: 0 if all goes good, else appropriate error message.
323  */
pru_load(struct udevice * dev,ulong addr,ulong size)324 static int pru_load(struct udevice *dev, ulong addr, ulong size)
325 {
326 	struct pru_privdata *priv;
327 	Elf32_Ehdr *ehdr;
328 	Elf32_Phdr *phdr;
329 	int i, ret = 0;
330 
331 	priv = dev_get_priv(dev);
332 
333 	ehdr = (Elf32_Ehdr *)addr;
334 	phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
335 
336 	/* go through the available ELF segments */
337 	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
338 		u32 da = phdr->p_paddr;
339 		u32 memsz = phdr->p_memsz;
340 		u32 filesz = phdr->p_filesz;
341 		u32 offset = phdr->p_offset;
342 		void *ptr;
343 
344 		if (phdr->p_type != PT_LOAD)
345 			continue;
346 
347 		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
348 			phdr->p_type, da, memsz, filesz);
349 
350 		if (filesz > memsz) {
351 			dev_dbg(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
352 				filesz, memsz);
353 			ret = -EINVAL;
354 			break;
355 		}
356 
357 		if (offset + filesz > size) {
358 			dev_dbg(dev, "truncated fw: need 0x%x avail 0x%zx\n",
359 				offset + filesz, size);
360 			ret = -EINVAL;
361 			break;
362 		}
363 
364 		/* grab the kernel address for this device address */
365 		ptr = pru_da_to_pa(priv, da, memsz,
366 				   RPROC_FLAGS_ELF_PHDR | phdr->p_flags);
367 		if (!ptr) {
368 			dev_dbg(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
369 			ret = -EINVAL;
370 			break;
371 		}
372 
373 		/* skip the memzero logic performed by remoteproc ELF loader */
374 		if (!phdr->p_filesz)
375 			continue;
376 
377 		ret = pru_rproc_memcpy(ptr,
378 				       (void *)addr + phdr->p_offset, filesz);
379 		if (ret) {
380 			dev_dbg(dev, "PRU custom memory copy failed for da 0x%x memsz 0x%x\n",
381 				da, memsz);
382 			break;
383 		}
384 	}
385 
386 	priv->bootaddr = ehdr->e_entry;
387 
388 	return ret;
389 }
390 
391 static const struct dm_rproc_ops pru_ops = {
392 	.init = pru_init,
393 	.start = pru_start,
394 	.stop = pru_stop,
395 	.load = pru_load,
396 };
397 
pru_set_id(struct pru_privdata * priv,struct udevice * dev)398 static void pru_set_id(struct pru_privdata *priv, struct udevice *dev)
399 {
400 	u32 mask2 = 0x38000;
401 
402 	if (device_is_compatible(dev, "ti,am654-rtu"))
403 		mask2 = 0x6000;
404 
405 	if (device_is_compatible(dev, "ti,am654-tx-pru"))
406 		mask2 = 0xc000;
407 
408 	if ((priv->pru_iram & mask2) == mask2)
409 		priv->id = 1;
410 	else
411 		priv->id = 0;
412 }
413 
414 /**
415  * pru_probe() - Basic probe
416  * @dev:	corresponding k3 remote processor device
417  *
418  * Return: 0 if all goes good, else appropriate error message.
419  */
pru_probe(struct udevice * dev)420 static int pru_probe(struct udevice *dev)
421 {
422 	struct pru_privdata *priv;
423 	ofnode node;
424 
425 	node = dev_ofnode(dev);
426 
427 	priv = dev_get_priv(dev);
428 	priv->prusspriv = dev_get_priv(dev->parent);
429 
430 	priv->pru_iram = devfdt_get_addr_size_index(dev, PRU_MEM_IRAM,
431 						    &priv->pru_iramsz);
432 	priv->pru_ctrl = devfdt_get_addr_size_index(dev, PRU_MEM_CTRL,
433 						    &priv->pru_ctrlsz);
434 	priv->pru_debug = devfdt_get_addr_size_index(dev, PRU_MEM_DEBUG,
435 						     &priv->pru_debugsz);
436 
437 	priv->iram_da = 0;
438 	priv->pdram_da = 0;
439 	priv->sdram_da = 0x2000;
440 	priv->shrdram_da = 0x10000;
441 
442 	pru_set_id(priv, dev);
443 
444 	return 0;
445 }
446 
447 static const struct udevice_id pru_ids[] = {
448 	{ .compatible = "ti,am654-pru"},
449 	{ .compatible = "ti,am654-rtu"},
450 	{ .compatible = "ti,am654-tx-pru" },
451 	{}
452 };
453 
454 U_BOOT_DRIVER(pru) = {
455 	.name = "pru",
456 	.of_match = pru_ids,
457 	.id = UCLASS_REMOTEPROC,
458 	.ops = &pru_ops,
459 	.probe = pru_probe,
460 	.priv_auto = sizeof(struct pru_privdata),
461 };
462