d33392bbd8afad846372f343ebc333cedcb49163
[linux-2.6-microblaze.git] / drivers / remoteproc / pru_rproc.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * PRU-ICSS remoteproc driver for various TI SoCs
4  *
5  * Copyright (C) 2014-2020 Texas Instruments Incorporated - https://www.ti.com/
6  *
7  * Author(s):
8  *      Suman Anna <s-anna@ti.com>
9  *      Andrew F. Davis <afd@ti.com>
10  *      Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org> for Texas Instruments
11  */
12
13 #include <linux/bitops.h>
14 #include <linux/module.h>
15 #include <linux/of_device.h>
16 #include <linux/pruss_driver.h>
17 #include <linux/remoteproc.h>
18
19 #include "remoteproc_internal.h"
20 #include "remoteproc_elf_helpers.h"
21
22 /* PRU_ICSS_PRU_CTRL registers */
23 #define PRU_CTRL_CTRL           0x0000
24 #define PRU_CTRL_STS            0x0004
25
26 /* CTRL register bit-fields */
27 #define CTRL_CTRL_SOFT_RST_N    BIT(0)
28 #define CTRL_CTRL_EN            BIT(1)
29 #define CTRL_CTRL_SLEEPING      BIT(2)
30 #define CTRL_CTRL_CTR_EN        BIT(3)
31 #define CTRL_CTRL_SINGLE_STEP   BIT(8)
32 #define CTRL_CTRL_RUNSTATE      BIT(15)
33
34 /* PRU Core IRAM address masks */
35 #define PRU_IRAM_ADDR_MASK      0x3ffff
36 #define PRU0_IRAM_ADDR_MASK     0x34000
37 #define PRU1_IRAM_ADDR_MASK     0x38000
38
39 /* PRU device addresses for various type of PRU RAMs */
40 #define PRU_IRAM_DA     0       /* Instruction RAM */
41 #define PRU_PDRAM_DA    0       /* Primary Data RAM */
42 #define PRU_SDRAM_DA    0x2000  /* Secondary Data RAM */
43 #define PRU_SHRDRAM_DA  0x10000 /* Shared Data RAM */
44
45 /**
46  * enum pru_iomem - PRU core memory/register range identifiers
47  *
48  * @PRU_IOMEM_IRAM: PRU Instruction RAM range
49  * @PRU_IOMEM_CTRL: PRU Control register range
50  * @PRU_IOMEM_DEBUG: PRU Debug register range
51  * @PRU_IOMEM_MAX: just keep this one at the end
52  */
53 enum pru_iomem {
54         PRU_IOMEM_IRAM = 0,
55         PRU_IOMEM_CTRL,
56         PRU_IOMEM_DEBUG,
57         PRU_IOMEM_MAX,
58 };
59
60 /**
61  * struct pru_rproc - PRU remoteproc structure
62  * @id: id of the PRU core within the PRUSS
63  * @dev: PRU core device pointer
64  * @pruss: back-reference to parent PRUSS structure
65  * @rproc: remoteproc pointer for this PRU core
66  * @mem_regions: data for each of the PRU memory regions
67  * @fw_name: name of firmware image used during loading
68  */
69 struct pru_rproc {
70         int id;
71         struct device *dev;
72         struct pruss *pruss;
73         struct rproc *rproc;
74         struct pruss_mem_region mem_regions[PRU_IOMEM_MAX];
75         const char *fw_name;
76 };
77
78 static inline u32 pru_control_read_reg(struct pru_rproc *pru, unsigned int reg)
79 {
80         return readl_relaxed(pru->mem_regions[PRU_IOMEM_CTRL].va + reg);
81 }
82
83 static inline
84 void pru_control_write_reg(struct pru_rproc *pru, unsigned int reg, u32 val)
85 {
86         writel_relaxed(val, pru->mem_regions[PRU_IOMEM_CTRL].va + reg);
87 }
88
89 static int pru_rproc_start(struct rproc *rproc)
90 {
91         struct device *dev = &rproc->dev;
92         struct pru_rproc *pru = rproc->priv;
93         u32 val;
94
95         dev_dbg(dev, "starting PRU%d: entry-point = 0x%llx\n",
96                 pru->id, (rproc->bootaddr >> 2));
97
98         val = CTRL_CTRL_EN | ((rproc->bootaddr >> 2) << 16);
99         pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
100
101         return 0;
102 }
103
104 static int pru_rproc_stop(struct rproc *rproc)
105 {
106         struct device *dev = &rproc->dev;
107         struct pru_rproc *pru = rproc->priv;
108         u32 val;
109
110         dev_dbg(dev, "stopping PRU%d\n", pru->id);
111
112         val = pru_control_read_reg(pru, PRU_CTRL_CTRL);
113         val &= ~CTRL_CTRL_EN;
114         pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
115
116         return 0;
117 }
118
119 /*
120  * Convert PRU device address (data spaces only) to kernel virtual address.
121  *
122  * Each PRU has access to all data memories within the PRUSS, accessible at
123  * different ranges. So, look through both its primary and secondary Data
124  * RAMs as well as any shared Data RAM to convert a PRU device address to
125  * kernel virtual address. Data RAM0 is primary Data RAM for PRU0 and Data
126  * RAM1 is primary Data RAM for PRU1.
127  */
128 static void *pru_d_da_to_va(struct pru_rproc *pru, u32 da, size_t len)
129 {
130         struct pruss_mem_region dram0, dram1, shrd_ram;
131         struct pruss *pruss = pru->pruss;
132         u32 offset;
133         void *va = NULL;
134
135         if (len == 0)
136                 return NULL;
137
138         dram0 = pruss->mem_regions[PRUSS_MEM_DRAM0];
139         dram1 = pruss->mem_regions[PRUSS_MEM_DRAM1];
140         /* PRU1 has its local RAM addresses reversed */
141         if (pru->id == 1)
142                 swap(dram0, dram1);
143         shrd_ram = pruss->mem_regions[PRUSS_MEM_SHRD_RAM2];
144
145         if (da >= PRU_PDRAM_DA && da + len <= PRU_PDRAM_DA + dram0.size) {
146                 offset = da - PRU_PDRAM_DA;
147                 va = (__force void *)(dram0.va + offset);
148         } else if (da >= PRU_SDRAM_DA &&
149                    da + len <= PRU_SDRAM_DA + dram1.size) {
150                 offset = da - PRU_SDRAM_DA;
151                 va = (__force void *)(dram1.va + offset);
152         } else if (da >= PRU_SHRDRAM_DA &&
153                    da + len <= PRU_SHRDRAM_DA + shrd_ram.size) {
154                 offset = da - PRU_SHRDRAM_DA;
155                 va = (__force void *)(shrd_ram.va + offset);
156         }
157
158         return va;
159 }
160
161 /*
162  * Convert PRU device address (instruction space) to kernel virtual address.
163  *
164  * A PRU does not have an unified address space. Each PRU has its very own
165  * private Instruction RAM, and its device address is identical to that of
166  * its primary Data RAM device address.
167  */
168 static void *pru_i_da_to_va(struct pru_rproc *pru, u32 da, size_t len)
169 {
170         u32 offset;
171         void *va = NULL;
172
173         if (len == 0)
174                 return NULL;
175
176         if (da >= PRU_IRAM_DA &&
177             da + len <= PRU_IRAM_DA + pru->mem_regions[PRU_IOMEM_IRAM].size) {
178                 offset = da - PRU_IRAM_DA;
179                 va = (__force void *)(pru->mem_regions[PRU_IOMEM_IRAM].va +
180                                       offset);
181         }
182
183         return va;
184 }
185
186 /*
187  * Provide address translations for only PRU Data RAMs through the remoteproc
188  * core for any PRU client drivers. The PRU Instruction RAM access is restricted
189  * only to the PRU loader code.
190  */
191 static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
192 {
193         struct pru_rproc *pru = rproc->priv;
194
195         return pru_d_da_to_va(pru, da, len);
196 }
197
198 /* PRU-specific address translator used by PRU loader. */
199 static void *pru_da_to_va(struct rproc *rproc, u64 da, size_t len, bool is_iram)
200 {
201         struct pru_rproc *pru = rproc->priv;
202         void *va;
203
204         if (is_iram)
205                 va = pru_i_da_to_va(pru, da, len);
206         else
207                 va = pru_d_da_to_va(pru, da, len);
208
209         return va;
210 }
211
212 static struct rproc_ops pru_rproc_ops = {
213         .start          = pru_rproc_start,
214         .stop           = pru_rproc_stop,
215         .da_to_va       = pru_rproc_da_to_va,
216 };
217
218 static int
219 pru_rproc_load_elf_segments(struct rproc *rproc, const struct firmware *fw)
220 {
221         struct device *dev = &rproc->dev;
222         struct elf32_hdr *ehdr;
223         struct elf32_phdr *phdr;
224         int i, ret = 0;
225         const u8 *elf_data = fw->data;
226
227         ehdr = (struct elf32_hdr *)elf_data;
228         phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
229
230         /* go through the available ELF segments */
231         for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
232                 u32 da = phdr->p_paddr;
233                 u32 memsz = phdr->p_memsz;
234                 u32 filesz = phdr->p_filesz;
235                 u32 offset = phdr->p_offset;
236                 bool is_iram;
237                 void *ptr;
238
239                 if (phdr->p_type != PT_LOAD || !filesz)
240                         continue;
241
242                 dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
243                         phdr->p_type, da, memsz, filesz);
244
245                 if (filesz > memsz) {
246                         dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
247                                 filesz, memsz);
248                         ret = -EINVAL;
249                         break;
250                 }
251
252                 if (offset + filesz > fw->size) {
253                         dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
254                                 offset + filesz, fw->size);
255                         ret = -EINVAL;
256                         break;
257                 }
258
259                 /* grab the kernel address for this device address */
260                 is_iram = phdr->p_flags & PF_X;
261                 ptr = pru_da_to_va(rproc, da, memsz, is_iram);
262                 if (!ptr) {
263                         dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
264                         ret = -EINVAL;
265                         break;
266                 }
267
268                 memcpy(ptr, elf_data + phdr->p_offset, filesz);
269
270                 /* skip the memzero logic performed by remoteproc ELF loader */
271         }
272
273         return ret;
274 }
275
276 /*
277  * Use a custom parse_fw callback function for dealing with PRU firmware
278  * specific sections.
279  */
280 static int pru_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
281 {
282         int ret;
283
284         /* load optional rsc table */
285         ret = rproc_elf_load_rsc_table(rproc, fw);
286         if (ret == -EINVAL)
287                 dev_dbg(&rproc->dev, "no resource table found for this fw\n");
288         else if (ret)
289                 return ret;
290
291         return 0;
292 }
293
294 /*
295  * Compute PRU id based on the IRAM addresses. The PRU IRAMs are
296  * always at a particular offset within the PRUSS address space.
297  */
298 static int pru_rproc_set_id(struct pru_rproc *pru)
299 {
300         int ret = 0;
301
302         switch (pru->mem_regions[PRU_IOMEM_IRAM].pa & PRU_IRAM_ADDR_MASK) {
303         case PRU0_IRAM_ADDR_MASK:
304                 pru->id = 0;
305                 break;
306         case PRU1_IRAM_ADDR_MASK:
307                 pru->id = 1;
308                 break;
309         default:
310                 ret = -EINVAL;
311         }
312
313         return ret;
314 }
315
316 static int pru_rproc_probe(struct platform_device *pdev)
317 {
318         struct device *dev = &pdev->dev;
319         struct device_node *np = dev->of_node;
320         struct platform_device *ppdev = to_platform_device(dev->parent);
321         struct pru_rproc *pru;
322         const char *fw_name;
323         struct rproc *rproc = NULL;
324         struct resource *res;
325         int i, ret;
326         const char *mem_names[PRU_IOMEM_MAX] = { "iram", "control", "debug" };
327
328         ret = of_property_read_string(np, "firmware-name", &fw_name);
329         if (ret) {
330                 dev_err(dev, "unable to retrieve firmware-name %d\n", ret);
331                 return ret;
332         }
333
334         rproc = devm_rproc_alloc(dev, pdev->name, &pru_rproc_ops, fw_name,
335                                  sizeof(*pru));
336         if (!rproc) {
337                 dev_err(dev, "rproc_alloc failed\n");
338                 return -ENOMEM;
339         }
340         /* use a custom load function to deal with PRU-specific quirks */
341         rproc->ops->load = pru_rproc_load_elf_segments;
342
343         /* use a custom parse function to deal with PRU-specific resources */
344         rproc->ops->parse_fw = pru_rproc_parse_fw;
345
346         /* error recovery is not supported for PRUs */
347         rproc->recovery_disabled = true;
348
349         /*
350          * rproc_add will auto-boot the processor normally, but this is not
351          * desired with PRU client driven boot-flow methodology. A PRU
352          * application/client driver will boot the corresponding PRU
353          * remote-processor as part of its state machine either through the
354          * remoteproc sysfs interface or through the equivalent kernel API.
355          */
356         rproc->auto_boot = false;
357
358         pru = rproc->priv;
359         pru->dev = dev;
360         pru->pruss = platform_get_drvdata(ppdev);
361         pru->rproc = rproc;
362         pru->fw_name = fw_name;
363
364         for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
365                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
366                                                    mem_names[i]);
367                 pru->mem_regions[i].va = devm_ioremap_resource(dev, res);
368                 if (IS_ERR(pru->mem_regions[i].va)) {
369                         dev_err(dev, "failed to parse and map memory resource %d %s\n",
370                                 i, mem_names[i]);
371                         ret = PTR_ERR(pru->mem_regions[i].va);
372                         return ret;
373                 }
374                 pru->mem_regions[i].pa = res->start;
375                 pru->mem_regions[i].size = resource_size(res);
376
377                 dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %pK\n",
378                         mem_names[i], &pru->mem_regions[i].pa,
379                         pru->mem_regions[i].size, pru->mem_regions[i].va);
380         }
381
382         ret = pru_rproc_set_id(pru);
383         if (ret < 0)
384                 return ret;
385
386         platform_set_drvdata(pdev, rproc);
387
388         ret = devm_rproc_add(dev, pru->rproc);
389         if (ret) {
390                 dev_err(dev, "rproc_add failed: %d\n", ret);
391                 return ret;
392         }
393
394         dev_dbg(dev, "PRU rproc node %pOF probed successfully\n", np);
395
396         return 0;
397 }
398
399 static int pru_rproc_remove(struct platform_device *pdev)
400 {
401         struct device *dev = &pdev->dev;
402         struct rproc *rproc = platform_get_drvdata(pdev);
403
404         dev_dbg(dev, "%s: removing rproc %s\n", __func__, rproc->name);
405
406         return 0;
407 }
408
409 static const struct of_device_id pru_rproc_match[] = {
410         { .compatible = "ti,am3356-pru", },
411         { .compatible = "ti,am4376-pru", },
412         { .compatible = "ti,am5728-pru", },
413         { .compatible = "ti,k2g-pru",    },
414         {},
415 };
416 MODULE_DEVICE_TABLE(of, pru_rproc_match);
417
418 static struct platform_driver pru_rproc_driver = {
419         .driver = {
420                 .name   = "pru-rproc",
421                 .of_match_table = pru_rproc_match,
422                 .suppress_bind_attrs = true,
423         },
424         .probe  = pru_rproc_probe,
425         .remove = pru_rproc_remove,
426 };
427 module_platform_driver(pru_rproc_driver);
428
429 MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
430 MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
431 MODULE_AUTHOR("Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org>");
432 MODULE_DESCRIPTION("PRU-ICSS Remote Processor Driver");
433 MODULE_LICENSE("GPL v2");