xref: /openbmc/linux/drivers/hwtracing/coresight/coresight-catu.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1fcacb5c1SSuzuki K Poulose // SPDX-License-Identifier: GPL-2.0
2fcacb5c1SSuzuki K Poulose /*
3fcacb5c1SSuzuki K Poulose  * Copyright (C) 2018 Arm Limited. All rights reserved.
4fcacb5c1SSuzuki K Poulose  *
5fcacb5c1SSuzuki K Poulose  * Coresight Address Translation Unit support
6fcacb5c1SSuzuki K Poulose  *
7fcacb5c1SSuzuki K Poulose  * Author: Suzuki K Poulose <suzuki.poulose@arm.com>
8fcacb5c1SSuzuki K Poulose  */
9fcacb5c1SSuzuki K Poulose 
10fcacb5c1SSuzuki K Poulose #include <linux/amba/bus.h>
11fcacb5c1SSuzuki K Poulose #include <linux/device.h>
12fcacb5c1SSuzuki K Poulose #include <linux/dma-mapping.h>
13fcacb5c1SSuzuki K Poulose #include <linux/io.h>
14fcacb5c1SSuzuki K Poulose #include <linux/kernel.h>
15fcacb5c1SSuzuki K Poulose #include <linux/slab.h>
16fcacb5c1SSuzuki K Poulose 
17fcacb5c1SSuzuki K Poulose #include "coresight-catu.h"
18fcacb5c1SSuzuki K Poulose #include "coresight-priv.h"
198ed536b1SSuzuki K Poulose #include "coresight-tmc.h"
20fcacb5c1SSuzuki K Poulose 
21fcacb5c1SSuzuki K Poulose #define csdev_to_catu_drvdata(csdev)	\
22fcacb5c1SSuzuki K Poulose 	dev_get_drvdata(csdev->dev.parent)
23fcacb5c1SSuzuki K Poulose 
248ed536b1SSuzuki K Poulose /* Verbose output for CATU table contents */
258ed536b1SSuzuki K Poulose #ifdef CATU_DEBUG
268ed536b1SSuzuki K Poulose #define catu_dbg(x, ...) dev_dbg(x, __VA_ARGS__)
278ed536b1SSuzuki K Poulose #else
288ed536b1SSuzuki K Poulose #define catu_dbg(x, ...) do {} while (0)
298ed536b1SSuzuki K Poulose #endif
308ed536b1SSuzuki K Poulose 
310f5f9b6bSSuzuki K Poulose DEFINE_CORESIGHT_DEVLIST(catu_devs, "catu");
320f5f9b6bSSuzuki K Poulose 
33434d611cSSuzuki K Poulose struct catu_etr_buf {
34434d611cSSuzuki K Poulose 	struct tmc_sg_table *catu_table;
35434d611cSSuzuki K Poulose 	dma_addr_t sladdr;
36434d611cSSuzuki K Poulose };
37434d611cSSuzuki K Poulose 
388ed536b1SSuzuki K Poulose /*
398ed536b1SSuzuki K Poulose  * CATU uses a page size of 4KB for page tables as well as data pages.
408ed536b1SSuzuki K Poulose  * Each 64bit entry in the table has the following format.
418ed536b1SSuzuki K Poulose  *
428ed536b1SSuzuki K Poulose  *	63			12	1  0
438ed536b1SSuzuki K Poulose  *	------------------------------------
448ed536b1SSuzuki K Poulose  *	|	 Address [63-12] | SBZ	| V|
458ed536b1SSuzuki K Poulose  *	------------------------------------
468ed536b1SSuzuki K Poulose  *
478ed536b1SSuzuki K Poulose  * Where bit[0] V indicates if the address is valid or not.
488ed536b1SSuzuki K Poulose  * Each 4K table pages have upto 256 data page pointers, taking upto 2K
498ed536b1SSuzuki K Poulose  * size. There are two Link pointers, pointing to the previous and next
508ed536b1SSuzuki K Poulose  * table pages respectively at the end of the 4K page. (i.e, entry 510
518ed536b1SSuzuki K Poulose  * and 511).
528ed536b1SSuzuki K Poulose  *  E.g, a table of two pages could look like :
538ed536b1SSuzuki K Poulose  *
548ed536b1SSuzuki K Poulose  *                 Table Page 0               Table Page 1
558ed536b1SSuzuki K Poulose  * SLADDR ===> x------------------x  x--> x-----------------x
568ed536b1SSuzuki K Poulose  * INADDR    ->|  Page 0      | V |  |    | Page 256    | V | <- INADDR+1M
578ed536b1SSuzuki K Poulose  *             |------------------|  |    |-----------------|
588ed536b1SSuzuki K Poulose  * INADDR+4K ->|  Page 1      | V |  |    |                 |
598ed536b1SSuzuki K Poulose  *             |------------------|  |    |-----------------|
608ed536b1SSuzuki K Poulose  *             |  Page 2      | V |  |    |                 |
618ed536b1SSuzuki K Poulose  *             |------------------|  |    |-----------------|
628ed536b1SSuzuki K Poulose  *             |   ...        | V |  |    |    ...          |
638ed536b1SSuzuki K Poulose  *             |------------------|  |    |-----------------|
648ed536b1SSuzuki K Poulose  * INADDR+1020K|  Page 255    | V |  |    |   Page 511  | V |
658ed536b1SSuzuki K Poulose  * SLADDR+2K==>|------------------|  |    |-----------------|
668ed536b1SSuzuki K Poulose  *             |  UNUSED      |   |  |    |                 |
678ed536b1SSuzuki K Poulose  *             |------------------|  |    |                 |
688ed536b1SSuzuki K Poulose  *             |  UNUSED      |   |  |    |                 |
698ed536b1SSuzuki K Poulose  *             |------------------|  |    |                 |
708ed536b1SSuzuki K Poulose  *             |    ...       |   |  |    |                 |
718ed536b1SSuzuki K Poulose  *             |------------------|  |    |-----------------|
728ed536b1SSuzuki K Poulose  *             |   IGNORED    | 0 |  |    | Table Page 0| 1 |
738ed536b1SSuzuki K Poulose  *             |------------------|  |    |-----------------|
748ed536b1SSuzuki K Poulose  *             |  Table Page 1| 1 |--x    | IGNORED     | 0 |
758ed536b1SSuzuki K Poulose  *             x------------------x       x-----------------x
768ed536b1SSuzuki K Poulose  * SLADDR+4K==>
778ed536b1SSuzuki K Poulose  *
788ed536b1SSuzuki K Poulose  * The base input address (used by the ETR, programmed in INADDR_{LO,HI})
798ed536b1SSuzuki K Poulose  * must be aligned to 1MB (the size addressable by a single page table).
808ed536b1SSuzuki K Poulose  * The CATU maps INADDR{LO:HI} to the first page in the table pointed
818ed536b1SSuzuki K Poulose  * to by SLADDR{LO:HI} and so on.
828ed536b1SSuzuki K Poulose  *
838ed536b1SSuzuki K Poulose  */
848ed536b1SSuzuki K Poulose typedef u64 cate_t;
858ed536b1SSuzuki K Poulose 
868ed536b1SSuzuki K Poulose #define CATU_PAGE_SHIFT		12
878ed536b1SSuzuki K Poulose #define CATU_PAGE_SIZE		(1UL << CATU_PAGE_SHIFT)
888ed536b1SSuzuki K Poulose #define CATU_PAGES_PER_SYSPAGE	(PAGE_SIZE / CATU_PAGE_SIZE)
898ed536b1SSuzuki K Poulose 
908ed536b1SSuzuki K Poulose /* Page pointers are only allocated in the first 2K half */
918ed536b1SSuzuki K Poulose #define CATU_PTRS_PER_PAGE	((CATU_PAGE_SIZE >> 1) / sizeof(cate_t))
928ed536b1SSuzuki K Poulose #define CATU_PTRS_PER_SYSPAGE	(CATU_PAGES_PER_SYSPAGE * CATU_PTRS_PER_PAGE)
938ed536b1SSuzuki K Poulose #define CATU_LINK_PREV		((CATU_PAGE_SIZE / sizeof(cate_t)) - 2)
948ed536b1SSuzuki K Poulose #define CATU_LINK_NEXT		((CATU_PAGE_SIZE / sizeof(cate_t)) - 1)
958ed536b1SSuzuki K Poulose 
968ed536b1SSuzuki K Poulose #define CATU_ADDR_SHIFT		12
978ed536b1SSuzuki K Poulose #define CATU_ADDR_MASK		~(((cate_t)1 << CATU_ADDR_SHIFT) - 1)
988ed536b1SSuzuki K Poulose #define CATU_ENTRY_VALID	((cate_t)0x1)
998ed536b1SSuzuki K Poulose #define CATU_VALID_ENTRY(addr) \
1008ed536b1SSuzuki K Poulose 	(((cate_t)(addr) & CATU_ADDR_MASK) | CATU_ENTRY_VALID)
1018ed536b1SSuzuki K Poulose #define CATU_ENTRY_ADDR(entry)	((cate_t)(entry) & ~((cate_t)CATU_ENTRY_VALID))
1028ed536b1SSuzuki K Poulose 
103434d611cSSuzuki K Poulose /* CATU expects the INADDR to be aligned to 1M. */
104434d611cSSuzuki K Poulose #define CATU_DEFAULT_INADDR	(1ULL << 20)
105434d611cSSuzuki K Poulose 
1068ed536b1SSuzuki K Poulose /*
1078ed536b1SSuzuki K Poulose  * catu_get_table : Retrieve the table pointers for the given @offset
1088ed536b1SSuzuki K Poulose  * within the buffer. The buffer is wrapped around to a valid offset.
1098ed536b1SSuzuki K Poulose  *
1108ed536b1SSuzuki K Poulose  * Returns : The CPU virtual address for the beginning of the table
1118ed536b1SSuzuki K Poulose  * containing the data page pointer for @offset. If @daddrp is not NULL,
1128ed536b1SSuzuki K Poulose  * @daddrp points the DMA address of the beginning of the table.
1138ed536b1SSuzuki K Poulose  */
catu_get_table(struct tmc_sg_table * catu_table,unsigned long offset,dma_addr_t * daddrp)1148ed536b1SSuzuki K Poulose static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
1158ed536b1SSuzuki K Poulose 				     unsigned long offset,
1168ed536b1SSuzuki K Poulose 				     dma_addr_t *daddrp)
1178ed536b1SSuzuki K Poulose {
1188ed536b1SSuzuki K Poulose 	unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
1198ed536b1SSuzuki K Poulose 	unsigned int table_nr, pg_idx, pg_offset;
1208ed536b1SSuzuki K Poulose 	struct tmc_pages *table_pages = &catu_table->table_pages;
1218ed536b1SSuzuki K Poulose 	void *ptr;
1228ed536b1SSuzuki K Poulose 
1238ed536b1SSuzuki K Poulose 	/* Make sure offset is within the range */
1248ed536b1SSuzuki K Poulose 	offset %= buf_size;
1258ed536b1SSuzuki K Poulose 
1268ed536b1SSuzuki K Poulose 	/*
1278ed536b1SSuzuki K Poulose 	 * Each table can address 1MB and a single kernel page can
1288ed536b1SSuzuki K Poulose 	 * contain "CATU_PAGES_PER_SYSPAGE" CATU tables.
1298ed536b1SSuzuki K Poulose 	 */
1308ed536b1SSuzuki K Poulose 	table_nr = offset >> 20;
1318ed536b1SSuzuki K Poulose 	/* Find the table page where the table_nr lies in */
1328ed536b1SSuzuki K Poulose 	pg_idx = table_nr / CATU_PAGES_PER_SYSPAGE;
1338ed536b1SSuzuki K Poulose 	pg_offset = (table_nr % CATU_PAGES_PER_SYSPAGE) * CATU_PAGE_SIZE;
1348ed536b1SSuzuki K Poulose 	if (daddrp)
1358ed536b1SSuzuki K Poulose 		*daddrp = table_pages->daddrs[pg_idx] + pg_offset;
1368ed536b1SSuzuki K Poulose 	ptr = page_address(table_pages->pages[pg_idx]);
1378ed536b1SSuzuki K Poulose 	return (cate_t *)((unsigned long)ptr + pg_offset);
1388ed536b1SSuzuki K Poulose }
1398ed536b1SSuzuki K Poulose 
1408ed536b1SSuzuki K Poulose #ifdef CATU_DEBUG
catu_dump_table(struct tmc_sg_table * catu_table)1418ed536b1SSuzuki K Poulose static void catu_dump_table(struct tmc_sg_table *catu_table)
1428ed536b1SSuzuki K Poulose {
1438ed536b1SSuzuki K Poulose 	int i;
1448ed536b1SSuzuki K Poulose 	cate_t *table;
1458ed536b1SSuzuki K Poulose 	unsigned long table_end, buf_size, offset = 0;
1468ed536b1SSuzuki K Poulose 
1478ed536b1SSuzuki K Poulose 	buf_size = tmc_sg_table_buf_size(catu_table);
1488ed536b1SSuzuki K Poulose 	dev_dbg(catu_table->dev,
1498ed536b1SSuzuki K Poulose 		"Dump table %p, tdaddr: %llx\n",
1508ed536b1SSuzuki K Poulose 		catu_table, catu_table->table_daddr);
1518ed536b1SSuzuki K Poulose 
1528ed536b1SSuzuki K Poulose 	while (offset < buf_size) {
1538ed536b1SSuzuki K Poulose 		table_end = offset + SZ_1M < buf_size ?
1548ed536b1SSuzuki K Poulose 			    offset + SZ_1M : buf_size;
1558ed536b1SSuzuki K Poulose 		table = catu_get_table(catu_table, offset, NULL);
1568ed536b1SSuzuki K Poulose 		for (i = 0; offset < table_end; i++, offset += CATU_PAGE_SIZE)
1578ed536b1SSuzuki K Poulose 			dev_dbg(catu_table->dev, "%d: %llx\n", i, table[i]);
1588ed536b1SSuzuki K Poulose 		dev_dbg(catu_table->dev, "Prev : %llx, Next: %llx\n",
1598ed536b1SSuzuki K Poulose 			table[CATU_LINK_PREV], table[CATU_LINK_NEXT]);
1608ed536b1SSuzuki K Poulose 		dev_dbg(catu_table->dev, "== End of sub-table ===");
1618ed536b1SSuzuki K Poulose 	}
1628ed536b1SSuzuki K Poulose 	dev_dbg(catu_table->dev, "== End of Table ===");
1638ed536b1SSuzuki K Poulose }
1648ed536b1SSuzuki K Poulose 
1658ed536b1SSuzuki K Poulose #else
catu_dump_table(struct tmc_sg_table * catu_table)1668ed536b1SSuzuki K Poulose static inline void catu_dump_table(struct tmc_sg_table *catu_table)
1678ed536b1SSuzuki K Poulose {
1688ed536b1SSuzuki K Poulose }
1698ed536b1SSuzuki K Poulose #endif
1708ed536b1SSuzuki K Poulose 
catu_make_entry(dma_addr_t addr)1718ed536b1SSuzuki K Poulose static inline cate_t catu_make_entry(dma_addr_t addr)
1728ed536b1SSuzuki K Poulose {
1738ed536b1SSuzuki K Poulose 	return addr ? CATU_VALID_ENTRY(addr) : 0;
1748ed536b1SSuzuki K Poulose }
1758ed536b1SSuzuki K Poulose 
1768ed536b1SSuzuki K Poulose /*
1778ed536b1SSuzuki K Poulose  * catu_populate_table : Populate the given CATU table.
1788ed536b1SSuzuki K Poulose  * The table is always populated as a circular table.
1798ed536b1SSuzuki K Poulose  * i.e, the "prev" link of the "first" table points to the "last"
1808ed536b1SSuzuki K Poulose  * table and the "next" link of the "last" table points to the
1818ed536b1SSuzuki K Poulose  * "first" table. The buffer should be made linear by calling
1828ed536b1SSuzuki K Poulose  * catu_set_table().
1838ed536b1SSuzuki K Poulose  */
1848ed536b1SSuzuki K Poulose static void
catu_populate_table(struct tmc_sg_table * catu_table)1858ed536b1SSuzuki K Poulose catu_populate_table(struct tmc_sg_table *catu_table)
1868ed536b1SSuzuki K Poulose {
1878ed536b1SSuzuki K Poulose 	int i;
1888ed536b1SSuzuki K Poulose 	int sys_pidx;	/* Index to current system data page */
1898ed536b1SSuzuki K Poulose 	int catu_pidx;	/* Index of CATU page within the system data page */
1908ed536b1SSuzuki K Poulose 	unsigned long offset, buf_size, table_end;
1918ed536b1SSuzuki K Poulose 	dma_addr_t data_daddr;
1928ed536b1SSuzuki K Poulose 	dma_addr_t prev_taddr, next_taddr, cur_taddr;
1938ed536b1SSuzuki K Poulose 	cate_t *table_ptr, *next_table;
1948ed536b1SSuzuki K Poulose 
1958ed536b1SSuzuki K Poulose 	buf_size = tmc_sg_table_buf_size(catu_table);
1968ed536b1SSuzuki K Poulose 	sys_pidx = catu_pidx = 0;
1978ed536b1SSuzuki K Poulose 	offset = 0;
1988ed536b1SSuzuki K Poulose 
1998ed536b1SSuzuki K Poulose 	table_ptr = catu_get_table(catu_table, 0, &cur_taddr);
2008ed536b1SSuzuki K Poulose 	prev_taddr = 0;	/* Prev link for the first table */
2018ed536b1SSuzuki K Poulose 
2028ed536b1SSuzuki K Poulose 	while (offset < buf_size) {
2038ed536b1SSuzuki K Poulose 		/*
2048ed536b1SSuzuki K Poulose 		 * The @offset is always 1M aligned here and we have an
2058ed536b1SSuzuki K Poulose 		 * empty table @table_ptr to fill. Each table can address
2068ed536b1SSuzuki K Poulose 		 * upto 1MB data buffer. The last table may have fewer
2078ed536b1SSuzuki K Poulose 		 * entries if the buffer size is not aligned.
2088ed536b1SSuzuki K Poulose 		 */
2098ed536b1SSuzuki K Poulose 		table_end = (offset + SZ_1M) < buf_size ?
2108ed536b1SSuzuki K Poulose 			    (offset + SZ_1M) : buf_size;
2118ed536b1SSuzuki K Poulose 		for (i = 0; offset < table_end;
2128ed536b1SSuzuki K Poulose 		     i++, offset += CATU_PAGE_SIZE) {
2138ed536b1SSuzuki K Poulose 
2148ed536b1SSuzuki K Poulose 			data_daddr = catu_table->data_pages.daddrs[sys_pidx] +
2158ed536b1SSuzuki K Poulose 				     catu_pidx * CATU_PAGE_SIZE;
2168ed536b1SSuzuki K Poulose 			catu_dbg(catu_table->dev,
2178ed536b1SSuzuki K Poulose 				"[table %5ld:%03d] 0x%llx\n",
2188ed536b1SSuzuki K Poulose 				(offset >> 20), i, data_daddr);
2198ed536b1SSuzuki K Poulose 			table_ptr[i] = catu_make_entry(data_daddr);
2208ed536b1SSuzuki K Poulose 			/* Move the pointers for data pages */
2218ed536b1SSuzuki K Poulose 			catu_pidx = (catu_pidx + 1) % CATU_PAGES_PER_SYSPAGE;
2228ed536b1SSuzuki K Poulose 			if (catu_pidx == 0)
2238ed536b1SSuzuki K Poulose 				sys_pidx++;
2248ed536b1SSuzuki K Poulose 		}
2258ed536b1SSuzuki K Poulose 
2268ed536b1SSuzuki K Poulose 		/*
2278ed536b1SSuzuki K Poulose 		 * If we have finished all the valid entries, fill the rest of
2288ed536b1SSuzuki K Poulose 		 * the table (i.e, last table page) with invalid entries,
2298ed536b1SSuzuki K Poulose 		 * to fail the lookups.
2308ed536b1SSuzuki K Poulose 		 */
2318ed536b1SSuzuki K Poulose 		if (offset == buf_size) {
2328ed536b1SSuzuki K Poulose 			memset(&table_ptr[i], 0,
2338ed536b1SSuzuki K Poulose 			       sizeof(cate_t) * (CATU_PTRS_PER_PAGE - i));
2348ed536b1SSuzuki K Poulose 			next_taddr = 0;
2358ed536b1SSuzuki K Poulose 		} else {
2368ed536b1SSuzuki K Poulose 			next_table = catu_get_table(catu_table,
2378ed536b1SSuzuki K Poulose 						    offset, &next_taddr);
2388ed536b1SSuzuki K Poulose 		}
2398ed536b1SSuzuki K Poulose 
2408ed536b1SSuzuki K Poulose 		table_ptr[CATU_LINK_PREV] = catu_make_entry(prev_taddr);
2418ed536b1SSuzuki K Poulose 		table_ptr[CATU_LINK_NEXT] = catu_make_entry(next_taddr);
2428ed536b1SSuzuki K Poulose 
2438ed536b1SSuzuki K Poulose 		catu_dbg(catu_table->dev,
2448ed536b1SSuzuki K Poulose 			"[table%5ld]: Cur: 0x%llx Prev: 0x%llx, Next: 0x%llx\n",
2458ed536b1SSuzuki K Poulose 			(offset >> 20) - 1,  cur_taddr, prev_taddr, next_taddr);
2468ed536b1SSuzuki K Poulose 
2478ed536b1SSuzuki K Poulose 		/* Update the prev/next addresses */
2488ed536b1SSuzuki K Poulose 		if (next_taddr) {
2498ed536b1SSuzuki K Poulose 			prev_taddr = cur_taddr;
2508ed536b1SSuzuki K Poulose 			cur_taddr = next_taddr;
2518ed536b1SSuzuki K Poulose 			table_ptr = next_table;
2528ed536b1SSuzuki K Poulose 		}
2538ed536b1SSuzuki K Poulose 	}
2548ed536b1SSuzuki K Poulose 
2558ed536b1SSuzuki K Poulose 	/* Sync the table for device */
2568ed536b1SSuzuki K Poulose 	tmc_sg_table_sync_table(catu_table);
2578ed536b1SSuzuki K Poulose }
2588ed536b1SSuzuki K Poulose 
259434d611cSSuzuki K Poulose static struct tmc_sg_table *
catu_init_sg_table(struct device * catu_dev,int node,ssize_t size,void ** pages)2608ed536b1SSuzuki K Poulose catu_init_sg_table(struct device *catu_dev, int node,
2618ed536b1SSuzuki K Poulose 		   ssize_t size, void **pages)
2628ed536b1SSuzuki K Poulose {
2638ed536b1SSuzuki K Poulose 	int nr_tpages;
2648ed536b1SSuzuki K Poulose 	struct tmc_sg_table *catu_table;
2658ed536b1SSuzuki K Poulose 
2668ed536b1SSuzuki K Poulose 	/*
2678ed536b1SSuzuki K Poulose 	 * Each table can address upto 1MB and we can have
2688ed536b1SSuzuki K Poulose 	 * CATU_PAGES_PER_SYSPAGE tables in a system page.
2698ed536b1SSuzuki K Poulose 	 */
2708ed536b1SSuzuki K Poulose 	nr_tpages = DIV_ROUND_UP(size, SZ_1M) / CATU_PAGES_PER_SYSPAGE;
2718ed536b1SSuzuki K Poulose 	catu_table = tmc_alloc_sg_table(catu_dev, node, nr_tpages,
2728ed536b1SSuzuki K Poulose 					size >> PAGE_SHIFT, pages);
2738ed536b1SSuzuki K Poulose 	if (IS_ERR(catu_table))
2748ed536b1SSuzuki K Poulose 		return catu_table;
2758ed536b1SSuzuki K Poulose 
2768ed536b1SSuzuki K Poulose 	catu_populate_table(catu_table);
2778ed536b1SSuzuki K Poulose 	dev_dbg(catu_dev,
2788ed536b1SSuzuki K Poulose 		"Setup table %p, size %ldKB, %d table pages\n",
2798ed536b1SSuzuki K Poulose 		catu_table, (unsigned long)size >> 10,  nr_tpages);
2808ed536b1SSuzuki K Poulose 	catu_dump_table(catu_table);
2818ed536b1SSuzuki K Poulose 	return catu_table;
2828ed536b1SSuzuki K Poulose }
2838ed536b1SSuzuki K Poulose 
catu_free_etr_buf(struct etr_buf * etr_buf)284434d611cSSuzuki K Poulose static void catu_free_etr_buf(struct etr_buf *etr_buf)
285434d611cSSuzuki K Poulose {
286434d611cSSuzuki K Poulose 	struct catu_etr_buf *catu_buf;
287434d611cSSuzuki K Poulose 
288434d611cSSuzuki K Poulose 	if (!etr_buf || etr_buf->mode != ETR_MODE_CATU || !etr_buf->private)
289434d611cSSuzuki K Poulose 		return;
290434d611cSSuzuki K Poulose 
291434d611cSSuzuki K Poulose 	catu_buf = etr_buf->private;
292434d611cSSuzuki K Poulose 	tmc_free_sg_table(catu_buf->catu_table);
293434d611cSSuzuki K Poulose 	kfree(catu_buf);
294434d611cSSuzuki K Poulose }
295434d611cSSuzuki K Poulose 
catu_get_data_etr_buf(struct etr_buf * etr_buf,u64 offset,size_t len,char ** bufpp)296434d611cSSuzuki K Poulose static ssize_t catu_get_data_etr_buf(struct etr_buf *etr_buf, u64 offset,
297434d611cSSuzuki K Poulose 				     size_t len, char **bufpp)
298434d611cSSuzuki K Poulose {
299434d611cSSuzuki K Poulose 	struct catu_etr_buf *catu_buf = etr_buf->private;
300434d611cSSuzuki K Poulose 
301434d611cSSuzuki K Poulose 	return tmc_sg_table_get_data(catu_buf->catu_table, offset, len, bufpp);
302434d611cSSuzuki K Poulose }
303434d611cSSuzuki K Poulose 
catu_sync_etr_buf(struct etr_buf * etr_buf,u64 rrp,u64 rwp)304434d611cSSuzuki K Poulose static void catu_sync_etr_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp)
305434d611cSSuzuki K Poulose {
306434d611cSSuzuki K Poulose 	struct catu_etr_buf *catu_buf = etr_buf->private;
307434d611cSSuzuki K Poulose 	struct tmc_sg_table *catu_table = catu_buf->catu_table;
308434d611cSSuzuki K Poulose 	u64 r_offset, w_offset;
309434d611cSSuzuki K Poulose 
310434d611cSSuzuki K Poulose 	/*
311434d611cSSuzuki K Poulose 	 * ETR started off at etr_buf->hwaddr. Convert the RRP/RWP to
312434d611cSSuzuki K Poulose 	 * offsets within the trace buffer.
313434d611cSSuzuki K Poulose 	 */
314434d611cSSuzuki K Poulose 	r_offset = rrp - etr_buf->hwaddr;
315434d611cSSuzuki K Poulose 	w_offset = rwp - etr_buf->hwaddr;
316434d611cSSuzuki K Poulose 
317434d611cSSuzuki K Poulose 	if (!etr_buf->full) {
318434d611cSSuzuki K Poulose 		etr_buf->len = w_offset - r_offset;
319434d611cSSuzuki K Poulose 		if (w_offset < r_offset)
320434d611cSSuzuki K Poulose 			etr_buf->len += etr_buf->size;
321434d611cSSuzuki K Poulose 	} else {
322434d611cSSuzuki K Poulose 		etr_buf->len = etr_buf->size;
323434d611cSSuzuki K Poulose 	}
324434d611cSSuzuki K Poulose 
325434d611cSSuzuki K Poulose 	etr_buf->offset = r_offset;
326434d611cSSuzuki K Poulose 	tmc_sg_table_sync_data_range(catu_table, r_offset, etr_buf->len);
327434d611cSSuzuki K Poulose }
328434d611cSSuzuki K Poulose 
catu_alloc_etr_buf(struct tmc_drvdata * tmc_drvdata,struct etr_buf * etr_buf,int node,void ** pages)329434d611cSSuzuki K Poulose static int catu_alloc_etr_buf(struct tmc_drvdata *tmc_drvdata,
330434d611cSSuzuki K Poulose 			      struct etr_buf *etr_buf, int node, void **pages)
331434d611cSSuzuki K Poulose {
332434d611cSSuzuki K Poulose 	struct coresight_device *csdev;
333434d611cSSuzuki K Poulose 	struct tmc_sg_table *catu_table;
334434d611cSSuzuki K Poulose 	struct catu_etr_buf *catu_buf;
335434d611cSSuzuki K Poulose 
336434d611cSSuzuki K Poulose 	csdev = tmc_etr_get_catu_device(tmc_drvdata);
337434d611cSSuzuki K Poulose 	if (!csdev)
338434d611cSSuzuki K Poulose 		return -ENODEV;
339434d611cSSuzuki K Poulose 	catu_buf = kzalloc(sizeof(*catu_buf), GFP_KERNEL);
340434d611cSSuzuki K Poulose 	if (!catu_buf)
341434d611cSSuzuki K Poulose 		return -ENOMEM;
342434d611cSSuzuki K Poulose 
3439dd0a920SSuzuki K Poulose 	catu_table = catu_init_sg_table(&csdev->dev, node,
3449dd0a920SSuzuki K Poulose 					etr_buf->size, pages);
345434d611cSSuzuki K Poulose 	if (IS_ERR(catu_table)) {
346434d611cSSuzuki K Poulose 		kfree(catu_buf);
347434d611cSSuzuki K Poulose 		return PTR_ERR(catu_table);
348434d611cSSuzuki K Poulose 	}
349434d611cSSuzuki K Poulose 
350434d611cSSuzuki K Poulose 	etr_buf->mode = ETR_MODE_CATU;
351434d611cSSuzuki K Poulose 	etr_buf->private = catu_buf;
352434d611cSSuzuki K Poulose 	etr_buf->hwaddr = CATU_DEFAULT_INADDR;
353434d611cSSuzuki K Poulose 
354434d611cSSuzuki K Poulose 	catu_buf->catu_table = catu_table;
355434d611cSSuzuki K Poulose 	/* Get the table base address */
356434d611cSSuzuki K Poulose 	catu_buf->sladdr = catu_table->table_daddr;
357434d611cSSuzuki K Poulose 
358434d611cSSuzuki K Poulose 	return 0;
359434d611cSSuzuki K Poulose }
360434d611cSSuzuki K Poulose 
36166af416dSMian Yousaf Kaukab static const struct etr_buf_operations etr_catu_buf_ops = {
362434d611cSSuzuki K Poulose 	.alloc = catu_alloc_etr_buf,
363434d611cSSuzuki K Poulose 	.free = catu_free_etr_buf,
364434d611cSSuzuki K Poulose 	.sync = catu_sync_etr_buf,
365434d611cSSuzuki K Poulose 	.get_data = catu_get_data_etr_buf,
366434d611cSSuzuki K Poulose };
367434d611cSSuzuki K Poulose 
368fcacb5c1SSuzuki K Poulose static struct attribute *catu_mgmt_attrs[] = {
36908e9fa5fSJames Clark 	coresight_simple_reg32(devid, CORESIGHT_DEVID),
37008e9fa5fSJames Clark 	coresight_simple_reg32(control, CATU_CONTROL),
37108e9fa5fSJames Clark 	coresight_simple_reg32(status, CATU_STATUS),
37208e9fa5fSJames Clark 	coresight_simple_reg32(mode, CATU_MODE),
37308e9fa5fSJames Clark 	coresight_simple_reg32(axictrl, CATU_AXICTRL),
37408e9fa5fSJames Clark 	coresight_simple_reg32(irqen, CATU_IRQEN),
37508e9fa5fSJames Clark 	coresight_simple_reg64(sladdr, CATU_SLADDRLO, CATU_SLADDRHI),
37608e9fa5fSJames Clark 	coresight_simple_reg64(inaddr, CATU_INADDRLO, CATU_INADDRHI),
377fcacb5c1SSuzuki K Poulose 	NULL,
378fcacb5c1SSuzuki K Poulose };
379fcacb5c1SSuzuki K Poulose 
380fcacb5c1SSuzuki K Poulose static const struct attribute_group catu_mgmt_group = {
381fcacb5c1SSuzuki K Poulose 	.attrs = catu_mgmt_attrs,
382fcacb5c1SSuzuki K Poulose 	.name = "mgmt",
383fcacb5c1SSuzuki K Poulose };
384fcacb5c1SSuzuki K Poulose 
385fcacb5c1SSuzuki K Poulose static const struct attribute_group *catu_groups[] = {
386fcacb5c1SSuzuki K Poulose 	&catu_mgmt_group,
387fcacb5c1SSuzuki K Poulose 	NULL,
388fcacb5c1SSuzuki K Poulose };
389fcacb5c1SSuzuki K Poulose 
390fcacb5c1SSuzuki K Poulose 
catu_wait_for_ready(struct catu_drvdata * drvdata)391fcacb5c1SSuzuki K Poulose static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
392fcacb5c1SSuzuki K Poulose {
39302005282SSuzuki K Poulose 	struct csdev_access *csa = &drvdata->csdev->access;
39402005282SSuzuki K Poulose 
39502005282SSuzuki K Poulose 	return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);
396fcacb5c1SSuzuki K Poulose }
397fcacb5c1SSuzuki K Poulose 
catu_enable_hw(struct catu_drvdata * drvdata,enum cs_mode cs_mode,void * data)398*61486528SJames Clark static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
399*61486528SJames Clark 			  void *data)
400fcacb5c1SSuzuki K Poulose {
401f92201b1SSuzuki K Poulose 	int rc;
402434d611cSSuzuki K Poulose 	u32 control, mode;
403*61486528SJames Clark 	struct etr_buf *etr_buf = NULL;
404c95e224fSSuzuki K Poulose 	struct device *dev = &drvdata->csdev->dev;
4058ce00296SSuzuki K Poulose 	struct coresight_device *csdev = drvdata->csdev;
406*61486528SJames Clark 	struct coresight_device *etrdev;
407*61486528SJames Clark 	union coresight_dev_subtype etr_subtype = {
408*61486528SJames Clark 		.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM
409*61486528SJames Clark 	};
410fcacb5c1SSuzuki K Poulose 
411fcacb5c1SSuzuki K Poulose 	if (catu_wait_for_ready(drvdata))
412c95e224fSSuzuki K Poulose 		dev_warn(dev, "Timeout while waiting for READY\n");
413fcacb5c1SSuzuki K Poulose 
414fcacb5c1SSuzuki K Poulose 	control = catu_read_control(drvdata);
415fcacb5c1SSuzuki K Poulose 	if (control & BIT(CATU_CONTROL_ENABLE)) {
416c95e224fSSuzuki K Poulose 		dev_warn(dev, "CATU is already enabled\n");
417fcacb5c1SSuzuki K Poulose 		return -EBUSY;
418fcacb5c1SSuzuki K Poulose 	}
419fcacb5c1SSuzuki K Poulose 
4208ce00296SSuzuki K Poulose 	rc = coresight_claim_device_unlocked(csdev);
421f92201b1SSuzuki K Poulose 	if (rc)
422f92201b1SSuzuki K Poulose 		return rc;
423f92201b1SSuzuki K Poulose 
424*61486528SJames Clark 	etrdev = coresight_find_input_type(
425*61486528SJames Clark 		csdev->pdata, CORESIGHT_DEV_TYPE_SINK, etr_subtype);
426*61486528SJames Clark 	if (etrdev) {
427*61486528SJames Clark 		etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, data);
428*61486528SJames Clark 		if (IS_ERR(etr_buf))
429*61486528SJames Clark 			return PTR_ERR(etr_buf);
430*61486528SJames Clark 	}
431fcacb5c1SSuzuki K Poulose 	control |= BIT(CATU_CONTROL_ENABLE);
432434d611cSSuzuki K Poulose 
433434d611cSSuzuki K Poulose 	if (etr_buf && etr_buf->mode == ETR_MODE_CATU) {
434434d611cSSuzuki K Poulose 		struct catu_etr_buf *catu_buf = etr_buf->private;
435434d611cSSuzuki K Poulose 
436434d611cSSuzuki K Poulose 		mode = CATU_MODE_TRANSLATE;
437434d611cSSuzuki K Poulose 		catu_write_axictrl(drvdata, CATU_OS_AXICTRL);
438434d611cSSuzuki K Poulose 		catu_write_sladdr(drvdata, catu_buf->sladdr);
439434d611cSSuzuki K Poulose 		catu_write_inaddr(drvdata, CATU_DEFAULT_INADDR);
440434d611cSSuzuki K Poulose 	} else {
441434d611cSSuzuki K Poulose 		mode = CATU_MODE_PASS_THROUGH;
442434d611cSSuzuki K Poulose 		catu_write_sladdr(drvdata, 0);
443434d611cSSuzuki K Poulose 		catu_write_inaddr(drvdata, 0);
444434d611cSSuzuki K Poulose 	}
445434d611cSSuzuki K Poulose 
446434d611cSSuzuki K Poulose 	catu_write_irqen(drvdata, 0);
447434d611cSSuzuki K Poulose 	catu_write_mode(drvdata, mode);
448fcacb5c1SSuzuki K Poulose 	catu_write_control(drvdata, control);
449c95e224fSSuzuki K Poulose 	dev_dbg(dev, "Enabled in %s mode\n",
450434d611cSSuzuki K Poulose 		(mode == CATU_MODE_PASS_THROUGH) ?
451434d611cSSuzuki K Poulose 		"Pass through" :
452434d611cSSuzuki K Poulose 		"Translate");
453fcacb5c1SSuzuki K Poulose 	return 0;
454fcacb5c1SSuzuki K Poulose }
455fcacb5c1SSuzuki K Poulose 
catu_enable(struct coresight_device * csdev,enum cs_mode mode,void * data)456*61486528SJames Clark static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
457*61486528SJames Clark 		       void *data)
458fcacb5c1SSuzuki K Poulose {
459fcacb5c1SSuzuki K Poulose 	int rc;
460fcacb5c1SSuzuki K Poulose 	struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
461fcacb5c1SSuzuki K Poulose 
462fcacb5c1SSuzuki K Poulose 	CS_UNLOCK(catu_drvdata->base);
463*61486528SJames Clark 	rc = catu_enable_hw(catu_drvdata, mode, data);
464fcacb5c1SSuzuki K Poulose 	CS_LOCK(catu_drvdata->base);
465fcacb5c1SSuzuki K Poulose 	return rc;
466fcacb5c1SSuzuki K Poulose }
467fcacb5c1SSuzuki K Poulose 
catu_disable_hw(struct catu_drvdata * drvdata)468fcacb5c1SSuzuki K Poulose static int catu_disable_hw(struct catu_drvdata *drvdata)
469fcacb5c1SSuzuki K Poulose {
470fcacb5c1SSuzuki K Poulose 	int rc = 0;
471c95e224fSSuzuki K Poulose 	struct device *dev = &drvdata->csdev->dev;
4728ce00296SSuzuki K Poulose 	struct coresight_device *csdev = drvdata->csdev;
473fcacb5c1SSuzuki K Poulose 
474fcacb5c1SSuzuki K Poulose 	catu_write_control(drvdata, 0);
4758ce00296SSuzuki K Poulose 	coresight_disclaim_device_unlocked(csdev);
476fcacb5c1SSuzuki K Poulose 	if (catu_wait_for_ready(drvdata)) {
477c95e224fSSuzuki K Poulose 		dev_info(dev, "Timeout while waiting for READY\n");
478fcacb5c1SSuzuki K Poulose 		rc = -EAGAIN;
479fcacb5c1SSuzuki K Poulose 	}
480fcacb5c1SSuzuki K Poulose 
481c95e224fSSuzuki K Poulose 	dev_dbg(dev, "Disabled\n");
482fcacb5c1SSuzuki K Poulose 	return rc;
483fcacb5c1SSuzuki K Poulose }
484fcacb5c1SSuzuki K Poulose 
catu_disable(struct coresight_device * csdev,void * __unused)485fcacb5c1SSuzuki K Poulose static int catu_disable(struct coresight_device *csdev, void *__unused)
486fcacb5c1SSuzuki K Poulose {
487fcacb5c1SSuzuki K Poulose 	int rc;
488fcacb5c1SSuzuki K Poulose 	struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
489fcacb5c1SSuzuki K Poulose 
490fcacb5c1SSuzuki K Poulose 	CS_UNLOCK(catu_drvdata->base);
491fcacb5c1SSuzuki K Poulose 	rc = catu_disable_hw(catu_drvdata);
492fcacb5c1SSuzuki K Poulose 	CS_LOCK(catu_drvdata->base);
493fcacb5c1SSuzuki K Poulose 	return rc;
494fcacb5c1SSuzuki K Poulose }
495fcacb5c1SSuzuki K Poulose 
49661810404SYueHaibing static const struct coresight_ops_helper catu_helper_ops = {
497fcacb5c1SSuzuki K Poulose 	.enable = catu_enable,
498fcacb5c1SSuzuki K Poulose 	.disable = catu_disable,
499fcacb5c1SSuzuki K Poulose };
500fcacb5c1SSuzuki K Poulose 
50161810404SYueHaibing static const struct coresight_ops catu_ops = {
502fcacb5c1SSuzuki K Poulose 	.helper_ops = &catu_helper_ops,
503fcacb5c1SSuzuki K Poulose };
504fcacb5c1SSuzuki K Poulose 
catu_probe(struct amba_device * adev,const struct amba_id * id)505fcacb5c1SSuzuki K Poulose static int catu_probe(struct amba_device *adev, const struct amba_id *id)
506fcacb5c1SSuzuki K Poulose {
507fcacb5c1SSuzuki K Poulose 	int ret = 0;
508fcacb5c1SSuzuki K Poulose 	u32 dma_mask;
509fcacb5c1SSuzuki K Poulose 	struct catu_drvdata *drvdata;
510fcacb5c1SSuzuki K Poulose 	struct coresight_desc catu_desc;
511fcacb5c1SSuzuki K Poulose 	struct coresight_platform_data *pdata = NULL;
512fcacb5c1SSuzuki K Poulose 	struct device *dev = &adev->dev;
513fcacb5c1SSuzuki K Poulose 	void __iomem *base;
514fcacb5c1SSuzuki K Poulose 
5150f5f9b6bSSuzuki K Poulose 	catu_desc.name = coresight_alloc_device_name(&catu_devs, dev);
5160f5f9b6bSSuzuki K Poulose 	if (!catu_desc.name)
5170f5f9b6bSSuzuki K Poulose 		return -ENOMEM;
5180f5f9b6bSSuzuki K Poulose 
519fcacb5c1SSuzuki K Poulose 	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
520fcacb5c1SSuzuki K Poulose 	if (!drvdata) {
521fcacb5c1SSuzuki K Poulose 		ret = -ENOMEM;
522fcacb5c1SSuzuki K Poulose 		goto out;
523fcacb5c1SSuzuki K Poulose 	}
524fcacb5c1SSuzuki K Poulose 
525fcacb5c1SSuzuki K Poulose 	dev_set_drvdata(dev, drvdata);
526fcacb5c1SSuzuki K Poulose 	base = devm_ioremap_resource(dev, &adev->res);
527fcacb5c1SSuzuki K Poulose 	if (IS_ERR(base)) {
528fcacb5c1SSuzuki K Poulose 		ret = PTR_ERR(base);
529fcacb5c1SSuzuki K Poulose 		goto out;
530fcacb5c1SSuzuki K Poulose 	}
531fcacb5c1SSuzuki K Poulose 
532fcacb5c1SSuzuki K Poulose 	/* Setup dma mask for the device */
533fcacb5c1SSuzuki K Poulose 	dma_mask = readl_relaxed(base + CORESIGHT_DEVID) & 0x3f;
534fcacb5c1SSuzuki K Poulose 	switch (dma_mask) {
535fcacb5c1SSuzuki K Poulose 	case 32:
536fcacb5c1SSuzuki K Poulose 	case 40:
537fcacb5c1SSuzuki K Poulose 	case 44:
538fcacb5c1SSuzuki K Poulose 	case 48:
539fcacb5c1SSuzuki K Poulose 	case 52:
540fcacb5c1SSuzuki K Poulose 	case 56:
541fcacb5c1SSuzuki K Poulose 	case 64:
542fcacb5c1SSuzuki K Poulose 		break;
543fcacb5c1SSuzuki K Poulose 	default:
544fcacb5c1SSuzuki K Poulose 		/* Default to the 40bits as supported by TMC-ETR */
545fcacb5c1SSuzuki K Poulose 		dma_mask = 40;
546fcacb5c1SSuzuki K Poulose 	}
547fcacb5c1SSuzuki K Poulose 	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_mask));
548fcacb5c1SSuzuki K Poulose 	if (ret)
549fcacb5c1SSuzuki K Poulose 		goto out;
550fcacb5c1SSuzuki K Poulose 
551af7cfd0fSSuzuki K Poulose 	pdata = coresight_get_platform_data(dev);
552af7cfd0fSSuzuki K Poulose 	if (IS_ERR(pdata)) {
553af7cfd0fSSuzuki K Poulose 		ret = PTR_ERR(pdata);
554af7cfd0fSSuzuki K Poulose 		goto out;
555af7cfd0fSSuzuki K Poulose 	}
556af7cfd0fSSuzuki K Poulose 	dev->platform_data = pdata;
557af7cfd0fSSuzuki K Poulose 
558fcacb5c1SSuzuki K Poulose 	drvdata->base = base;
5596e736c60SSuzuki K Poulose 	catu_desc.access = CSDEV_ACCESS_IOMEM(base);
560fcacb5c1SSuzuki K Poulose 	catu_desc.pdata = pdata;
561fcacb5c1SSuzuki K Poulose 	catu_desc.dev = dev;
562fcacb5c1SSuzuki K Poulose 	catu_desc.groups = catu_groups;
563fcacb5c1SSuzuki K Poulose 	catu_desc.type = CORESIGHT_DEV_TYPE_HELPER;
564fcacb5c1SSuzuki K Poulose 	catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
565fcacb5c1SSuzuki K Poulose 	catu_desc.ops = &catu_ops;
5662ede79a6SSuzuki K Poulose 
567fcacb5c1SSuzuki K Poulose 	drvdata->csdev = coresight_register(&catu_desc);
568fcacb5c1SSuzuki K Poulose 	if (IS_ERR(drvdata->csdev))
569fcacb5c1SSuzuki K Poulose 		ret = PTR_ERR(drvdata->csdev);
5702390d458SSuzuki K Poulose 	else
571fcacb5c1SSuzuki K Poulose 		pm_runtime_put(&adev->dev);
5722390d458SSuzuki K Poulose out:
573fcacb5c1SSuzuki K Poulose 	return ret;
574fcacb5c1SSuzuki K Poulose }
575fcacb5c1SSuzuki K Poulose 
catu_remove(struct amba_device * adev)5763fd269e7SUwe Kleine-König static void catu_remove(struct amba_device *adev)
577a114dbeaSTingwei Zhang {
578a114dbeaSTingwei Zhang 	struct catu_drvdata *drvdata = dev_get_drvdata(&adev->dev);
579a114dbeaSTingwei Zhang 
580a114dbeaSTingwei Zhang 	coresight_unregister(drvdata->csdev);
581a114dbeaSTingwei Zhang }
582a114dbeaSTingwei Zhang 
583fcacb5c1SSuzuki K Poulose static struct amba_id catu_ids[] = {
5849cfb5563SSai Prakash Ranjan 	CS_AMBA_ID(0x000bb9ee),
585fcacb5c1SSuzuki K Poulose 	{},
586fcacb5c1SSuzuki K Poulose };
587fcacb5c1SSuzuki K Poulose 
588a114dbeaSTingwei Zhang MODULE_DEVICE_TABLE(amba, catu_ids);
589a114dbeaSTingwei Zhang 
590fcacb5c1SSuzuki K Poulose static struct amba_driver catu_driver = {
591fcacb5c1SSuzuki K Poulose 	.drv = {
592fcacb5c1SSuzuki K Poulose 		.name			= "coresight-catu",
593fcacb5c1SSuzuki K Poulose 		.owner			= THIS_MODULE,
594fcacb5c1SSuzuki K Poulose 		.suppress_bind_attrs	= true,
595fcacb5c1SSuzuki K Poulose 	},
596fcacb5c1SSuzuki K Poulose 	.probe				= catu_probe,
597a114dbeaSTingwei Zhang 	.remove				= catu_remove,
598fcacb5c1SSuzuki K Poulose 	.id_table			= catu_ids,
599fcacb5c1SSuzuki K Poulose };
600fcacb5c1SSuzuki K Poulose 
catu_init(void)60166af416dSMian Yousaf Kaukab static int __init catu_init(void)
60266af416dSMian Yousaf Kaukab {
60366af416dSMian Yousaf Kaukab 	int ret;
60466af416dSMian Yousaf Kaukab 
60566af416dSMian Yousaf Kaukab 	ret = amba_driver_register(&catu_driver);
60666af416dSMian Yousaf Kaukab 	if (ret)
60766af416dSMian Yousaf Kaukab 		pr_info("Error registering catu driver\n");
60866af416dSMian Yousaf Kaukab 	tmc_etr_set_catu_ops(&etr_catu_buf_ops);
60966af416dSMian Yousaf Kaukab 	return ret;
61066af416dSMian Yousaf Kaukab }
61166af416dSMian Yousaf Kaukab 
catu_exit(void)61266af416dSMian Yousaf Kaukab static void __exit catu_exit(void)
61366af416dSMian Yousaf Kaukab {
61466af416dSMian Yousaf Kaukab 	tmc_etr_remove_catu_ops();
61566af416dSMian Yousaf Kaukab 	amba_driver_unregister(&catu_driver);
61666af416dSMian Yousaf Kaukab }
61766af416dSMian Yousaf Kaukab 
61866af416dSMian Yousaf Kaukab module_init(catu_init);
61966af416dSMian Yousaf Kaukab module_exit(catu_exit);
620a114dbeaSTingwei Zhang 
621a114dbeaSTingwei Zhang MODULE_AUTHOR("Suzuki K Poulose <suzuki.poulose@arm.com>");
622a114dbeaSTingwei Zhang MODULE_DESCRIPTION("Arm CoreSight Address Translation Unit (CATU) Driver");
623a114dbeaSTingwei Zhang MODULE_LICENSE("GPL v2");
624