722 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2018 Arm Limited. All rights reserved.4 *5 * Coresight Address Translation Unit support6 *7 * Author: Suzuki K Poulose <suzuki.poulose@arm.com>8 */9 10#include <linux/acpi.h>11#include <linux/amba/bus.h>12#include <linux/device.h>13#include <linux/dma-mapping.h>14#include <linux/io.h>15#include <linux/kernel.h>16#include <linux/platform_device.h>17#include <linux/slab.h>18 19#include "coresight-catu.h"20#include "coresight-priv.h"21#include "coresight-tmc.h"22 23#define csdev_to_catu_drvdata(csdev) \24 dev_get_drvdata(csdev->dev.parent)25 26/* Verbose output for CATU table contents */27#ifdef CATU_DEBUG28#define catu_dbg(x, ...) dev_dbg(x, __VA_ARGS__)29#else30#define catu_dbg(x, ...) do {} while (0)31#endif32 33DEFINE_CORESIGHT_DEVLIST(catu_devs, "catu");34 35struct catu_etr_buf {36 struct tmc_sg_table *catu_table;37 dma_addr_t sladdr;38};39 40/*41 * CATU uses a page size of 4KB for page tables as well as data pages.42 * Each 64bit entry in the table has the following format.43 *44 * 63 12 1 045 * ------------------------------------46 * | Address [63-12] | SBZ | V|47 * ------------------------------------48 *49 * Where bit[0] V indicates if the address is valid or not.50 * Each 4K table pages have upto 256 data page pointers, taking upto 2K51 * size. There are two Link pointers, pointing to the previous and next52 * table pages respectively at the end of the 4K page. (i.e, entry 51053 * and 511).54 * E.g, a table of two pages could look like :55 *56 * Table Page 0 Table Page 157 * SLADDR ===> x------------------x x--> x-----------------x58 * INADDR ->| Page 0 | V | | | Page 256 | V | <- INADDR+1M59 * |------------------| | |-----------------|60 * INADDR+4K ->| Page 1 | V | | | |61 * |------------------| | |-----------------|62 * | Page 2 | V | | | |63 * |------------------| | |-----------------|64 * | ... | V | | | ... |65 * |------------------| | |-----------------|66 * INADDR+1020K| Page 255 | V | | | Page 511 | V |67 * SLADDR+2K==>|------------------| | |-----------------|68 * | UNUSED | | | | |69 * |------------------| | | |70 * | UNUSED | | | | |71 * |------------------| | | |72 * | ... | | | | |73 * |------------------| | |-----------------|74 * | IGNORED | 0 | | | Table Page 0| 1 |75 * |------------------| | |-----------------|76 * | Table Page 1| 1 |--x | IGNORED | 0 |77 * x------------------x x-----------------x78 * SLADDR+4K==>79 *80 * The base input address (used by the ETR, programmed in INADDR_{LO,HI})81 * must be aligned to 1MB (the size addressable by a single page table).82 * The CATU maps INADDR{LO:HI} to the first page in the table pointed83 * to by SLADDR{LO:HI} and so on.84 *85 */86typedef u64 cate_t;87 88#define CATU_PAGE_SHIFT 1289#define CATU_PAGE_SIZE (1UL << CATU_PAGE_SHIFT)90#define CATU_PAGES_PER_SYSPAGE (PAGE_SIZE / CATU_PAGE_SIZE)91 92/* Page pointers are only allocated in the first 2K half */93#define CATU_PTRS_PER_PAGE ((CATU_PAGE_SIZE >> 1) / sizeof(cate_t))94#define CATU_PTRS_PER_SYSPAGE (CATU_PAGES_PER_SYSPAGE * CATU_PTRS_PER_PAGE)95#define CATU_LINK_PREV ((CATU_PAGE_SIZE / sizeof(cate_t)) - 2)96#define CATU_LINK_NEXT ((CATU_PAGE_SIZE / sizeof(cate_t)) - 1)97 98#define CATU_ADDR_SHIFT 1299#define CATU_ADDR_MASK ~(((cate_t)1 << CATU_ADDR_SHIFT) - 1)100#define CATU_ENTRY_VALID ((cate_t)0x1)101#define CATU_VALID_ENTRY(addr) \102 (((cate_t)(addr) & CATU_ADDR_MASK) | CATU_ENTRY_VALID)103#define CATU_ENTRY_ADDR(entry) ((cate_t)(entry) & ~((cate_t)CATU_ENTRY_VALID))104 105/* CATU expects the INADDR to be aligned to 1M. */106#define CATU_DEFAULT_INADDR (1ULL << 20)107 108/*109 * catu_get_table : Retrieve the table pointers for the given @offset110 * within the buffer. The buffer is wrapped around to a valid offset.111 *112 * Returns : The CPU virtual address for the beginning of the table113 * containing the data page pointer for @offset. If @daddrp is not NULL,114 * @daddrp points the DMA address of the beginning of the table.115 */116static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,117 unsigned long offset,118 dma_addr_t *daddrp)119{120 unsigned long buf_size = tmc_sg_table_buf_size(catu_table);121 unsigned int table_nr, pg_idx, pg_offset;122 struct tmc_pages *table_pages = &catu_table->table_pages;123 void *ptr;124 125 /* Make sure offset is within the range */126 offset %= buf_size;127 128 /*129 * Each table can address 1MB and a single kernel page can130 * contain "CATU_PAGES_PER_SYSPAGE" CATU tables.131 */132 table_nr = offset >> 20;133 /* Find the table page where the table_nr lies in */134 pg_idx = table_nr / CATU_PAGES_PER_SYSPAGE;135 pg_offset = (table_nr % CATU_PAGES_PER_SYSPAGE) * CATU_PAGE_SIZE;136 if (daddrp)137 *daddrp = table_pages->daddrs[pg_idx] + pg_offset;138 ptr = page_address(table_pages->pages[pg_idx]);139 return (cate_t *)((unsigned long)ptr + pg_offset);140}141 142#ifdef CATU_DEBUG143static void catu_dump_table(struct tmc_sg_table *catu_table)144{145 int i;146 cate_t *table;147 unsigned long table_end, buf_size, offset = 0;148 149 buf_size = tmc_sg_table_buf_size(catu_table);150 dev_dbg(catu_table->dev,151 "Dump table %p, tdaddr: %llx\n",152 catu_table, catu_table->table_daddr);153 154 while (offset < buf_size) {155 table_end = offset + SZ_1M < buf_size ?156 offset + SZ_1M : buf_size;157 table = catu_get_table(catu_table, offset, NULL);158 for (i = 0; offset < table_end; i++, offset += CATU_PAGE_SIZE)159 dev_dbg(catu_table->dev, "%d: %llx\n", i, table[i]);160 dev_dbg(catu_table->dev, "Prev : %llx, Next: %llx\n",161 table[CATU_LINK_PREV], table[CATU_LINK_NEXT]);162 dev_dbg(catu_table->dev, "== End of sub-table ===");163 }164 dev_dbg(catu_table->dev, "== End of Table ===");165}166 167#else168static inline void catu_dump_table(struct tmc_sg_table *catu_table)169{170}171#endif172 173static inline cate_t catu_make_entry(dma_addr_t addr)174{175 return addr ? CATU_VALID_ENTRY(addr) : 0;176}177 178/*179 * catu_populate_table : Populate the given CATU table.180 * The table is always populated as a circular table.181 * i.e, the "prev" link of the "first" table points to the "last"182 * table and the "next" link of the "last" table points to the183 * "first" table. The buffer should be made linear by calling184 * catu_set_table().185 */186static void187catu_populate_table(struct tmc_sg_table *catu_table)188{189 int i;190 int sys_pidx; /* Index to current system data page */191 int catu_pidx; /* Index of CATU page within the system data page */192 unsigned long offset, buf_size, table_end;193 dma_addr_t data_daddr;194 dma_addr_t prev_taddr, next_taddr, cur_taddr;195 cate_t *table_ptr, *next_table;196 197 buf_size = tmc_sg_table_buf_size(catu_table);198 sys_pidx = catu_pidx = 0;199 offset = 0;200 201 table_ptr = catu_get_table(catu_table, 0, &cur_taddr);202 prev_taddr = 0; /* Prev link for the first table */203 204 while (offset < buf_size) {205 /*206 * The @offset is always 1M aligned here and we have an207 * empty table @table_ptr to fill. Each table can address208 * upto 1MB data buffer. The last table may have fewer209 * entries if the buffer size is not aligned.210 */211 table_end = (offset + SZ_1M) < buf_size ?212 (offset + SZ_1M) : buf_size;213 for (i = 0; offset < table_end;214 i++, offset += CATU_PAGE_SIZE) {215 216 data_daddr = catu_table->data_pages.daddrs[sys_pidx] +217 catu_pidx * CATU_PAGE_SIZE;218 catu_dbg(catu_table->dev,219 "[table %5ld:%03d] 0x%llx\n",220 (offset >> 20), i, data_daddr);221 table_ptr[i] = catu_make_entry(data_daddr);222 /* Move the pointers for data pages */223 catu_pidx = (catu_pidx + 1) % CATU_PAGES_PER_SYSPAGE;224 if (catu_pidx == 0)225 sys_pidx++;226 }227 228 /*229 * If we have finished all the valid entries, fill the rest of230 * the table (i.e, last table page) with invalid entries,231 * to fail the lookups.232 */233 if (offset == buf_size) {234 memset(&table_ptr[i], 0,235 sizeof(cate_t) * (CATU_PTRS_PER_PAGE - i));236 next_taddr = 0;237 } else {238 next_table = catu_get_table(catu_table,239 offset, &next_taddr);240 }241 242 table_ptr[CATU_LINK_PREV] = catu_make_entry(prev_taddr);243 table_ptr[CATU_LINK_NEXT] = catu_make_entry(next_taddr);244 245 catu_dbg(catu_table->dev,246 "[table%5ld]: Cur: 0x%llx Prev: 0x%llx, Next: 0x%llx\n",247 (offset >> 20) - 1, cur_taddr, prev_taddr, next_taddr);248 249 /* Update the prev/next addresses */250 if (next_taddr) {251 prev_taddr = cur_taddr;252 cur_taddr = next_taddr;253 table_ptr = next_table;254 }255 }256 257 /* Sync the table for device */258 tmc_sg_table_sync_table(catu_table);259}260 261static struct tmc_sg_table *262catu_init_sg_table(struct device *catu_dev, int node,263 ssize_t size, void **pages)264{265 int nr_tpages;266 struct tmc_sg_table *catu_table;267 268 /*269 * Each table can address upto 1MB and we can have270 * CATU_PAGES_PER_SYSPAGE tables in a system page.271 */272 nr_tpages = DIV_ROUND_UP(size, SZ_1M) / CATU_PAGES_PER_SYSPAGE;273 catu_table = tmc_alloc_sg_table(catu_dev, node, nr_tpages,274 size >> PAGE_SHIFT, pages);275 if (IS_ERR(catu_table))276 return catu_table;277 278 catu_populate_table(catu_table);279 dev_dbg(catu_dev,280 "Setup table %p, size %ldKB, %d table pages\n",281 catu_table, (unsigned long)size >> 10, nr_tpages);282 catu_dump_table(catu_table);283 return catu_table;284}285 286static void catu_free_etr_buf(struct etr_buf *etr_buf)287{288 struct catu_etr_buf *catu_buf;289 290 if (!etr_buf || etr_buf->mode != ETR_MODE_CATU || !etr_buf->private)291 return;292 293 catu_buf = etr_buf->private;294 tmc_free_sg_table(catu_buf->catu_table);295 kfree(catu_buf);296}297 298static ssize_t catu_get_data_etr_buf(struct etr_buf *etr_buf, u64 offset,299 size_t len, char **bufpp)300{301 struct catu_etr_buf *catu_buf = etr_buf->private;302 303 return tmc_sg_table_get_data(catu_buf->catu_table, offset, len, bufpp);304}305 306static void catu_sync_etr_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp)307{308 struct catu_etr_buf *catu_buf = etr_buf->private;309 struct tmc_sg_table *catu_table = catu_buf->catu_table;310 u64 r_offset, w_offset;311 312 /*313 * ETR started off at etr_buf->hwaddr. Convert the RRP/RWP to314 * offsets within the trace buffer.315 */316 r_offset = rrp - etr_buf->hwaddr;317 w_offset = rwp - etr_buf->hwaddr;318 319 if (!etr_buf->full) {320 etr_buf->len = w_offset - r_offset;321 if (w_offset < r_offset)322 etr_buf->len += etr_buf->size;323 } else {324 etr_buf->len = etr_buf->size;325 }326 327 etr_buf->offset = r_offset;328 tmc_sg_table_sync_data_range(catu_table, r_offset, etr_buf->len);329}330 331static int catu_alloc_etr_buf(struct tmc_drvdata *tmc_drvdata,332 struct etr_buf *etr_buf, int node, void **pages)333{334 struct coresight_device *csdev;335 struct tmc_sg_table *catu_table;336 struct catu_etr_buf *catu_buf;337 338 csdev = tmc_etr_get_catu_device(tmc_drvdata);339 if (!csdev)340 return -ENODEV;341 catu_buf = kzalloc(sizeof(*catu_buf), GFP_KERNEL);342 if (!catu_buf)343 return -ENOMEM;344 345 catu_table = catu_init_sg_table(&csdev->dev, node,346 etr_buf->size, pages);347 if (IS_ERR(catu_table)) {348 kfree(catu_buf);349 return PTR_ERR(catu_table);350 }351 352 etr_buf->mode = ETR_MODE_CATU;353 etr_buf->private = catu_buf;354 etr_buf->hwaddr = CATU_DEFAULT_INADDR;355 356 catu_buf->catu_table = catu_table;357 /* Get the table base address */358 catu_buf->sladdr = catu_table->table_daddr;359 360 return 0;361}362 363static const struct etr_buf_operations etr_catu_buf_ops = {364 .alloc = catu_alloc_etr_buf,365 .free = catu_free_etr_buf,366 .sync = catu_sync_etr_buf,367 .get_data = catu_get_data_etr_buf,368};369 370static struct attribute *catu_mgmt_attrs[] = {371 coresight_simple_reg32(devid, CORESIGHT_DEVID),372 coresight_simple_reg32(control, CATU_CONTROL),373 coresight_simple_reg32(status, CATU_STATUS),374 coresight_simple_reg32(mode, CATU_MODE),375 coresight_simple_reg32(axictrl, CATU_AXICTRL),376 coresight_simple_reg32(irqen, CATU_IRQEN),377 coresight_simple_reg64(sladdr, CATU_SLADDRLO, CATU_SLADDRHI),378 coresight_simple_reg64(inaddr, CATU_INADDRLO, CATU_INADDRHI),379 NULL,380};381 382static const struct attribute_group catu_mgmt_group = {383 .attrs = catu_mgmt_attrs,384 .name = "mgmt",385};386 387static const struct attribute_group *catu_groups[] = {388 &catu_mgmt_group,389 NULL,390};391 392 393static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)394{395 struct csdev_access *csa = &drvdata->csdev->access;396 397 return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);398}399 400static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,401 void *data)402{403 int rc;404 u32 control, mode;405 struct etr_buf *etr_buf = NULL;406 struct device *dev = &drvdata->csdev->dev;407 struct coresight_device *csdev = drvdata->csdev;408 struct coresight_device *etrdev;409 union coresight_dev_subtype etr_subtype = {410 .sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM411 };412 413 if (catu_wait_for_ready(drvdata))414 dev_warn(dev, "Timeout while waiting for READY\n");415 416 control = catu_read_control(drvdata);417 if (control & BIT(CATU_CONTROL_ENABLE)) {418 dev_warn(dev, "CATU is already enabled\n");419 return -EBUSY;420 }421 422 rc = coresight_claim_device_unlocked(csdev);423 if (rc)424 return rc;425 426 etrdev = coresight_find_input_type(427 csdev->pdata, CORESIGHT_DEV_TYPE_SINK, etr_subtype);428 if (etrdev) {429 etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, data);430 if (IS_ERR(etr_buf))431 return PTR_ERR(etr_buf);432 }433 control |= BIT(CATU_CONTROL_ENABLE);434 435 if (etr_buf && etr_buf->mode == ETR_MODE_CATU) {436 struct catu_etr_buf *catu_buf = etr_buf->private;437 438 mode = CATU_MODE_TRANSLATE;439 catu_write_axictrl(drvdata, CATU_OS_AXICTRL);440 catu_write_sladdr(drvdata, catu_buf->sladdr);441 catu_write_inaddr(drvdata, CATU_DEFAULT_INADDR);442 } else {443 mode = CATU_MODE_PASS_THROUGH;444 catu_write_sladdr(drvdata, 0);445 catu_write_inaddr(drvdata, 0);446 }447 448 catu_write_irqen(drvdata, 0);449 catu_write_mode(drvdata, mode);450 catu_write_control(drvdata, control);451 dev_dbg(dev, "Enabled in %s mode\n",452 (mode == CATU_MODE_PASS_THROUGH) ?453 "Pass through" :454 "Translate");455 return 0;456}457 458static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,459 void *data)460{461 int rc;462 struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);463 464 CS_UNLOCK(catu_drvdata->base);465 rc = catu_enable_hw(catu_drvdata, mode, data);466 CS_LOCK(catu_drvdata->base);467 return rc;468}469 470static int catu_disable_hw(struct catu_drvdata *drvdata)471{472 int rc = 0;473 struct device *dev = &drvdata->csdev->dev;474 struct coresight_device *csdev = drvdata->csdev;475 476 catu_write_control(drvdata, 0);477 coresight_disclaim_device_unlocked(csdev);478 if (catu_wait_for_ready(drvdata)) {479 dev_info(dev, "Timeout while waiting for READY\n");480 rc = -EAGAIN;481 }482 483 dev_dbg(dev, "Disabled\n");484 return rc;485}486 487static int catu_disable(struct coresight_device *csdev, void *__unused)488{489 int rc;490 struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);491 492 CS_UNLOCK(catu_drvdata->base);493 rc = catu_disable_hw(catu_drvdata);494 CS_LOCK(catu_drvdata->base);495 return rc;496}497 498static const struct coresight_ops_helper catu_helper_ops = {499 .enable = catu_enable,500 .disable = catu_disable,501};502 503static const struct coresight_ops catu_ops = {504 .helper_ops = &catu_helper_ops,505};506 507static int __catu_probe(struct device *dev, struct resource *res)508{509 int ret = 0;510 u32 dma_mask;511 struct catu_drvdata *drvdata = dev_get_drvdata(dev);512 struct coresight_desc catu_desc;513 struct coresight_platform_data *pdata = NULL;514 void __iomem *base;515 516 catu_desc.name = coresight_alloc_device_name(&catu_devs, dev);517 if (!catu_desc.name)518 return -ENOMEM;519 520 base = devm_ioremap_resource(dev, res);521 if (IS_ERR(base)) {522 ret = PTR_ERR(base);523 goto out;524 }525 526 /* Setup dma mask for the device */527 dma_mask = readl_relaxed(base + CORESIGHT_DEVID) & 0x3f;528 switch (dma_mask) {529 case 32:530 case 40:531 case 44:532 case 48:533 case 52:534 case 56:535 case 64:536 break;537 default:538 /* Default to the 40bits as supported by TMC-ETR */539 dma_mask = 40;540 }541 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_mask));542 if (ret)543 goto out;544 545 pdata = coresight_get_platform_data(dev);546 if (IS_ERR(pdata)) {547 ret = PTR_ERR(pdata);548 goto out;549 }550 dev->platform_data = pdata;551 552 drvdata->base = base;553 catu_desc.access = CSDEV_ACCESS_IOMEM(base);554 catu_desc.pdata = pdata;555 catu_desc.dev = dev;556 catu_desc.groups = catu_groups;557 catu_desc.type = CORESIGHT_DEV_TYPE_HELPER;558 catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;559 catu_desc.ops = &catu_ops;560 561 drvdata->csdev = coresight_register(&catu_desc);562 if (IS_ERR(drvdata->csdev))563 ret = PTR_ERR(drvdata->csdev);564out:565 return ret;566}567 568static int catu_probe(struct amba_device *adev, const struct amba_id *id)569{570 struct catu_drvdata *drvdata;571 int ret;572 573 drvdata = devm_kzalloc(&adev->dev, sizeof(*drvdata), GFP_KERNEL);574 if (!drvdata)575 return -ENOMEM;576 577 amba_set_drvdata(adev, drvdata);578 ret = __catu_probe(&adev->dev, &adev->res);579 if (!ret)580 pm_runtime_put(&adev->dev);581 582 return ret;583}584 585static void __catu_remove(struct device *dev)586{587 struct catu_drvdata *drvdata = dev_get_drvdata(dev);588 589 coresight_unregister(drvdata->csdev);590}591 592static void catu_remove(struct amba_device *adev)593{594 __catu_remove(&adev->dev);595}596 597static struct amba_id catu_ids[] = {598 CS_AMBA_ID(0x000bb9ee),599 {},600};601 602MODULE_DEVICE_TABLE(amba, catu_ids);603 604static struct amba_driver catu_driver = {605 .drv = {606 .name = "coresight-catu",607 .suppress_bind_attrs = true,608 },609 .probe = catu_probe,610 .remove = catu_remove,611 .id_table = catu_ids,612};613 614static int catu_platform_probe(struct platform_device *pdev)615{616 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);617 struct catu_drvdata *drvdata;618 int ret = 0;619 620 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);621 if (!drvdata)622 return -ENOMEM;623 624 drvdata->pclk = coresight_get_enable_apb_pclk(&pdev->dev);625 if (IS_ERR(drvdata->pclk))626 return -ENODEV;627 628 pm_runtime_get_noresume(&pdev->dev);629 pm_runtime_set_active(&pdev->dev);630 pm_runtime_enable(&pdev->dev);631 632 dev_set_drvdata(&pdev->dev, drvdata);633 ret = __catu_probe(&pdev->dev, res);634 pm_runtime_put(&pdev->dev);635 if (ret) {636 pm_runtime_disable(&pdev->dev);637 if (!IS_ERR_OR_NULL(drvdata->pclk))638 clk_put(drvdata->pclk);639 }640 641 return ret;642}643 644static void catu_platform_remove(struct platform_device *pdev)645{646 struct catu_drvdata *drvdata = dev_get_drvdata(&pdev->dev);647 648 if (WARN_ON(!drvdata))649 return;650 651 __catu_remove(&pdev->dev);652 pm_runtime_disable(&pdev->dev);653 if (!IS_ERR_OR_NULL(drvdata->pclk))654 clk_put(drvdata->pclk);655}656 657#ifdef CONFIG_PM658static int catu_runtime_suspend(struct device *dev)659{660 struct catu_drvdata *drvdata = dev_get_drvdata(dev);661 662 if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))663 clk_disable_unprepare(drvdata->pclk);664 return 0;665}666 667static int catu_runtime_resume(struct device *dev)668{669 struct catu_drvdata *drvdata = dev_get_drvdata(dev);670 671 if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))672 clk_prepare_enable(drvdata->pclk);673 return 0;674}675#endif676 677static const struct dev_pm_ops catu_dev_pm_ops = {678 SET_RUNTIME_PM_OPS(catu_runtime_suspend, catu_runtime_resume, NULL)679};680 681#ifdef CONFIG_ACPI682static const struct acpi_device_id catu_acpi_ids[] = {683 {"ARMHC9CA", 0, 0, 0}, /* ARM CoreSight CATU */684 {},685};686 687MODULE_DEVICE_TABLE(acpi, catu_acpi_ids);688#endif689 690static struct platform_driver catu_platform_driver = {691 .probe = catu_platform_probe,692 .remove_new = catu_platform_remove,693 .driver = {694 .name = "coresight-catu-platform",695 .acpi_match_table = ACPI_PTR(catu_acpi_ids),696 .suppress_bind_attrs = true,697 .pm = &catu_dev_pm_ops,698 },699};700 701static int __init catu_init(void)702{703 int ret;704 705 ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver);706 tmc_etr_set_catu_ops(&etr_catu_buf_ops);707 return ret;708}709 710static void __exit catu_exit(void)711{712 tmc_etr_remove_catu_ops();713 coresight_remove_driver(&catu_driver, &catu_platform_driver);714}715 716module_init(catu_init);717module_exit(catu_exit);718 719MODULE_AUTHOR("Suzuki K Poulose <suzuki.poulose@arm.com>");720MODULE_DESCRIPTION("Arm CoreSight Address Translation Unit (CATU) Driver");721MODULE_LICENSE("GPL v2");722