Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright(C) 2020 Linaro Limited. All rights reserved.
0004  * Author: Mike Leach <mike.leach@linaro.org>
0005  */
0006 
0007 #include "coresight-etm4x.h"
0008 #include "coresight-etm4x-cfg.h"
0009 #include "coresight-priv.h"
0010 #include "coresight-syscfg.h"
0011 
0012 /* defines to associate register IDs with driver data locations */
0013 #define CHECKREG(cval, elem) \
0014     { \
0015         if (offset == cval) { \
0016             reg_csdev->driver_regval = &drvcfg->elem; \
0017             err = 0; \
0018             break; \
0019         } \
0020     }
0021 
0022 #define CHECKREGIDX(cval, elem, off_idx, mask)  \
0023     { \
0024         if (mask == cval) { \
0025             reg_csdev->driver_regval = &drvcfg->elem[off_idx]; \
0026             err = 0; \
0027             break; \
0028         } \
0029     }
0030 
0031 /**
0032  * etm4_cfg_map_reg_offset - validate and map the register offset into a
0033  *               location in the driver config struct.
0034  *
0035  * Limits the number of registers that can be accessed and programmed in
0036  * features, to those which are used to control the trace capture parameters.
0037  *
0038  * Omits or limits access to those which the driver must use exclusively.
0039  *
0040  * Invalid offsets will result in fail code return and feature load failure.
0041  *
0042  * @drvdata:    driver data to map into.
0043  * @reg:    register to map.
0044  * @offset: device offset for the register
0045  */
0046 static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
0047                    struct cscfg_regval_csdev *reg_csdev, u32 offset)
0048 {
0049     int err = -EINVAL, idx;
0050     struct etmv4_config *drvcfg = &drvdata->config;
0051     u32 off_mask;
0052 
0053     if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) ||
0054         ((offset >= TRCSEQRSTEVR) && (offset <= TRCEXTINSELR)) ||
0055         ((offset >= TRCCIDCCTLR0) && (offset <= TRCVMIDCCTLR1))) {
0056         do {
0057             CHECKREG(TRCEVENTCTL0R, eventctrl0);
0058             CHECKREG(TRCEVENTCTL1R, eventctrl1);
0059             CHECKREG(TRCSTALLCTLR, stall_ctrl);
0060             CHECKREG(TRCTSCTLR, ts_ctrl);
0061             CHECKREG(TRCSYNCPR, syncfreq);
0062             CHECKREG(TRCCCCTLR, ccctlr);
0063             CHECKREG(TRCBBCTLR, bb_ctrl);
0064             CHECKREG(TRCVICTLR, vinst_ctrl);
0065             CHECKREG(TRCVIIECTLR, viiectlr);
0066             CHECKREG(TRCVISSCTLR, vissctlr);
0067             CHECKREG(TRCVIPCSSCTLR, vipcssctlr);
0068             CHECKREG(TRCSEQRSTEVR, seq_rst);
0069             CHECKREG(TRCSEQSTR, seq_state);
0070             CHECKREG(TRCEXTINSELR, ext_inp);
0071             CHECKREG(TRCCIDCCTLR0, ctxid_mask0);
0072             CHECKREG(TRCCIDCCTLR1, ctxid_mask1);
0073             CHECKREG(TRCVMIDCCTLR0, vmid_mask0);
0074             CHECKREG(TRCVMIDCCTLR1, vmid_mask1);
0075         } while (0);
0076     } else if ((offset & GENMASK(11, 4)) == TRCSEQEVRn(0)) {
0077         /* sequencer state control registers */
0078         idx = (offset & GENMASK(3, 0)) / 4;
0079         if (idx < ETM_MAX_SEQ_STATES) {
0080             reg_csdev->driver_regval = &drvcfg->seq_ctrl[idx];
0081             err = 0;
0082         }
0083     } else if ((offset >= TRCSSCCRn(0)) && (offset <= TRCSSPCICRn(7))) {
0084         /* 32 bit, 8 off indexed register sets */
0085         idx = (offset & GENMASK(4, 0)) / 4;
0086         off_mask =  (offset & GENMASK(11, 5));
0087         do {
0088             CHECKREGIDX(TRCSSCCRn(0), ss_ctrl, idx, off_mask);
0089             CHECKREGIDX(TRCSSCSRn(0), ss_status, idx, off_mask);
0090             CHECKREGIDX(TRCSSPCICRn(0), ss_pe_cmp, idx, off_mask);
0091         } while (0);
0092     } else if ((offset >= TRCCIDCVRn(0)) && (offset <= TRCVMIDCVRn(7))) {
0093         /* 64 bit, 8 off indexed register sets */
0094         idx = (offset & GENMASK(5, 0)) / 8;
0095         off_mask = (offset & GENMASK(11, 6));
0096         do {
0097             CHECKREGIDX(TRCCIDCVRn(0), ctxid_pid, idx, off_mask);
0098             CHECKREGIDX(TRCVMIDCVRn(0), vmid_val, idx, off_mask);
0099         } while (0);
0100     } else if ((offset >= TRCRSCTLRn(2)) &&
0101            (offset <= TRCRSCTLRn((ETM_MAX_RES_SEL - 1)))) {
0102         /* 32 bit resource selection regs, 32 off, skip fixed 0,1 */
0103         idx = (offset & GENMASK(6, 0)) / 4;
0104         if (idx < ETM_MAX_RES_SEL) {
0105             reg_csdev->driver_regval = &drvcfg->res_ctrl[idx];
0106             err = 0;
0107         }
0108     } else if ((offset >= TRCACVRn(0)) &&
0109            (offset <= TRCACATRn((ETM_MAX_SINGLE_ADDR_CMP - 1)))) {
0110         /* 64 bit addr cmp regs, 16 off */
0111         idx = (offset & GENMASK(6, 0)) / 8;
0112         off_mask = offset & GENMASK(11, 7);
0113         do {
0114             CHECKREGIDX(TRCACVRn(0), addr_val, idx, off_mask);
0115             CHECKREGIDX(TRCACATRn(0), addr_acc, idx, off_mask);
0116         } while (0);
0117     } else if ((offset >= TRCCNTRLDVRn(0)) &&
0118            (offset <= TRCCNTVRn((ETMv4_MAX_CNTR - 1)))) {
0119         /* 32 bit counter regs, 4 off (ETMv4_MAX_CNTR - 1) */
0120         idx = (offset &  GENMASK(3, 0)) / 4;
0121         off_mask = offset &  GENMASK(11, 4);
0122         do {
0123             CHECKREGIDX(TRCCNTRLDVRn(0), cntrldvr, idx, off_mask);
0124             CHECKREGIDX(TRCCNTCTLRn(0), cntr_ctrl, idx, off_mask);
0125             CHECKREGIDX(TRCCNTVRn(0), cntr_val, idx, off_mask);
0126         } while (0);
0127     }
0128     return err;
0129 }
0130 
0131 /**
0132  * etm4_cfg_load_feature - load a feature into a device instance.
0133  *
0134  * @csdev:  An ETMv4 CoreSight device.
0135  * @feat:   The feature to be loaded.
0136  *
0137  * The function will load a feature instance into the device, checking that
0138  * the register definitions are valid for the device.
0139  *
0140  * Parameter and register definitions will be converted into internal
0141  * structures that are used to set the values in the driver when the
0142  * feature is enabled for the device.
0143  *
0144  * The feature spinlock pointer is initialised to the same spinlock
0145  * that the driver uses to protect the internal register values.
0146  */
0147 static int etm4_cfg_load_feature(struct coresight_device *csdev,
0148                  struct cscfg_feature_csdev *feat_csdev)
0149 {
0150     struct device *dev = csdev->dev.parent;
0151     struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
0152     const struct cscfg_feature_desc *feat_desc = feat_csdev->feat_desc;
0153     u32 offset;
0154     int i = 0, err = 0;
0155 
0156     /*
0157      * essential we set the device spinlock - this is used in the generic
0158      * programming routines when copying values into the drvdata structures
0159      * via the pointers setup in etm4_cfg_map_reg_offset().
0160      */
0161     feat_csdev->drv_spinlock = &drvdata->spinlock;
0162 
0163     /* process the register descriptions */
0164     for (i = 0; i < feat_csdev->nr_regs && !err; i++) {
0165         offset = feat_desc->regs_desc[i].offset;
0166         err = etm4_cfg_map_reg_offset(drvdata, &feat_csdev->regs_csdev[i], offset);
0167     }
0168     return err;
0169 }
0170 
0171 /* match information when loading configurations */
0172 #define CS_CFG_ETM4_MATCH_FLAGS (CS_CFG_MATCH_CLASS_SRC_ALL | \
0173                  CS_CFG_MATCH_CLASS_SRC_ETM4)
0174 
0175 int etm4_cscfg_register(struct coresight_device *csdev)
0176 {
0177     struct cscfg_csdev_feat_ops ops;
0178 
0179     ops.load_feat = &etm4_cfg_load_feature;
0180 
0181     return cscfg_register_csdev(csdev, CS_CFG_ETM4_MATCH_FLAGS, &ops);
0182 }