0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/amba/bus.h>
0011 #include <linux/device.h>
0012 #include <linux/dma-mapping.h>
0013 #include <linux/io.h>
0014 #include <linux/kernel.h>
0015 #include <linux/slab.h>
0016
0017 #include "coresight-catu.h"
0018 #include "coresight-priv.h"
0019 #include "coresight-tmc.h"
0020
0021 #define csdev_to_catu_drvdata(csdev) \
0022 dev_get_drvdata(csdev->dev.parent)
0023
0024
0025 #ifdef CATU_DEBUG
0026 #define catu_dbg(x, ...) dev_dbg(x, __VA_ARGS__)
0027 #else
0028 #define catu_dbg(x, ...) do {} while (0)
0029 #endif
0030
0031 DEFINE_CORESIGHT_DEVLIST(catu_devs, "catu");
0032
0033 struct catu_etr_buf {
0034 struct tmc_sg_table *catu_table;
0035 dma_addr_t sladdr;
0036 };
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 typedef u64 cate_t;
0085
0086 #define CATU_PAGE_SHIFT 12
0087 #define CATU_PAGE_SIZE (1UL << CATU_PAGE_SHIFT)
0088 #define CATU_PAGES_PER_SYSPAGE (PAGE_SIZE / CATU_PAGE_SIZE)
0089
0090
0091 #define CATU_PTRS_PER_PAGE ((CATU_PAGE_SIZE >> 1) / sizeof(cate_t))
0092 #define CATU_PTRS_PER_SYSPAGE (CATU_PAGES_PER_SYSPAGE * CATU_PTRS_PER_PAGE)
0093 #define CATU_LINK_PREV ((CATU_PAGE_SIZE / sizeof(cate_t)) - 2)
0094 #define CATU_LINK_NEXT ((CATU_PAGE_SIZE / sizeof(cate_t)) - 1)
0095
0096 #define CATU_ADDR_SHIFT 12
0097 #define CATU_ADDR_MASK ~(((cate_t)1 << CATU_ADDR_SHIFT) - 1)
0098 #define CATU_ENTRY_VALID ((cate_t)0x1)
0099 #define CATU_VALID_ENTRY(addr) \
0100 (((cate_t)(addr) & CATU_ADDR_MASK) | CATU_ENTRY_VALID)
0101 #define CATU_ENTRY_ADDR(entry) ((cate_t)(entry) & ~((cate_t)CATU_ENTRY_VALID))
0102
0103
0104 #define CATU_DEFAULT_INADDR (1ULL << 20)
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
0115 unsigned long offset,
0116 dma_addr_t *daddrp)
0117 {
0118 unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
0119 unsigned int table_nr, pg_idx, pg_offset;
0120 struct tmc_pages *table_pages = &catu_table->table_pages;
0121 void *ptr;
0122
0123
0124 offset %= buf_size;
0125
0126
0127
0128
0129
0130 table_nr = offset >> 20;
0131
0132 pg_idx = table_nr / CATU_PAGES_PER_SYSPAGE;
0133 pg_offset = (table_nr % CATU_PAGES_PER_SYSPAGE) * CATU_PAGE_SIZE;
0134 if (daddrp)
0135 *daddrp = table_pages->daddrs[pg_idx] + pg_offset;
0136 ptr = page_address(table_pages->pages[pg_idx]);
0137 return (cate_t *)((unsigned long)ptr + pg_offset);
0138 }
0139
0140 #ifdef CATU_DEBUG
0141 static void catu_dump_table(struct tmc_sg_table *catu_table)
0142 {
0143 int i;
0144 cate_t *table;
0145 unsigned long table_end, buf_size, offset = 0;
0146
0147 buf_size = tmc_sg_table_buf_size(catu_table);
0148 dev_dbg(catu_table->dev,
0149 "Dump table %p, tdaddr: %llx\n",
0150 catu_table, catu_table->table_daddr);
0151
0152 while (offset < buf_size) {
0153 table_end = offset + SZ_1M < buf_size ?
0154 offset + SZ_1M : buf_size;
0155 table = catu_get_table(catu_table, offset, NULL);
0156 for (i = 0; offset < table_end; i++, offset += CATU_PAGE_SIZE)
0157 dev_dbg(catu_table->dev, "%d: %llx\n", i, table[i]);
0158 dev_dbg(catu_table->dev, "Prev : %llx, Next: %llx\n",
0159 table[CATU_LINK_PREV], table[CATU_LINK_NEXT]);
0160 dev_dbg(catu_table->dev, "== End of sub-table ===");
0161 }
0162 dev_dbg(catu_table->dev, "== End of Table ===");
0163 }
0164
0165 #else
0166 static inline void catu_dump_table(struct tmc_sg_table *catu_table)
0167 {
0168 }
0169 #endif
0170
0171 static inline cate_t catu_make_entry(dma_addr_t addr)
0172 {
0173 return addr ? CATU_VALID_ENTRY(addr) : 0;
0174 }
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184 static void
0185 catu_populate_table(struct tmc_sg_table *catu_table)
0186 {
0187 int i;
0188 int sys_pidx;
0189 int catu_pidx;
0190 unsigned long offset, buf_size, table_end;
0191 dma_addr_t data_daddr;
0192 dma_addr_t prev_taddr, next_taddr, cur_taddr;
0193 cate_t *table_ptr, *next_table;
0194
0195 buf_size = tmc_sg_table_buf_size(catu_table);
0196 sys_pidx = catu_pidx = 0;
0197 offset = 0;
0198
0199 table_ptr = catu_get_table(catu_table, 0, &cur_taddr);
0200 prev_taddr = 0;
0201
0202 while (offset < buf_size) {
0203
0204
0205
0206
0207
0208
0209 table_end = (offset + SZ_1M) < buf_size ?
0210 (offset + SZ_1M) : buf_size;
0211 for (i = 0; offset < table_end;
0212 i++, offset += CATU_PAGE_SIZE) {
0213
0214 data_daddr = catu_table->data_pages.daddrs[sys_pidx] +
0215 catu_pidx * CATU_PAGE_SIZE;
0216 catu_dbg(catu_table->dev,
0217 "[table %5ld:%03d] 0x%llx\n",
0218 (offset >> 20), i, data_daddr);
0219 table_ptr[i] = catu_make_entry(data_daddr);
0220
0221 catu_pidx = (catu_pidx + 1) % CATU_PAGES_PER_SYSPAGE;
0222 if (catu_pidx == 0)
0223 sys_pidx++;
0224 }
0225
0226
0227
0228
0229
0230
0231 if (offset == buf_size) {
0232 memset(&table_ptr[i], 0,
0233 sizeof(cate_t) * (CATU_PTRS_PER_PAGE - i));
0234 next_taddr = 0;
0235 } else {
0236 next_table = catu_get_table(catu_table,
0237 offset, &next_taddr);
0238 }
0239
0240 table_ptr[CATU_LINK_PREV] = catu_make_entry(prev_taddr);
0241 table_ptr[CATU_LINK_NEXT] = catu_make_entry(next_taddr);
0242
0243 catu_dbg(catu_table->dev,
0244 "[table%5ld]: Cur: 0x%llx Prev: 0x%llx, Next: 0x%llx\n",
0245 (offset >> 20) - 1, cur_taddr, prev_taddr, next_taddr);
0246
0247
0248 if (next_taddr) {
0249 prev_taddr = cur_taddr;
0250 cur_taddr = next_taddr;
0251 table_ptr = next_table;
0252 }
0253 }
0254
0255
0256 tmc_sg_table_sync_table(catu_table);
0257 }
0258
0259 static struct tmc_sg_table *
0260 catu_init_sg_table(struct device *catu_dev, int node,
0261 ssize_t size, void **pages)
0262 {
0263 int nr_tpages;
0264 struct tmc_sg_table *catu_table;
0265
0266
0267
0268
0269
0270 nr_tpages = DIV_ROUND_UP(size, SZ_1M) / CATU_PAGES_PER_SYSPAGE;
0271 catu_table = tmc_alloc_sg_table(catu_dev, node, nr_tpages,
0272 size >> PAGE_SHIFT, pages);
0273 if (IS_ERR(catu_table))
0274 return catu_table;
0275
0276 catu_populate_table(catu_table);
0277 dev_dbg(catu_dev,
0278 "Setup table %p, size %ldKB, %d table pages\n",
0279 catu_table, (unsigned long)size >> 10, nr_tpages);
0280 catu_dump_table(catu_table);
0281 return catu_table;
0282 }
0283
0284 static void catu_free_etr_buf(struct etr_buf *etr_buf)
0285 {
0286 struct catu_etr_buf *catu_buf;
0287
0288 if (!etr_buf || etr_buf->mode != ETR_MODE_CATU || !etr_buf->private)
0289 return;
0290
0291 catu_buf = etr_buf->private;
0292 tmc_free_sg_table(catu_buf->catu_table);
0293 kfree(catu_buf);
0294 }
0295
0296 static ssize_t catu_get_data_etr_buf(struct etr_buf *etr_buf, u64 offset,
0297 size_t len, char **bufpp)
0298 {
0299 struct catu_etr_buf *catu_buf = etr_buf->private;
0300
0301 return tmc_sg_table_get_data(catu_buf->catu_table, offset, len, bufpp);
0302 }
0303
0304 static void catu_sync_etr_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp)
0305 {
0306 struct catu_etr_buf *catu_buf = etr_buf->private;
0307 struct tmc_sg_table *catu_table = catu_buf->catu_table;
0308 u64 r_offset, w_offset;
0309
0310
0311
0312
0313
0314 r_offset = rrp - etr_buf->hwaddr;
0315 w_offset = rwp - etr_buf->hwaddr;
0316
0317 if (!etr_buf->full) {
0318 etr_buf->len = w_offset - r_offset;
0319 if (w_offset < r_offset)
0320 etr_buf->len += etr_buf->size;
0321 } else {
0322 etr_buf->len = etr_buf->size;
0323 }
0324
0325 etr_buf->offset = r_offset;
0326 tmc_sg_table_sync_data_range(catu_table, r_offset, etr_buf->len);
0327 }
0328
0329 static int catu_alloc_etr_buf(struct tmc_drvdata *tmc_drvdata,
0330 struct etr_buf *etr_buf, int node, void **pages)
0331 {
0332 struct coresight_device *csdev;
0333 struct tmc_sg_table *catu_table;
0334 struct catu_etr_buf *catu_buf;
0335
0336 csdev = tmc_etr_get_catu_device(tmc_drvdata);
0337 if (!csdev)
0338 return -ENODEV;
0339 catu_buf = kzalloc(sizeof(*catu_buf), GFP_KERNEL);
0340 if (!catu_buf)
0341 return -ENOMEM;
0342
0343 catu_table = catu_init_sg_table(&csdev->dev, node,
0344 etr_buf->size, pages);
0345 if (IS_ERR(catu_table)) {
0346 kfree(catu_buf);
0347 return PTR_ERR(catu_table);
0348 }
0349
0350 etr_buf->mode = ETR_MODE_CATU;
0351 etr_buf->private = catu_buf;
0352 etr_buf->hwaddr = CATU_DEFAULT_INADDR;
0353
0354 catu_buf->catu_table = catu_table;
0355
0356 catu_buf->sladdr = catu_table->table_daddr;
0357
0358 return 0;
0359 }
0360
0361 static const struct etr_buf_operations etr_catu_buf_ops = {
0362 .alloc = catu_alloc_etr_buf,
0363 .free = catu_free_etr_buf,
0364 .sync = catu_sync_etr_buf,
0365 .get_data = catu_get_data_etr_buf,
0366 };
0367
0368 coresight_simple_reg32(struct catu_drvdata, devid, CORESIGHT_DEVID);
0369 coresight_simple_reg32(struct catu_drvdata, control, CATU_CONTROL);
0370 coresight_simple_reg32(struct catu_drvdata, status, CATU_STATUS);
0371 coresight_simple_reg32(struct catu_drvdata, mode, CATU_MODE);
0372 coresight_simple_reg32(struct catu_drvdata, axictrl, CATU_AXICTRL);
0373 coresight_simple_reg32(struct catu_drvdata, irqen, CATU_IRQEN);
0374 coresight_simple_reg64(struct catu_drvdata, sladdr,
0375 CATU_SLADDRLO, CATU_SLADDRHI);
0376 coresight_simple_reg64(struct catu_drvdata, inaddr,
0377 CATU_INADDRLO, CATU_INADDRHI);
0378
0379 static struct attribute *catu_mgmt_attrs[] = {
0380 &dev_attr_devid.attr,
0381 &dev_attr_control.attr,
0382 &dev_attr_status.attr,
0383 &dev_attr_mode.attr,
0384 &dev_attr_axictrl.attr,
0385 &dev_attr_irqen.attr,
0386 &dev_attr_sladdr.attr,
0387 &dev_attr_inaddr.attr,
0388 NULL,
0389 };
0390
0391 static const struct attribute_group catu_mgmt_group = {
0392 .attrs = catu_mgmt_attrs,
0393 .name = "mgmt",
0394 };
0395
0396 static const struct attribute_group *catu_groups[] = {
0397 &catu_mgmt_group,
0398 NULL,
0399 };
0400
0401
0402 static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
0403 {
0404 struct csdev_access *csa = &drvdata->csdev->access;
0405
0406 return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);
0407 }
0408
0409 static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
0410 {
0411 int rc;
0412 u32 control, mode;
0413 struct etr_buf *etr_buf = data;
0414 struct device *dev = &drvdata->csdev->dev;
0415 struct coresight_device *csdev = drvdata->csdev;
0416
0417 if (catu_wait_for_ready(drvdata))
0418 dev_warn(dev, "Timeout while waiting for READY\n");
0419
0420 control = catu_read_control(drvdata);
0421 if (control & BIT(CATU_CONTROL_ENABLE)) {
0422 dev_warn(dev, "CATU is already enabled\n");
0423 return -EBUSY;
0424 }
0425
0426 rc = coresight_claim_device_unlocked(csdev);
0427 if (rc)
0428 return rc;
0429
0430 control |= BIT(CATU_CONTROL_ENABLE);
0431
0432 if (etr_buf && etr_buf->mode == ETR_MODE_CATU) {
0433 struct catu_etr_buf *catu_buf = etr_buf->private;
0434
0435 mode = CATU_MODE_TRANSLATE;
0436 catu_write_axictrl(drvdata, CATU_OS_AXICTRL);
0437 catu_write_sladdr(drvdata, catu_buf->sladdr);
0438 catu_write_inaddr(drvdata, CATU_DEFAULT_INADDR);
0439 } else {
0440 mode = CATU_MODE_PASS_THROUGH;
0441 catu_write_sladdr(drvdata, 0);
0442 catu_write_inaddr(drvdata, 0);
0443 }
0444
0445 catu_write_irqen(drvdata, 0);
0446 catu_write_mode(drvdata, mode);
0447 catu_write_control(drvdata, control);
0448 dev_dbg(dev, "Enabled in %s mode\n",
0449 (mode == CATU_MODE_PASS_THROUGH) ?
0450 "Pass through" :
0451 "Translate");
0452 return 0;
0453 }
0454
0455 static int catu_enable(struct coresight_device *csdev, void *data)
0456 {
0457 int rc;
0458 struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
0459
0460 CS_UNLOCK(catu_drvdata->base);
0461 rc = catu_enable_hw(catu_drvdata, data);
0462 CS_LOCK(catu_drvdata->base);
0463 return rc;
0464 }
0465
0466 static int catu_disable_hw(struct catu_drvdata *drvdata)
0467 {
0468 int rc = 0;
0469 struct device *dev = &drvdata->csdev->dev;
0470 struct coresight_device *csdev = drvdata->csdev;
0471
0472 catu_write_control(drvdata, 0);
0473 coresight_disclaim_device_unlocked(csdev);
0474 if (catu_wait_for_ready(drvdata)) {
0475 dev_info(dev, "Timeout while waiting for READY\n");
0476 rc = -EAGAIN;
0477 }
0478
0479 dev_dbg(dev, "Disabled\n");
0480 return rc;
0481 }
0482
0483 static int catu_disable(struct coresight_device *csdev, void *__unused)
0484 {
0485 int rc;
0486 struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
0487
0488 CS_UNLOCK(catu_drvdata->base);
0489 rc = catu_disable_hw(catu_drvdata);
0490 CS_LOCK(catu_drvdata->base);
0491 return rc;
0492 }
0493
0494 static const struct coresight_ops_helper catu_helper_ops = {
0495 .enable = catu_enable,
0496 .disable = catu_disable,
0497 };
0498
0499 static const struct coresight_ops catu_ops = {
0500 .helper_ops = &catu_helper_ops,
0501 };
0502
0503 static int catu_probe(struct amba_device *adev, const struct amba_id *id)
0504 {
0505 int ret = 0;
0506 u32 dma_mask;
0507 struct catu_drvdata *drvdata;
0508 struct coresight_desc catu_desc;
0509 struct coresight_platform_data *pdata = NULL;
0510 struct device *dev = &adev->dev;
0511 void __iomem *base;
0512
0513 catu_desc.name = coresight_alloc_device_name(&catu_devs, dev);
0514 if (!catu_desc.name)
0515 return -ENOMEM;
0516
0517 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
0518 if (!drvdata) {
0519 ret = -ENOMEM;
0520 goto out;
0521 }
0522
0523 dev_set_drvdata(dev, drvdata);
0524 base = devm_ioremap_resource(dev, &adev->res);
0525 if (IS_ERR(base)) {
0526 ret = PTR_ERR(base);
0527 goto out;
0528 }
0529
0530
0531 dma_mask = readl_relaxed(base + CORESIGHT_DEVID) & 0x3f;
0532 switch (dma_mask) {
0533 case 32:
0534 case 40:
0535 case 44:
0536 case 48:
0537 case 52:
0538 case 56:
0539 case 64:
0540 break;
0541 default:
0542
0543 dma_mask = 40;
0544 }
0545 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_mask));
0546 if (ret)
0547 goto out;
0548
0549 pdata = coresight_get_platform_data(dev);
0550 if (IS_ERR(pdata)) {
0551 ret = PTR_ERR(pdata);
0552 goto out;
0553 }
0554 dev->platform_data = pdata;
0555
0556 drvdata->base = base;
0557 catu_desc.access = CSDEV_ACCESS_IOMEM(base);
0558 catu_desc.pdata = pdata;
0559 catu_desc.dev = dev;
0560 catu_desc.groups = catu_groups;
0561 catu_desc.type = CORESIGHT_DEV_TYPE_HELPER;
0562 catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
0563 catu_desc.ops = &catu_ops;
0564
0565 drvdata->csdev = coresight_register(&catu_desc);
0566 if (IS_ERR(drvdata->csdev))
0567 ret = PTR_ERR(drvdata->csdev);
0568 else
0569 pm_runtime_put(&adev->dev);
0570 out:
0571 return ret;
0572 }
0573
0574 static void catu_remove(struct amba_device *adev)
0575 {
0576 struct catu_drvdata *drvdata = dev_get_drvdata(&adev->dev);
0577
0578 coresight_unregister(drvdata->csdev);
0579 }
0580
0581 static struct amba_id catu_ids[] = {
0582 CS_AMBA_ID(0x000bb9ee),
0583 {},
0584 };
0585
0586 MODULE_DEVICE_TABLE(amba, catu_ids);
0587
0588 static struct amba_driver catu_driver = {
0589 .drv = {
0590 .name = "coresight-catu",
0591 .owner = THIS_MODULE,
0592 .suppress_bind_attrs = true,
0593 },
0594 .probe = catu_probe,
0595 .remove = catu_remove,
0596 .id_table = catu_ids,
0597 };
0598
0599 static int __init catu_init(void)
0600 {
0601 int ret;
0602
0603 ret = amba_driver_register(&catu_driver);
0604 if (ret)
0605 pr_info("Error registering catu driver\n");
0606 tmc_etr_set_catu_ops(&etr_catu_buf_ops);
0607 return ret;
0608 }
0609
0610 static void __exit catu_exit(void)
0611 {
0612 tmc_etr_remove_catu_ops();
0613 amba_driver_unregister(&catu_driver);
0614 }
0615
0616 module_init(catu_init);
0617 module_exit(catu_exit);
0618
0619 MODULE_AUTHOR("Suzuki K Poulose <suzuki.poulose@arm.com>");
0620 MODULE_DESCRIPTION("Arm CoreSight Address Translation Unit (CATU) Driver");
0621 MODULE_LICENSE("GPL v2");