Lines Matching full:pru
3 * PRU-ICSS remoteproc driver for various TI SoCs
49 /* PRU/RTU/Tx_PRU Core IRAM address masks */
58 /* PRU device addresses for various type of PRU RAMs */
67 * enum pru_iomem - PRU core memory/register range identifiers
69 * @PRU_IOMEM_IRAM: PRU Instruction RAM range
70 * @PRU_IOMEM_CTRL: PRU Control register range
71 * @PRU_IOMEM_DEBUG: PRU Debug register range
82 * enum pru_type - PRU core type identifier
97 * struct pru_private_data - device data for a PRU core
98 * @type: type of the PRU core (PRU, RTU, Tx_PRU)
107 * struct pru_rproc - PRU remoteproc structure
108 * @id: id of the PRU core within the PRUSS
109 * @dev: PRU core device pointer
111 * @rproc: remoteproc pointer for this PRU core
112 * @data: PRU core specific data
113 * @mem_regions: data for each of the PRU memory regions
118 * @dbg_single_step: debug state variable to set PRU into single step mode
119 * @dbg_continuous: debug state variable to restore PRU execution mode
138 static inline u32 pru_control_read_reg(struct pru_rproc *pru, unsigned int reg) in pru_control_read_reg() argument
140 return readl_relaxed(pru->mem_regions[PRU_IOMEM_CTRL].va + reg); in pru_control_read_reg()
144 void pru_control_write_reg(struct pru_rproc *pru, unsigned int reg, u32 val) in pru_control_write_reg() argument
146 writel_relaxed(val, pru->mem_regions[PRU_IOMEM_CTRL].va + reg); in pru_control_write_reg()
149 static inline u32 pru_debug_read_reg(struct pru_rproc *pru, unsigned int reg) in pru_debug_read_reg() argument
151 return readl_relaxed(pru->mem_regions[PRU_IOMEM_DEBUG].va + reg); in pru_debug_read_reg()
157 struct pru_rproc *pru = rproc->priv; in regs_show() local
164 pru_control_read_reg(pru, PRU_CTRL_CTRL)); in regs_show()
165 pru_sts = pru_control_read_reg(pru, PRU_CTRL_STS); in regs_show()
168 pru_control_read_reg(pru, PRU_CTRL_WAKEUP_EN)); in regs_show()
170 pru_control_read_reg(pru, PRU_CTRL_CYCLE)); in regs_show()
172 pru_control_read_reg(pru, PRU_CTRL_STALL)); in regs_show()
174 pru_control_read_reg(pru, PRU_CTRL_CTBIR0)); in regs_show()
176 pru_control_read_reg(pru, PRU_CTRL_CTBIR1)); in regs_show()
178 pru_control_read_reg(pru, PRU_CTRL_CTPPR0)); in regs_show()
180 pru_control_read_reg(pru, PRU_CTRL_CTPPR1)); in regs_show()
183 pru_is_running = pru_control_read_reg(pru, PRU_CTRL_CTRL) & in regs_show()
186 seq_puts(s, "PRU is executing, cannot print/access debug registers.\n"); in regs_show()
192 i, pru_debug_read_reg(pru, PRU_DEBUG_GPREG(i)), in regs_show()
193 i, pru_debug_read_reg(pru, PRU_DEBUG_CT_REG(i))); in regs_show()
201 * Control PRU single-step mode
204 * mode of the PRU. The PRU Debug registers are not accessible when the
205 * PRU is in RUNNING state.
207 * Writing a non-zero value sets the PRU into single-step mode irrespective
208 * of its previous state. The PRU mode is saved only on the first set into
209 * a single-step mode. Writing a zero value will restore the PRU into its
215 struct pru_rproc *pru = rproc->priv; in pru_rproc_debug_ss_set() local
219 if (!val && !pru->dbg_single_step) in pru_rproc_debug_ss_set()
222 reg_val = pru_control_read_reg(pru, PRU_CTRL_CTRL); in pru_rproc_debug_ss_set()
224 if (val && !pru->dbg_single_step) in pru_rproc_debug_ss_set()
225 pru->dbg_continuous = reg_val; in pru_rproc_debug_ss_set()
230 reg_val = pru->dbg_continuous; in pru_rproc_debug_ss_set()
232 pru->dbg_single_step = val; in pru_rproc_debug_ss_set()
233 pru_control_write_reg(pru, PRU_CTRL_CTRL, reg_val); in pru_rproc_debug_ss_set()
241 struct pru_rproc *pru = rproc->priv; in pru_rproc_debug_ss_get() local
243 *val = pru->dbg_single_step; in pru_rproc_debug_ss_get()
251 * Create PRU-specific debugfs entries
267 static void pru_dispose_irq_mapping(struct pru_rproc *pru) in pru_dispose_irq_mapping() argument
269 if (!pru->mapped_irq) in pru_dispose_irq_mapping()
272 while (pru->evt_count) { in pru_dispose_irq_mapping()
273 pru->evt_count--; in pru_dispose_irq_mapping()
274 if (pru->mapped_irq[pru->evt_count] > 0) in pru_dispose_irq_mapping()
275 irq_dispose_mapping(pru->mapped_irq[pru->evt_count]); in pru_dispose_irq_mapping()
278 kfree(pru->mapped_irq); in pru_dispose_irq_mapping()
279 pru->mapped_irq = NULL; in pru_dispose_irq_mapping()
283 * Parse the custom PRU interrupt map resource and configure the INTC
289 struct pru_rproc *pru = rproc->priv; in pru_handle_intrmap() local
290 struct pru_irq_rsc *rsc = pru->pru_interrupt_map; in pru_handle_intrmap()
309 pru->pru_interrupt_map_sz) in pru_handle_intrmap()
312 pru->evt_count = rsc->num_evts; in pru_handle_intrmap()
313 pru->mapped_irq = kcalloc(pru->evt_count, sizeof(unsigned int), in pru_handle_intrmap()
315 if (!pru->mapped_irq) { in pru_handle_intrmap()
316 pru->evt_count = 0; in pru_handle_intrmap()
323 * for these mappings for a given PRU remoteproc is always its in pru_handle_intrmap()
326 parent = of_get_parent(dev_of_node(pru->dev)); in pru_handle_intrmap()
328 kfree(pru->mapped_irq); in pru_handle_intrmap()
329 pru->mapped_irq = NULL; in pru_handle_intrmap()
330 pru->evt_count = 0; in pru_handle_intrmap()
337 kfree(pru->mapped_irq); in pru_handle_intrmap()
338 pru->mapped_irq = NULL; in pru_handle_intrmap()
339 pru->evt_count = 0; in pru_handle_intrmap()
345 for (i = 0; i < pru->evt_count; i++) { in pru_handle_intrmap()
353 pru->mapped_irq[i] = irq_create_fwspec_mapping(&fwspec); in pru_handle_intrmap()
354 if (!pru->mapped_irq[i]) { in pru_handle_intrmap()
367 pru_dispose_irq_mapping(pru); in pru_handle_intrmap()
376 struct pru_rproc *pru = rproc->priv; in pru_rproc_start() local
377 const char *names[PRU_TYPE_MAX] = { "PRU", "RTU", "Tx_PRU" }; in pru_rproc_start()
382 names[pru->data->type], pru->id, (rproc->bootaddr >> 2)); in pru_rproc_start()
386 * reset references to pru interrupt map - they will stop being valid in pru_rproc_start()
389 pru->pru_interrupt_map = NULL; in pru_rproc_start()
390 pru->pru_interrupt_map_sz = 0; in pru_rproc_start()
395 pru_control_write_reg(pru, PRU_CTRL_CTRL, val); in pru_rproc_start()
403 struct pru_rproc *pru = rproc->priv; in pru_rproc_stop() local
404 const char *names[PRU_TYPE_MAX] = { "PRU", "RTU", "Tx_PRU" }; in pru_rproc_stop()
407 dev_dbg(dev, "stopping %s%d\n", names[pru->data->type], pru->id); in pru_rproc_stop()
409 val = pru_control_read_reg(pru, PRU_CTRL_CTRL); in pru_rproc_stop()
411 pru_control_write_reg(pru, PRU_CTRL_CTRL, val); in pru_rproc_stop()
414 pru_dispose_irq_mapping(pru); in pru_rproc_stop()
420 * Convert PRU device address (data spaces only) to kernel virtual address.
422 * Each PRU has access to all data memories within the PRUSS, accessible at
424 * RAMs as well as any shared Data RAM to convert a PRU device address to
428 static void *pru_d_da_to_va(struct pru_rproc *pru, u32 da, size_t len) in pru_d_da_to_va() argument
431 struct pruss *pruss = pru->pruss; in pru_d_da_to_va()
441 if (pru->id == 1) in pru_d_da_to_va()
462 * Convert PRU device address (instruction space) to kernel virtual address.
464 * A PRU does not have an unified address space. Each PRU has its very own
468 static void *pru_i_da_to_va(struct pru_rproc *pru, u32 da, size_t len) in pru_i_da_to_va() argument
484 * bits anyway. PRU architecture limits the program counter to 16-bit in pru_i_da_to_va()
495 da + len <= PRU_IRAM_DA + pru->mem_regions[PRU_IOMEM_IRAM].size) { in pru_i_da_to_va()
497 va = (__force void *)(pru->mem_regions[PRU_IOMEM_IRAM].va + in pru_i_da_to_va()
505 * Provide address translations for only PRU Data RAMs through the remoteproc
506 * core for any PRU client drivers. The PRU Instruction RAM access is restricted
507 * only to the PRU loader code.
511 struct pru_rproc *pru = rproc->priv; in pru_rproc_da_to_va() local
513 return pru_d_da_to_va(pru, da, len); in pru_rproc_da_to_va()
516 /* PRU-specific address translator used by PRU loader. */
519 struct pru_rproc *pru = rproc->priv; in pru_da_to_va() local
523 va = pru_i_da_to_va(pru, da, len); in pru_da_to_va()
525 va = pru_d_da_to_va(pru, da, len); in pru_da_to_va()
537 * Custom memory copy implementation for ICSSG PRU/RTU/Tx_PRU Cores
539 * The ICSSG PRU/RTU/Tx_PRU cores have a memory copying issue with IRAM
581 struct pru_rproc *pru = rproc->priv; in pru_rproc_load_elf_segments() local
629 if (pru->data->is_k3) { in pru_rproc_load_elf_segments()
633 dev_err(dev, "PRU memory copy failed for da 0x%x memsz 0x%x\n", in pru_rproc_load_elf_segments()
694 * Use a custom parse_fw callback function for dealing with PRU firmware
699 * description, which needs to be setup before powering on the PRU core. To
701 * firmware linker) and therefore is not loaded to PRU memory.
706 struct pru_rproc *pru = rproc->priv; in pru_rproc_parse_fw() local
728 /* preserve pointer to PRU interrupt map together with it size */ in pru_rproc_parse_fw()
730 pru->pru_interrupt_map = (struct pru_irq_rsc *)(elf_data + sh_offset); in pru_rproc_parse_fw()
731 pru->pru_interrupt_map_sz = elf_shdr_get_sh_size(class, shdr); in pru_rproc_parse_fw()
737 * Compute PRU id based on the IRAM addresses. The PRU IRAMs are
740 static int pru_rproc_set_id(struct pru_rproc *pru) in pru_rproc_set_id() argument
744 switch (pru->mem_regions[PRU_IOMEM_IRAM].pa & PRU_IRAM_ADDR_MASK) { in pru_rproc_set_id()
750 pru->id = 0; in pru_rproc_set_id()
757 pru->id = 1; in pru_rproc_set_id()
771 struct pru_rproc *pru; in pru_rproc_probe() local
790 sizeof(*pru)); in pru_rproc_probe()
795 /* use a custom load function to deal with PRU-specific quirks */ in pru_rproc_probe()
798 /* use a custom parse function to deal with PRU-specific resources */ in pru_rproc_probe()
806 * desired with PRU client driven boot-flow methodology. A PRU in pru_rproc_probe()
807 * application/client driver will boot the corresponding PRU in pru_rproc_probe()
813 pru = rproc->priv; in pru_rproc_probe()
814 pru->dev = dev; in pru_rproc_probe()
815 pru->data = data; in pru_rproc_probe()
816 pru->pruss = platform_get_drvdata(ppdev); in pru_rproc_probe()
817 pru->rproc = rproc; in pru_rproc_probe()
818 pru->fw_name = fw_name; in pru_rproc_probe()
823 pru->mem_regions[i].va = devm_ioremap_resource(dev, res); in pru_rproc_probe()
824 if (IS_ERR(pru->mem_regions[i].va)) { in pru_rproc_probe()
827 ret = PTR_ERR(pru->mem_regions[i].va); in pru_rproc_probe()
830 pru->mem_regions[i].pa = res->start; in pru_rproc_probe()
831 pru->mem_regions[i].size = resource_size(res); in pru_rproc_probe()
834 mem_names[i], &pru->mem_regions[i].pa, in pru_rproc_probe()
835 pru->mem_regions[i].size, pru->mem_regions[i].va); in pru_rproc_probe()
838 ret = pru_rproc_set_id(pru); in pru_rproc_probe()
844 ret = devm_rproc_add(dev, pru->rproc); in pru_rproc_probe()
852 dev_dbg(dev, "PRU rproc node %pOF probed successfully\n", np); in pru_rproc_probe()
887 { .compatible = "ti,am3356-pru", .data = &pru_data },
888 { .compatible = "ti,am4376-pru", .data = &pru_data },
889 { .compatible = "ti,am5728-pru", .data = &pru_data },
890 { .compatible = "ti,am642-pru", .data = &k3_pru_data },
892 { .compatible = "ti,am642-tx-pru", .data = &k3_tx_pru_data },
893 { .compatible = "ti,k2g-pru", .data = &pru_data },
894 { .compatible = "ti,am654-pru", .data = &k3_pru_data },
896 { .compatible = "ti,am654-tx-pru", .data = &k3_tx_pru_data },
897 { .compatible = "ti,j721e-pru", .data = &k3_pru_data },
899 { .compatible = "ti,j721e-tx-pru", .data = &k3_tx_pru_data },
900 { .compatible = "ti,am625-pru", .data = &k3_pru_data },
907 .name = "pru-rproc",
919 MODULE_DESCRIPTION("PRU-ICSS Remote Processor Driver");