162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * The driver handles Error's from Control Backbone(CBB) version 2.0. 662306a36Sopenharmony_ci * generated due to illegal accesses. The driver prints debug information 762306a36Sopenharmony_ci * about failed transaction on receiving interrupt from Error Notifier. 862306a36Sopenharmony_ci * Error types supported by CBB2.0 are: 962306a36Sopenharmony_ci * UNSUPPORTED_ERR, PWRDOWN_ERR, TIMEOUT_ERR, FIREWALL_ERR, DECODE_ERR, 1062306a36Sopenharmony_ci * SLAVE_ERR 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/acpi.h> 1462306a36Sopenharmony_ci#include <linux/clk.h> 1562306a36Sopenharmony_ci#include <linux/cpufeature.h> 1662306a36Sopenharmony_ci#include <linux/debugfs.h> 1762306a36Sopenharmony_ci#include <linux/module.h> 1862306a36Sopenharmony_ci#include <linux/of.h> 1962306a36Sopenharmony_ci#include <linux/platform_device.h> 2062306a36Sopenharmony_ci#include <linux/device.h> 2162306a36Sopenharmony_ci#include <linux/io.h> 2262306a36Sopenharmony_ci#include <linux/interrupt.h> 2362306a36Sopenharmony_ci#include <linux/ioport.h> 2462306a36Sopenharmony_ci#include <soc/tegra/fuse.h> 2562306a36Sopenharmony_ci#include <soc/tegra/tegra-cbb.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define FABRIC_EN_CFG_INTERRUPT_ENABLE_0_0 0x0 2862306a36Sopenharmony_ci#define FABRIC_EN_CFG_STATUS_0_0 0x40 2962306a36Sopenharmony_ci#define FABRIC_EN_CFG_ADDR_INDEX_0_0 0x60 3062306a36Sopenharmony_ci#define FABRIC_EN_CFG_ADDR_LOW_0 0x80 3162306a36Sopenharmony_ci#define FABRIC_EN_CFG_ADDR_HI_0 0x84 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define FABRIC_MN_MASTER_ERR_EN_0 0x200 3462306a36Sopenharmony_ci#define FABRIC_MN_MASTER_ERR_FORCE_0 0x204 3562306a36Sopenharmony_ci#define FABRIC_MN_MASTER_ERR_STATUS_0 0x208 3662306a36Sopenharmony_ci#define FABRIC_MN_MASTER_ERR_OVERFLOW_STATUS_0 0x20c 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define FABRIC_MN_MASTER_LOG_ERR_STATUS_0 0x300 3962306a36Sopenharmony_ci#define FABRIC_MN_MASTER_LOG_ADDR_LOW_0 0x304 4062306a36Sopenharmony_ci#define FABRIC_MN_MASTER_LOG_ADDR_HIGH_0 0x308 4162306a36Sopenharmony_ci#define FABRIC_MN_MASTER_LOG_ATTRIBUTES0_0 0x30c 4262306a36Sopenharmony_ci#define FABRIC_MN_MASTER_LOG_ATTRIBUTES1_0 0x310 4362306a36Sopenharmony_ci#define FABRIC_MN_MASTER_LOG_ATTRIBUTES2_0 0x314 4462306a36Sopenharmony_ci#define FABRIC_MN_MASTER_LOG_USER_BITS0_0 0x318 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define AXI_SLV_TIMEOUT_STATUS_0_0 0x8 4762306a36Sopenharmony_ci#define APB_BLOCK_TMO_STATUS_0 0xc00 4862306a36Sopenharmony_ci#define APB_BLOCK_NUM_TMO_OFFSET 0x20 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define FAB_EM_EL_MSTRID GENMASK(29, 24) 5162306a36Sopenharmony_ci#define FAB_EM_EL_VQC GENMASK(17, 16) 5262306a36Sopenharmony_ci#define FAB_EM_EL_GRPSEC GENMASK(14, 8) 5362306a36Sopenharmony_ci#define FAB_EM_EL_FALCONSEC GENMASK(1, 0) 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define FAB_EM_EL_FABID GENMASK(20, 16) 5662306a36Sopenharmony_ci#define FAB_EM_EL_SLAVEID GENMASK(7, 0) 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define FAB_EM_EL_ACCESSID GENMASK(7, 0) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define FAB_EM_EL_AXCACHE GENMASK(27, 24) 6162306a36Sopenharmony_ci#define FAB_EM_EL_AXPROT GENMASK(22, 20) 6262306a36Sopenharmony_ci#define FAB_EM_EL_BURSTLENGTH GENMASK(19, 12) 6362306a36Sopenharmony_ci#define FAB_EM_EL_BURSTTYPE GENMASK(9, 8) 6462306a36Sopenharmony_ci#define FAB_EM_EL_BEATSIZE GENMASK(6, 4) 6562306a36Sopenharmony_ci#define FAB_EM_EL_ACCESSTYPE GENMASK(0, 0) 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define USRBITS_MSTR_ID GENMASK(29, 24) 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci#define REQ_SOCKET_ID GENMASK(27, 24) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define CCPLEX_MSTRID 0x1 7262306a36Sopenharmony_ci#define FIREWALL_APERTURE_SZ 0x10000 7362306a36Sopenharmony_ci/* Write firewall check enable */ 7462306a36Sopenharmony_ci#define WEN 0x20000 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cienum tegra234_cbb_fabric_ids { 7762306a36Sopenharmony_ci CBB_FAB_ID, 7862306a36Sopenharmony_ci SCE_FAB_ID, 7962306a36Sopenharmony_ci RCE_FAB_ID, 8062306a36Sopenharmony_ci DCE_FAB_ID, 8162306a36Sopenharmony_ci AON_FAB_ID, 8262306a36Sopenharmony_ci PSC_FAB_ID, 8362306a36Sopenharmony_ci BPMP_FAB_ID, 8462306a36Sopenharmony_ci FSI_FAB_ID, 8562306a36Sopenharmony_ci MAX_FAB_ID, 8662306a36Sopenharmony_ci}; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistruct tegra234_slave_lookup { 8962306a36Sopenharmony_ci const char *name; 9062306a36Sopenharmony_ci unsigned int offset; 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistruct tegra234_cbb_fabric { 9462306a36Sopenharmony_ci const char *name; 9562306a36Sopenharmony_ci phys_addr_t off_mask_erd; 9662306a36Sopenharmony_ci phys_addr_t firewall_base; 9762306a36Sopenharmony_ci unsigned int firewall_ctl; 9862306a36Sopenharmony_ci unsigned int firewall_wr_ctl; 9962306a36Sopenharmony_ci const char * const *master_id; 10062306a36Sopenharmony_ci unsigned int notifier_offset; 10162306a36Sopenharmony_ci const struct tegra_cbb_error *errors; 10262306a36Sopenharmony_ci const int max_errors; 10362306a36Sopenharmony_ci const struct tegra234_slave_lookup *slave_map; 10462306a36Sopenharmony_ci const int max_slaves; 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistruct tegra234_cbb { 10862306a36Sopenharmony_ci struct tegra_cbb base; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci const struct tegra234_cbb_fabric *fabric; 11162306a36Sopenharmony_ci struct resource *res; 11262306a36Sopenharmony_ci void __iomem *regs; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci int num_intr; 11562306a36Sopenharmony_ci int sec_irq; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* record */ 11862306a36Sopenharmony_ci void __iomem *mon; 11962306a36Sopenharmony_ci unsigned int type; 12062306a36Sopenharmony_ci u32 mask; 12162306a36Sopenharmony_ci u64 access; 12262306a36Sopenharmony_ci u32 mn_attr0; 12362306a36Sopenharmony_ci u32 mn_attr1; 12462306a36Sopenharmony_ci u32 mn_attr2; 12562306a36Sopenharmony_ci u32 mn_user_bits; 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic inline struct tegra234_cbb *to_tegra234_cbb(struct tegra_cbb *cbb) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci return container_of(cbb, struct tegra234_cbb, base); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic LIST_HEAD(cbb_list); 13462306a36Sopenharmony_cistatic DEFINE_SPINLOCK(cbb_lock); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic bool 13762306a36Sopenharmony_citegra234_cbb_write_access_allowed(struct platform_device *pdev, struct tegra234_cbb *cbb) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci u32 val; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if (!cbb->fabric->firewall_base || 14262306a36Sopenharmony_ci !cbb->fabric->firewall_ctl || 14362306a36Sopenharmony_ci !cbb->fabric->firewall_wr_ctl) { 14462306a36Sopenharmony_ci dev_info(&pdev->dev, "SoC data missing for firewall\n"); 14562306a36Sopenharmony_ci return false; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if ((cbb->fabric->firewall_ctl > FIREWALL_APERTURE_SZ) || 14962306a36Sopenharmony_ci (cbb->fabric->firewall_wr_ctl > FIREWALL_APERTURE_SZ)) { 15062306a36Sopenharmony_ci dev_err(&pdev->dev, "wrong firewall offset value\n"); 15162306a36Sopenharmony_ci return false; 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci val = readl(cbb->regs + cbb->fabric->firewall_base + cbb->fabric->firewall_ctl); 15562306a36Sopenharmony_ci /* 15662306a36Sopenharmony_ci * If the firewall check feature for allowing or blocking the 15762306a36Sopenharmony_ci * write accesses through the firewall of a fabric is disabled 15862306a36Sopenharmony_ci * then CCPLEX can write to the registers of that fabric. 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_ci if (!(val & WEN)) 16162306a36Sopenharmony_ci return true; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci /* 16462306a36Sopenharmony_ci * If the firewall check is enabled then check whether CCPLEX 16562306a36Sopenharmony_ci * has write access to the fabric's error notifier registers 16662306a36Sopenharmony_ci */ 16762306a36Sopenharmony_ci val = readl(cbb->regs + cbb->fabric->firewall_base + cbb->fabric->firewall_wr_ctl); 16862306a36Sopenharmony_ci if (val & (BIT(CCPLEX_MSTRID))) 16962306a36Sopenharmony_ci return true; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return false; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic void tegra234_cbb_fault_enable(struct tegra_cbb *cbb) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 17762306a36Sopenharmony_ci void __iomem *addr; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci addr = priv->regs + priv->fabric->notifier_offset; 18062306a36Sopenharmony_ci writel(0x1ff, addr + FABRIC_EN_CFG_INTERRUPT_ENABLE_0_0); 18162306a36Sopenharmony_ci dsb(sy); 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic void tegra234_cbb_error_clear(struct tegra_cbb *cbb) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci writel(0x3f, priv->mon + FABRIC_MN_MASTER_ERR_STATUS_0); 18962306a36Sopenharmony_ci dsb(sy); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic u32 tegra234_cbb_get_status(struct tegra_cbb *cbb) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 19562306a36Sopenharmony_ci void __iomem *addr; 19662306a36Sopenharmony_ci u32 value; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci addr = priv->regs + priv->fabric->notifier_offset; 19962306a36Sopenharmony_ci value = readl(addr + FABRIC_EN_CFG_STATUS_0_0); 20062306a36Sopenharmony_ci dsb(sy); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci return value; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic void tegra234_cbb_mask_serror(struct tegra234_cbb *cbb) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci writel(0x1, cbb->regs + cbb->fabric->off_mask_erd); 20862306a36Sopenharmony_ci dsb(sy); 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic u32 tegra234_cbb_get_tmo_slv(void __iomem *addr) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci u32 timeout; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci timeout = readl(addr); 21662306a36Sopenharmony_ci return timeout; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic void tegra234_cbb_tmo_slv(struct seq_file *file, const char *slave, void __iomem *addr, 22062306a36Sopenharmony_ci u32 status) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t %s : %#x\n", slave, status); 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic void tegra234_cbb_lookup_apbslv(struct seq_file *file, const char *slave, 22662306a36Sopenharmony_ci void __iomem *base) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci unsigned int block = 0; 22962306a36Sopenharmony_ci void __iomem *addr; 23062306a36Sopenharmony_ci char name[64]; 23162306a36Sopenharmony_ci u32 status; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci status = tegra234_cbb_get_tmo_slv(base); 23462306a36Sopenharmony_ci if (status) 23562306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t %s_BLOCK_TMO_STATUS : %#x\n", slave, status); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci while (status) { 23862306a36Sopenharmony_ci if (status & BIT(0)) { 23962306a36Sopenharmony_ci u32 timeout, clients, client = 0; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci addr = base + APB_BLOCK_NUM_TMO_OFFSET + (block * 4); 24262306a36Sopenharmony_ci timeout = tegra234_cbb_get_tmo_slv(addr); 24362306a36Sopenharmony_ci clients = timeout; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci while (timeout) { 24662306a36Sopenharmony_ci if (timeout & BIT(0)) { 24762306a36Sopenharmony_ci if (clients != 0xffffffff) 24862306a36Sopenharmony_ci clients &= BIT(client); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci sprintf(name, "%s_BLOCK%d_TMO", slave, block); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci tegra234_cbb_tmo_slv(file, name, addr, clients); 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci timeout >>= 1; 25662306a36Sopenharmony_ci client++; 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci status >>= 1; 26162306a36Sopenharmony_ci block++; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic void tegra234_lookup_slave_timeout(struct seq_file *file, struct tegra234_cbb *cbb, 26662306a36Sopenharmony_ci u8 slave_id, u8 fab_id) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci const struct tegra234_slave_lookup *map = cbb->fabric->slave_map; 26962306a36Sopenharmony_ci void __iomem *addr; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* 27262306a36Sopenharmony_ci * 1) Get slave node name and address mapping using slave_id. 27362306a36Sopenharmony_ci * 2) Check if the timed out slave node is APB or AXI. 27462306a36Sopenharmony_ci * 3) If AXI, then print timeout register and reset axi slave 27562306a36Sopenharmony_ci * using <FABRIC>_SN_<>_SLV_TIMEOUT_STATUS_0_0 register. 27662306a36Sopenharmony_ci * 4) If APB, then perform an additional lookup to find the client 27762306a36Sopenharmony_ci * which timed out. 27862306a36Sopenharmony_ci * a) Get block number from the index of set bit in 27962306a36Sopenharmony_ci * <FABRIC>_SN_AXI2APB_<>_BLOCK_TMO_STATUS_0 register. 28062306a36Sopenharmony_ci * b) Get address of register repective to block number i.e. 28162306a36Sopenharmony_ci * <FABRIC>_SN_AXI2APB_<>_BLOCK<index-set-bit>_TMO_0. 28262306a36Sopenharmony_ci * c) Read the register in above step to get client_id which 28362306a36Sopenharmony_ci * timed out as per the set bits. 28462306a36Sopenharmony_ci * d) Reset the timedout client and print details. 28562306a36Sopenharmony_ci * e) Goto step-a till all bits are set. 28662306a36Sopenharmony_ci */ 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci addr = cbb->regs + map[slave_id].offset; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci if (strstr(map[slave_id].name, "AXI2APB")) { 29162306a36Sopenharmony_ci addr += APB_BLOCK_TMO_STATUS_0; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci tegra234_cbb_lookup_apbslv(file, map[slave_id].name, addr); 29462306a36Sopenharmony_ci } else { 29562306a36Sopenharmony_ci char name[64]; 29662306a36Sopenharmony_ci u32 status; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci addr += AXI_SLV_TIMEOUT_STATUS_0_0; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci status = tegra234_cbb_get_tmo_slv(addr); 30162306a36Sopenharmony_ci if (status) { 30262306a36Sopenharmony_ci sprintf(name, "%s_SLV_TIMEOUT_STATUS", map[slave_id].name); 30362306a36Sopenharmony_ci tegra234_cbb_tmo_slv(file, name, addr, status); 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb *cbb, u32 status, 30962306a36Sopenharmony_ci u32 overflow) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci unsigned int type = 0; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (status & (status - 1)) 31462306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Multiple type of errors reported\n"); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci while (status) { 31762306a36Sopenharmony_ci if (type >= cbb->fabric->max_errors) { 31862306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Wrong type index:%u, status:%u\n", 31962306a36Sopenharmony_ci type, status); 32062306a36Sopenharmony_ci return; 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (status & 0x1) 32462306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", 32562306a36Sopenharmony_ci cbb->fabric->errors[type].code); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci status >>= 1; 32862306a36Sopenharmony_ci type++; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci type = 0; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci while (overflow) { 33462306a36Sopenharmony_ci if (type >= cbb->fabric->max_errors) { 33562306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Wrong type index:%u, overflow:%u\n", 33662306a36Sopenharmony_ci type, overflow); 33762306a36Sopenharmony_ci return; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (overflow & 0x1) 34162306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Overflow\t\t: Multiple %s\n", 34262306a36Sopenharmony_ci cbb->fabric->errors[type].code); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci overflow >>= 1; 34562306a36Sopenharmony_ci type++; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cistatic void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci u8 cache_type, prot_type, burst_length, mstr_id, grpsec, vqc, falconsec, beat_size; 35262306a36Sopenharmony_ci u8 access_type, access_id, requester_socket_id, local_socket_id, slave_id, fab_id; 35362306a36Sopenharmony_ci char fabric_name[20]; 35462306a36Sopenharmony_ci bool is_numa = false; 35562306a36Sopenharmony_ci u8 burst_type; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci if (num_possible_nodes() > 1) 35862306a36Sopenharmony_ci is_numa = true; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci mstr_id = FIELD_GET(FAB_EM_EL_MSTRID, cbb->mn_user_bits); 36162306a36Sopenharmony_ci vqc = FIELD_GET(FAB_EM_EL_VQC, cbb->mn_user_bits); 36262306a36Sopenharmony_ci grpsec = FIELD_GET(FAB_EM_EL_GRPSEC, cbb->mn_user_bits); 36362306a36Sopenharmony_ci falconsec = FIELD_GET(FAB_EM_EL_FALCONSEC, cbb->mn_user_bits); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci /* 36662306a36Sopenharmony_ci * For SOC with multiple NUMA nodes, print cross socket access 36762306a36Sopenharmony_ci * errors only if initiator/master_id is CCPLEX, CPMU or GPU. 36862306a36Sopenharmony_ci */ 36962306a36Sopenharmony_ci if (is_numa) { 37062306a36Sopenharmony_ci local_socket_id = numa_node_id(); 37162306a36Sopenharmony_ci requester_socket_id = FIELD_GET(REQ_SOCKET_ID, cbb->mn_attr2); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci if (requester_socket_id != local_socket_id) { 37462306a36Sopenharmony_ci if ((mstr_id != 0x1) && (mstr_id != 0x2) && (mstr_id != 0xB)) 37562306a36Sopenharmony_ci return; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci fab_id = FIELD_GET(FAB_EM_EL_FABID, cbb->mn_attr2); 38062306a36Sopenharmony_ci slave_id = FIELD_GET(FAB_EM_EL_SLAVEID, cbb->mn_attr2); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci access_id = FIELD_GET(FAB_EM_EL_ACCESSID, cbb->mn_attr1); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci cache_type = FIELD_GET(FAB_EM_EL_AXCACHE, cbb->mn_attr0); 38562306a36Sopenharmony_ci prot_type = FIELD_GET(FAB_EM_EL_AXPROT, cbb->mn_attr0); 38662306a36Sopenharmony_ci burst_length = FIELD_GET(FAB_EM_EL_BURSTLENGTH, cbb->mn_attr0); 38762306a36Sopenharmony_ci burst_type = FIELD_GET(FAB_EM_EL_BURSTTYPE, cbb->mn_attr0); 38862306a36Sopenharmony_ci beat_size = FIELD_GET(FAB_EM_EL_BEATSIZE, cbb->mn_attr0); 38962306a36Sopenharmony_ci access_type = FIELD_GET(FAB_EM_EL_ACCESSTYPE, cbb->mn_attr0); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci tegra_cbb_print_err(file, "\n"); 39262306a36Sopenharmony_ci if (cbb->type < cbb->fabric->max_errors) 39362306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", 39462306a36Sopenharmony_ci cbb->fabric->errors[cbb->type].code); 39562306a36Sopenharmony_ci else 39662306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Wrong type index:%u\n", cbb->type); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t MASTER_ID\t\t: %s\n", cbb->fabric->master_id[mstr_id]); 39962306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Address\t\t: %#llx\n", cbb->access); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci tegra_cbb_print_cache(file, cache_type); 40262306a36Sopenharmony_ci tegra_cbb_print_prot(file, prot_type); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Access_Type\t\t: %s", (access_type) ? "Write\n" : "Read\n"); 40562306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Access_ID\t\t: %#x", access_id); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci if (fab_id == PSC_FAB_ID) 40862306a36Sopenharmony_ci strcpy(fabric_name, "psc-fabric"); 40962306a36Sopenharmony_ci else if (fab_id == FSI_FAB_ID) 41062306a36Sopenharmony_ci strcpy(fabric_name, "fsi-fabric"); 41162306a36Sopenharmony_ci else 41262306a36Sopenharmony_ci strcpy(fabric_name, cbb->fabric->name); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci if (is_numa) { 41562306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Requester_Socket_Id\t: %#x\n", 41662306a36Sopenharmony_ci requester_socket_id); 41762306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Local_Socket_Id\t: %#x\n", 41862306a36Sopenharmony_ci local_socket_id); 41962306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t No. of NUMA_NODES\t: %#x\n", 42062306a36Sopenharmony_ci num_possible_nodes()); 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Fabric\t\t: %s\n", fabric_name); 42462306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Slave_Id\t\t: %#x\n", slave_id); 42562306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Burst_length\t\t: %#x\n", burst_length); 42662306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Burst_type\t\t: %#x\n", burst_type); 42762306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Beat_size\t\t: %#x\n", beat_size); 42862306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t VQC\t\t\t: %#x\n", vqc); 42962306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t GRPSEC\t\t: %#x\n", grpsec); 43062306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t FALCONSEC\t\t: %#x\n", falconsec); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if ((fab_id == PSC_FAB_ID) || (fab_id == FSI_FAB_ID)) 43362306a36Sopenharmony_ci return; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci if (slave_id >= cbb->fabric->max_slaves) { 43662306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Invalid slave_id:%d\n", slave_id); 43762306a36Sopenharmony_ci return; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci if (!strcmp(cbb->fabric->errors[cbb->type].code, "TIMEOUT_ERR")) { 44162306a36Sopenharmony_ci tegra234_lookup_slave_timeout(file, cbb, slave_id, fab_id); 44262306a36Sopenharmony_ci return; 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t Slave\t\t\t: %s\n", cbb->fabric->slave_map[slave_id].name); 44662306a36Sopenharmony_ci} 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic int print_errmonX_info(struct seq_file *file, struct tegra234_cbb *cbb) 44962306a36Sopenharmony_ci{ 45062306a36Sopenharmony_ci u32 overflow, status, error; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci status = readl(cbb->mon + FABRIC_MN_MASTER_ERR_STATUS_0); 45362306a36Sopenharmony_ci if (!status) { 45462306a36Sopenharmony_ci pr_err("Error Notifier received a spurious notification\n"); 45562306a36Sopenharmony_ci return -ENODATA; 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci if (status == 0xffffffff) { 45962306a36Sopenharmony_ci pr_err("CBB registers returning all 1's which is invalid\n"); 46062306a36Sopenharmony_ci return -EINVAL; 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci overflow = readl(cbb->mon + FABRIC_MN_MASTER_ERR_OVERFLOW_STATUS_0); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci tegra234_cbb_print_error(file, cbb, status, overflow); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci error = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ERR_STATUS_0); 46862306a36Sopenharmony_ci if (!error) { 46962306a36Sopenharmony_ci pr_info("Error Monitor doesn't have Error Logger\n"); 47062306a36Sopenharmony_ci return -EINVAL; 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci cbb->type = 0; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci while (error) { 47662306a36Sopenharmony_ci if (error & BIT(0)) { 47762306a36Sopenharmony_ci u32 hi, lo; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci hi = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ADDR_HIGH_0); 48062306a36Sopenharmony_ci lo = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ADDR_LOW_0); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci cbb->access = (u64)hi << 32 | lo; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci cbb->mn_attr0 = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ATTRIBUTES0_0); 48562306a36Sopenharmony_ci cbb->mn_attr1 = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ATTRIBUTES1_0); 48662306a36Sopenharmony_ci cbb->mn_attr2 = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ATTRIBUTES2_0); 48762306a36Sopenharmony_ci cbb->mn_user_bits = readl(cbb->mon + FABRIC_MN_MASTER_LOG_USER_BITS0_0); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci print_errlog_err(file, cbb); 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci cbb->type++; 49362306a36Sopenharmony_ci error >>= 1; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci return 0; 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_cistatic int print_err_notifier(struct seq_file *file, struct tegra234_cbb *cbb, u32 status) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci unsigned int index = 0; 50262306a36Sopenharmony_ci int err; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci pr_crit("**************************************\n"); 50562306a36Sopenharmony_ci pr_crit("CPU:%d, Error:%s, Errmon:%d\n", smp_processor_id(), 50662306a36Sopenharmony_ci cbb->fabric->name, status); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci while (status) { 50962306a36Sopenharmony_ci if (status & BIT(0)) { 51062306a36Sopenharmony_ci unsigned int notifier = cbb->fabric->notifier_offset; 51162306a36Sopenharmony_ci u32 hi, lo, mask = BIT(index); 51262306a36Sopenharmony_ci phys_addr_t addr; 51362306a36Sopenharmony_ci u64 offset; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci writel(mask, cbb->regs + notifier + FABRIC_EN_CFG_ADDR_INDEX_0_0); 51662306a36Sopenharmony_ci hi = readl(cbb->regs + notifier + FABRIC_EN_CFG_ADDR_HI_0); 51762306a36Sopenharmony_ci lo = readl(cbb->regs + notifier + FABRIC_EN_CFG_ADDR_LOW_0); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci addr = (u64)hi << 32 | lo; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci offset = addr - cbb->res->start; 52262306a36Sopenharmony_ci cbb->mon = cbb->regs + offset; 52362306a36Sopenharmony_ci cbb->mask = BIT(index); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci err = print_errmonX_info(file, cbb); 52662306a36Sopenharmony_ci tegra234_cbb_error_clear(&cbb->base); 52762306a36Sopenharmony_ci if (err) 52862306a36Sopenharmony_ci return err; 52962306a36Sopenharmony_ci } 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci status >>= 1; 53262306a36Sopenharmony_ci index++; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci tegra_cbb_print_err(file, "\t**************************************\n"); 53662306a36Sopenharmony_ci return 0; 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 54062306a36Sopenharmony_cistatic DEFINE_MUTEX(cbb_debugfs_mutex); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic int tegra234_cbb_debugfs_show(struct tegra_cbb *cbb, struct seq_file *file, void *data) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci int err = 0; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci mutex_lock(&cbb_debugfs_mutex); 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci list_for_each_entry(cbb, &cbb_list, node) { 54962306a36Sopenharmony_ci struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 55062306a36Sopenharmony_ci u32 status; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci status = tegra_cbb_get_status(&priv->base); 55362306a36Sopenharmony_ci if (status) { 55462306a36Sopenharmony_ci err = print_err_notifier(file, priv, status); 55562306a36Sopenharmony_ci if (err) 55662306a36Sopenharmony_ci break; 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci } 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci mutex_unlock(&cbb_debugfs_mutex); 56162306a36Sopenharmony_ci return err; 56262306a36Sopenharmony_ci} 56362306a36Sopenharmony_ci#endif 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci/* 56662306a36Sopenharmony_ci * Handler for CBB errors 56762306a36Sopenharmony_ci */ 56862306a36Sopenharmony_cistatic irqreturn_t tegra234_cbb_isr(int irq, void *data) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci bool is_inband_err = false; 57162306a36Sopenharmony_ci struct tegra_cbb *cbb; 57262306a36Sopenharmony_ci unsigned long flags; 57362306a36Sopenharmony_ci u8 mstr_id; 57462306a36Sopenharmony_ci int err; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci spin_lock_irqsave(&cbb_lock, flags); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci list_for_each_entry(cbb, &cbb_list, node) { 57962306a36Sopenharmony_ci struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 58062306a36Sopenharmony_ci u32 status = tegra_cbb_get_status(cbb); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci if (status && (irq == priv->sec_irq)) { 58362306a36Sopenharmony_ci tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@0x%llx, irq=%d\n", 58462306a36Sopenharmony_ci smp_processor_id(), priv->fabric->name, 58562306a36Sopenharmony_ci priv->res->start, irq); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci err = print_err_notifier(NULL, priv, status); 58862306a36Sopenharmony_ci if (err) 58962306a36Sopenharmony_ci goto unlock; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci /* 59262306a36Sopenharmony_ci * If illegal request is from CCPLEX(id:0x1) master then call WARN() 59362306a36Sopenharmony_ci */ 59462306a36Sopenharmony_ci if (priv->fabric->off_mask_erd) { 59562306a36Sopenharmony_ci mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->mn_user_bits); 59662306a36Sopenharmony_ci if (mstr_id == CCPLEX_MSTRID) 59762306a36Sopenharmony_ci is_inband_err = 1; 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci } 60062306a36Sopenharmony_ci } 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ciunlock: 60362306a36Sopenharmony_ci spin_unlock_irqrestore(&cbb_lock, flags); 60462306a36Sopenharmony_ci WARN_ON(is_inband_err); 60562306a36Sopenharmony_ci return IRQ_HANDLED; 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci/* 60962306a36Sopenharmony_ci * Register handler for CBB_SECURE interrupt for reporting errors 61062306a36Sopenharmony_ci */ 61162306a36Sopenharmony_cistatic int tegra234_cbb_interrupt_enable(struct tegra_cbb *cbb) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci struct tegra234_cbb *priv = to_tegra234_cbb(cbb); 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci if (priv->sec_irq) { 61662306a36Sopenharmony_ci int err = devm_request_irq(cbb->dev, priv->sec_irq, tegra234_cbb_isr, 0, 61762306a36Sopenharmony_ci dev_name(cbb->dev), priv); 61862306a36Sopenharmony_ci if (err) { 61962306a36Sopenharmony_ci dev_err(cbb->dev, "failed to register interrupt %u: %d\n", priv->sec_irq, 62062306a36Sopenharmony_ci err); 62162306a36Sopenharmony_ci return err; 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci } 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci return 0; 62662306a36Sopenharmony_ci} 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_cistatic void tegra234_cbb_error_enable(struct tegra_cbb *cbb) 62962306a36Sopenharmony_ci{ 63062306a36Sopenharmony_ci tegra_cbb_fault_enable(cbb); 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic const struct tegra_cbb_ops tegra234_cbb_ops = { 63462306a36Sopenharmony_ci .get_status = tegra234_cbb_get_status, 63562306a36Sopenharmony_ci .error_clear = tegra234_cbb_error_clear, 63662306a36Sopenharmony_ci .fault_enable = tegra234_cbb_fault_enable, 63762306a36Sopenharmony_ci .error_enable = tegra234_cbb_error_enable, 63862306a36Sopenharmony_ci .interrupt_enable = tegra234_cbb_interrupt_enable, 63962306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 64062306a36Sopenharmony_ci .debugfs_show = tegra234_cbb_debugfs_show, 64162306a36Sopenharmony_ci#endif 64262306a36Sopenharmony_ci}; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_cistatic const char * const tegra234_master_id[] = { 64562306a36Sopenharmony_ci [0x00] = "TZ", 64662306a36Sopenharmony_ci [0x01] = "CCPLEX", 64762306a36Sopenharmony_ci [0x02] = "CCPMU", 64862306a36Sopenharmony_ci [0x03] = "BPMP_FW", 64962306a36Sopenharmony_ci [0x04] = "AON", 65062306a36Sopenharmony_ci [0x05] = "SCE", 65162306a36Sopenharmony_ci [0x06] = "GPCDMA_P", 65262306a36Sopenharmony_ci [0x07] = "TSECA_NONSECURE", 65362306a36Sopenharmony_ci [0x08] = "TSECA_LIGHTSECURE", 65462306a36Sopenharmony_ci [0x09] = "TSECA_HEAVYSECURE", 65562306a36Sopenharmony_ci [0x0a] = "CORESIGHT", 65662306a36Sopenharmony_ci [0x0b] = "APE", 65762306a36Sopenharmony_ci [0x0c] = "PEATRANS", 65862306a36Sopenharmony_ci [0x0d] = "JTAGM_DFT", 65962306a36Sopenharmony_ci [0x0e] = "RCE", 66062306a36Sopenharmony_ci [0x0f] = "DCE", 66162306a36Sopenharmony_ci [0x10] = "PSC_FW_USER", 66262306a36Sopenharmony_ci [0x11] = "PSC_FW_SUPERVISOR", 66362306a36Sopenharmony_ci [0x12] = "PSC_FW_MACHINE", 66462306a36Sopenharmony_ci [0x13] = "PSC_BOOT", 66562306a36Sopenharmony_ci [0x14] = "BPMP_BOOT", 66662306a36Sopenharmony_ci [0x15] = "NVDEC_NONSECURE", 66762306a36Sopenharmony_ci [0x16] = "NVDEC_LIGHTSECURE", 66862306a36Sopenharmony_ci [0x17] = "NVDEC_HEAVYSECURE", 66962306a36Sopenharmony_ci [0x18] = "CBB_INTERNAL", 67062306a36Sopenharmony_ci [0x19] = "RSVD" 67162306a36Sopenharmony_ci}; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_cistatic const struct tegra_cbb_error tegra234_cbb_errors[] = { 67462306a36Sopenharmony_ci { 67562306a36Sopenharmony_ci .code = "SLAVE_ERR", 67662306a36Sopenharmony_ci .desc = "Slave being accessed responded with an error" 67762306a36Sopenharmony_ci }, { 67862306a36Sopenharmony_ci .code = "DECODE_ERR", 67962306a36Sopenharmony_ci .desc = "Attempt to access an address hole" 68062306a36Sopenharmony_ci }, { 68162306a36Sopenharmony_ci .code = "FIREWALL_ERR", 68262306a36Sopenharmony_ci .desc = "Attempt to access a region which is firewall protected" 68362306a36Sopenharmony_ci }, { 68462306a36Sopenharmony_ci .code = "TIMEOUT_ERR", 68562306a36Sopenharmony_ci .desc = "No response returned by slave" 68662306a36Sopenharmony_ci }, { 68762306a36Sopenharmony_ci .code = "PWRDOWN_ERR", 68862306a36Sopenharmony_ci .desc = "Attempt to access a portion of fabric that is powered down" 68962306a36Sopenharmony_ci }, { 69062306a36Sopenharmony_ci .code = "UNSUPPORTED_ERR", 69162306a36Sopenharmony_ci .desc = "Attempt to access a slave through an unsupported access" 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci}; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_cistatic const struct tegra234_slave_lookup tegra234_aon_slave_map[] = { 69662306a36Sopenharmony_ci { "AXI2APB", 0x00000 }, 69762306a36Sopenharmony_ci { "AST", 0x14000 }, 69862306a36Sopenharmony_ci { "CBB", 0x15000 }, 69962306a36Sopenharmony_ci { "CPU", 0x16000 }, 70062306a36Sopenharmony_ci}; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_cistatic const struct tegra234_cbb_fabric tegra234_aon_fabric = { 70362306a36Sopenharmony_ci .name = "aon-fabric", 70462306a36Sopenharmony_ci .master_id = tegra234_master_id, 70562306a36Sopenharmony_ci .slave_map = tegra234_aon_slave_map, 70662306a36Sopenharmony_ci .max_slaves = ARRAY_SIZE(tegra234_aon_slave_map), 70762306a36Sopenharmony_ci .errors = tegra234_cbb_errors, 70862306a36Sopenharmony_ci .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 70962306a36Sopenharmony_ci .notifier_offset = 0x17000, 71062306a36Sopenharmony_ci .firewall_base = 0x30000, 71162306a36Sopenharmony_ci .firewall_ctl = 0x8d0, 71262306a36Sopenharmony_ci .firewall_wr_ctl = 0x8c8, 71362306a36Sopenharmony_ci}; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_cistatic const struct tegra234_slave_lookup tegra234_bpmp_slave_map[] = { 71662306a36Sopenharmony_ci { "AXI2APB", 0x00000 }, 71762306a36Sopenharmony_ci { "AST0", 0x15000 }, 71862306a36Sopenharmony_ci { "AST1", 0x16000 }, 71962306a36Sopenharmony_ci { "CBB", 0x17000 }, 72062306a36Sopenharmony_ci { "CPU", 0x18000 }, 72162306a36Sopenharmony_ci}; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_cistatic const struct tegra234_cbb_fabric tegra234_bpmp_fabric = { 72462306a36Sopenharmony_ci .name = "bpmp-fabric", 72562306a36Sopenharmony_ci .master_id = tegra234_master_id, 72662306a36Sopenharmony_ci .slave_map = tegra234_bpmp_slave_map, 72762306a36Sopenharmony_ci .max_slaves = ARRAY_SIZE(tegra234_bpmp_slave_map), 72862306a36Sopenharmony_ci .errors = tegra234_cbb_errors, 72962306a36Sopenharmony_ci .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 73062306a36Sopenharmony_ci .notifier_offset = 0x19000, 73162306a36Sopenharmony_ci .firewall_base = 0x30000, 73262306a36Sopenharmony_ci .firewall_ctl = 0x8f0, 73362306a36Sopenharmony_ci .firewall_wr_ctl = 0x8e8, 73462306a36Sopenharmony_ci}; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_cistatic const struct tegra234_slave_lookup tegra234_cbb_slave_map[] = { 73762306a36Sopenharmony_ci { "AON", 0x40000 }, 73862306a36Sopenharmony_ci { "BPMP", 0x41000 }, 73962306a36Sopenharmony_ci { "CBB", 0x42000 }, 74062306a36Sopenharmony_ci { "HOST1X", 0x43000 }, 74162306a36Sopenharmony_ci { "STM", 0x44000 }, 74262306a36Sopenharmony_ci { "FSI", 0x45000 }, 74362306a36Sopenharmony_ci { "PSC", 0x46000 }, 74462306a36Sopenharmony_ci { "PCIE_C1", 0x47000 }, 74562306a36Sopenharmony_ci { "PCIE_C2", 0x48000 }, 74662306a36Sopenharmony_ci { "PCIE_C3", 0x49000 }, 74762306a36Sopenharmony_ci { "PCIE_C0", 0x4a000 }, 74862306a36Sopenharmony_ci { "PCIE_C4", 0x4b000 }, 74962306a36Sopenharmony_ci { "GPU", 0x4c000 }, 75062306a36Sopenharmony_ci { "SMMU0", 0x4d000 }, 75162306a36Sopenharmony_ci { "SMMU1", 0x4e000 }, 75262306a36Sopenharmony_ci { "SMMU2", 0x4f000 }, 75362306a36Sopenharmony_ci { "SMMU3", 0x50000 }, 75462306a36Sopenharmony_ci { "SMMU4", 0x51000 }, 75562306a36Sopenharmony_ci { "PCIE_C10", 0x52000 }, 75662306a36Sopenharmony_ci { "PCIE_C7", 0x53000 }, 75762306a36Sopenharmony_ci { "PCIE_C8", 0x54000 }, 75862306a36Sopenharmony_ci { "PCIE_C9", 0x55000 }, 75962306a36Sopenharmony_ci { "PCIE_C5", 0x56000 }, 76062306a36Sopenharmony_ci { "PCIE_C6", 0x57000 }, 76162306a36Sopenharmony_ci { "DCE", 0x58000 }, 76262306a36Sopenharmony_ci { "RCE", 0x59000 }, 76362306a36Sopenharmony_ci { "SCE", 0x5a000 }, 76462306a36Sopenharmony_ci { "AXI2APB_1", 0x70000 }, 76562306a36Sopenharmony_ci { "AXI2APB_10", 0x71000 }, 76662306a36Sopenharmony_ci { "AXI2APB_11", 0x72000 }, 76762306a36Sopenharmony_ci { "AXI2APB_12", 0x73000 }, 76862306a36Sopenharmony_ci { "AXI2APB_13", 0x74000 }, 76962306a36Sopenharmony_ci { "AXI2APB_14", 0x75000 }, 77062306a36Sopenharmony_ci { "AXI2APB_15", 0x76000 }, 77162306a36Sopenharmony_ci { "AXI2APB_16", 0x77000 }, 77262306a36Sopenharmony_ci { "AXI2APB_17", 0x78000 }, 77362306a36Sopenharmony_ci { "AXI2APB_18", 0x79000 }, 77462306a36Sopenharmony_ci { "AXI2APB_19", 0x7a000 }, 77562306a36Sopenharmony_ci { "AXI2APB_2", 0x7b000 }, 77662306a36Sopenharmony_ci { "AXI2APB_20", 0x7c000 }, 77762306a36Sopenharmony_ci { "AXI2APB_21", 0x7d000 }, 77862306a36Sopenharmony_ci { "AXI2APB_22", 0x7e000 }, 77962306a36Sopenharmony_ci { "AXI2APB_23", 0x7f000 }, 78062306a36Sopenharmony_ci { "AXI2APB_25", 0x80000 }, 78162306a36Sopenharmony_ci { "AXI2APB_26", 0x81000 }, 78262306a36Sopenharmony_ci { "AXI2APB_27", 0x82000 }, 78362306a36Sopenharmony_ci { "AXI2APB_28", 0x83000 }, 78462306a36Sopenharmony_ci { "AXI2APB_29", 0x84000 }, 78562306a36Sopenharmony_ci { "AXI2APB_30", 0x85000 }, 78662306a36Sopenharmony_ci { "AXI2APB_31", 0x86000 }, 78762306a36Sopenharmony_ci { "AXI2APB_32", 0x87000 }, 78862306a36Sopenharmony_ci { "AXI2APB_33", 0x88000 }, 78962306a36Sopenharmony_ci { "AXI2APB_34", 0x89000 }, 79062306a36Sopenharmony_ci { "AXI2APB_35", 0x92000 }, 79162306a36Sopenharmony_ci { "AXI2APB_4", 0x8b000 }, 79262306a36Sopenharmony_ci { "AXI2APB_5", 0x8c000 }, 79362306a36Sopenharmony_ci { "AXI2APB_6", 0x8d000 }, 79462306a36Sopenharmony_ci { "AXI2APB_7", 0x8e000 }, 79562306a36Sopenharmony_ci { "AXI2APB_8", 0x8f000 }, 79662306a36Sopenharmony_ci { "AXI2APB_9", 0x90000 }, 79762306a36Sopenharmony_ci { "AXI2APB_3", 0x91000 }, 79862306a36Sopenharmony_ci}; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_cistatic const struct tegra234_cbb_fabric tegra234_cbb_fabric = { 80162306a36Sopenharmony_ci .name = "cbb-fabric", 80262306a36Sopenharmony_ci .master_id = tegra234_master_id, 80362306a36Sopenharmony_ci .slave_map = tegra234_cbb_slave_map, 80462306a36Sopenharmony_ci .max_slaves = ARRAY_SIZE(tegra234_cbb_slave_map), 80562306a36Sopenharmony_ci .errors = tegra234_cbb_errors, 80662306a36Sopenharmony_ci .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 80762306a36Sopenharmony_ci .notifier_offset = 0x60000, 80862306a36Sopenharmony_ci .off_mask_erd = 0x3a004, 80962306a36Sopenharmony_ci .firewall_base = 0x10000, 81062306a36Sopenharmony_ci .firewall_ctl = 0x23f0, 81162306a36Sopenharmony_ci .firewall_wr_ctl = 0x23e8, 81262306a36Sopenharmony_ci}; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_cistatic const struct tegra234_slave_lookup tegra234_common_slave_map[] = { 81562306a36Sopenharmony_ci { "AXI2APB", 0x00000 }, 81662306a36Sopenharmony_ci { "AST0", 0x15000 }, 81762306a36Sopenharmony_ci { "AST1", 0x16000 }, 81862306a36Sopenharmony_ci { "CBB", 0x17000 }, 81962306a36Sopenharmony_ci { "RSVD", 0x00000 }, 82062306a36Sopenharmony_ci { "CPU", 0x18000 }, 82162306a36Sopenharmony_ci}; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic const struct tegra234_cbb_fabric tegra234_dce_fabric = { 82462306a36Sopenharmony_ci .name = "dce-fabric", 82562306a36Sopenharmony_ci .master_id = tegra234_master_id, 82662306a36Sopenharmony_ci .slave_map = tegra234_common_slave_map, 82762306a36Sopenharmony_ci .max_slaves = ARRAY_SIZE(tegra234_common_slave_map), 82862306a36Sopenharmony_ci .errors = tegra234_cbb_errors, 82962306a36Sopenharmony_ci .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 83062306a36Sopenharmony_ci .notifier_offset = 0x19000, 83162306a36Sopenharmony_ci .firewall_base = 0x30000, 83262306a36Sopenharmony_ci .firewall_ctl = 0x290, 83362306a36Sopenharmony_ci .firewall_wr_ctl = 0x288, 83462306a36Sopenharmony_ci}; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_cistatic const struct tegra234_cbb_fabric tegra234_rce_fabric = { 83762306a36Sopenharmony_ci .name = "rce-fabric", 83862306a36Sopenharmony_ci .master_id = tegra234_master_id, 83962306a36Sopenharmony_ci .slave_map = tegra234_common_slave_map, 84062306a36Sopenharmony_ci .max_slaves = ARRAY_SIZE(tegra234_common_slave_map), 84162306a36Sopenharmony_ci .errors = tegra234_cbb_errors, 84262306a36Sopenharmony_ci .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 84362306a36Sopenharmony_ci .notifier_offset = 0x19000, 84462306a36Sopenharmony_ci .firewall_base = 0x30000, 84562306a36Sopenharmony_ci .firewall_ctl = 0x290, 84662306a36Sopenharmony_ci .firewall_wr_ctl = 0x288, 84762306a36Sopenharmony_ci}; 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_cistatic const struct tegra234_cbb_fabric tegra234_sce_fabric = { 85062306a36Sopenharmony_ci .name = "sce-fabric", 85162306a36Sopenharmony_ci .master_id = tegra234_master_id, 85262306a36Sopenharmony_ci .slave_map = tegra234_common_slave_map, 85362306a36Sopenharmony_ci .max_slaves = ARRAY_SIZE(tegra234_common_slave_map), 85462306a36Sopenharmony_ci .errors = tegra234_cbb_errors, 85562306a36Sopenharmony_ci .max_errors = ARRAY_SIZE(tegra234_cbb_errors), 85662306a36Sopenharmony_ci .notifier_offset = 0x19000, 85762306a36Sopenharmony_ci .firewall_base = 0x30000, 85862306a36Sopenharmony_ci .firewall_ctl = 0x290, 85962306a36Sopenharmony_ci .firewall_wr_ctl = 0x288, 86062306a36Sopenharmony_ci}; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_cistatic const char * const tegra241_master_id[] = { 86362306a36Sopenharmony_ci [0x0] = "TZ", 86462306a36Sopenharmony_ci [0x1] = "CCPLEX", 86562306a36Sopenharmony_ci [0x2] = "CCPMU", 86662306a36Sopenharmony_ci [0x3] = "BPMP_FW", 86762306a36Sopenharmony_ci [0x4] = "PSC_FW_USER", 86862306a36Sopenharmony_ci [0x5] = "PSC_FW_SUPERVISOR", 86962306a36Sopenharmony_ci [0x6] = "PSC_FW_MACHINE", 87062306a36Sopenharmony_ci [0x7] = "PSC_BOOT", 87162306a36Sopenharmony_ci [0x8] = "BPMP_BOOT", 87262306a36Sopenharmony_ci [0x9] = "JTAGM_DFT", 87362306a36Sopenharmony_ci [0xa] = "CORESIGHT", 87462306a36Sopenharmony_ci [0xb] = "GPU", 87562306a36Sopenharmony_ci [0xc] = "PEATRANS", 87662306a36Sopenharmony_ci [0xd ... 0x3f] = "RSVD" 87762306a36Sopenharmony_ci}; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci/* 88062306a36Sopenharmony_ci * Possible causes for Slave and Timeout errors. 88162306a36Sopenharmony_ci * SLAVE_ERR: 88262306a36Sopenharmony_ci * Slave being accessed responded with an error. Slave could return 88362306a36Sopenharmony_ci * an error for various cases : 88462306a36Sopenharmony_ci * Unsupported access, clamp setting when power gated, register 88562306a36Sopenharmony_ci * level firewall(SCR), address hole within the slave, etc 88662306a36Sopenharmony_ci * 88762306a36Sopenharmony_ci * TIMEOUT_ERR: 88862306a36Sopenharmony_ci * No response returned by slave. Can be due to slave being clock 88962306a36Sopenharmony_ci * gated, under reset, powered down or slave inability to respond 89062306a36Sopenharmony_ci * for an internal slave issue 89162306a36Sopenharmony_ci */ 89262306a36Sopenharmony_cistatic const struct tegra_cbb_error tegra241_cbb_errors[] = { 89362306a36Sopenharmony_ci { 89462306a36Sopenharmony_ci .code = "SLAVE_ERR", 89562306a36Sopenharmony_ci .desc = "Slave being accessed responded with an error." 89662306a36Sopenharmony_ci }, { 89762306a36Sopenharmony_ci .code = "DECODE_ERR", 89862306a36Sopenharmony_ci .desc = "Attempt to access an address hole or Reserved region of memory." 89962306a36Sopenharmony_ci }, { 90062306a36Sopenharmony_ci .code = "FIREWALL_ERR", 90162306a36Sopenharmony_ci .desc = "Attempt to access a region which is firewalled." 90262306a36Sopenharmony_ci }, { 90362306a36Sopenharmony_ci .code = "TIMEOUT_ERR", 90462306a36Sopenharmony_ci .desc = "No response returned by slave." 90562306a36Sopenharmony_ci }, { 90662306a36Sopenharmony_ci .code = "PWRDOWN_ERR", 90762306a36Sopenharmony_ci .desc = "Attempt to access a portion of the fabric that is powered down." 90862306a36Sopenharmony_ci }, { 90962306a36Sopenharmony_ci .code = "UNSUPPORTED_ERR", 91062306a36Sopenharmony_ci .desc = "Attempt to access a slave through an unsupported access." 91162306a36Sopenharmony_ci }, { 91262306a36Sopenharmony_ci .code = "POISON_ERR", 91362306a36Sopenharmony_ci .desc = "Slave responds with poison error to indicate error in data." 91462306a36Sopenharmony_ci }, { 91562306a36Sopenharmony_ci .code = "RSVD" 91662306a36Sopenharmony_ci }, { 91762306a36Sopenharmony_ci .code = "RSVD" 91862306a36Sopenharmony_ci }, { 91962306a36Sopenharmony_ci .code = "RSVD" 92062306a36Sopenharmony_ci }, { 92162306a36Sopenharmony_ci .code = "RSVD" 92262306a36Sopenharmony_ci }, { 92362306a36Sopenharmony_ci .code = "RSVD" 92462306a36Sopenharmony_ci }, { 92562306a36Sopenharmony_ci .code = "RSVD" 92662306a36Sopenharmony_ci }, { 92762306a36Sopenharmony_ci .code = "RSVD" 92862306a36Sopenharmony_ci }, { 92962306a36Sopenharmony_ci .code = "RSVD" 93062306a36Sopenharmony_ci }, { 93162306a36Sopenharmony_ci .code = "RSVD" 93262306a36Sopenharmony_ci }, { 93362306a36Sopenharmony_ci .code = "NO_SUCH_ADDRESS_ERR", 93462306a36Sopenharmony_ci .desc = "The address belongs to the pri_target range but there is no register " 93562306a36Sopenharmony_ci "implemented at the address." 93662306a36Sopenharmony_ci }, { 93762306a36Sopenharmony_ci .code = "TASK_ERR", 93862306a36Sopenharmony_ci .desc = "Attempt to update a PRI task when the current task has still not " 93962306a36Sopenharmony_ci "completed." 94062306a36Sopenharmony_ci }, { 94162306a36Sopenharmony_ci .code = "EXTERNAL_ERR", 94262306a36Sopenharmony_ci .desc = "Indicates that an external PRI register access met with an error due to " 94362306a36Sopenharmony_ci "any issue in the unit." 94462306a36Sopenharmony_ci }, { 94562306a36Sopenharmony_ci .code = "INDEX_ERR", 94662306a36Sopenharmony_ci .desc = "Applicable to PRI index aperture pair, when the programmed index is " 94762306a36Sopenharmony_ci "outside the range defined in the manual." 94862306a36Sopenharmony_ci }, { 94962306a36Sopenharmony_ci .code = "RESET_ERR", 95062306a36Sopenharmony_ci .desc = "Target in Reset Error: Attempt to access a SubPri or external PRI " 95162306a36Sopenharmony_ci "register but they are in reset." 95262306a36Sopenharmony_ci }, { 95362306a36Sopenharmony_ci .code = "REGISTER_RST_ERR", 95462306a36Sopenharmony_ci .desc = "Attempt to access a PRI register but the register is partial or " 95562306a36Sopenharmony_ci "completely in reset." 95662306a36Sopenharmony_ci }, { 95762306a36Sopenharmony_ci .code = "POWER_GATED_ERR", 95862306a36Sopenharmony_ci .desc = "Returned by external PRI client when the external access goes to a power " 95962306a36Sopenharmony_ci "gated domain." 96062306a36Sopenharmony_ci }, { 96162306a36Sopenharmony_ci .code = "SUBPRI_FS_ERR", 96262306a36Sopenharmony_ci .desc = "Subpri is floorswept: Attempt to access a subpri through the main pri " 96362306a36Sopenharmony_ci "target but subPri logic is floorswept." 96462306a36Sopenharmony_ci }, { 96562306a36Sopenharmony_ci .code = "SUBPRI_CLK_OFF_ERR", 96662306a36Sopenharmony_ci .desc = "Subpri clock is off: Attempt to access a subpri through the main pri " 96762306a36Sopenharmony_ci "target but subPris clock is gated/off." 96862306a36Sopenharmony_ci }, 96962306a36Sopenharmony_ci}; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_cistatic const struct tegra234_slave_lookup tegra241_cbb_slave_map[] = { 97262306a36Sopenharmony_ci { "RSVD", 0x00000 }, 97362306a36Sopenharmony_ci { "PCIE_C8", 0x51000 }, 97462306a36Sopenharmony_ci { "PCIE_C9", 0x52000 }, 97562306a36Sopenharmony_ci { "RSVD", 0x00000 }, 97662306a36Sopenharmony_ci { "RSVD", 0x00000 }, 97762306a36Sopenharmony_ci { "RSVD", 0x00000 }, 97862306a36Sopenharmony_ci { "RSVD", 0x00000 }, 97962306a36Sopenharmony_ci { "RSVD", 0x00000 }, 98062306a36Sopenharmony_ci { "RSVD", 0x00000 }, 98162306a36Sopenharmony_ci { "RSVD", 0x00000 }, 98262306a36Sopenharmony_ci { "RSVD", 0x00000 }, 98362306a36Sopenharmony_ci { "AON", 0x5b000 }, 98462306a36Sopenharmony_ci { "BPMP", 0x5c000 }, 98562306a36Sopenharmony_ci { "RSVD", 0x00000 }, 98662306a36Sopenharmony_ci { "RSVD", 0x00000 }, 98762306a36Sopenharmony_ci { "PSC", 0x5d000 }, 98862306a36Sopenharmony_ci { "STM", 0x5e000 }, 98962306a36Sopenharmony_ci { "AXI2APB_1", 0x70000 }, 99062306a36Sopenharmony_ci { "AXI2APB_10", 0x71000 }, 99162306a36Sopenharmony_ci { "AXI2APB_11", 0x72000 }, 99262306a36Sopenharmony_ci { "AXI2APB_12", 0x73000 }, 99362306a36Sopenharmony_ci { "AXI2APB_13", 0x74000 }, 99462306a36Sopenharmony_ci { "AXI2APB_14", 0x75000 }, 99562306a36Sopenharmony_ci { "AXI2APB_15", 0x76000 }, 99662306a36Sopenharmony_ci { "AXI2APB_16", 0x77000 }, 99762306a36Sopenharmony_ci { "AXI2APB_17", 0x78000 }, 99862306a36Sopenharmony_ci { "AXI2APB_18", 0x79000 }, 99962306a36Sopenharmony_ci { "AXI2APB_19", 0x7a000 }, 100062306a36Sopenharmony_ci { "AXI2APB_2", 0x7b000 }, 100162306a36Sopenharmony_ci { "AXI2APB_20", 0x7c000 }, 100262306a36Sopenharmony_ci { "AXI2APB_4", 0x87000 }, 100362306a36Sopenharmony_ci { "AXI2APB_5", 0x88000 }, 100462306a36Sopenharmony_ci { "AXI2APB_6", 0x89000 }, 100562306a36Sopenharmony_ci { "AXI2APB_7", 0x8a000 }, 100662306a36Sopenharmony_ci { "AXI2APB_8", 0x8b000 }, 100762306a36Sopenharmony_ci { "AXI2APB_9", 0x8c000 }, 100862306a36Sopenharmony_ci { "AXI2APB_3", 0x8d000 }, 100962306a36Sopenharmony_ci { "AXI2APB_21", 0x7d000 }, 101062306a36Sopenharmony_ci { "AXI2APB_22", 0x7e000 }, 101162306a36Sopenharmony_ci { "AXI2APB_23", 0x7f000 }, 101262306a36Sopenharmony_ci { "AXI2APB_24", 0x80000 }, 101362306a36Sopenharmony_ci { "AXI2APB_25", 0x81000 }, 101462306a36Sopenharmony_ci { "AXI2APB_26", 0x82000 }, 101562306a36Sopenharmony_ci { "AXI2APB_27", 0x83000 }, 101662306a36Sopenharmony_ci { "AXI2APB_28", 0x84000 }, 101762306a36Sopenharmony_ci { "PCIE_C4", 0x53000 }, 101862306a36Sopenharmony_ci { "PCIE_C5", 0x54000 }, 101962306a36Sopenharmony_ci { "PCIE_C6", 0x55000 }, 102062306a36Sopenharmony_ci { "PCIE_C7", 0x56000 }, 102162306a36Sopenharmony_ci { "PCIE_C2", 0x57000 }, 102262306a36Sopenharmony_ci { "PCIE_C3", 0x58000 }, 102362306a36Sopenharmony_ci { "PCIE_C0", 0x59000 }, 102462306a36Sopenharmony_ci { "PCIE_C1", 0x5a000 }, 102562306a36Sopenharmony_ci { "CCPLEX", 0x50000 }, 102662306a36Sopenharmony_ci { "AXI2APB_29", 0x85000 }, 102762306a36Sopenharmony_ci { "AXI2APB_30", 0x86000 }, 102862306a36Sopenharmony_ci { "CBB_CENTRAL", 0x00000 }, 102962306a36Sopenharmony_ci { "AXI2APB_31", 0x8E000 }, 103062306a36Sopenharmony_ci { "AXI2APB_32", 0x8F000 }, 103162306a36Sopenharmony_ci}; 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_cistatic const struct tegra234_cbb_fabric tegra241_cbb_fabric = { 103462306a36Sopenharmony_ci .name = "cbb-fabric", 103562306a36Sopenharmony_ci .master_id = tegra241_master_id, 103662306a36Sopenharmony_ci .slave_map = tegra241_cbb_slave_map, 103762306a36Sopenharmony_ci .max_slaves = ARRAY_SIZE(tegra241_cbb_slave_map), 103862306a36Sopenharmony_ci .errors = tegra241_cbb_errors, 103962306a36Sopenharmony_ci .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 104062306a36Sopenharmony_ci .notifier_offset = 0x60000, 104162306a36Sopenharmony_ci .off_mask_erd = 0x40004, 104262306a36Sopenharmony_ci .firewall_base = 0x20000, 104362306a36Sopenharmony_ci .firewall_ctl = 0x2370, 104462306a36Sopenharmony_ci .firewall_wr_ctl = 0x2368, 104562306a36Sopenharmony_ci}; 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_cistatic const struct tegra234_slave_lookup tegra241_bpmp_slave_map[] = { 104862306a36Sopenharmony_ci { "RSVD", 0x00000 }, 104962306a36Sopenharmony_ci { "RSVD", 0x00000 }, 105062306a36Sopenharmony_ci { "RSVD", 0x00000 }, 105162306a36Sopenharmony_ci { "CBB", 0x15000 }, 105262306a36Sopenharmony_ci { "CPU", 0x16000 }, 105362306a36Sopenharmony_ci { "AXI2APB", 0x00000 }, 105462306a36Sopenharmony_ci { "DBB0", 0x17000 }, 105562306a36Sopenharmony_ci { "DBB1", 0x18000 }, 105662306a36Sopenharmony_ci}; 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_cistatic const struct tegra234_cbb_fabric tegra241_bpmp_fabric = { 105962306a36Sopenharmony_ci .name = "bpmp-fabric", 106062306a36Sopenharmony_ci .master_id = tegra241_master_id, 106162306a36Sopenharmony_ci .slave_map = tegra241_bpmp_slave_map, 106262306a36Sopenharmony_ci .max_slaves = ARRAY_SIZE(tegra241_bpmp_slave_map), 106362306a36Sopenharmony_ci .errors = tegra241_cbb_errors, 106462306a36Sopenharmony_ci .max_errors = ARRAY_SIZE(tegra241_cbb_errors), 106562306a36Sopenharmony_ci .notifier_offset = 0x19000, 106662306a36Sopenharmony_ci .firewall_base = 0x30000, 106762306a36Sopenharmony_ci .firewall_ctl = 0x8f0, 106862306a36Sopenharmony_ci .firewall_wr_ctl = 0x8e8, 106962306a36Sopenharmony_ci}; 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_cistatic const struct of_device_id tegra234_cbb_dt_ids[] = { 107262306a36Sopenharmony_ci { .compatible = "nvidia,tegra234-cbb-fabric", .data = &tegra234_cbb_fabric }, 107362306a36Sopenharmony_ci { .compatible = "nvidia,tegra234-aon-fabric", .data = &tegra234_aon_fabric }, 107462306a36Sopenharmony_ci { .compatible = "nvidia,tegra234-bpmp-fabric", .data = &tegra234_bpmp_fabric }, 107562306a36Sopenharmony_ci { .compatible = "nvidia,tegra234-dce-fabric", .data = &tegra234_dce_fabric }, 107662306a36Sopenharmony_ci { .compatible = "nvidia,tegra234-rce-fabric", .data = &tegra234_rce_fabric }, 107762306a36Sopenharmony_ci { .compatible = "nvidia,tegra234-sce-fabric", .data = &tegra234_sce_fabric }, 107862306a36Sopenharmony_ci { /* sentinel */ }, 107962306a36Sopenharmony_ci}; 108062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, tegra234_cbb_dt_ids); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_cistruct tegra234_cbb_acpi_uid { 108362306a36Sopenharmony_ci const char *hid; 108462306a36Sopenharmony_ci const char *uid; 108562306a36Sopenharmony_ci const struct tegra234_cbb_fabric *fabric; 108662306a36Sopenharmony_ci}; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_cistatic const struct tegra234_cbb_acpi_uid tegra234_cbb_acpi_uids[] = { 108962306a36Sopenharmony_ci { "NVDA1070", "1", &tegra241_cbb_fabric }, 109062306a36Sopenharmony_ci { "NVDA1070", "2", &tegra241_bpmp_fabric }, 109162306a36Sopenharmony_ci { }, 109262306a36Sopenharmony_ci}; 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_cistatic const struct 109562306a36Sopenharmony_citegra234_cbb_fabric *tegra234_cbb_acpi_get_fabric(struct acpi_device *adev) 109662306a36Sopenharmony_ci{ 109762306a36Sopenharmony_ci const struct tegra234_cbb_acpi_uid *entry; 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci for (entry = tegra234_cbb_acpi_uids; entry->hid; entry++) { 110062306a36Sopenharmony_ci if (acpi_dev_hid_uid_match(adev, entry->hid, entry->uid)) 110162306a36Sopenharmony_ci return entry->fabric; 110262306a36Sopenharmony_ci } 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci return NULL; 110562306a36Sopenharmony_ci} 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_cistatic const struct acpi_device_id tegra241_cbb_acpi_ids[] = { 110862306a36Sopenharmony_ci { "NVDA1070" }, 110962306a36Sopenharmony_ci { }, 111062306a36Sopenharmony_ci}; 111162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, tegra241_cbb_acpi_ids); 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_cistatic int tegra234_cbb_probe(struct platform_device *pdev) 111462306a36Sopenharmony_ci{ 111562306a36Sopenharmony_ci const struct tegra234_cbb_fabric *fabric; 111662306a36Sopenharmony_ci struct tegra234_cbb *cbb; 111762306a36Sopenharmony_ci unsigned long flags = 0; 111862306a36Sopenharmony_ci int err; 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci if (pdev->dev.of_node) { 112162306a36Sopenharmony_ci fabric = of_device_get_match_data(&pdev->dev); 112262306a36Sopenharmony_ci } else { 112362306a36Sopenharmony_ci struct acpi_device *device = ACPI_COMPANION(&pdev->dev); 112462306a36Sopenharmony_ci if (!device) 112562306a36Sopenharmony_ci return -ENODEV; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci fabric = tegra234_cbb_acpi_get_fabric(device); 112862306a36Sopenharmony_ci if (!fabric) { 112962306a36Sopenharmony_ci dev_err(&pdev->dev, "no device match found\n"); 113062306a36Sopenharmony_ci return -ENODEV; 113162306a36Sopenharmony_ci } 113262306a36Sopenharmony_ci } 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci cbb = devm_kzalloc(&pdev->dev, sizeof(*cbb), GFP_KERNEL); 113562306a36Sopenharmony_ci if (!cbb) 113662306a36Sopenharmony_ci return -ENOMEM; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci INIT_LIST_HEAD(&cbb->base.node); 113962306a36Sopenharmony_ci cbb->base.ops = &tegra234_cbb_ops; 114062306a36Sopenharmony_ci cbb->base.dev = &pdev->dev; 114162306a36Sopenharmony_ci cbb->fabric = fabric; 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci cbb->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &cbb->res); 114462306a36Sopenharmony_ci if (IS_ERR(cbb->regs)) 114562306a36Sopenharmony_ci return PTR_ERR(cbb->regs); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci err = tegra_cbb_get_irq(pdev, NULL, &cbb->sec_irq); 114862306a36Sopenharmony_ci if (err) 114962306a36Sopenharmony_ci return err; 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci platform_set_drvdata(pdev, cbb); 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci /* 115462306a36Sopenharmony_ci * Don't enable error reporting for a Fabric if write to it's registers 115562306a36Sopenharmony_ci * is blocked by CBB firewall. 115662306a36Sopenharmony_ci */ 115762306a36Sopenharmony_ci if (!tegra234_cbb_write_access_allowed(pdev, cbb)) { 115862306a36Sopenharmony_ci dev_info(&pdev->dev, "error reporting not enabled due to firewall\n"); 115962306a36Sopenharmony_ci return 0; 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci spin_lock_irqsave(&cbb_lock, flags); 116362306a36Sopenharmony_ci list_add(&cbb->base.node, &cbb_list); 116462306a36Sopenharmony_ci spin_unlock_irqrestore(&cbb_lock, flags); 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci /* set ERD bit to mask SError and generate interrupt to report error */ 116762306a36Sopenharmony_ci if (cbb->fabric->off_mask_erd) 116862306a36Sopenharmony_ci tegra234_cbb_mask_serror(cbb); 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci return tegra_cbb_register(&cbb->base); 117162306a36Sopenharmony_ci} 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_cistatic int __maybe_unused tegra234_cbb_resume_noirq(struct device *dev) 117462306a36Sopenharmony_ci{ 117562306a36Sopenharmony_ci struct tegra234_cbb *cbb = dev_get_drvdata(dev); 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci tegra234_cbb_error_enable(&cbb->base); 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci dev_dbg(dev, "%s resumed\n", cbb->fabric->name); 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci return 0; 118262306a36Sopenharmony_ci} 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_cistatic const struct dev_pm_ops tegra234_cbb_pm = { 118562306a36Sopenharmony_ci SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, tegra234_cbb_resume_noirq) 118662306a36Sopenharmony_ci}; 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_cistatic struct platform_driver tegra234_cbb_driver = { 118962306a36Sopenharmony_ci .probe = tegra234_cbb_probe, 119062306a36Sopenharmony_ci .driver = { 119162306a36Sopenharmony_ci .name = "tegra234-cbb", 119262306a36Sopenharmony_ci .of_match_table = tegra234_cbb_dt_ids, 119362306a36Sopenharmony_ci .acpi_match_table = tegra241_cbb_acpi_ids, 119462306a36Sopenharmony_ci .pm = &tegra234_cbb_pm, 119562306a36Sopenharmony_ci }, 119662306a36Sopenharmony_ci}; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_cistatic int __init tegra234_cbb_init(void) 119962306a36Sopenharmony_ci{ 120062306a36Sopenharmony_ci return platform_driver_register(&tegra234_cbb_driver); 120162306a36Sopenharmony_ci} 120262306a36Sopenharmony_cipure_initcall(tegra234_cbb_init); 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_cistatic void __exit tegra234_cbb_exit(void) 120562306a36Sopenharmony_ci{ 120662306a36Sopenharmony_ci platform_driver_unregister(&tegra234_cbb_driver); 120762306a36Sopenharmony_ci} 120862306a36Sopenharmony_cimodule_exit(tegra234_cbb_exit); 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ciMODULE_DESCRIPTION("Control Backbone 2.0 error handling driver for Tegra234"); 1211