coresight-catu.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2018 Arm Limited. All rights reserved.
  4. *
  5. * Coresight Address Translation Unit support
  6. *
  7. * Author: Suzuki K Poulose <suzuki.poulose@arm.com>
  8. */
  9. #include <linux/amba/bus.h>
  10. #include <linux/device.h>
  11. #include <linux/dma-mapping.h>
  12. #include <linux/io.h>
  13. #include <linux/kernel.h>
  14. #include <linux/slab.h>
  15. #include "coresight-catu.h"
  16. #include "coresight-priv.h"
  17. #include "coresight-tmc.h"
  18. #define csdev_to_catu_drvdata(csdev) \
  19. dev_get_drvdata(csdev->dev.parent)
  20. /* Verbose output for CATU table contents */
  21. #ifdef CATU_DEBUG
  22. #define catu_dbg(x, ...) dev_dbg(x, __VA_ARGS__)
  23. #else
  24. #define catu_dbg(x, ...) do {} while (0)
  25. #endif
  26. struct catu_etr_buf {
  27. struct tmc_sg_table *catu_table;
  28. dma_addr_t sladdr;
  29. };
  30. /*
  31. * CATU uses a page size of 4KB for page tables as well as data pages.
  32. * Each 64bit entry in the table has the following format.
  33. *
  34. * 63 12 1 0
  35. * ------------------------------------
  36. * | Address [63-12] | SBZ | V|
  37. * ------------------------------------
  38. *
  39. * Where bit[0] V indicates if the address is valid or not.
  40. * Each 4K table pages have upto 256 data page pointers, taking upto 2K
  41. * size. There are two Link pointers, pointing to the previous and next
  42. * table pages respectively at the end of the 4K page. (i.e, entry 510
  43. * and 511).
  44. * E.g, a table of two pages could look like :
  45. *
  46. * Table Page 0 Table Page 1
  47. * SLADDR ===> x------------------x x--> x-----------------x
  48. * INADDR ->| Page 0 | V | | | Page 256 | V | <- INADDR+1M
  49. * |------------------| | |-----------------|
  50. * INADDR+4K ->| Page 1 | V | | | |
  51. * |------------------| | |-----------------|
  52. * | Page 2 | V | | | |
  53. * |------------------| | |-----------------|
  54. * | ... | V | | | ... |
  55. * |------------------| | |-----------------|
  56. * INADDR+1020K| Page 255 | V | | | Page 511 | V |
  57. * SLADDR+2K==>|------------------| | |-----------------|
  58. * | UNUSED | | | | |
  59. * |------------------| | | |
  60. * | UNUSED | | | | |
  61. * |------------------| | | |
  62. * | ... | | | | |
  63. * |------------------| | |-----------------|
  64. * | IGNORED | 0 | | | Table Page 0| 1 |
  65. * |------------------| | |-----------------|
  66. * | Table Page 1| 1 |--x | IGNORED | 0 |
  67. * x------------------x x-----------------x
  68. * SLADDR+4K==>
  69. *
  70. * The base input address (used by the ETR, programmed in INADDR_{LO,HI})
  71. * must be aligned to 1MB (the size addressable by a single page table).
  72. * The CATU maps INADDR{LO:HI} to the first page in the table pointed
  73. * to by SLADDR{LO:HI} and so on.
  74. *
  75. */
  76. typedef u64 cate_t;
  77. #define CATU_PAGE_SHIFT 12
  78. #define CATU_PAGE_SIZE (1UL << CATU_PAGE_SHIFT)
  79. #define CATU_PAGES_PER_SYSPAGE (PAGE_SIZE / CATU_PAGE_SIZE)
  80. /* Page pointers are only allocated in the first 2K half */
  81. #define CATU_PTRS_PER_PAGE ((CATU_PAGE_SIZE >> 1) / sizeof(cate_t))
  82. #define CATU_PTRS_PER_SYSPAGE (CATU_PAGES_PER_SYSPAGE * CATU_PTRS_PER_PAGE)
  83. #define CATU_LINK_PREV ((CATU_PAGE_SIZE / sizeof(cate_t)) - 2)
  84. #define CATU_LINK_NEXT ((CATU_PAGE_SIZE / sizeof(cate_t)) - 1)
  85. #define CATU_ADDR_SHIFT 12
  86. #define CATU_ADDR_MASK ~(((cate_t)1 << CATU_ADDR_SHIFT) - 1)
  87. #define CATU_ENTRY_VALID ((cate_t)0x1)
  88. #define CATU_VALID_ENTRY(addr) \
  89. (((cate_t)(addr) & CATU_ADDR_MASK) | CATU_ENTRY_VALID)
  90. #define CATU_ENTRY_ADDR(entry) ((cate_t)(entry) & ~((cate_t)CATU_ENTRY_VALID))
  91. /* CATU expects the INADDR to be aligned to 1M. */
  92. #define CATU_DEFAULT_INADDR (1ULL << 20)
  93. /*
  94. * catu_get_table : Retrieve the table pointers for the given @offset
  95. * within the buffer. The buffer is wrapped around to a valid offset.
  96. *
  97. * Returns : The CPU virtual address for the beginning of the table
  98. * containing the data page pointer for @offset. If @daddrp is not NULL,
  99. * @daddrp points the DMA address of the beginning of the table.
  100. */
  101. static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
  102. unsigned long offset,
  103. dma_addr_t *daddrp)
  104. {
  105. unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
  106. unsigned int table_nr, pg_idx, pg_offset;
  107. struct tmc_pages *table_pages = &catu_table->table_pages;
  108. void *ptr;
  109. /* Make sure offset is within the range */
  110. offset %= buf_size;
  111. /*
  112. * Each table can address 1MB and a single kernel page can
  113. * contain "CATU_PAGES_PER_SYSPAGE" CATU tables.
  114. */
  115. table_nr = offset >> 20;
  116. /* Find the table page where the table_nr lies in */
  117. pg_idx = table_nr / CATU_PAGES_PER_SYSPAGE;
  118. pg_offset = (table_nr % CATU_PAGES_PER_SYSPAGE) * CATU_PAGE_SIZE;
  119. if (daddrp)
  120. *daddrp = table_pages->daddrs[pg_idx] + pg_offset;
  121. ptr = page_address(table_pages->pages[pg_idx]);
  122. return (cate_t *)((unsigned long)ptr + pg_offset);
  123. }
  124. #ifdef CATU_DEBUG
  125. static void catu_dump_table(struct tmc_sg_table *catu_table)
  126. {
  127. int i;
  128. cate_t *table;
  129. unsigned long table_end, buf_size, offset = 0;
  130. buf_size = tmc_sg_table_buf_size(catu_table);
  131. dev_dbg(catu_table->dev,
  132. "Dump table %p, tdaddr: %llx\n",
  133. catu_table, catu_table->table_daddr);
  134. while (offset < buf_size) {
  135. table_end = offset + SZ_1M < buf_size ?
  136. offset + SZ_1M : buf_size;
  137. table = catu_get_table(catu_table, offset, NULL);
  138. for (i = 0; offset < table_end; i++, offset += CATU_PAGE_SIZE)
  139. dev_dbg(catu_table->dev, "%d: %llx\n", i, table[i]);
  140. dev_dbg(catu_table->dev, "Prev : %llx, Next: %llx\n",
  141. table[CATU_LINK_PREV], table[CATU_LINK_NEXT]);
  142. dev_dbg(catu_table->dev, "== End of sub-table ===");
  143. }
  144. dev_dbg(catu_table->dev, "== End of Table ===");
  145. }
  146. #else
  147. static inline void catu_dump_table(struct tmc_sg_table *catu_table)
  148. {
  149. }
  150. #endif
  151. static inline cate_t catu_make_entry(dma_addr_t addr)
  152. {
  153. return addr ? CATU_VALID_ENTRY(addr) : 0;
  154. }
  155. /*
  156. * catu_populate_table : Populate the given CATU table.
  157. * The table is always populated as a circular table.
  158. * i.e, the "prev" link of the "first" table points to the "last"
  159. * table and the "next" link of the "last" table points to the
  160. * "first" table. The buffer should be made linear by calling
  161. * catu_set_table().
  162. */
  163. static void
  164. catu_populate_table(struct tmc_sg_table *catu_table)
  165. {
  166. int i;
  167. int sys_pidx; /* Index to current system data page */
  168. int catu_pidx; /* Index of CATU page within the system data page */
  169. unsigned long offset, buf_size, table_end;
  170. dma_addr_t data_daddr;
  171. dma_addr_t prev_taddr, next_taddr, cur_taddr;
  172. cate_t *table_ptr, *next_table;
  173. buf_size = tmc_sg_table_buf_size(catu_table);
  174. sys_pidx = catu_pidx = 0;
  175. offset = 0;
  176. table_ptr = catu_get_table(catu_table, 0, &cur_taddr);
  177. prev_taddr = 0; /* Prev link for the first table */
  178. while (offset < buf_size) {
  179. /*
  180. * The @offset is always 1M aligned here and we have an
  181. * empty table @table_ptr to fill. Each table can address
  182. * upto 1MB data buffer. The last table may have fewer
  183. * entries if the buffer size is not aligned.
  184. */
  185. table_end = (offset + SZ_1M) < buf_size ?
  186. (offset + SZ_1M) : buf_size;
  187. for (i = 0; offset < table_end;
  188. i++, offset += CATU_PAGE_SIZE) {
  189. data_daddr = catu_table->data_pages.daddrs[sys_pidx] +
  190. catu_pidx * CATU_PAGE_SIZE;
  191. catu_dbg(catu_table->dev,
  192. "[table %5ld:%03d] 0x%llx\n",
  193. (offset >> 20), i, data_daddr);
  194. table_ptr[i] = catu_make_entry(data_daddr);
  195. /* Move the pointers for data pages */
  196. catu_pidx = (catu_pidx + 1) % CATU_PAGES_PER_SYSPAGE;
  197. if (catu_pidx == 0)
  198. sys_pidx++;
  199. }
  200. /*
  201. * If we have finished all the valid entries, fill the rest of
  202. * the table (i.e, last table page) with invalid entries,
  203. * to fail the lookups.
  204. */
  205. if (offset == buf_size) {
  206. memset(&table_ptr[i], 0,
  207. sizeof(cate_t) * (CATU_PTRS_PER_PAGE - i));
  208. next_taddr = 0;
  209. } else {
  210. next_table = catu_get_table(catu_table,
  211. offset, &next_taddr);
  212. }
  213. table_ptr[CATU_LINK_PREV] = catu_make_entry(prev_taddr);
  214. table_ptr[CATU_LINK_NEXT] = catu_make_entry(next_taddr);
  215. catu_dbg(catu_table->dev,
  216. "[table%5ld]: Cur: 0x%llx Prev: 0x%llx, Next: 0x%llx\n",
  217. (offset >> 20) - 1, cur_taddr, prev_taddr, next_taddr);
  218. /* Update the prev/next addresses */
  219. if (next_taddr) {
  220. prev_taddr = cur_taddr;
  221. cur_taddr = next_taddr;
  222. table_ptr = next_table;
  223. }
  224. }
  225. /* Sync the table for device */
  226. tmc_sg_table_sync_table(catu_table);
  227. }
  228. static struct tmc_sg_table *
  229. catu_init_sg_table(struct device *catu_dev, int node,
  230. ssize_t size, void **pages)
  231. {
  232. int nr_tpages;
  233. struct tmc_sg_table *catu_table;
  234. /*
  235. * Each table can address upto 1MB and we can have
  236. * CATU_PAGES_PER_SYSPAGE tables in a system page.
  237. */
  238. nr_tpages = DIV_ROUND_UP(size, SZ_1M) / CATU_PAGES_PER_SYSPAGE;
  239. catu_table = tmc_alloc_sg_table(catu_dev, node, nr_tpages,
  240. size >> PAGE_SHIFT, pages);
  241. if (IS_ERR(catu_table))
  242. return catu_table;
  243. catu_populate_table(catu_table);
  244. dev_dbg(catu_dev,
  245. "Setup table %p, size %ldKB, %d table pages\n",
  246. catu_table, (unsigned long)size >> 10, nr_tpages);
  247. catu_dump_table(catu_table);
  248. return catu_table;
  249. }
  250. static void catu_free_etr_buf(struct etr_buf *etr_buf)
  251. {
  252. struct catu_etr_buf *catu_buf;
  253. if (!etr_buf || etr_buf->mode != ETR_MODE_CATU || !etr_buf->private)
  254. return;
  255. catu_buf = etr_buf->private;
  256. tmc_free_sg_table(catu_buf->catu_table);
  257. kfree(catu_buf);
  258. }
  259. static ssize_t catu_get_data_etr_buf(struct etr_buf *etr_buf, u64 offset,
  260. size_t len, char **bufpp)
  261. {
  262. struct catu_etr_buf *catu_buf = etr_buf->private;
  263. return tmc_sg_table_get_data(catu_buf->catu_table, offset, len, bufpp);
  264. }
  265. static void catu_sync_etr_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp)
  266. {
  267. struct catu_etr_buf *catu_buf = etr_buf->private;
  268. struct tmc_sg_table *catu_table = catu_buf->catu_table;
  269. u64 r_offset, w_offset;
  270. /*
  271. * ETR started off at etr_buf->hwaddr. Convert the RRP/RWP to
  272. * offsets within the trace buffer.
  273. */
  274. r_offset = rrp - etr_buf->hwaddr;
  275. w_offset = rwp - etr_buf->hwaddr;
  276. if (!etr_buf->full) {
  277. etr_buf->len = w_offset - r_offset;
  278. if (w_offset < r_offset)
  279. etr_buf->len += etr_buf->size;
  280. } else {
  281. etr_buf->len = etr_buf->size;
  282. }
  283. etr_buf->offset = r_offset;
  284. tmc_sg_table_sync_data_range(catu_table, r_offset, etr_buf->len);
  285. }
  286. static int catu_alloc_etr_buf(struct tmc_drvdata *tmc_drvdata,
  287. struct etr_buf *etr_buf, int node, void **pages)
  288. {
  289. struct coresight_device *csdev;
  290. struct device *catu_dev;
  291. struct tmc_sg_table *catu_table;
  292. struct catu_etr_buf *catu_buf;
  293. csdev = tmc_etr_get_catu_device(tmc_drvdata);
  294. if (!csdev)
  295. return -ENODEV;
  296. catu_dev = csdev->dev.parent;
  297. catu_buf = kzalloc(sizeof(*catu_buf), GFP_KERNEL);
  298. if (!catu_buf)
  299. return -ENOMEM;
  300. catu_table = catu_init_sg_table(catu_dev, node, etr_buf->size, pages);
  301. if (IS_ERR(catu_table)) {
  302. kfree(catu_buf);
  303. return PTR_ERR(catu_table);
  304. }
  305. etr_buf->mode = ETR_MODE_CATU;
  306. etr_buf->private = catu_buf;
  307. etr_buf->hwaddr = CATU_DEFAULT_INADDR;
  308. catu_buf->catu_table = catu_table;
  309. /* Get the table base address */
  310. catu_buf->sladdr = catu_table->table_daddr;
  311. return 0;
  312. }
  313. const struct etr_buf_operations etr_catu_buf_ops = {
  314. .alloc = catu_alloc_etr_buf,
  315. .free = catu_free_etr_buf,
  316. .sync = catu_sync_etr_buf,
  317. .get_data = catu_get_data_etr_buf,
  318. };
  319. coresight_simple_reg32(struct catu_drvdata, devid, CORESIGHT_DEVID);
  320. coresight_simple_reg32(struct catu_drvdata, control, CATU_CONTROL);
  321. coresight_simple_reg32(struct catu_drvdata, status, CATU_STATUS);
  322. coresight_simple_reg32(struct catu_drvdata, mode, CATU_MODE);
  323. coresight_simple_reg32(struct catu_drvdata, axictrl, CATU_AXICTRL);
  324. coresight_simple_reg32(struct catu_drvdata, irqen, CATU_IRQEN);
  325. coresight_simple_reg64(struct catu_drvdata, sladdr,
  326. CATU_SLADDRLO, CATU_SLADDRHI);
  327. coresight_simple_reg64(struct catu_drvdata, inaddr,
  328. CATU_INADDRLO, CATU_INADDRHI);
  329. static struct attribute *catu_mgmt_attrs[] = {
  330. &dev_attr_devid.attr,
  331. &dev_attr_control.attr,
  332. &dev_attr_status.attr,
  333. &dev_attr_mode.attr,
  334. &dev_attr_axictrl.attr,
  335. &dev_attr_irqen.attr,
  336. &dev_attr_sladdr.attr,
  337. &dev_attr_inaddr.attr,
  338. NULL,
  339. };
  340. static const struct attribute_group catu_mgmt_group = {
  341. .attrs = catu_mgmt_attrs,
  342. .name = "mgmt",
  343. };
  344. static const struct attribute_group *catu_groups[] = {
  345. &catu_mgmt_group,
  346. NULL,
  347. };
  348. static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
  349. {
  350. return coresight_timeout(drvdata->base,
  351. CATU_STATUS, CATU_STATUS_READY, 1);
  352. }
  353. static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
  354. {
  355. int rc;
  356. u32 control, mode;
  357. struct etr_buf *etr_buf = data;
  358. if (catu_wait_for_ready(drvdata))
  359. dev_warn(drvdata->dev, "Timeout while waiting for READY\n");
  360. control = catu_read_control(drvdata);
  361. if (control & BIT(CATU_CONTROL_ENABLE)) {
  362. dev_warn(drvdata->dev, "CATU is already enabled\n");
  363. return -EBUSY;
  364. }
  365. rc = coresight_claim_device_unlocked(drvdata->base);
  366. if (rc)
  367. return rc;
  368. control |= BIT(CATU_CONTROL_ENABLE);
  369. if (etr_buf && etr_buf->mode == ETR_MODE_CATU) {
  370. struct catu_etr_buf *catu_buf = etr_buf->private;
  371. mode = CATU_MODE_TRANSLATE;
  372. catu_write_axictrl(drvdata, CATU_OS_AXICTRL);
  373. catu_write_sladdr(drvdata, catu_buf->sladdr);
  374. catu_write_inaddr(drvdata, CATU_DEFAULT_INADDR);
  375. } else {
  376. mode = CATU_MODE_PASS_THROUGH;
  377. catu_write_sladdr(drvdata, 0);
  378. catu_write_inaddr(drvdata, 0);
  379. }
  380. catu_write_irqen(drvdata, 0);
  381. catu_write_mode(drvdata, mode);
  382. catu_write_control(drvdata, control);
  383. dev_dbg(drvdata->dev, "Enabled in %s mode\n",
  384. (mode == CATU_MODE_PASS_THROUGH) ?
  385. "Pass through" :
  386. "Translate");
  387. return 0;
  388. }
  389. static int catu_enable(struct coresight_device *csdev, void *data)
  390. {
  391. int rc;
  392. struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
  393. CS_UNLOCK(catu_drvdata->base);
  394. rc = catu_enable_hw(catu_drvdata, data);
  395. CS_LOCK(catu_drvdata->base);
  396. return rc;
  397. }
  398. static int catu_disable_hw(struct catu_drvdata *drvdata)
  399. {
  400. int rc = 0;
  401. catu_write_control(drvdata, 0);
  402. coresight_disclaim_device_unlocked(drvdata->base);
  403. if (catu_wait_for_ready(drvdata)) {
  404. dev_info(drvdata->dev, "Timeout while waiting for READY\n");
  405. rc = -EAGAIN;
  406. }
  407. dev_dbg(drvdata->dev, "Disabled\n");
  408. return rc;
  409. }
  410. static int catu_disable(struct coresight_device *csdev, void *__unused)
  411. {
  412. int rc;
  413. struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
  414. CS_UNLOCK(catu_drvdata->base);
  415. rc = catu_disable_hw(catu_drvdata);
  416. CS_LOCK(catu_drvdata->base);
  417. return rc;
  418. }
  419. const struct coresight_ops_helper catu_helper_ops = {
  420. .enable = catu_enable,
  421. .disable = catu_disable,
  422. };
  423. const struct coresight_ops catu_ops = {
  424. .helper_ops = &catu_helper_ops,
  425. };
  426. static int catu_probe(struct amba_device *adev, const struct amba_id *id)
  427. {
  428. int ret = 0;
  429. u32 dma_mask;
  430. struct catu_drvdata *drvdata;
  431. struct coresight_desc catu_desc;
  432. struct coresight_platform_data *pdata = NULL;
  433. struct device *dev = &adev->dev;
  434. struct device_node *np = dev->of_node;
  435. void __iomem *base;
  436. if (np) {
  437. pdata = of_get_coresight_platform_data(dev, np);
  438. if (IS_ERR(pdata)) {
  439. ret = PTR_ERR(pdata);
  440. goto out;
  441. }
  442. dev->platform_data = pdata;
  443. }
  444. drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
  445. if (!drvdata) {
  446. ret = -ENOMEM;
  447. goto out;
  448. }
  449. drvdata->dev = dev;
  450. dev_set_drvdata(dev, drvdata);
  451. base = devm_ioremap_resource(dev, &adev->res);
  452. if (IS_ERR(base)) {
  453. ret = PTR_ERR(base);
  454. goto out;
  455. }
  456. /* Setup dma mask for the device */
  457. dma_mask = readl_relaxed(base + CORESIGHT_DEVID) & 0x3f;
  458. switch (dma_mask) {
  459. case 32:
  460. case 40:
  461. case 44:
  462. case 48:
  463. case 52:
  464. case 56:
  465. case 64:
  466. break;
  467. default:
  468. /* Default to the 40bits as supported by TMC-ETR */
  469. dma_mask = 40;
  470. }
  471. ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_mask));
  472. if (ret)
  473. goto out;
  474. drvdata->base = base;
  475. catu_desc.pdata = pdata;
  476. catu_desc.dev = dev;
  477. catu_desc.groups = catu_groups;
  478. catu_desc.type = CORESIGHT_DEV_TYPE_HELPER;
  479. catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
  480. catu_desc.ops = &catu_ops;
  481. drvdata->csdev = coresight_register(&catu_desc);
  482. if (IS_ERR(drvdata->csdev))
  483. ret = PTR_ERR(drvdata->csdev);
  484. out:
  485. pm_runtime_put(&adev->dev);
  486. return ret;
  487. }
  488. static struct amba_id catu_ids[] = {
  489. {
  490. .id = 0x000bb9ee,
  491. .mask = 0x000fffff,
  492. },
  493. {},
  494. };
  495. static struct amba_driver catu_driver = {
  496. .drv = {
  497. .name = "coresight-catu",
  498. .owner = THIS_MODULE,
  499. .suppress_bind_attrs = true,
  500. },
  501. .probe = catu_probe,
  502. .id_table = catu_ids,
  503. };
  504. builtin_amba_driver(catu_driver);