pru_rproc.c 11 KB

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