1063 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.4 *5 * Description: CoreSight System Trace Macrocell driver6 *7 * Initial implementation by Pratik Patel8 * (C) 2014-2015 Pratik Patel <pratikp@codeaurora.org>9 *10 * Serious refactoring, code cleanup and upgrading to the Coresight upstream11 * framework by Mathieu Poirier12 * (C) 2015-2016 Mathieu Poirier <mathieu.poirier@linaro.org>13 *14 * Guaranteed timing and support for various packet type coming from the15 * generic STM API by Chunyan Zhang16 * (C) 2015-2016 Chunyan Zhang <zhang.chunyan@linaro.org>17 */18#include <asm/local.h>19#include <linux/acpi.h>20#include <linux/amba/bus.h>21#include <linux/bitmap.h>22#include <linux/clk.h>23#include <linux/coresight.h>24#include <linux/coresight-stm.h>25#include <linux/err.h>26#include <linux/kernel.h>27#include <linux/moduleparam.h>28#include <linux/of_address.h>29#include <linux/perf_event.h>30#include <linux/pm_runtime.h>31#include <linux/stm.h>32#include <linux/platform_device.h>33 34#include "coresight-priv.h"35#include "coresight-trace-id.h"36 37#define STMDMASTARTR 0xc0438#define STMDMASTOPR 0xc0839#define STMDMASTATR 0xc0c40#define STMDMACTLR 0xc1041#define STMDMAIDR 0xcfc42#define STMHEER 0xd0043#define STMHETER 0xd2044#define STMHEBSR 0xd6045#define STMHEMCR 0xd6446#define STMHEMASTR 0xdf447#define STMHEFEAT1R 0xdf848#define STMHEIDR 0xdfc49#define STMSPER 0xe0050#define STMSPTER 0xe2051#define STMPRIVMASKR 0xe4052#define STMSPSCR 0xe6053#define STMSPMSCR 0xe6454#define STMSPOVERRIDER 0xe6855#define STMSPMOVERRIDER 0xe6c56#define STMSPTRIGCSR 0xe7057#define STMTCSR 0xe8058#define STMTSSTIMR 0xe8459#define STMTSFREQR 0xe8c60#define STMSYNCR 0xe9061#define STMAUXCR 0xe9462#define STMSPFEAT1R 0xea063#define STMSPFEAT2R 0xea464#define STMSPFEAT3R 0xea865#define STMITTRIGGER 0xee866#define STMITATBDATA0 0xeec67#define STMITATBCTR2 0xef068#define STMITATBID 0xef469#define STMITATBCTR0 0xef870 71#define STM_32_CHANNEL 3272#define BYTES_PER_CHANNEL 25673#define STM_TRACE_BUF_SIZE 409674#define STM_SW_MASTER_END 12775 76/* Register bit definition */77#define STMTCSR_BUSY_BIT 2378/* Reserve the first 10 channels for kernel usage */79#define STM_CHANNEL_OFFSET 080 81enum stm_pkt_type {82 STM_PKT_TYPE_DATA = 0x98,83 STM_PKT_TYPE_FLAG = 0xE8,84 STM_PKT_TYPE_TRIG = 0xF8,85};86 87#define stm_channel_addr(drvdata, ch) (drvdata->chs.base + \88 (ch * BYTES_PER_CHANNEL))89#define stm_channel_off(type, opts) (type & ~opts)90 91static int boot_nr_channel;92 93/*94 * Not really modular but using module_param is the easiest way to95 * remain consistent with existing use cases for now.96 */97module_param_named(98 boot_nr_channel, boot_nr_channel, int, S_IRUGO99);100 101/*102 * struct channel_space - central management entity for extended ports103 * @base: memory mapped base address where channels start.104 * @phys: physical base address of channel region.105 * @guaraneed: is the channel delivery guaranteed.106 */107struct channel_space {108 void __iomem *base;109 phys_addr_t phys;110 unsigned long *guaranteed;111};112 113DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm");114 115/**116 * struct stm_drvdata - specifics associated to an STM component117 * @base: memory mapped base address for this component.118 * @atclk: optional clock for the core parts of the STM.119 * @pclk: APB clock if present, otherwise NULL120 * @csdev: component vitals needed by the framework.121 * @spinlock: only one at a time pls.122 * @chs: the channels accociated to this STM.123 * @stm: structure associated to the generic STM interface.124 * @traceid: value of the current ID for this component.125 * @write_bytes: Maximus bytes this STM can write at a time.126 * @stmsper: settings for register STMSPER.127 * @stmspscr: settings for register STMSPSCR.128 * @numsp: the total number of stimulus port support by this STM.129 * @stmheer: settings for register STMHEER.130 * @stmheter: settings for register STMHETER.131 * @stmhebsr: settings for register STMHEBSR.132 */133struct stm_drvdata {134 void __iomem *base;135 struct clk *atclk;136 struct clk *pclk;137 struct coresight_device *csdev;138 spinlock_t spinlock;139 struct channel_space chs;140 struct stm_data stm;141 u8 traceid;142 u32 write_bytes;143 u32 stmsper;144 u32 stmspscr;145 u32 numsp;146 u32 stmheer;147 u32 stmheter;148 u32 stmhebsr;149};150 151static void stm_hwevent_enable_hw(struct stm_drvdata *drvdata)152{153 CS_UNLOCK(drvdata->base);154 155 writel_relaxed(drvdata->stmhebsr, drvdata->base + STMHEBSR);156 writel_relaxed(drvdata->stmheter, drvdata->base + STMHETER);157 writel_relaxed(drvdata->stmheer, drvdata->base + STMHEER);158 writel_relaxed(0x01 | /* Enable HW event tracing */159 0x04, /* Error detection on event tracing */160 drvdata->base + STMHEMCR);161 162 CS_LOCK(drvdata->base);163}164 165static void stm_port_enable_hw(struct stm_drvdata *drvdata)166{167 CS_UNLOCK(drvdata->base);168 /* ATB trigger enable on direct writes to TRIG locations */169 writel_relaxed(0x10,170 drvdata->base + STMSPTRIGCSR);171 writel_relaxed(drvdata->stmspscr, drvdata->base + STMSPSCR);172 writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);173 174 CS_LOCK(drvdata->base);175}176 177static void stm_enable_hw(struct stm_drvdata *drvdata)178{179 if (drvdata->stmheer)180 stm_hwevent_enable_hw(drvdata);181 182 stm_port_enable_hw(drvdata);183 184 CS_UNLOCK(drvdata->base);185 186 /* 4096 byte between synchronisation packets */187 writel_relaxed(0xFFF, drvdata->base + STMSYNCR);188 writel_relaxed((drvdata->traceid << 16 | /* trace id */189 0x02 | /* timestamp enable */190 0x01), /* global STM enable */191 drvdata->base + STMTCSR);192 193 CS_LOCK(drvdata->base);194}195 196static int stm_enable(struct coresight_device *csdev, struct perf_event *event,197 enum cs_mode mode,198 __maybe_unused struct coresight_trace_id_map *trace_id)199{200 struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);201 202 if (mode != CS_MODE_SYSFS)203 return -EINVAL;204 205 if (!coresight_take_mode(csdev, mode)) {206 /* Someone is already using the tracer */207 return -EBUSY;208 }209 210 pm_runtime_get_sync(csdev->dev.parent);211 212 spin_lock(&drvdata->spinlock);213 stm_enable_hw(drvdata);214 spin_unlock(&drvdata->spinlock);215 216 dev_dbg(&csdev->dev, "STM tracing enabled\n");217 return 0;218}219 220static void stm_hwevent_disable_hw(struct stm_drvdata *drvdata)221{222 CS_UNLOCK(drvdata->base);223 224 writel_relaxed(0x0, drvdata->base + STMHEMCR);225 writel_relaxed(0x0, drvdata->base + STMHEER);226 writel_relaxed(0x0, drvdata->base + STMHETER);227 228 CS_LOCK(drvdata->base);229}230 231static void stm_port_disable_hw(struct stm_drvdata *drvdata)232{233 CS_UNLOCK(drvdata->base);234 235 writel_relaxed(0x0, drvdata->base + STMSPER);236 writel_relaxed(0x0, drvdata->base + STMSPTRIGCSR);237 238 CS_LOCK(drvdata->base);239}240 241static void stm_disable_hw(struct stm_drvdata *drvdata)242{243 u32 val;244 245 CS_UNLOCK(drvdata->base);246 247 val = readl_relaxed(drvdata->base + STMTCSR);248 val &= ~0x1; /* clear global STM enable [0] */249 writel_relaxed(val, drvdata->base + STMTCSR);250 251 CS_LOCK(drvdata->base);252 253 stm_port_disable_hw(drvdata);254 if (drvdata->stmheer)255 stm_hwevent_disable_hw(drvdata);256}257 258static void stm_disable(struct coresight_device *csdev,259 struct perf_event *event)260{261 struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);262 struct csdev_access *csa = &csdev->access;263 264 /*265 * For as long as the tracer isn't disabled another entity can't266 * change its status. As such we can read the status here without267 * fearing it will change under us.268 */269 if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {270 spin_lock(&drvdata->spinlock);271 stm_disable_hw(drvdata);272 spin_unlock(&drvdata->spinlock);273 274 /* Wait until the engine has completely stopped */275 coresight_timeout(csa, STMTCSR, STMTCSR_BUSY_BIT, 0);276 277 pm_runtime_put(csdev->dev.parent);278 279 coresight_set_mode(csdev, CS_MODE_DISABLED);280 dev_dbg(&csdev->dev, "STM tracing disabled\n");281 }282}283 284static const struct coresight_ops_source stm_source_ops = {285 .enable = stm_enable,286 .disable = stm_disable,287};288 289static const struct coresight_ops stm_cs_ops = {290 .source_ops = &stm_source_ops,291};292 293static inline bool stm_addr_unaligned(const void *addr, u8 write_bytes)294{295 return ((unsigned long)addr & (write_bytes - 1));296}297 298static void stm_send(void __iomem *addr, const void *data,299 u32 size, u8 write_bytes)300{301 u8 paload[8];302 303 if (stm_addr_unaligned(data, write_bytes)) {304 memcpy(paload, data, size);305 data = paload;306 }307 308 /* now we are 64bit/32bit aligned */309 switch (size) {310#ifdef CONFIG_64BIT311 case 8:312 writeq_relaxed(*(u64 *)data, addr);313 break;314#endif315 case 4:316 writel_relaxed(*(u32 *)data, addr);317 break;318 case 2:319 writew_relaxed(*(u16 *)data, addr);320 break;321 case 1:322 writeb_relaxed(*(u8 *)data, addr);323 break;324 default:325 break;326 }327}328 329static int stm_generic_link(struct stm_data *stm_data,330 unsigned int master, unsigned int channel)331{332 struct stm_drvdata *drvdata = container_of(stm_data,333 struct stm_drvdata, stm);334 if (!drvdata || !drvdata->csdev)335 return -EINVAL;336 337 return coresight_enable_sysfs(drvdata->csdev);338}339 340static void stm_generic_unlink(struct stm_data *stm_data,341 unsigned int master, unsigned int channel)342{343 struct stm_drvdata *drvdata = container_of(stm_data,344 struct stm_drvdata, stm);345 if (!drvdata || !drvdata->csdev)346 return;347 348 coresight_disable_sysfs(drvdata->csdev);349}350 351static phys_addr_t352stm_mmio_addr(struct stm_data *stm_data, unsigned int master,353 unsigned int channel, unsigned int nr_chans)354{355 struct stm_drvdata *drvdata = container_of(stm_data,356 struct stm_drvdata, stm);357 phys_addr_t addr;358 359 addr = drvdata->chs.phys + channel * BYTES_PER_CHANNEL;360 361 if (offset_in_page(addr) ||362 offset_in_page(nr_chans * BYTES_PER_CHANNEL))363 return 0;364 365 return addr;366}367 368static long stm_generic_set_options(struct stm_data *stm_data,369 unsigned int master,370 unsigned int channel,371 unsigned int nr_chans,372 unsigned long options)373{374 struct stm_drvdata *drvdata = container_of(stm_data,375 struct stm_drvdata, stm);376 if (!(drvdata && coresight_get_mode(drvdata->csdev)))377 return -EINVAL;378 379 if (channel >= drvdata->numsp)380 return -EINVAL;381 382 switch (options) {383 case STM_OPTION_GUARANTEED:384 set_bit(channel, drvdata->chs.guaranteed);385 break;386 387 case STM_OPTION_INVARIANT:388 clear_bit(channel, drvdata->chs.guaranteed);389 break;390 391 default:392 return -EINVAL;393 }394 395 return 0;396}397 398static ssize_t notrace stm_generic_packet(struct stm_data *stm_data,399 unsigned int master,400 unsigned int channel,401 unsigned int packet,402 unsigned int flags,403 unsigned int size,404 const unsigned char *payload)405{406 void __iomem *ch_addr;407 struct stm_drvdata *drvdata = container_of(stm_data,408 struct stm_drvdata, stm);409 unsigned int stm_flags;410 411 if (!(drvdata && coresight_get_mode(drvdata->csdev)))412 return -EACCES;413 414 if (channel >= drvdata->numsp)415 return -EINVAL;416 417 ch_addr = stm_channel_addr(drvdata, channel);418 419 stm_flags = (flags & STP_PACKET_TIMESTAMPED) ?420 STM_FLAG_TIMESTAMPED : 0;421 stm_flags |= test_bit(channel, drvdata->chs.guaranteed) ?422 STM_FLAG_GUARANTEED : 0;423 424 if (size > drvdata->write_bytes)425 size = drvdata->write_bytes;426 else427 size = rounddown_pow_of_two(size);428 429 switch (packet) {430 case STP_PACKET_FLAG:431 ch_addr += stm_channel_off(STM_PKT_TYPE_FLAG, stm_flags);432 433 /*434 * The generic STM core sets a size of '0' on flag packets.435 * As such send a flag packet of size '1' and tell the436 * core we did so.437 */438 stm_send(ch_addr, payload, 1, drvdata->write_bytes);439 size = 1;440 break;441 442 case STP_PACKET_DATA:443 stm_flags |= (flags & STP_PACKET_MARKED) ? STM_FLAG_MARKED : 0;444 ch_addr += stm_channel_off(STM_PKT_TYPE_DATA, stm_flags);445 stm_send(ch_addr, payload, size,446 drvdata->write_bytes);447 break;448 449 default:450 return -ENOTSUPP;451 }452 453 return size;454}455 456static ssize_t hwevent_enable_show(struct device *dev,457 struct device_attribute *attr, char *buf)458{459 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);460 unsigned long val = drvdata->stmheer;461 462 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);463}464 465static ssize_t hwevent_enable_store(struct device *dev,466 struct device_attribute *attr,467 const char *buf, size_t size)468{469 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);470 unsigned long val;471 int ret = 0;472 473 ret = kstrtoul(buf, 16, &val);474 if (ret)475 return -EINVAL;476 477 drvdata->stmheer = val;478 /* HW event enable and trigger go hand in hand */479 drvdata->stmheter = val;480 481 return size;482}483static DEVICE_ATTR_RW(hwevent_enable);484 485static ssize_t hwevent_select_show(struct device *dev,486 struct device_attribute *attr, char *buf)487{488 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);489 unsigned long val = drvdata->stmhebsr;490 491 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);492}493 494static ssize_t hwevent_select_store(struct device *dev,495 struct device_attribute *attr,496 const char *buf, size_t size)497{498 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);499 unsigned long val;500 int ret = 0;501 502 ret = kstrtoul(buf, 16, &val);503 if (ret)504 return -EINVAL;505 506 drvdata->stmhebsr = val;507 508 return size;509}510static DEVICE_ATTR_RW(hwevent_select);511 512static ssize_t port_select_show(struct device *dev,513 struct device_attribute *attr, char *buf)514{515 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);516 unsigned long val;517 518 if (!coresight_get_mode(drvdata->csdev)) {519 val = drvdata->stmspscr;520 } else {521 spin_lock(&drvdata->spinlock);522 val = readl_relaxed(drvdata->base + STMSPSCR);523 spin_unlock(&drvdata->spinlock);524 }525 526 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);527}528 529static ssize_t port_select_store(struct device *dev,530 struct device_attribute *attr,531 const char *buf, size_t size)532{533 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);534 unsigned long val, stmsper;535 int ret = 0;536 537 ret = kstrtoul(buf, 16, &val);538 if (ret)539 return ret;540 541 spin_lock(&drvdata->spinlock);542 drvdata->stmspscr = val;543 544 if (coresight_get_mode(drvdata->csdev)) {545 CS_UNLOCK(drvdata->base);546 /* Process as per ARM's TRM recommendation */547 stmsper = readl_relaxed(drvdata->base + STMSPER);548 writel_relaxed(0x0, drvdata->base + STMSPER);549 writel_relaxed(drvdata->stmspscr, drvdata->base + STMSPSCR);550 writel_relaxed(stmsper, drvdata->base + STMSPER);551 CS_LOCK(drvdata->base);552 }553 spin_unlock(&drvdata->spinlock);554 555 return size;556}557static DEVICE_ATTR_RW(port_select);558 559static ssize_t port_enable_show(struct device *dev,560 struct device_attribute *attr, char *buf)561{562 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);563 unsigned long val;564 565 if (!coresight_get_mode(drvdata->csdev)) {566 val = drvdata->stmsper;567 } else {568 spin_lock(&drvdata->spinlock);569 val = readl_relaxed(drvdata->base + STMSPER);570 spin_unlock(&drvdata->spinlock);571 }572 573 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);574}575 576static ssize_t port_enable_store(struct device *dev,577 struct device_attribute *attr,578 const char *buf, size_t size)579{580 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);581 unsigned long val;582 int ret = 0;583 584 ret = kstrtoul(buf, 16, &val);585 if (ret)586 return ret;587 588 spin_lock(&drvdata->spinlock);589 drvdata->stmsper = val;590 591 if (coresight_get_mode(drvdata->csdev)) {592 CS_UNLOCK(drvdata->base);593 writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);594 CS_LOCK(drvdata->base);595 }596 spin_unlock(&drvdata->spinlock);597 598 return size;599}600static DEVICE_ATTR_RW(port_enable);601 602static ssize_t traceid_show(struct device *dev,603 struct device_attribute *attr, char *buf)604{605 unsigned long val;606 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);607 608 val = drvdata->traceid;609 return sprintf(buf, "%#lx\n", val);610}611static DEVICE_ATTR_RO(traceid);612 613static struct attribute *coresight_stm_attrs[] = {614 &dev_attr_hwevent_enable.attr,615 &dev_attr_hwevent_select.attr,616 &dev_attr_port_enable.attr,617 &dev_attr_port_select.attr,618 &dev_attr_traceid.attr,619 NULL,620};621 622static struct attribute *coresight_stm_mgmt_attrs[] = {623 coresight_simple_reg32(tcsr, STMTCSR),624 coresight_simple_reg32(tsfreqr, STMTSFREQR),625 coresight_simple_reg32(syncr, STMSYNCR),626 coresight_simple_reg32(sper, STMSPER),627 coresight_simple_reg32(spter, STMSPTER),628 coresight_simple_reg32(privmaskr, STMPRIVMASKR),629 coresight_simple_reg32(spscr, STMSPSCR),630 coresight_simple_reg32(spmscr, STMSPMSCR),631 coresight_simple_reg32(spfeat1r, STMSPFEAT1R),632 coresight_simple_reg32(spfeat2r, STMSPFEAT2R),633 coresight_simple_reg32(spfeat3r, STMSPFEAT3R),634 coresight_simple_reg32(devid, CORESIGHT_DEVID),635 NULL,636};637 638static const struct attribute_group coresight_stm_group = {639 .attrs = coresight_stm_attrs,640};641 642static const struct attribute_group coresight_stm_mgmt_group = {643 .attrs = coresight_stm_mgmt_attrs,644 .name = "mgmt",645};646 647static const struct attribute_group *coresight_stm_groups[] = {648 &coresight_stm_group,649 &coresight_stm_mgmt_group,650 NULL,651};652 653#ifdef CONFIG_OF654static int of_stm_get_stimulus_area(struct device *dev, struct resource *res)655{656 const char *name = NULL;657 int index = 0, found = 0;658 struct device_node *np = dev->of_node;659 660 while (!of_property_read_string_index(np, "reg-names", index, &name)) {661 if (strcmp("stm-stimulus-base", name)) {662 index++;663 continue;664 }665 666 /* We have a match and @index is where it's at */667 found = 1;668 break;669 }670 671 if (!found)672 return -EINVAL;673 674 return of_address_to_resource(np, index, res);675}676#else677static inline int of_stm_get_stimulus_area(struct device *dev,678 struct resource *res)679{680 return -ENOENT;681}682#endif683 684#ifdef CONFIG_ACPI685static int acpi_stm_get_stimulus_area(struct device *dev, struct resource *res)686{687 int rc;688 bool found_base = false;689 struct resource_entry *rent;690 LIST_HEAD(res_list);691 692 struct acpi_device *adev = ACPI_COMPANION(dev);693 694 rc = acpi_dev_get_resources(adev, &res_list, NULL, NULL);695 if (rc < 0)696 return rc;697 698 /*699 * The stimulus base for STM device must be listed as the second memory700 * resource, followed by the programming base address as described in701 * "Section 2.3 Resources" in ACPI for CoreSightTM 1.0 Platform Design702 * document (DEN0067).703 */704 rc = -ENOENT;705 list_for_each_entry(rent, &res_list, node) {706 if (resource_type(rent->res) != IORESOURCE_MEM)707 continue;708 if (found_base) {709 *res = *rent->res;710 rc = 0;711 break;712 }713 714 found_base = true;715 }716 717 acpi_dev_free_resource_list(&res_list);718 return rc;719}720#else721static inline int acpi_stm_get_stimulus_area(struct device *dev,722 struct resource *res)723{724 return -ENOENT;725}726#endif727 728static int stm_get_stimulus_area(struct device *dev, struct resource *res)729{730 struct fwnode_handle *fwnode = dev_fwnode(dev);731 732 if (is_of_node(fwnode))733 return of_stm_get_stimulus_area(dev, res);734 else if (is_acpi_node(fwnode))735 return acpi_stm_get_stimulus_area(dev, res);736 return -ENOENT;737}738 739static u32 stm_fundamental_data_size(struct stm_drvdata *drvdata)740{741 u32 stmspfeat2r;742 743 if (!IS_ENABLED(CONFIG_64BIT))744 return 4;745 746 stmspfeat2r = readl_relaxed(drvdata->base + STMSPFEAT2R);747 748 /*749 * bit[15:12] represents the fundamental data size750 * 0 - 32-bit data751 * 1 - 64-bit data752 */753 return BMVAL(stmspfeat2r, 12, 15) ? 8 : 4;754}755 756static u32 stm_num_stimulus_port(struct stm_drvdata *drvdata)757{758 u32 numsp;759 760 numsp = readl_relaxed(drvdata->base + CORESIGHT_DEVID);761 /*762 * NUMPS in STMDEVID is 17 bit long and if equal to 0x0,763 * 32 stimulus ports are supported.764 */765 numsp &= 0x1ffff;766 if (!numsp)767 numsp = STM_32_CHANNEL;768 return numsp;769}770 771static void stm_init_default_data(struct stm_drvdata *drvdata)772{773 /* Don't use port selection */774 drvdata->stmspscr = 0x0;775 /*776 * Enable all channel regardless of their number. When port777 * selection isn't used (see above) STMSPER applies to all778 * 32 channel group available, hence setting all 32 bits to 1779 */780 drvdata->stmsper = ~0x0;781 782 /* Set invariant transaction timing on all channels */783 bitmap_clear(drvdata->chs.guaranteed, 0, drvdata->numsp);784}785 786static void stm_init_generic_data(struct stm_drvdata *drvdata,787 const char *name)788{789 drvdata->stm.name = name;790 791 /*792 * MasterIDs are assigned at HW design phase. As such the core is793 * using a single master for interaction with this device.794 */795 drvdata->stm.sw_start = 1;796 drvdata->stm.sw_end = 1;797 drvdata->stm.hw_override = true;798 drvdata->stm.sw_nchannels = drvdata->numsp;799 drvdata->stm.sw_mmiosz = BYTES_PER_CHANNEL;800 drvdata->stm.packet = stm_generic_packet;801 drvdata->stm.mmio_addr = stm_mmio_addr;802 drvdata->stm.link = stm_generic_link;803 drvdata->stm.unlink = stm_generic_unlink;804 drvdata->stm.set_options = stm_generic_set_options;805}806 807static const struct amba_id stm_ids[];808 809static char *stm_csdev_name(struct coresight_device *csdev)810{811 u32 stm_pid = coresight_get_pid(&csdev->access);812 void *uci_data = coresight_get_uci_data_from_amba(stm_ids, stm_pid);813 814 return uci_data ? (char *)uci_data : "STM";815}816 817static int __stm_probe(struct device *dev, struct resource *res)818{819 int ret, trace_id;820 void __iomem *base;821 struct coresight_platform_data *pdata = NULL;822 struct stm_drvdata *drvdata;823 struct resource ch_res;824 struct coresight_desc desc = { 0 };825 826 desc.name = coresight_alloc_device_name(&stm_devs, dev);827 if (!desc.name)828 return -ENOMEM;829 830 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);831 if (!drvdata)832 return -ENOMEM;833 834 drvdata->atclk = devm_clk_get(dev, "atclk"); /* optional */835 if (!IS_ERR(drvdata->atclk)) {836 ret = clk_prepare_enable(drvdata->atclk);837 if (ret)838 return ret;839 }840 841 drvdata->pclk = coresight_get_enable_apb_pclk(dev);842 if (IS_ERR(drvdata->pclk))843 return -ENODEV;844 dev_set_drvdata(dev, drvdata);845 846 base = devm_ioremap_resource(dev, res);847 if (IS_ERR(base))848 return PTR_ERR(base);849 drvdata->base = base;850 desc.access = CSDEV_ACCESS_IOMEM(base);851 852 ret = stm_get_stimulus_area(dev, &ch_res);853 if (ret)854 return ret;855 drvdata->chs.phys = ch_res.start;856 857 base = devm_ioremap_resource(dev, &ch_res);858 if (IS_ERR(base))859 return PTR_ERR(base);860 drvdata->chs.base = base;861 862 drvdata->write_bytes = stm_fundamental_data_size(drvdata);863 864 if (boot_nr_channel)865 drvdata->numsp = boot_nr_channel;866 else867 drvdata->numsp = stm_num_stimulus_port(drvdata);868 869 drvdata->chs.guaranteed = devm_bitmap_zalloc(dev, drvdata->numsp,870 GFP_KERNEL);871 if (!drvdata->chs.guaranteed)872 return -ENOMEM;873 874 spin_lock_init(&drvdata->spinlock);875 876 stm_init_default_data(drvdata);877 stm_init_generic_data(drvdata, desc.name);878 879 if (stm_register_device(dev, &drvdata->stm, THIS_MODULE)) {880 dev_info(dev,881 "%s : stm_register_device failed, probing deferred\n",882 desc.name);883 return -EPROBE_DEFER;884 }885 886 pdata = coresight_get_platform_data(dev);887 if (IS_ERR(pdata)) {888 ret = PTR_ERR(pdata);889 goto stm_unregister;890 }891 dev->platform_data = pdata;892 893 desc.type = CORESIGHT_DEV_TYPE_SOURCE;894 desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE;895 desc.ops = &stm_cs_ops;896 desc.pdata = pdata;897 desc.dev = dev;898 desc.groups = coresight_stm_groups;899 drvdata->csdev = coresight_register(&desc);900 if (IS_ERR(drvdata->csdev)) {901 ret = PTR_ERR(drvdata->csdev);902 goto stm_unregister;903 }904 905 trace_id = coresight_trace_id_get_system_id();906 if (trace_id < 0) {907 ret = trace_id;908 goto cs_unregister;909 }910 drvdata->traceid = (u8)trace_id;911 912 dev_info(&drvdata->csdev->dev, "%s initialized\n",913 stm_csdev_name(drvdata->csdev));914 return 0;915 916cs_unregister:917 coresight_unregister(drvdata->csdev);918 919stm_unregister:920 stm_unregister_device(&drvdata->stm);921 return ret;922}923 924static int stm_probe(struct amba_device *adev, const struct amba_id *id)925{926 int ret;927 928 ret = __stm_probe(&adev->dev, &adev->res);929 if (!ret)930 pm_runtime_put(&adev->dev);931 932 return ret;933}934 935static void __stm_remove(struct device *dev)936{937 struct stm_drvdata *drvdata = dev_get_drvdata(dev);938 939 coresight_trace_id_put_system_id(drvdata->traceid);940 coresight_unregister(drvdata->csdev);941 942 stm_unregister_device(&drvdata->stm);943}944 945static void stm_remove(struct amba_device *adev)946{947 __stm_remove(&adev->dev);948}949 950#ifdef CONFIG_PM951static int stm_runtime_suspend(struct device *dev)952{953 struct stm_drvdata *drvdata = dev_get_drvdata(dev);954 955 if (drvdata && !IS_ERR(drvdata->atclk))956 clk_disable_unprepare(drvdata->atclk);957 958 if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))959 clk_disable_unprepare(drvdata->pclk);960 return 0;961}962 963static int stm_runtime_resume(struct device *dev)964{965 struct stm_drvdata *drvdata = dev_get_drvdata(dev);966 967 if (drvdata && !IS_ERR(drvdata->atclk))968 clk_prepare_enable(drvdata->atclk);969 970 if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))971 clk_prepare_enable(drvdata->pclk);972 return 0;973}974#endif975 976static const struct dev_pm_ops stm_dev_pm_ops = {977 SET_RUNTIME_PM_OPS(stm_runtime_suspend, stm_runtime_resume, NULL)978};979 980static const struct amba_id stm_ids[] = {981 CS_AMBA_ID_DATA(0x000bb962, "STM32"),982 CS_AMBA_ID_DATA(0x000bb963, "STM500"),983 { 0, 0, NULL },984};985 986MODULE_DEVICE_TABLE(amba, stm_ids);987 988static struct amba_driver stm_driver = {989 .drv = {990 .name = "coresight-stm",991 .pm = &stm_dev_pm_ops,992 .suppress_bind_attrs = true,993 },994 .probe = stm_probe,995 .remove = stm_remove,996 .id_table = stm_ids,997};998 999static int stm_platform_probe(struct platform_device *pdev)1000{1001 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);1002 int ret = 0;1003 1004 pm_runtime_get_noresume(&pdev->dev);1005 pm_runtime_set_active(&pdev->dev);1006 pm_runtime_enable(&pdev->dev);1007 1008 ret = __stm_probe(&pdev->dev, res);1009 pm_runtime_put(&pdev->dev);1010 if (ret)1011 pm_runtime_disable(&pdev->dev);1012 1013 return ret;1014}1015 1016static void stm_platform_remove(struct platform_device *pdev)1017{1018 struct stm_drvdata *drvdata = dev_get_drvdata(&pdev->dev);1019 1020 if (WARN_ON(!drvdata))1021 return;1022 1023 __stm_remove(&pdev->dev);1024 pm_runtime_disable(&pdev->dev);1025 if (!IS_ERR_OR_NULL(drvdata->pclk))1026 clk_put(drvdata->pclk);1027}1028 1029#ifdef CONFIG_ACPI1030static const struct acpi_device_id stm_acpi_ids[] = {1031 {"ARMHC502", 0, 0, 0}, /* ARM CoreSight STM */1032 {},1033};1034MODULE_DEVICE_TABLE(acpi, stm_acpi_ids);1035#endif1036 1037static struct platform_driver stm_platform_driver = {1038 .probe = stm_platform_probe,1039 .remove_new = stm_platform_remove,1040 .driver = {1041 .name = "coresight-stm-platform",1042 .acpi_match_table = ACPI_PTR(stm_acpi_ids),1043 .suppress_bind_attrs = true,1044 .pm = &stm_dev_pm_ops,1045 },1046};1047 1048static int __init stm_init(void)1049{1050 return coresight_init_driver("stm", &stm_driver, &stm_platform_driver);1051}1052 1053static void __exit stm_exit(void)1054{1055 coresight_remove_driver(&stm_driver, &stm_platform_driver);1056}1057module_init(stm_init);1058module_exit(stm_exit);1059 1060MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>");1061MODULE_DESCRIPTION("Arm CoreSight System Trace Macrocell driver");1062MODULE_LICENSE("GPL v2");1063