Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/soc/tegra/cbb/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 45 kB image not shown  

Quelle  tegra234-cbb.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2021-2025, NVIDIA CORPORATION. All rights reserved
 *
 * The driver handles Error's from Control Backbone(CBB) version 2.0.
 * generated due to illegal accesses. The driver prints debug information
 * about failed transaction on receiving interrupt from Error Notifier.
 * Error types supported by CBB2.0 are:
 *   UNSUPPORTED_ERR, PWRDOWN_ERR, TIMEOUT_ERR, FIREWALL_ERR, DECODE_ERR,
 *   TARGET_ERR
 */


#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/cpufeature.h>
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <soc/tegra/fuse.h>
#include <soc/tegra/tegra-cbb.h>

#define FABRIC_EN_CFG_INTERRUPT_ENABLE_0_0 0x0
#define FABRIC_EN_CFG_STATUS_0_0  0x40
#define FABRIC_EN_CFG_ADDR_INDEX_0_0  0x60
#define FABRIC_EN_CFG_ADDR_LOW_0  0x80
#define FABRIC_EN_CFG_ADDR_HI_0   0x84

#define FABRIC_EN_CFG_TARGET_NODE_ADDR_INDEX_0_0 0x100
#define FABRIC_EN_CFG_TARGET_NODE_ADDR_LOW_0    0x140
#define FABRIC_EN_CFG_TARGET_NODE_ADDR_HI_0     0x144

#define FABRIC_MN_INITIATOR_ERR_EN_0  0x200
#define FABRIC_MN_INITIATOR_ERR_FORCE_0  0x204
#define FABRIC_MN_INITIATOR_ERR_STATUS_0 0x208
#define FABRIC_MN_INITIATOR_ERR_OVERFLOW_STATUS_0 0x20c

#define FABRIC_MN_INITIATOR_LOG_ERR_STATUS_0 0x300
#define FABRIC_MN_INITIATOR_LOG_ADDR_LOW_0 0x304
#define FABRIC_MN_INITIATOR_LOG_ADDR_HIGH_0 0x308
#define FABRIC_MN_INITIATOR_LOG_ATTRIBUTES0_0 0x30c
#define FABRIC_MN_INITIATOR_LOG_ATTRIBUTES1_0 0x310
#define FABRIC_MN_INITIATOR_LOG_ATTRIBUTES2_0 0x314
#define FABRIC_MN_INITIATOR_LOG_USER_BITS0_0 0x318

#define AXI_SLV_TIMEOUT_STATUS_0_0  0x8
#define APB_BLOCK_TMO_STATUS_0   0xc00
#define APB_BLOCK_NUM_TMO_OFFSET  0x20

#define FAB_EM_EL_MSTRID  GENMASK(29, 24)
#define FAB_EM_EL_VQC   GENMASK(17, 16)
#define FAB_EM_EL_GRPSEC  GENMASK(14, 8)
#define FAB_EM_EL_FALCONSEC  GENMASK(1, 0)

#define FAB_EM_EL_FABID   GENMASK(20, 16)
#define FAB_EM_EL_TARGETID  GENMASK(7, 0)

#define FAB_EM_EL_ACCESSID  GENMASK(7, 0)

#define FAB_EM_EL_AXCACHE  GENMASK(27, 24)
#define FAB_EM_EL_AXPROT  GENMASK(22, 20)
#define FAB_EM_EL_BURSTLENGTH  GENMASK(19, 12)
#define FAB_EM_EL_BURSTTYPE  GENMASK(9, 8)
#define FAB_EM_EL_BEATSIZE  GENMASK(6, 4)
#define FAB_EM_EL_ACCESSTYPE  GENMASK(0, 0)

#define USRBITS_MSTR_ID   GENMASK(29, 24)

#define REQ_SOCKET_ID   GENMASK(27, 24)

#define CCPLEX_MSTRID   0x1
#define FIREWALL_APERTURE_SZ  0x10000
/* Write firewall check enable */
#define WEN    0x20000

enum tegra234_cbb_fabric_ids {
 T234_CBB_FABRIC_ID,
 T234_SCE_FABRIC_ID,
 T234_RCE_FABRIC_ID,
 T234_DCE_FABRIC_ID,
 T234_AON_FABRIC_ID,
 T234_PSC_FABRIC_ID,
 T234_BPMP_FABRIC_ID,
 T234_FSI_FABRIC_ID,
 T234_MAX_FABRIC_ID,
};

enum tegra264_cbb_fabric_ids {
 T264_SYSTEM_CBB_FABRIC_ID,
 T264_TOP_0_CBB_FABRIC_ID,
 T264_VISION_CBB_FABRIC_ID,
 T264_DISP_USB_CBB_FABRIC_ID,
 T264_UPHY0_CBB_FABRIC_ID,
 T264_RSVD0_FABRIC_ID,
 T264_RSVD1_FABRIC_ID,
 T264_RSVD2_FABRIC_ID,
 T264_RSVD3_FABRIC_ID,
 T264_RSVD4_FABRIC_ID,
 T264_RSVD5_FABRIC_ID,
 T264_AON_FABRIC_ID,
 T264_PSC_FABRIC_ID,
 T264_OESP_FABRIC_ID,
 T264_APE_FABRIC_ID,
 T264_BPMP_FABRIC_ID,
 T264_RCE_0_FABRIC_ID,
 T264_RCE_1_FABRIC_ID,
 T264_RSVD6_FABRIC_ID,
 T264_DCE_FABRIC_ID,
 T264_FSI_FABRIC_ID,
 T264_ISC_FABRIC_ID,
 T264_SB_FABRIC_ID,
 T264_ISC_CPU_FABRIC_ID,
 T264_RSVD7_FABRIC_ID,
};

enum t254_cbb_fabric_ids {
 T254_DCE_FABRIC_ID             = 19,
 T254_DISP_CLUSTER_FABRIC_ID    = 25,
 T254_C2C_FABRIC_ID             = 26,
 T254_GPU_FABRIC_ID             = 27,
 T254_DISP_CLUSTER_1_FABRIC_ID  = 28,
 T254_MAX_FABRIC_ID,
};

struct tegra234_target_lookup {
 const char *name;
 unsigned int offset;
};

struct tegra234_fabric_lookup {
 const char *name;
 bool is_lookup;
 const struct tegra234_target_lookup *target_map;
 const int max_targets;
};

struct tegra234_cbb_fabric {
 int fab_id;
 phys_addr_t off_mask_erd;
 phys_addr_t firewall_base;
 unsigned int firewall_ctl;
 unsigned int firewall_wr_ctl;
 const char * const *initiator_id;
 unsigned int notifier_offset;
 const struct tegra_cbb_error *errors;
 const int max_errors;
 const struct tegra234_fabric_lookup *fab_list;
 const u32 err_intr_enbl;
 const u32 err_status_clr;
};

struct tegra234_cbb {
 struct tegra_cbb base;

 const struct tegra234_cbb_fabric *fabric;
 struct resource *res;
 void __iomem *regs;

 int num_intr;
 int sec_irq;

 /* record */
 void __iomem *mon;
 unsigned int type;
 u32 mask;
 u64 access;
 u32 mn_attr0;
 u32 mn_attr1;
 u32 mn_attr2;
 u32 mn_user_bits;
};

static inline struct tegra234_cbb *to_tegra234_cbb(struct tegra_cbb *cbb)
{
 return container_of(cbb, struct tegra234_cbb, base);
}

static LIST_HEAD(cbb_list);
static DEFINE_SPINLOCK(cbb_lock);

static bool
tegra234_cbb_write_access_allowed(struct platform_device *pdev, struct tegra234_cbb *cbb)
{
 u32 val;

 if (!cbb->fabric->firewall_base ||
     !cbb->fabric->firewall_ctl ||
     !cbb->fabric->firewall_wr_ctl) {
  dev_info(&pdev->dev, "SoC data missing for firewall\n");
  return false;
 }

 if ((cbb->fabric->firewall_ctl > FIREWALL_APERTURE_SZ) ||
     (cbb->fabric->firewall_wr_ctl > FIREWALL_APERTURE_SZ)) {
  dev_err(&pdev->dev, "wrong firewall offset value\n");
  return false;
 }

 val = readl(cbb->regs + cbb->fabric->firewall_base + cbb->fabric->firewall_ctl);
 /*
 * If the firewall check feature for allowing or blocking the
 * write accesses through the firewall of a fabric is disabled
 * then CCPLEX can write to the registers of that fabric.
 */

 if (!(val & WEN))
  return true;

 /*
 * If the firewall check is enabled then check whether CCPLEX
 * has write access to the fabric's error notifier registers
 */

 val = readl(cbb->regs + cbb->fabric->firewall_base + cbb->fabric->firewall_wr_ctl);
 if (val & (BIT(CCPLEX_MSTRID)))
  return true;

 return false;
}

static void tegra234_cbb_fault_enable(struct tegra_cbb *cbb)
{
 struct tegra234_cbb *priv = to_tegra234_cbb(cbb);
 void __iomem *addr;

 addr = priv->regs + priv->fabric->notifier_offset;
 writel(priv->fabric->err_intr_enbl, addr + FABRIC_EN_CFG_INTERRUPT_ENABLE_0_0);
 dsb(sy);
}

static void tegra234_cbb_error_clear(struct tegra_cbb *cbb)
{
 struct tegra234_cbb *priv = to_tegra234_cbb(cbb);

 writel(0, priv->mon + FABRIC_MN_INITIATOR_ERR_FORCE_0);

 writel(priv->fabric->err_status_clr, priv->mon + FABRIC_MN_INITIATOR_ERR_STATUS_0);
 dsb(sy);
}

static u32 tegra234_cbb_get_status(struct tegra_cbb *cbb)
{
 struct tegra234_cbb *priv = to_tegra234_cbb(cbb);
 void __iomem *addr;
 u32 value;

 addr = priv->regs + priv->fabric->notifier_offset;
 value = readl(addr + FABRIC_EN_CFG_STATUS_0_0);
 dsb(sy);

 return value;
}

static void tegra234_cbb_mask_serror(struct tegra234_cbb *cbb)
{
 writel(0x1, cbb->regs + cbb->fabric->off_mask_erd);
 dsb(sy);
}

static u32 tegra234_cbb_get_tmo_slv(void __iomem *addr)
{
 u32 timeout;

 timeout = readl(addr);
 return timeout;
}

static void tegra234_cbb_tmo_slv(struct seq_file *file, const char *target, void __iomem *addr,
     u32 status)
{
 tegra_cbb_print_err(file, "\t %s : %#x\n", target, status);
}

static void tegra234_cbb_lookup_apbslv(struct seq_file *file, const char *target,
           void __iomem *base)
{
 unsigned int block = 0;
 void __iomem *addr;
 char name[64];
 u32 status;

 status = tegra234_cbb_get_tmo_slv(base);
 if (status)
  tegra_cbb_print_err(file, "\t %s_BLOCK_TMO_STATUS : %#x\n", target, status);

 while (status) {
  if (status & BIT(0)) {
   u32 timeout, clients, client = 0;

   addr = base + APB_BLOCK_NUM_TMO_OFFSET + (block * 4);
   timeout = tegra234_cbb_get_tmo_slv(addr);
   clients = timeout;

   while (timeout) {
    if (timeout & BIT(0)) {
     if (clients != 0xffffffff)
      clients &= BIT(client);

     sprintf(name, "%s_BLOCK%d_TMO", target, block);

     tegra234_cbb_tmo_slv(file, name, addr, clients);
    }

    timeout >>= 1;
    client++;
   }
  }

  status >>= 1;
  block++;
 }
}

static void tegra234_sw_lookup_target_timeout(struct seq_file *file, struct tegra234_cbb *cbb,
           u8 target_id, u8 fab_id)
{
 const struct tegra234_target_lookup *map = cbb->fabric->fab_list[fab_id].target_map;
 void __iomem *addr;

 if (target_id >= cbb->fabric->fab_list[fab_id].max_targets) {
  tegra_cbb_print_err(file, "\t Invalid target_id:%d\n", target_id);
  return;
 }

 /*
 * 1) Get target node name and address mapping using target_id.
 * 2) Check if the timed out target node is APB or AXI.
 * 3) If AXI, then print timeout register and reset axi target
 *    using <FABRIC>_SN_<>_SLV_TIMEOUT_STATUS_0_0 register.
 * 4) If APB, then perform an additional lookup to find the client
 *    which timed out.
 * a) Get block number from the index of set bit in
 *    <FABRIC>_SN_AXI2APB_<>_BLOCK_TMO_STATUS_0 register.
 * b) Get address of register respective to block number i.e.
 *    <FABRIC>_SN_AXI2APB_<>_BLOCK<index-set-bit>_TMO_0.
 * c) Read the register in above step to get client_id which
 *    timed out as per the set bits.
 *      d) Reset the timedout client and print details.
 * e) Goto step-a till all bits are set.
 */


 addr = cbb->regs + map[target_id].offset;

 if (strstr(map[target_id].name, "AXI2APB")) {
  addr += APB_BLOCK_TMO_STATUS_0;

  tegra234_cbb_lookup_apbslv(file, map[target_id].name, addr);
 } else {
  char name[64];
  u32 status;

  addr += AXI_SLV_TIMEOUT_STATUS_0_0;

  status = tegra234_cbb_get_tmo_slv(addr);
  if (status) {
   sprintf(name, "%s_SLV_TIMEOUT_STATUS", map[target_id].name);
   tegra234_cbb_tmo_slv(file, name, addr, status);
  }
 }
}

static void tegra234_hw_lookup_target_timeout(struct seq_file *file, struct tegra234_cbb *cbb,
           u8 target_id, u8 fab_id)
{
 unsigned int notifier = cbb->fabric->notifier_offset;
 u32 hi, lo;
 u64 addr;

 writel(target_id, cbb->regs + notifier + FABRIC_EN_CFG_TARGET_NODE_ADDR_INDEX_0_0);

 hi = readl(cbb->regs + notifier + FABRIC_EN_CFG_TARGET_NODE_ADDR_HI_0);
 lo = readl(cbb->regs + notifier + FABRIC_EN_CFG_TARGET_NODE_ADDR_LOW_0);

 addr = (u64)hi << 32 | lo;

 tegra_cbb_print_err(file, "\t Target Node Addr : %#llx\n", addr);
}

static void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb *cbb, u32 status,
         u32 overflow)
{
 unsigned int type = 0;

 if (status & (status - 1))
  tegra_cbb_print_err(file, "\t Multiple type of errors reported\n");

 while (status) {
  if (type >= cbb->fabric->max_errors) {
   tegra_cbb_print_err(file, "\t Wrong type index:%u, status:%u\n",
         type, status);
   return;
  }

  if (status & 0x1)
   tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n",
         cbb->fabric->errors[type].code);

  status >>= 1;
  type++;
 }

 type = 0;

 while (overflow) {
  if (type >= cbb->fabric->max_errors) {
   tegra_cbb_print_err(file, "\t Wrong type index:%u, overflow:%u\n",
         type, overflow);
   return;
  }

  if (overflow & 0x1)
   tegra_cbb_print_err(file, "\t Overflow\t\t: Multiple %s\n",
         cbb->fabric->errors[type].code);

  overflow >>= 1;
  type++;
 }
}

static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb)
{
 u8 cache_type, prot_type, burst_length, mstr_id, grpsec, vqc, falconsec, beat_size;
 u8 access_type, access_id, requester_socket_id, local_socket_id, target_id, fab_id;
 bool is_numa = false;
 u8 burst_type;

 if (num_possible_nodes() > 1)
  is_numa = true;

 mstr_id = FIELD_GET(FAB_EM_EL_MSTRID, cbb->mn_user_bits);
 vqc = FIELD_GET(FAB_EM_EL_VQC, cbb->mn_user_bits);
 grpsec = FIELD_GET(FAB_EM_EL_GRPSEC, cbb->mn_user_bits);
 falconsec = FIELD_GET(FAB_EM_EL_FALCONSEC, cbb->mn_user_bits);

 /*
 * For SOC with multiple NUMA nodes, print cross socket access
 * errors only if initiator_id is CCPLEX, CPMU or GPU.
 */

 if (is_numa) {
  local_socket_id = numa_node_id();
  requester_socket_id = FIELD_GET(REQ_SOCKET_ID, cbb->mn_attr2);

  if (requester_socket_id != local_socket_id) {
   if ((mstr_id != 0x1) && (mstr_id != 0x2) && (mstr_id != 0xB))
    return;
  }
 }

 fab_id = FIELD_GET(FAB_EM_EL_FABID, cbb->mn_attr2);
 target_id = FIELD_GET(FAB_EM_EL_TARGETID, cbb->mn_attr2);

 access_id = FIELD_GET(FAB_EM_EL_ACCESSID, cbb->mn_attr1);

 cache_type = FIELD_GET(FAB_EM_EL_AXCACHE, cbb->mn_attr0);
 prot_type = FIELD_GET(FAB_EM_EL_AXPROT, cbb->mn_attr0);
 burst_length = FIELD_GET(FAB_EM_EL_BURSTLENGTH, cbb->mn_attr0);
 burst_type = FIELD_GET(FAB_EM_EL_BURSTTYPE, cbb->mn_attr0);
 beat_size = FIELD_GET(FAB_EM_EL_BEATSIZE, cbb->mn_attr0);
 access_type = FIELD_GET(FAB_EM_EL_ACCESSTYPE, cbb->mn_attr0);

 tegra_cbb_print_err(file, "\n");
 if (cbb->type < cbb->fabric->max_errors)
  tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n",
        cbb->fabric->errors[cbb->type].code);
 else
  tegra_cbb_print_err(file, "\t Wrong type index:%u\n", cbb->type);

 tegra_cbb_print_err(file, "\t Initiator_Id\t\t: %#x\n", mstr_id);
 if (cbb->fabric->initiator_id)
  tegra_cbb_print_err(file, "\t Initiator\t\t: %s\n",
        cbb->fabric->initiator_id[mstr_id]);

 tegra_cbb_print_err(file, "\t Address\t\t: %#llx\n", cbb->access);

 tegra_cbb_print_cache(file, cache_type);
 tegra_cbb_print_prot(file, prot_type);

 tegra_cbb_print_err(file, "\t Access_Type\t\t: %s", (access_type) ? "Write\n" : "Read\n");
 tegra_cbb_print_err(file, "\t Access_ID\t\t: %#x\n", access_id);

 if (is_numa) {
  tegra_cbb_print_err(file, "\t Requester_Socket_Id\t: %#x\n",
        requester_socket_id);
  tegra_cbb_print_err(file, "\t Local_Socket_Id\t: %#x\n",
        local_socket_id);
  tegra_cbb_print_err(file, "\t No. of NUMA_NODES\t: %#x\n",
        num_possible_nodes());
 }

 tegra_cbb_print_err(file, "\t Fabric\t\t: %s (id:%#x)\n",
       cbb->fabric->fab_list[fab_id].name, fab_id);

 if (of_machine_is_compatible("nvidia,tegra264") && fab_id == T264_UPHY0_CBB_FABRIC_ID) {
  /*
 * In T264, AON Fabric ID value is incorrectly same as UPHY0 fabric ID.
 * For 'ID = 0x4', we must check for the address which caused the error
 * to find the correct fabric which returned error.
 */

  tegra_cbb_print_err(file, "\t or Fabric\t\t: %s\n",
        cbb->fabric->fab_list[T264_AON_FABRIC_ID].name);
  tegra_cbb_print_err(file, "\t Please use Address to determine correct fabric.\n");
 }

 tegra_cbb_print_err(file, "\t Target_Id\t\t: %#x\n", target_id);
 tegra_cbb_print_err(file, "\t Burst_length\t\t: %#x\n", burst_length);
 tegra_cbb_print_err(file, "\t Burst_type\t\t: %#x\n", burst_type);
 tegra_cbb_print_err(file, "\t Beat_size\t\t: %#x\n", beat_size);
 tegra_cbb_print_err(file, "\t VQC\t\t\t: %#x\n", vqc);
 tegra_cbb_print_err(file, "\t GRPSEC\t\t: %#x\n", grpsec);
 tegra_cbb_print_err(file, "\t FALCONSEC\t\t: %#x\n", falconsec);

 if (!cbb->fabric->fab_list[fab_id].is_lookup)
  return;

 /*
 * If is_lookup field is set in fabric_lookup table of soc data, it
 * means that address lookup of target is supported for Timeout errors.
 * If is_lookup is set and the target_map is not populated making
 * max_targets as zero, then it means HW lookup is to be performed.
 */

 if (!strcmp(cbb->fabric->errors[cbb->type].code, "TIMEOUT_ERR")) {
  if (cbb->fabric->fab_list[fab_id].max_targets)
   tegra234_sw_lookup_target_timeout(file, cbb, target_id, fab_id);
  else
   tegra234_hw_lookup_target_timeout(file, cbb, target_id, fab_id);
 }

 return;
}

static int print_errmonX_info(struct seq_file *file, struct tegra234_cbb *cbb)
{
 u32 overflow, status, error;

 status = readl(cbb->mon + FABRIC_MN_INITIATOR_ERR_STATUS_0);
 if (!status) {
  pr_err("Error Notifier received a spurious notification\n");
  return -ENODATA;
 }

 if (status == 0xffffffff) {
  pr_err("CBB registers returning all 1's which is invalid\n");
  return -EINVAL;
 }

 overflow = readl(cbb->mon + FABRIC_MN_INITIATOR_ERR_OVERFLOW_STATUS_0);

 tegra234_cbb_print_error(file, cbb, status, overflow);

 error = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ERR_STATUS_0);
 if (!error) {
  pr_info("Error Monitor doesn't have Error Logger\n");
  return -EINVAL;
 }

 cbb->type = 0;

 while (error) {
  if (error & BIT(0)) {
   u32 hi, lo;

   hi = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ADDR_HIGH_0);
   lo = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ADDR_LOW_0);

   cbb->access = (u64)hi << 32 | lo;

   cbb->mn_attr0 = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ATTRIBUTES0_0);
   cbb->mn_attr1 = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ATTRIBUTES1_0);
   cbb->mn_attr2 = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_ATTRIBUTES2_0);
   cbb->mn_user_bits = readl(cbb->mon + FABRIC_MN_INITIATOR_LOG_USER_BITS0_0);

   print_errlog_err(file, cbb);
  }

  cbb->type++;
  error >>= 1;
 }

 return 0;
}

static int print_err_notifier(struct seq_file *file, struct tegra234_cbb *cbb, u32 status)
{
 unsigned int index = 0;
 int err;

 pr_crit("**************************************\n");
 pr_crit("CPU:%d, Error:%s, Errmon:%d\n", smp_processor_id(),
  cbb->fabric->fab_list[cbb->fabric->fab_id].name, status);

 while (status) {
  if (status & BIT(0)) {
   unsigned int notifier = cbb->fabric->notifier_offset;
   u32 hi, lo, mask = BIT(index);
   phys_addr_t addr;
   u64 offset;

   writel(mask, cbb->regs + notifier + FABRIC_EN_CFG_ADDR_INDEX_0_0);
   hi = readl(cbb->regs + notifier + FABRIC_EN_CFG_ADDR_HI_0);
   lo = readl(cbb->regs + notifier + FABRIC_EN_CFG_ADDR_LOW_0);

   addr = (u64)hi << 32 | lo;

   offset = addr - cbb->res->start;
   cbb->mon = cbb->regs + offset;
   cbb->mask = BIT(index);

   err = print_errmonX_info(file, cbb);
   tegra234_cbb_error_clear(&cbb->base);
   if (err)
    return err;
   tegra_cbb_print_err(file, "\t**************************************\n");
  }

  status >>= 1;
  index++;
 }

 return 0;
}

#ifdef CONFIG_DEBUG_FS
static DEFINE_MUTEX(cbb_debugfs_mutex);

static int tegra234_cbb_debugfs_show(struct tegra_cbb *cbb, struct seq_file *file, void *data)
{
 int err = 0;

 mutex_lock(&cbb_debugfs_mutex);

 list_for_each_entry(cbb, &cbb_list, node) {
  struct tegra234_cbb *priv = to_tegra234_cbb(cbb);
  u32 status;

  status = tegra_cbb_get_status(&priv->base);
  if (status) {
   err = print_err_notifier(file, priv, status);
   if (err)
    break;
  }
 }

 mutex_unlock(&cbb_debugfs_mutex);
 return err;
}
#endif

/*
 * Handler for CBB errors
 */

static irqreturn_t tegra234_cbb_isr(int irq, void *data)
{
 bool is_inband_err = false;
 struct tegra_cbb *cbb;
 unsigned long flags;
 u8 mstr_id;
 int err;

 spin_lock_irqsave(&cbb_lock, flags);

 list_for_each_entry(cbb, &cbb_list, node) {
  struct tegra234_cbb *priv = to_tegra234_cbb(cbb);
  u32 status = tegra_cbb_get_status(cbb);

  if (status && (irq == priv->sec_irq)) {
   tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@0x%llx, irq=%d\n",
         smp_processor_id(),
         priv->fabric->fab_list[priv->fabric->fab_id].name,
         priv->res->start, irq);

   err = print_err_notifier(NULL, priv, status);
   if (err)
    goto unlock;

   /*
 * If illegal request is from CCPLEX(id:0x1) initiator then call WARN()
 */

   if (priv->fabric->off_mask_erd) {
    mstr_id =  FIELD_GET(USRBITS_MSTR_ID, priv->mn_user_bits);
    if (mstr_id == CCPLEX_MSTRID)
     is_inband_err = 1;
   }
  }
 }

unlock:
 spin_unlock_irqrestore(&cbb_lock, flags);
 WARN_ON(is_inband_err);
 return IRQ_HANDLED;
}

/*
 * Register handler for CBB_SECURE interrupt for reporting errors
 */

static int tegra234_cbb_interrupt_enable(struct tegra_cbb *cbb)
{
 struct tegra234_cbb *priv = to_tegra234_cbb(cbb);

 if (priv->sec_irq) {
  int err = devm_request_irq(cbb->dev, priv->sec_irq, tegra234_cbb_isr, 0,
        dev_name(cbb->dev), priv);
  if (err) {
   dev_err(cbb->dev, "failed to register interrupt %u: %d\n", priv->sec_irq,
    err);
   return err;
  }
 }

 return 0;
}

static void tegra234_cbb_error_enable(struct tegra_cbb *cbb)
{
 tegra_cbb_fault_enable(cbb);
}

static const struct tegra_cbb_ops tegra234_cbb_ops = {
 .get_status = tegra234_cbb_get_status,
 .error_clear = tegra234_cbb_error_clear,
 .fault_enable = tegra234_cbb_fault_enable,
 .error_enable = tegra234_cbb_error_enable,
 .interrupt_enable = tegra234_cbb_interrupt_enable,
#ifdef CONFIG_DEBUG_FS
 .debugfs_show = tegra234_cbb_debugfs_show,
#endif
};

static const char * const tegra234_initiator_id[] = {
 [0x00] = "TZ",
 [0x01] = "CCPLEX",
 [0x02] = "CCPMU",
 [0x03] = "BPMP_FW",
 [0x04] = "AON",
 [0x05] = "SCE",
 [0x06] = "GPCDMA_P",
 [0x07] = "TSECA_NONSECURE",
 [0x08] = "TSECA_LIGHTSECURE",
 [0x09] = "TSECA_HEAVYSECURE",
 [0x0a] = "CORESIGHT",
 [0x0b] = "APE",
 [0x0c] = "PEATRANS",
 [0x0d] = "JTAGM_DFT",
 [0x0e] = "RCE",
 [0x0f] = "DCE",
 [0x10] = "PSC_FW_USER",
 [0x11] = "PSC_FW_SUPERVISOR",
 [0x12] = "PSC_FW_MACHINE",
 [0x13] = "PSC_BOOT",
 [0x14] = "BPMP_BOOT",
 [0x15] = "NVDEC_NONSECURE",
 [0x16] = "NVDEC_LIGHTSECURE",
 [0x17] = "NVDEC_HEAVYSECURE",
 [0x18] = "CBB_INTERNAL",
 [0x19] = "RSVD"
};

static const struct tegra_cbb_error tegra234_cbb_errors[] = {
 {
  .code = "TARGET_ERR",
  .desc = "Target being accessed responded with an error"
 }, {
  .code = "DECODE_ERR",
  .desc = "Attempt to access an address hole"
 }, {
  .code = "FIREWALL_ERR",
  .desc = "Attempt to access a region which is firewall protected"
 }, {
  .code = "TIMEOUT_ERR",
  .desc = "No response returned by target"
 }, {
  .code = "PWRDOWN_ERR",
  .desc = "Attempt to access a portion of fabric that is powered down"
 }, {
  .code = "UNSUPPORTED_ERR",
  .desc = "Attempt to access a target through an unsupported access"
 }
};

static const struct tegra234_target_lookup tegra234_aon_target_map[] = {
 { "AXI2APB", 0x00000 },
 { "AST",     0x14000 },
 { "CBB",     0x15000 },
 { "CPU",     0x16000 },
};

static const struct tegra234_target_lookup tegra234_bpmp_target_map[] = {
 { "AXI2APB", 0x00000 },
 { "AST0",    0x15000 },
 { "AST1",    0x16000 },
 { "CBB",     0x17000 },
 { "CPU",     0x18000 },
};

static const struct tegra234_target_lookup tegra234_common_target_map[] = {
 { "AXI2APB", 0x00000 },
 { "AST0",    0x15000 },
 { "AST1",    0x16000 },
 { "CBB",     0x17000 },
 { "RSVD",    0x00000 },
 { "CPU",     0x18000 },
};

static const struct tegra234_target_lookup tegra234_cbb_target_map[] = {
 { "AON",        0x40000 },
 { "BPMP",       0x41000 },
 { "CBB",        0x42000 },
 { "HOST1X",     0x43000 },
 { "STM",        0x44000 },
 { "FSI",        0x45000 },
 { "PSC",        0x46000 },
 { "PCIE_C1",    0x47000 },
 { "PCIE_C2",    0x48000 },
 { "PCIE_C3",    0x49000 },
 { "PCIE_C0",    0x4a000 },
 { "PCIE_C4",    0x4b000 },
 { "GPU",        0x4c000 },
 { "SMMU0",      0x4d000 },
 { "SMMU1",      0x4e000 },
 { "SMMU2",      0x4f000 },
 { "SMMU3",      0x50000 },
 { "SMMU4",      0x51000 },
 { "PCIE_C10",   0x52000 },
 { "PCIE_C7",    0x53000 },
 { "PCIE_C8",    0x54000 },
 { "PCIE_C9",    0x55000 },
 { "PCIE_C5",    0x56000 },
 { "PCIE_C6",    0x57000 },
 { "DCE",        0x58000 },
 { "RCE",        0x59000 },
 { "SCE",        0x5a000 },
 { "AXI2APB_1",  0x70000 },
 { "AXI2APB_10", 0x71000 },
 { "AXI2APB_11", 0x72000 },
 { "AXI2APB_12", 0x73000 },
 { "AXI2APB_13", 0x74000 },
 { "AXI2APB_14", 0x75000 },
 { "AXI2APB_15", 0x76000 },
 { "AXI2APB_16", 0x77000 },
 { "AXI2APB_17", 0x78000 },
 { "AXI2APB_18", 0x79000 },
 { "AXI2APB_19", 0x7a000 },
 { "AXI2APB_2",  0x7b000 },
 { "AXI2APB_20", 0x7c000 },
 { "AXI2APB_21", 0x7d000 },
 { "AXI2APB_22", 0x7e000 },
 { "AXI2APB_23", 0x7f000 },
 { "AXI2APB_25", 0x80000 },
 { "AXI2APB_26", 0x81000 },
 { "AXI2APB_27", 0x82000 },
 { "AXI2APB_28", 0x83000 },
 { "AXI2APB_29", 0x84000 },
 { "AXI2APB_30", 0x85000 },
 { "AXI2APB_31", 0x86000 },
 { "AXI2APB_32", 0x87000 },
 { "AXI2APB_33", 0x88000 },
 { "AXI2APB_34", 0x89000 },
 { "AXI2APB_35", 0x92000 },
 { "AXI2APB_4",  0x8b000 },
 { "AXI2APB_5",  0x8c000 },
 { "AXI2APB_6",  0x8d000 },
 { "AXI2APB_7",  0x8e000 },
 { "AXI2APB_8",  0x8f000 },
 { "AXI2APB_9",  0x90000 },
 { "AXI2APB_3",  0x91000 },
};

static const struct tegra234_fabric_lookup tegra234_cbb_fab_list[] = {
 [T234_CBB_FABRIC_ID] = { "cbb-fabric"true,
     tegra234_cbb_target_map,
     ARRAY_SIZE(tegra234_cbb_target_map) },
 [T234_SCE_FABRIC_ID] = { "sce-fabric"true,
     tegra234_common_target_map,
     ARRAY_SIZE(tegra234_common_target_map) },
 [T234_RCE_FABRIC_ID] = { "rce-fabric"true,
     tegra234_common_target_map,
     ARRAY_SIZE(tegra234_common_target_map) },
 [T234_DCE_FABRIC_ID] = { "dce-fabric"true,
     tegra234_common_target_map,
     ARRAY_SIZE(tegra234_common_target_map) },
 [T234_AON_FABRIC_ID] = { "aon-fabric"true,
     tegra234_aon_target_map,
     ARRAY_SIZE(tegra234_bpmp_target_map) },
 [T234_PSC_FABRIC_ID] = { "psc-fabric" },
 [T234_BPMP_FABRIC_ID] = { "bpmp-fabric"true,
     tegra234_bpmp_target_map,
     ARRAY_SIZE(tegra234_bpmp_target_map) },
 [T234_FSI_FABRIC_ID] = { "fsi-fabric" },
};

static const struct tegra234_cbb_fabric tegra234_aon_fabric = {
 .fab_id = T234_AON_FABRIC_ID,
 .fab_list = tegra234_cbb_fab_list,
 .initiator_id = tegra234_initiator_id,
 .errors = tegra234_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra234_cbb_errors),
 .err_intr_enbl = 0x7,
 .err_status_clr = 0x3f,
 .notifier_offset = 0x17000,
 .firewall_base = 0x30000,
 .firewall_ctl = 0x8d0,
 .firewall_wr_ctl = 0x8c8,
};

static const struct tegra234_cbb_fabric tegra234_bpmp_fabric = {
 .fab_id = T234_BPMP_FABRIC_ID,
 .fab_list = tegra234_cbb_fab_list,
 .initiator_id = tegra234_initiator_id,
 .errors = tegra234_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra234_cbb_errors),
 .err_intr_enbl = 0xf,
 .err_status_clr = 0x3f,
 .notifier_offset = 0x19000,
 .firewall_base = 0x30000,
 .firewall_ctl = 0x8f0,
 .firewall_wr_ctl = 0x8e8,
};

static const struct tegra234_cbb_fabric tegra234_cbb_fabric = {
 .fab_id = T234_CBB_FABRIC_ID,
 .fab_list = tegra234_cbb_fab_list,
 .initiator_id = tegra234_initiator_id,
 .errors = tegra234_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra234_cbb_errors),
 .err_intr_enbl = 0x7f,
 .err_status_clr = 0x3f,
 .notifier_offset = 0x60000,
 .off_mask_erd = 0x3a004,
 .firewall_base = 0x10000,
 .firewall_ctl = 0x23f0,
 .firewall_wr_ctl = 0x23e8,
};

static const struct tegra234_cbb_fabric tegra234_dce_fabric = {
 .fab_id = T234_DCE_FABRIC_ID,
 .fab_list = tegra234_cbb_fab_list,
 .initiator_id = tegra234_initiator_id,
 .errors = tegra234_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra234_cbb_errors),
 .err_intr_enbl = 0xf,
 .err_status_clr = 0x3f,
 .notifier_offset = 0x19000,
 .firewall_base = 0x30000,
 .firewall_ctl = 0x290,
 .firewall_wr_ctl = 0x288,
};

static const struct tegra234_cbb_fabric tegra234_rce_fabric = {
 .fab_id = T234_RCE_FABRIC_ID,
 .fab_list = tegra234_cbb_fab_list,
 .initiator_id = tegra234_initiator_id,
 .errors = tegra234_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra234_cbb_errors),
 .err_intr_enbl = 0xf,
 .err_status_clr = 0x3f,
 .notifier_offset = 0x19000,
 .firewall_base = 0x30000,
 .firewall_ctl = 0x290,
 .firewall_wr_ctl = 0x288,
};

static const struct tegra234_cbb_fabric tegra234_sce_fabric = {
 .fab_id = T234_SCE_FABRIC_ID,
 .fab_list = tegra234_cbb_fab_list,
 .initiator_id = tegra234_initiator_id,
 .errors = tegra234_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra234_cbb_errors),
 .err_intr_enbl = 0xf,
 .err_status_clr = 0x3f,
 .notifier_offset = 0x19000,
 .firewall_base = 0x30000,
 .firewall_ctl = 0x290,
 .firewall_wr_ctl = 0x288,
};

static const char * const tegra241_initiator_id[] = {
 [0x0] = "TZ",
 [0x1] = "CCPLEX",
 [0x2] = "CCPMU",
 [0x3] = "BPMP_FW",
 [0x4] = "PSC_FW_USER",
 [0x5] = "PSC_FW_SUPERVISOR",
 [0x6] = "PSC_FW_MACHINE",
 [0x7] = "PSC_BOOT",
 [0x8] = "BPMP_BOOT",
 [0x9] = "JTAGM_DFT",
 [0xa] = "CORESIGHT",
 [0xb] = "GPU",
 [0xc] = "PEATRANS",
 [0xd ... 0x3f] = "RSVD"
};

/*
 * Possible causes for Target and Timeout errors.
 * TARGET_ERR:
 * Target being accessed responded with an error. Target could return
 * an error for various cases :
 *   Unsupported access, clamp setting when power gated, register
 *   level firewall(SCR), address hole within the target, etc
 *
 * TIMEOUT_ERR:
 * No response returned by target. Can be due to target being clock
 * gated, under reset, powered down or target inability to respond
 * for an internal target issue
 */

static const struct tegra_cbb_error tegra241_cbb_errors[] = {
 {
  .code = "TARGET_ERR",
  .desc = "Target being accessed responded with an error."
 }, {
  .code = "DECODE_ERR",
  .desc = "Attempt to access an address hole or Reserved region of memory."
 }, {
  .code = "FIREWALL_ERR",
  .desc = "Attempt to access a region which is firewalled."
 }, {
  .code = "TIMEOUT_ERR",
  .desc = "No response returned by target."
 }, {
  .code = "PWRDOWN_ERR",
  .desc = "Attempt to access a portion of the fabric that is powered down."
 }, {
  .code = "UNSUPPORTED_ERR",
  .desc = "Attempt to access a target through an unsupported access."
 }, {
  .code = "POISON_ERR",
  .desc = "Target responds with poison error to indicate error in data."
 }, {
  .code = "RSVD"
 }, {
  .code = "RSVD"
 }, {
  .code = "RSVD"
 }, {
  .code = "RSVD"
 }, {
  .code = "RSVD"
 }, {
  .code = "RSVD"
 }, {
  .code = "RSVD"
 }, {
  .code = "RSVD"
 }, {
  .code = "RSVD"
 }, {
  .code = "NO_SUCH_ADDRESS_ERR",
  .desc = "The address belongs to the pri_target range but there is no register "
   "implemented at the address."
 }, {
  .code = "TASK_ERR",
  .desc = "Attempt to update a PRI task when the current task has still not "
   "completed."
 }, {
  .code = "EXTERNAL_ERR",
  .desc = "Indicates that an external PRI register access met with an error due to "
   "any issue in the unit."
 }, {
  .code = "INDEX_ERR",
  .desc = "Applicable to PRI index aperture pair, when the programmed index is "
   "outside the range defined in the manual."
 }, {
  .code = "RESET_ERR",
  .desc = "Target in Reset Error: Attempt to access a SubPri or external PRI "
   "register but they are in reset."
 }, {
  .code = "REGISTER_RST_ERR",
  .desc = "Attempt to access a PRI register but the register is partial or "
   "completely in reset."
 }, {
  .code = "POWER_GATED_ERR",
  .desc = "Returned by external PRI client when the external access goes to a power "
   "gated domain."
 }, {
  .code = "SUBPRI_FS_ERR",
  .desc = "Subpri is floorswept: Attempt to access a subpri through the main pri "
   "target but subPri logic is floorswept."
 }, {
  .code = "SUBPRI_CLK_OFF_ERR",
  .desc = "Subpri clock is off: Attempt to access a subpri through the main pri "
   "target but subPris clock is gated/off."
 },
};

static const struct tegra234_target_lookup tegra241_bpmp_target_map[] = {
 { "RSVD",    0x00000 },
 { "RSVD",    0x00000 },
 { "RSVD",    0x00000 },
 { "CBB",     0x15000 },
 { "CPU",     0x16000 },
 { "AXI2APB", 0x00000 },
 { "DBB0",    0x17000 },
 { "DBB1",    0x18000 },
};

static const struct tegra234_target_lookup tegra241_cbb_target_map[] = {
 { "RSVD",       0x00000 },
 { "PCIE_C8",    0x51000 },
 { "PCIE_C9",    0x52000 },
 { "RSVD",       0x00000 },
 { "RSVD",       0x00000 },
 { "RSVD",       0x00000 },
 { "RSVD",       0x00000 },
 { "RSVD",       0x00000 },
 { "RSVD",       0x00000 },
 { "RSVD",       0x00000 },
 { "RSVD",       0x00000 },
 { "AON",        0x5b000 },
 { "BPMP",       0x5c000 },
 { "RSVD",       0x00000 },
 { "RSVD",       0x00000 },
 { "PSC",        0x5d000 },
 { "STM",        0x5e000 },
 { "AXI2APB_1",  0x70000 },
 { "AXI2APB_10", 0x71000 },
 { "AXI2APB_11", 0x72000 },
 { "AXI2APB_12", 0x73000 },
 { "AXI2APB_13", 0x74000 },
 { "AXI2APB_14", 0x75000 },
 { "AXI2APB_15", 0x76000 },
 { "AXI2APB_16", 0x77000 },
 { "AXI2APB_17", 0x78000 },
 { "AXI2APB_18", 0x79000 },
 { "AXI2APB_19", 0x7a000 },
 { "AXI2APB_2",  0x7b000 },
 { "AXI2APB_20", 0x7c000 },
 { "AXI2APB_4",  0x87000 },
 { "AXI2APB_5",  0x88000 },
 { "AXI2APB_6",  0x89000 },
 { "AXI2APB_7",  0x8a000 },
 { "AXI2APB_8",  0x8b000 },
 { "AXI2APB_9",  0x8c000 },
 { "AXI2APB_3",  0x8d000 },
 { "AXI2APB_21", 0x7d000 },
 { "AXI2APB_22", 0x7e000 },
 { "AXI2APB_23", 0x7f000 },
 { "AXI2APB_24", 0x80000 },
 { "AXI2APB_25", 0x81000 },
 { "AXI2APB_26", 0x82000 },
 { "AXI2APB_27", 0x83000 },
 { "AXI2APB_28", 0x84000 },
 { "PCIE_C4",    0x53000 },
 { "PCIE_C5",    0x54000 },
 { "PCIE_C6",    0x55000 },
 { "PCIE_C7",    0x56000 },
 { "PCIE_C2",    0x57000 },
 { "PCIE_C3",    0x58000 },
 { "PCIE_C0",    0x59000 },
 { "PCIE_C1",    0x5a000 },
 { "CCPLEX",     0x50000 },
 { "AXI2APB_29", 0x85000 },
 { "AXI2APB_30", 0x86000 },
 { "CBB_CENTRAL", 0x00000 },
 { "AXI2APB_31", 0x8E000 },
 { "AXI2APB_32", 0x8F000 },
};

static const struct tegra234_fabric_lookup tegra241_cbb_fab_list[] = {
 [T234_CBB_FABRIC_ID]  = { "cbb-fabric"true,
      tegra241_cbb_target_map, ARRAY_SIZE(tegra241_cbb_target_map) },
 [T234_BPMP_FABRIC_ID] = { "bpmp-fabric"true,
      tegra241_bpmp_target_map, ARRAY_SIZE(tegra241_cbb_target_map) },
};
static const struct tegra234_cbb_fabric tegra241_cbb_fabric = {
 .fab_id = T234_CBB_FABRIC_ID,
 .fab_list = tegra241_cbb_fab_list,
 .initiator_id = tegra241_initiator_id,
 .errors = tegra241_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra241_cbb_errors),
 .err_intr_enbl = 0x7,
 .err_status_clr = 0x1ff007f,
 .notifier_offset = 0x60000,
 .off_mask_erd = 0x40004,
 .firewall_base = 0x20000,
 .firewall_ctl = 0x2370,
 .firewall_wr_ctl = 0x2368,
};

static const struct tegra234_cbb_fabric tegra241_bpmp_fabric = {
 .fab_id = T234_BPMP_FABRIC_ID,
 .fab_list = tegra241_cbb_fab_list,
 .initiator_id = tegra241_initiator_id,
 .errors = tegra241_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra241_cbb_errors),
 .err_intr_enbl = 0xf,
 .err_status_clr = 0x1ff007f,
 .notifier_offset = 0x19000,
 .firewall_base = 0x30000,
 .firewall_ctl = 0x8f0,
 .firewall_wr_ctl = 0x8e8,
};

static const char * const tegra264_initiator_id[] = {
 [0x0] = "TZ",
 [0x1] = "CCPLEX",
 [0x2] = "ISC",
 [0x3] = "BPMP_FW",
 [0x4] = "AON",
 [0x5] = "MSS_SEQ",
 [0x6] = "GPCDMA_P",
 [0x7] = "TSECA_NONSECURE",
 [0x8] = "TSECA_LIGHTSECURE",
 [0x9] = "TSECA_HEAVYSECURE",
 [0xa] = "CORESIGHT",
 [0xb] = "APE_0",
 [0xc] = "APE_1",
 [0xd] = "PEATRANS",
 [0xe] = "JTAGM_DFT",
 [0xf] = "RCE",
 [0x10] = "DCE",
 [0x11] = "PSC_FW_USER",
 [0x12] = "PSC_FW_SUPERVISOR",
 [0x13] = "PSC_FW_MACHINE",
 [0x14] = "PSC_BOOT",
 [0x15] = "BPMP_BOOT",
 [0x16] = "GPU_0",
 [0x17] = "GPU_1",
 [0x18] = "GPU_2",
 [0x19] = "GPU_3",
 [0x1a] = "GPU_4",
 [0x1b] = "PSC_EXT_BOOT",
 [0x1c] = "PSC_EXT_RUNTIME",
 [0x1d] = "OESP_EXT",
 [0x1e] = "SB_EXT",
 [0x1f] = "FSI_SAFETY_0",
 [0x20] = "FSI_SAFETY_1",
 [0x21] = "FSI_SAFETY_2",
 [0x22] = "FSI_SAFETY_3",
 [0x23] = "FSI_CHSM",
 [0x24] = "RCE_1",
 [0x25] = "BPMP_OEM_FW",
 [0x26 ... 0x3d] = "RSVD",
 [0x3e] = "CBB_SMN",
 [0x3f] = "CBB_RSVD"
};

static const struct tegra234_target_lookup tegra264_top0_cbb_target_map[] = {
 { "RSVD",               0x000000 },
 { "CBB_CENTRAL",        0xC020000 },
 { "AXI2APB_1",          0x80000 },
 { "AXI2APB_10",         0x81000 },
 { "AXI2APB_11",         0x82000 },
 { "RSVD",               0x00000 },
 { "RSVD",               0x00000 },
 { "AXI2APB_14",         0x83000 },
 { "AXI2APB_15",         0x84000 },
 { "AXI2APB_16",         0x85000 },
 { "AXI2APB_17",         0x86000 },
 { "AXI2APB_2",          0x87000 },
 { "AXI2APB_3",          0x88000 },
 { "RSVD",               0x00000 },
 { "AXI2APB_5",          0x8A000 },
 { "AXI2APB_6",          0x8B000 },
 { "AXI2APB_7",          0x8C000 },
 { "AXI2APB_8",          0x8D000 },
 { "AXI2APB_9",          0x8E000 },
 { "FSI_SLAVE",          0x64000 },
 { "DISP_USB_CBB_T",     0x65000 },
 { "SYSTEM_CBB_T",       0x66000 },
 { "UPHY0_CBB_T",        0x67000 },
 { "VISION_CBB_T",       0x68000 },
 { "CCPLEX_SLAVE",       0x69000 },
 { "PCIE_C0",            0x6A000 },
 { "SMN_UCF_RX_0",       0x6B000 },
 { "SMN_UCF_RX_1",       0x6C000 },
 { "AXI2APB_4",          0x89000 },
};

static const struct tegra234_target_lookup tegra264_sys_cbb_target_map[] = {
 { "RSVD",               0x00000 },
 { "AXI2APB_1",          0xE1000 },
 { "RSVD",               0x00000 },
 { "AON_SLAVE",          0x79000 },
 { "APE_SLAVE",          0x73000 },
 { "BPMP_SLAVE",         0x74000 },
 { "OESP_SLAVE",         0x75000 },
 { "PSC_SLAVE",          0x76000 },
 { "SB_SLAVE",           0x7A000 },
 { "SMN_SYSTEM_RX",      0x7B000 },
 { "STM",                0x77000 },
 { "RSVD",               0x00000 },
 { "AXI2APB_3",          0xE3000 },
 { "TOP_CBB_T",          0x7C000 },
 { "AXI2APB_2",          0xE4000 },
 { "AXI2APB_4",          0xE5000 },
 { "AXI2APB_5",          0xE6000 },
};

static const struct tegra234_target_lookup tegra264_uphy0_cbb_target_map[] = {
 [0 ... 20] =  { "RSVD", 0x00000 },
 { "AXI2APB_1",          0x71000 },
 { "RSVD",               0x00000 },
 { "AXI2APB_3",          0x75000 },
 { "SMN_UPHY0_RX",       0x53000 },
 { "RSVD",               0x00000 },
 { "RSVD",               0x00000 },
 { "RSVD",               0x00000 },
 { "RSVD",               0x00000 },
 { "PCIE_C4",            0x4B000 },
 { "AXI2APB_2",          0x74000 },
 { "AXI2APB_4",          0x76000 },
 { "AXI2APB_5",          0x77000 },
 { "RSVD",               0x00000 },
 { "AXI2APB_7",          0x79000 },
 { "PCIE_C2",            0x56000 },
 { "RSVD",               0x00000 },
 { "RSVD",               0x00000 },
 { "PCIE_C1",            0x55000 },
 { "RSVD",               0x00000 },
 { "AXI2APB_10",         0x72000 },
 { "AXI2APB_11",         0x7C000 },
 { "AXI2APB_8",          0x7A000 },
 { "AXI2APB_9",          0x7B000 },
 { "RSVD",               0x00000 },
 { "RSVD",               0x00000 },
 { "PCIE_C5",            0x4E000 },
 { "PCIE_C3",            0x58000 },
 { "RSVD",               0x00000 },
 { "ISC_SLAVE",          0x54000 },
 { "TOP_CBB_T",          0x57000 },
 { "AXI2APB_12",         0x7D000 },
 { "AXI2APB_13",         0x70000 },
 { "AXI2APB_6",          0x7E000 },
};

static const struct tegra234_target_lookup tegra264_vision_cbb_target_map[] = {
 [0 ... 5] =       { "RSVD", 0x0 },
 { "HOST1X",             0x45000 },
 { "RSVD",               0x00000 },
 { "RSVD",               0x00000 },
 { "AXI2APB_2",          0x71000 },
 { "RSVD",               0x00000 },
 { "RSVD",               0x00000 },
 { "SMN_VISION_RX",      0x47000 },
 [13 ... 19] =     { "RSVD", 0x0 },
 { "RCE_0_SLAVE",        0x4B000 },
 { "RCE_1_SLAVE",        0x4C000 },
 { "AXI2APB_1",          0x72000 },
 { "AXI2APB_3",          0x73000 },
 { "TOP_CBB_T",          0x4D000 },

};

static const struct tegra234_fabric_lookup tegra264_cbb_fab_list[] = {
 [T264_SYSTEM_CBB_FABRIC_ID]   = { "system-cbb-fabric"true,
       tegra264_sys_cbb_target_map,
       ARRAY_SIZE(tegra264_sys_cbb_target_map) },
 [T264_TOP_0_CBB_FABRIC_ID]    = { "top0-cbb-fabric"true,
       tegra264_top0_cbb_target_map,
       ARRAY_SIZE(tegra264_top0_cbb_target_map) },
 [T264_VISION_CBB_FABRIC_ID]   = { "vision-cbb-fabric"true,
       tegra264_vision_cbb_target_map,
       ARRAY_SIZE(tegra264_vision_cbb_target_map) },
 [T264_DISP_USB_CBB_FABRIC_ID] = { "disp-usb-cbb-fabric" },
 [T264_UPHY0_CBB_FABRIC_ID]    = { "uphy0-cbb-fabric"true,
       tegra264_uphy0_cbb_target_map,
       ARRAY_SIZE(tegra264_uphy0_cbb_target_map) },
 [T264_AON_FABRIC_ID]          = { "aon-fabric" },
 [T264_PSC_FABRIC_ID]          = { "psc-fabric" },
 [T264_OESP_FABRIC_ID]         = { "oesp-fabric" },
 [T264_APE_FABRIC_ID]          = { "ape-fabirc" },
 [T264_BPMP_FABRIC_ID]         = { "bpmp-fabric" },
 [T264_RCE_0_FABRIC_ID]        = { "rce0-fabric" },
 [T264_RCE_1_FABRIC_ID]        = { "rce1-fabric" },
 [T264_DCE_FABRIC_ID]          = { "dce-fabric" },
 [T264_FSI_FABRIC_ID]          = { "fsi-fabric" },
 [T264_ISC_FABRIC_ID]          = { "isc-fabric" },
 [T264_SB_FABRIC_ID]           = { "sb-fabric" },
 [T264_ISC_CPU_FABRIC_ID]      = { "isc-cpu-fabric" },
};

static const struct tegra234_cbb_fabric tegra264_top0_cbb_fabric = {
 .fab_id = T264_TOP_0_CBB_FABRIC_ID,
 .fab_list = tegra264_cbb_fab_list,
 .initiator_id = tegra264_initiator_id,
 .errors = tegra241_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra241_cbb_errors),
 .err_intr_enbl = 0x7,
 .err_status_clr = 0x1ff007f,
 .notifier_offset = 0x90000,
 .off_mask_erd    = 0x4a004,
 .firewall_base   = 0x3c0000,
 .firewall_ctl    = 0x5b0,
 .firewall_wr_ctl = 0x5a8,
};

static const struct tegra234_cbb_fabric tegra264_sys_cbb_fabric = {
 .fab_id = T264_SYSTEM_CBB_FABRIC_ID,
 .fab_list = tegra264_cbb_fab_list,
 .initiator_id = tegra264_initiator_id,
 .errors = tegra241_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra241_cbb_errors),
 .err_intr_enbl = 0xf,
 .err_status_clr = 0x1ff007f,
 .notifier_offset = 0x40000,
 .firewall_base   = 0x29c000,
 .firewall_ctl    = 0x170,
 .firewall_wr_ctl = 0x168,
};

static const struct tegra234_cbb_fabric tegra264_uphy0_cbb_fabric = {
 .fab_id = T264_UPHY0_CBB_FABRIC_ID,
 .fab_list = tegra264_cbb_fab_list,
 .initiator_id = tegra264_initiator_id,
 .errors = tegra241_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra241_cbb_errors),
 .err_intr_enbl = 0x1,
 .err_status_clr = 0x1ff007f,
 .notifier_offset = 0x80000,
 .firewall_base   = 0x360000,
 .firewall_ctl    = 0x590,
 .firewall_wr_ctl = 0x588,
};

static const struct tegra234_cbb_fabric tegra264_vision_cbb_fabric = {
 .fab_id = T264_VISION_CBB_FABRIC_ID,
 .fab_list = tegra264_cbb_fab_list,
 .initiator_id = tegra264_initiator_id,
 .errors = tegra241_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra241_cbb_errors),
 .err_intr_enbl = 0x1,
 .err_status_clr = 0x1ff007f,
 .notifier_offset = 0x80000,
 .firewall_base   = 0x290000,
 .firewall_ctl    = 0x5d0,
 .firewall_wr_ctl = 0x5c8,
};

static const struct tegra234_fabric_lookup t254_cbb_fab_list[] = {
 [T254_C2C_FABRIC_ID] = { "c2c-fabric"true },
 [T254_DISP_CLUSTER_FABRIC_ID] = { "display-cluster-fabric"true },
 [T254_GPU_FABRIC_ID] = { "gpu-fabric"true },
};

static const struct tegra234_cbb_fabric t254_c2c_fabric = {
 .fab_id = T254_C2C_FABRIC_ID,
 .fab_list = t254_cbb_fab_list,
 .errors = tegra241_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra241_cbb_errors),
 .err_intr_enbl = 0xf,
 .err_status_clr = 0x1ff007f,
 .notifier_offset = 0x50000,
 .off_mask_erd = 0x14004,
 .firewall_base = 0x40000,
 .firewall_ctl = 0x9b0,
 .firewall_wr_ctl = 0x9a8,
};

static const struct tegra234_cbb_fabric t254_disp_fabric = {
 .fab_id = T254_DISP_CLUSTER_FABRIC_ID,
 .fab_list = t254_cbb_fab_list,
 .errors = tegra241_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra241_cbb_errors),
 .err_intr_enbl = 0x1,
 .err_status_clr = 0x1ff007f,
 .notifier_offset = 0x50000,
 .firewall_base = 0x30000,
 .firewall_ctl = 0x810,
 .firewall_wr_ctl = 0x808,
};

static const struct tegra234_cbb_fabric t254_gpu_fabric = {
 .fab_id = T254_GPU_FABRIC_ID,
 .fab_list = t254_cbb_fab_list,
 .errors = tegra241_cbb_errors,
 .max_errors = ARRAY_SIZE(tegra241_cbb_errors),
 .err_intr_enbl = 0x1f,
 .err_status_clr = 0x1ff007f,
 .notifier_offset = 0x50000,
 .firewall_base = 0x30000,
 .firewall_ctl = 0x930,
 .firewall_wr_ctl = 0x928,
};

static const struct of_device_id tegra234_cbb_dt_ids[] = {
 { .compatible = "nvidia,tegra234-cbb-fabric", .data = &tegra234_cbb_fabric },
 { .compatible = "nvidia,tegra234-aon-fabric", .data = &tegra234_aon_fabric },
 { .compatible = "nvidia,tegra234-bpmp-fabric", .data = &tegra234_bpmp_fabric },
 { .compatible = "nvidia,tegra234-dce-fabric", .data = &tegra234_dce_fabric },
 { .compatible = "nvidia,tegra234-rce-fabric", .data = &tegra234_rce_fabric },
 { .compatible = "nvidia,tegra234-sce-fabric", .data = &tegra234_sce_fabric },
 { .compatible = "nvidia,tegra264-sys-cbb-fabric", .data = &tegra264_sys_cbb_fabric },
 { .compatible = "nvidia,tegra264-top0-cbb-fabric", .data = &tegra264_top0_cbb_fabric },
 { .compatible = "nvidia,tegra264-uphy0-cbb-fabric", .data = &tegra264_uphy0_cbb_fabric },
 { .compatible = "nvidia,tegra264-vision-cbb-fabric", .data = &tegra264_vision_cbb_fabric },
 { /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, tegra234_cbb_dt_ids);

struct tegra234_cbb_acpi_uid {
 const char *hid;
 const char *uid;
 const struct tegra234_cbb_fabric *fabric;
};

static const struct tegra234_cbb_acpi_uid tegra234_cbb_acpi_uids[] = {
 { "NVDA1070""1", &tegra241_cbb_fabric },
 { "NVDA1070""2", &tegra241_bpmp_fabric },
 { "NVDA1070""3", &t254_c2c_fabric },
 { "NVDA1070""4", &t254_disp_fabric },
 { "NVDA1070""5", &t254_gpu_fabric },
 { },
};

static const struct
tegra234_cbb_fabric *tegra234_cbb_acpi_get_fabric(struct acpi_device *adev)
{
 const struct tegra234_cbb_acpi_uid *entry;

 for (entry = tegra234_cbb_acpi_uids; entry->hid; entry++) {
  if (acpi_dev_hid_uid_match(adev, entry->hid, entry->uid))
   return entry->fabric;
 }

 return NULL;
}

static const struct acpi_device_id tegra241_cbb_acpi_ids[] = {
 { "NVDA1070" },
 { },
};
MODULE_DEVICE_TABLE(acpi, tegra241_cbb_acpi_ids);

static int tegra234_cbb_probe(struct platform_device *pdev)
{
 const struct tegra234_cbb_fabric *fabric;
 struct tegra234_cbb *cbb;
 unsigned long flags = 0;
 int err;

 if (pdev->dev.of_node) {
  fabric = of_device_get_match_data(&pdev->dev);
 } else {
  struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
  if (!device)
   return -ENODEV;

  fabric = tegra234_cbb_acpi_get_fabric(device);
  if (!fabric) {
   dev_err(&pdev->dev, "no device match found\n");
   return -ENODEV;
  }
 }

 cbb = devm_kzalloc(&pdev->dev, sizeof(*cbb), GFP_KERNEL);
 if (!cbb)
  return -ENOMEM;

 INIT_LIST_HEAD(&cbb->base.node);
 cbb->base.ops = &tegra234_cbb_ops;
 cbb->base.dev = &pdev->dev;
 cbb->fabric = fabric;

 cbb->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &cbb->res);
 if (IS_ERR(cbb->regs))
  return PTR_ERR(cbb->regs);

 err = tegra_cbb_get_irq(pdev, NULL, &cbb->sec_irq);
 if (err)
  return err;

 platform_set_drvdata(pdev, cbb);

 /*
 * Don't enable error reporting for a Fabric if write to it's registers
 * is blocked by CBB firewall.
 */

 if (!tegra234_cbb_write_access_allowed(pdev, cbb)) {
  dev_info(&pdev->dev, "error reporting not enabled due to firewall\n");
  return 0;
 }

 spin_lock_irqsave(&cbb_lock, flags);
 list_add(&cbb->base.node, &cbb_list);
 spin_unlock_irqrestore(&cbb_lock, flags);

 /* set ERD bit to mask SError and generate interrupt to report error */
 if (cbb->fabric->off_mask_erd)
  tegra234_cbb_mask_serror(cbb);

 return tegra_cbb_register(&cbb->base);
}

static int __maybe_unused tegra234_cbb_resume_noirq(struct device *dev)
{
 struct tegra234_cbb *cbb = dev_get_drvdata(dev);

 tegra234_cbb_error_enable(&cbb->base);

 dev_dbg(dev, "%s resumed\n", cbb->fabric->fab_list[cbb->fabric->fab_id].name);

 return 0;
}

static const struct dev_pm_ops tegra234_cbb_pm = {
 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, tegra234_cbb_resume_noirq)
};

static struct platform_driver tegra234_cbb_driver = {
 .probe = tegra234_cbb_probe,
 .driver = {
  .name = "tegra234-cbb",
  .of_match_table = tegra234_cbb_dt_ids,
  .acpi_match_table = tegra241_cbb_acpi_ids,
  .pm = &tegra234_cbb_pm,
 },
};

static int __init tegra234_cbb_init(void)
{
 return platform_driver_register(&tegra234_cbb_driver);
}
pure_initcall(tegra234_cbb_init);

static void __exit tegra234_cbb_exit(void)
{
 platform_driver_unregister(&tegra234_cbb_driver);
}
module_exit(tegra234_cbb_exit);

MODULE_DESCRIPTION("Control Backbone 2.0 error handling driver for Tegra234");

Messung V0.5
C=97 H=98 G=97

¤ Dauer der Verarbeitung: 0.13 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.