soc/tegra: Changes for v6.2-rc1

In addition to a number of improvements and cleanups this contains a
 fix for the FUSE access on newer chips, adds Tegra234 I/O pad support
 and fixes various issues with wake events.
 
 The SoC sysfs revision attribute is updated to include the platform
 information so drivers can check for silicon vs. pre-silicon, among
 other things.
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAmN7rkATHHRyZWRpbmdA
 bnZpZGlhLmNvbQAKCRDdI6zXfz6zoU/qEACtzNEmghAtJ+sSSr8+mawvM8DzcffW
 z5NaGkBnRCu588W+X5BLzHFKZA00SDfGCf/+wJE63lG4sZ7FxN3MoS1F/Wq/cpJ1
 eMKarEfzVmdGA2bk91OY5QgUmTi/zm6nlWZiXapbYv20xu6b73PLOR6egiMTBxl8
 dmbDugNhaQQ8hxQwS5fM/5KGP5emxjeCAtHX+l5lEQx/WVfU2qZLU7vaXuh3rvcV
 BTRfTbHSxpan80E/Rw8M91ymgqQTZCQ1Gwvzh412dgxTclHb6HCzliK9cLJHNHa6
 ipSZ9Sy8KSQrGwg+v5IPTuWHUTrkph8nzr0BtuLhqFS8TM4nYfiTeUHVLCn1EXoT
 AqzycHiZTjqThmP7dOIgJWr55RRj9184n/eJ3a5QLvtDx04nWMx/Wg40UsprpgiK
 dxGib/G0j17eK7UB/SWrSjJTVjsbWd+RCeNe4vhgD7nkhRvB+NMfq8o/U0nwIpSD
 +q7JL2jGD4wCJw0uNlTuqG2ZOyjENyKntyVRfH9e0IdWmXjTDBPYcpW5+4D37P9s
 NhBsKr3HOHuPjI4vMZh4MhVrEjwO1vcG6hKRZ8zrlmPI7avWdNb9iOktqm3S6+K8
 TBhfil/FHC1/ATQS9hgNG/vAwa1Ohq+lIPEEVQgCiHgaYLUejmsR/644E3Epstv7
 qN7xiIiWMPqAOA==
 =3mDo
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmN9OvcACgkQmmx57+YA
 GNn+gQ//X94tiKiL8D5K1Y3tby7Q1RraH0uYGHrzhKMX6+zL7wEIz5/SkR2BLVTV
 MHgYQ3mAsoF8HziPfKGo/mRmEWb8UsQYFwnZpbfCGxeHxuXOI/paEkyXQz9Omi7/
 v6XSliBolw5aRxXil0+E8gjnVysLg+IwTvZs78v7EkR8bgbs3D/yzEJu3aLgvuhn
 Ozg2Ix0B8QPK/ltjKp49Z1X7ai7/TI1JaW0ZLqDTJrpAFyyDqWI5KDwcK8pKPezI
 NV4sHwbZ2JHuig2Pl5AUwkuh+76oW0V1qwaEgkgWYyJQXKzXMDkxyTeU1+tZfcC6
 v7EwFrCJxpmBiTacCyPlGJeR7yg+EfKhtP0Mextgw+iRlwYpYqfBuh+0nCg9Ne4U
 3bzgtjqYRRqr13kem4vdlSbZTaOYOytfaZxEHRs1tjwniuWtHJECYQkwCEw8l5JE
 g2b4DiH5GwDwLVC63iNuDTOrmw+42bLihQJAxMwRn3i84Yy22p1a7Dvo6l0jmIOI
 CNF8wpbTNrc19pPTmsa4mAF8tsVd7VUE2nAyknBc9o1kZXjTKDow7KtWM28nIuff
 58lxarZsHKq/1JH+rPOtbZ2cNxZJl8+dqHHDVFrK/NulQUwQPt9OnU79zxnLujab
 vXCUg1n8q+edrEWcmihprqgmK/D0iDrGTop8GNygf0GU1tgau34=
 =A2Gp
 -----END PGP SIGNATURE-----

Merge tag 'tegra-for-6.2-soc-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into soc/drivers

soc/tegra: Changes for v6.2-rc1

In addition to a number of improvements and cleanups this contains a
fix for the FUSE access on newer chips, adds Tegra234 I/O pad support
and fixes various issues with wake events.

The SoC sysfs revision attribute is updated to include the platform
information so drivers can check for silicon vs. pre-silicon, among
other things.

* tag 'tegra-for-6.2-soc-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  soc/tegra: cbb: Remove redundant dev_err call
  soc/tegra: cbb: Use DEFINE_SHOW_ATTRIBUTE to simplify tegra_cbb_err
  firmware: tegra: include IVC header file only once
  soc/tegra: cbb: Check firewall before enabling error reporting
  soc/tegra: cbb: Add checks for potential out of bound errors
  soc/tegra: cbb: Update slave maps for Tegra234
  soc/tegra: cbb: Use correct master_id mask for CBB NOC in Tegra194
  soc/tegra: fuse: Use platform info with SoC revision
  soc/tegra: pmc: Process wake events during resume
  soc/tegra: pmc: Fix dual edge triggered wakes
  soc/tegra: pmc: Add I/O pad table for Tegra234
  soc/tegra: fuse: Add nvmem keepout list
  soc/tegra: fuse: Use SoC specific nvmem cells
  soc/tegra: pmc: Select IRQ_DOMAIN_HIERARCHY

Link: https://lore.kernel.org/r/20221121171239.2041835-1-thierry.reding@gmail.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2022-11-22 22:04:37 +01:00
commit 2a26daeeb8
12 changed files with 1092 additions and 427 deletions

View File

@ -143,6 +143,7 @@ config SOC_TEGRA_FLOWCTRL
config SOC_TEGRA_PMC
bool
select GENERIC_PINCONF
select IRQ_DOMAIN_HIERARCHY
select PM_OPP
select PM_GENERIC_DOMAINS
select REGMAP

View File

@ -72,18 +72,7 @@ static int tegra_cbb_err_show(struct seq_file *file, void *data)
return cbb->ops->debugfs_show(cbb, file, data);
}
static int tegra_cbb_err_open(struct inode *inode, struct file *file)
{
return single_open(file, tegra_cbb_err_show, inode->i_private);
}
static const struct file_operations tegra_cbb_err_fops = {
.open = tegra_cbb_err_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release
};
DEFINE_SHOW_ATTRIBUTE(tegra_cbb_err);
static int tegra_cbb_err_debugfs_init(struct tegra_cbb *cbb)
{

View File

@ -102,8 +102,6 @@
#define CLUSTER_NOC_VQC GENMASK(17, 16)
#define CLUSTER_NOC_MSTR_ID GENMASK(21, 18)
#define USRBITS_MSTR_ID GENMASK(21, 18)
#define CBB_ERR_OPC GENMASK(4, 1)
#define CBB_ERR_ERRCODE GENMASK(10, 8)
#define CBB_ERR_LEN1 GENMASK(27, 16)
@ -2038,15 +2036,17 @@ static irqreturn_t tegra194_cbb_err_isr(int irq, void *data)
smp_processor_id(), priv->noc->name, priv->res->start,
irq);
mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->errlog5) - 1;
is_fatal = print_errlog(NULL, priv, status);
/*
* If illegal request is from CCPLEX(0x1)
* initiator then call BUG() to crash system.
* If illegal request is from CCPLEX(0x1) initiator
* and error is fatal then call BUG() to crash system.
*/
if ((mstr_id == 0x1) && priv->noc->erd_mask_inband_err)
is_inband_err = 1;
if (priv->noc->erd_mask_inband_err) {
mstr_id = FIELD_GET(CBB_NOC_MSTR_ID, priv->errlog5);
if (mstr_id == 0x1)
is_inband_err = 1;
}
}
}
@ -2226,10 +2226,8 @@ static int tegra194_cbb_get_bridges(struct tegra194_cbb *cbb, struct device_node
cbb->bridges[i].base = devm_ioremap_resource(cbb->base.dev,
&cbb->bridges[i].res);
if (IS_ERR(cbb->bridges[i].base)) {
dev_err(cbb->base.dev, "failed to map AXI2APB range\n");
if (IS_ERR(cbb->bridges[i].base))
return PTR_ERR(cbb->bridges[i].base);
}
}
}

View File

@ -72,6 +72,11 @@
#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 {
CBB_FAB_ID,
SCE_FAB_ID,
@ -92,11 +97,15 @@ struct tegra234_slave_lookup {
struct tegra234_cbb_fabric {
const char *name;
phys_addr_t off_mask_erd;
bool erd_mask_inband_err;
phys_addr_t firewall_base;
unsigned int firewall_ctl;
unsigned int firewall_wr_ctl;
const char * const *master_id;
unsigned int notifier_offset;
const struct tegra_cbb_error *errors;
const int max_errors;
const struct tegra234_slave_lookup *slave_map;
const int max_slaves;
};
struct tegra234_cbb {
@ -128,6 +137,44 @@ static inline struct tegra234_cbb *to_tegra234_cbb(struct tegra_cbb *cbb)
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);
@ -271,6 +318,12 @@ static void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb
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);
@ -282,6 +335,12 @@ static void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb
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);
@ -334,8 +393,11 @@ static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb)
access_type = FIELD_GET(FAB_EM_EL_ACCESSTYPE, cbb->mn_attr0);
tegra_cbb_print_err(file, "\n");
tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n",
cbb->fabric->errors[cbb->type].code);
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 MASTER_ID\t\t: %s\n", cbb->fabric->master_id[mstr_id]);
tegra_cbb_print_err(file, "\t Address\t\t: %#llx\n", cbb->access);
@ -374,6 +436,11 @@ static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb)
if ((fab_id == PSC_FAB_ID) || (fab_id == FSI_FAB_ID))
return;
if (slave_id >= cbb->fabric->max_slaves) {
tegra_cbb_print_err(file, "\t Invalid slave_id:%d\n", slave_id);
return;
}
if (!strcmp(cbb->fabric->errors[cbb->type].code, "TIMEOUT_ERR")) {
tegra234_lookup_slave_timeout(file, cbb, slave_id, fab_id);
return;
@ -517,7 +584,7 @@ static irqreturn_t tegra234_cbb_isr(int irq, void *data)
u32 status = tegra_cbb_get_status(cbb);
if (status && (irq == priv->sec_irq)) {
tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@%llx, irq=%d\n",
tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@0x%llx, irq=%d\n",
smp_processor_id(), priv->fabric->name,
priv->res->start, irq);
@ -525,14 +592,14 @@ static irqreturn_t tegra234_cbb_isr(int irq, void *data)
if (err)
goto unlock;
mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->mn_user_bits);
/*
* If illegal request is from CCPLEX(id:0x1) master then call BUG() to
* crash system.
* If illegal request is from CCPLEX(id:0x1) master then call WARN()
*/
if ((mstr_id == 0x1) && priv->fabric->off_mask_erd)
is_inband_err = 1;
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;
}
}
}
@ -640,8 +707,13 @@ static const struct tegra234_cbb_fabric tegra234_aon_fabric = {
.name = "aon-fabric",
.master_id = tegra234_master_id,
.slave_map = tegra234_aon_slave_map,
.max_slaves = ARRAY_SIZE(tegra234_aon_slave_map),
.errors = tegra234_cbb_errors,
.max_errors = ARRAY_SIZE(tegra234_cbb_errors),
.notifier_offset = 0x17000,
.firewall_base = 0x30000,
.firewall_ctl = 0x8d0,
.firewall_wr_ctl = 0x8c8,
};
static const struct tegra234_slave_lookup tegra234_bpmp_slave_map[] = {
@ -656,8 +728,13 @@ static const struct tegra234_cbb_fabric tegra234_bpmp_fabric = {
.name = "bpmp-fabric",
.master_id = tegra234_master_id,
.slave_map = tegra234_bpmp_slave_map,
.max_slaves = ARRAY_SIZE(tegra234_bpmp_slave_map),
.errors = tegra234_cbb_errors,
.max_errors = ARRAY_SIZE(tegra234_cbb_errors),
.notifier_offset = 0x19000,
.firewall_base = 0x30000,
.firewall_ctl = 0x8f0,
.firewall_wr_ctl = 0x8e8,
};
static const struct tegra234_slave_lookup tegra234_cbb_slave_map[] = {
@ -728,55 +805,62 @@ static const struct tegra234_cbb_fabric tegra234_cbb_fabric = {
.name = "cbb-fabric",
.master_id = tegra234_master_id,
.slave_map = tegra234_cbb_slave_map,
.max_slaves = ARRAY_SIZE(tegra234_cbb_slave_map),
.errors = tegra234_cbb_errors,
.max_errors = ARRAY_SIZE(tegra234_cbb_errors),
.notifier_offset = 0x60000,
.off_mask_erd = 0x3a004
.off_mask_erd = 0x3a004,
.firewall_base = 0x10000,
.firewall_ctl = 0x23f0,
.firewall_wr_ctl = 0x23e8,
};
static const struct tegra234_slave_lookup tegra234_dce_slave_map[] = {
static const struct tegra234_slave_lookup tegra234_common_slave_map[] = {
{ "AXI2APB", 0x00000 },
{ "AST0", 0x15000 },
{ "AST1", 0x16000 },
{ "CBB", 0x17000 },
{ "RSVD", 0x00000 },
{ "CPU", 0x18000 },
};
static const struct tegra234_cbb_fabric tegra234_dce_fabric = {
.name = "dce-fabric",
.master_id = tegra234_master_id,
.slave_map = tegra234_dce_slave_map,
.slave_map = tegra234_common_slave_map,
.max_slaves = ARRAY_SIZE(tegra234_common_slave_map),
.errors = tegra234_cbb_errors,
.max_errors = ARRAY_SIZE(tegra234_cbb_errors),
.notifier_offset = 0x19000,
};
static const struct tegra234_slave_lookup tegra234_rce_slave_map[] = {
{ "AXI2APB", 0x00000 },
{ "AST0", 0x15000 },
{ "AST1", 0x16000 },
{ "CPU", 0x18000 },
.firewall_base = 0x30000,
.firewall_ctl = 0x290,
.firewall_wr_ctl = 0x288,
};
static const struct tegra234_cbb_fabric tegra234_rce_fabric = {
.name = "rce-fabric",
.master_id = tegra234_master_id,
.slave_map = tegra234_rce_slave_map,
.slave_map = tegra234_common_slave_map,
.max_slaves = ARRAY_SIZE(tegra234_common_slave_map),
.errors = tegra234_cbb_errors,
.max_errors = ARRAY_SIZE(tegra234_cbb_errors),
.notifier_offset = 0x19000,
};
static const struct tegra234_slave_lookup tegra234_sce_slave_map[] = {
{ "AXI2APB", 0x00000 },
{ "AST0", 0x15000 },
{ "AST1", 0x16000 },
{ "CBB", 0x17000 },
{ "CPU", 0x18000 },
.firewall_base = 0x30000,
.firewall_ctl = 0x290,
.firewall_wr_ctl = 0x288,
};
static const struct tegra234_cbb_fabric tegra234_sce_fabric = {
.name = "sce-fabric",
.master_id = tegra234_master_id,
.slave_map = tegra234_sce_slave_map,
.slave_map = tegra234_common_slave_map,
.max_slaves = ARRAY_SIZE(tegra234_common_slave_map),
.errors = tegra234_cbb_errors,
.max_errors = ARRAY_SIZE(tegra234_cbb_errors),
.notifier_offset = 0x19000,
.firewall_base = 0x30000,
.firewall_ctl = 0x290,
.firewall_wr_ctl = 0x288,
};
static const char * const tegra241_master_id[] = {
@ -889,7 +973,7 @@ static const struct tegra_cbb_error tegra241_cbb_errors[] = {
};
static const struct tegra234_slave_lookup tegra241_cbb_slave_map[] = {
{ "CCPLEX", 0x50000 },
{ "RSVD", 0x00000 },
{ "PCIE_C8", 0x51000 },
{ "PCIE_C9", 0x52000 },
{ "RSVD", 0x00000 },
@ -942,20 +1026,30 @@ static const struct tegra234_slave_lookup tegra241_cbb_slave_map[] = {
{ "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_cbb_fabric tegra241_cbb_fabric = {
.name = "cbb-fabric",
.master_id = tegra241_master_id,
.slave_map = tegra241_cbb_slave_map,
.max_slaves = ARRAY_SIZE(tegra241_cbb_slave_map),
.errors = tegra241_cbb_errors,
.max_errors = ARRAY_SIZE(tegra241_cbb_errors),
.notifier_offset = 0x60000,
.off_mask_erd = 0x40004,
.firewall_base = 0x20000,
.firewall_ctl = 0x2370,
.firewall_wr_ctl = 0x2368,
};
static const struct tegra234_slave_lookup tegra241_bpmp_slave_map[] = {
{ "RSVD", 0x00000 },
{ "RSVD", 0x00000 },
{ "RSVD", 0x00000 },
{ "CBB", 0x15000 },
@ -969,8 +1063,13 @@ static const struct tegra234_cbb_fabric tegra241_bpmp_fabric = {
.name = "bpmp-fabric",
.master_id = tegra241_master_id,
.slave_map = tegra241_bpmp_slave_map,
.max_slaves = ARRAY_SIZE(tegra241_bpmp_slave_map),
.errors = tegra241_cbb_errors,
.max_errors = ARRAY_SIZE(tegra241_cbb_errors),
.notifier_offset = 0x19000,
.firewall_base = 0x30000,
.firewall_ctl = 0x8f0,
.firewall_wr_ctl = 0x8e8,
};
static const struct of_device_id tegra234_cbb_dt_ids[] = {
@ -1055,6 +1154,15 @@ static int tegra234_cbb_probe(struct platform_device *pdev)
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);

View File

@ -35,6 +35,19 @@ static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
[TEGRA_REVISION_A04] = "A04",
};
static const char *tegra_platform_name[TEGRA_PLATFORM_MAX] = {
[TEGRA_PLATFORM_SILICON] = "Silicon",
[TEGRA_PLATFORM_QT] = "QT",
[TEGRA_PLATFORM_SYSTEM_FPGA] = "System FPGA",
[TEGRA_PLATFORM_UNIT_FPGA] = "Unit FPGA",
[TEGRA_PLATFORM_ASIM_QT] = "Asim QT",
[TEGRA_PLATFORM_ASIM_LINSIM] = "Asim Linsim",
[TEGRA_PLATFORM_DSIM_ASIM_LINSIM] = "Dsim Asim Linsim",
[TEGRA_PLATFORM_VERIFICATION_SIMULATION] = "Verification Simulation",
[TEGRA_PLATFORM_VDK] = "VDK",
[TEGRA_PLATFORM_VSP] = "VSP",
};
static const struct of_device_id car_match[] __initconst = {
{ .compatible = "nvidia,tegra20-car", },
{ .compatible = "nvidia,tegra30-car", },
@ -94,112 +107,6 @@ static int tegra_fuse_read(void *priv, unsigned int offset, void *value,
return 0;
}
static const struct nvmem_cell_info tegra_fuse_cells[] = {
{
.name = "tsensor-cpu1",
.offset = 0x084,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-cpu2",
.offset = 0x088,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-cpu0",
.offset = 0x098,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "xusb-pad-calibration",
.offset = 0x0f0,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-cpu3",
.offset = 0x12c,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "sata-calibration",
.offset = 0x124,
.bytes = 1,
.bit_offset = 0,
.nbits = 2,
}, {
.name = "tsensor-gpu",
.offset = 0x154,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-mem0",
.offset = 0x158,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-mem1",
.offset = 0x15c,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-pllx",
.offset = 0x160,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-common",
.offset = 0x180,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "gpu-gcplex-config-fuse",
.offset = 0x1c8,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-realignment",
.offset = 0x1fc,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "gpu-calibration",
.offset = 0x204,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "xusb-pad-calibration-ext",
.offset = 0x250,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "gpu-pdi0",
.offset = 0x300,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "gpu-pdi1",
.offset = 0x304,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
},
};
static void tegra_fuse_restore(void *base)
{
fuse->base = (void __iomem *)base;
@ -253,8 +160,10 @@ static int tegra_fuse_probe(struct platform_device *pdev)
nvmem.name = "fuse";
nvmem.id = -1;
nvmem.owner = THIS_MODULE;
nvmem.cells = tegra_fuse_cells;
nvmem.ncells = ARRAY_SIZE(tegra_fuse_cells);
nvmem.cells = fuse->soc->cells;
nvmem.ncells = fuse->soc->num_cells;
nvmem.keepout = fuse->soc->keepouts;
nvmem.nkeepout = fuse->soc->num_keepouts;
nvmem.type = NVMEM_TYPE_OTP;
nvmem.read_only = true;
nvmem.root_only = true;
@ -474,8 +383,13 @@ struct device * __init tegra_soc_device_register(void)
return NULL;
attr->family = kasprintf(GFP_KERNEL, "Tegra");
attr->revision = kasprintf(GFP_KERNEL, "%s",
tegra_revision_name[tegra_sku_info.revision]);
if (tegra_is_silicon())
attr->revision = kasprintf(GFP_KERNEL, "%s %s",
tegra_platform_name[tegra_sku_info.platform],
tegra_revision_name[tegra_sku_info.revision]);
else
attr->revision = kasprintf(GFP_KERNEL, "%s",
tegra_platform_name[tegra_sku_info.platform]);
attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id());
attr->custom_attr_group = fuse->soc->soc_attr_group;

View File

@ -9,6 +9,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/nvmem-consumer.h>
#include <linux/nvmem-provider.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
@ -133,6 +134,82 @@ const struct tegra_fuse_soc tegra114_fuse_soc = {
#endif
#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
static const struct nvmem_cell_info tegra124_fuse_cells[] = {
{
.name = "tsensor-cpu1",
.offset = 0x084,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-cpu2",
.offset = 0x088,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-cpu0",
.offset = 0x098,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "xusb-pad-calibration",
.offset = 0x0f0,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-cpu3",
.offset = 0x12c,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "sata-calibration",
.offset = 0x124,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-gpu",
.offset = 0x154,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-mem0",
.offset = 0x158,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-mem1",
.offset = 0x15c,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-pllx",
.offset = 0x160,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-common",
.offset = 0x180,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-realignment",
.offset = 0x1fc,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
},
};
static const struct nvmem_cell_lookup tegra124_fuse_lookups[] = {
{
.nvmem_name = "fuse",
@ -209,12 +286,96 @@ const struct tegra_fuse_soc tegra124_fuse_soc = {
.info = &tegra124_fuse_info,
.lookups = tegra124_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra124_fuse_lookups),
.cells = tegra124_fuse_cells,
.num_cells = ARRAY_SIZE(tegra124_fuse_cells),
.soc_attr_group = &tegra_soc_attr_group,
.clk_suspend_on = true,
};
#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
static const struct nvmem_cell_info tegra210_fuse_cells[] = {
{
.name = "tsensor-cpu1",
.offset = 0x084,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-cpu2",
.offset = 0x088,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-cpu0",
.offset = 0x098,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "xusb-pad-calibration",
.offset = 0x0f0,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-cpu3",
.offset = 0x12c,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "sata-calibration",
.offset = 0x124,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-gpu",
.offset = 0x154,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-mem0",
.offset = 0x158,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-mem1",
.offset = 0x15c,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-pllx",
.offset = 0x160,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "tsensor-common",
.offset = 0x180,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "gpu-calibration",
.offset = 0x204,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "xusb-pad-calibration-ext",
.offset = 0x250,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
},
};
static const struct nvmem_cell_lookup tegra210_fuse_lookups[] = {
{
.nvmem_name = "fuse",
@ -295,6 +456,8 @@ const struct tegra_fuse_soc tegra210_fuse_soc = {
.speedo_init = tegra210_init_speedo_data,
.info = &tegra210_fuse_info,
.lookups = tegra210_fuse_lookups,
.cells = tegra210_fuse_cells,
.num_cells = ARRAY_SIZE(tegra210_fuse_cells),
.num_lookups = ARRAY_SIZE(tegra210_fuse_lookups),
.soc_attr_group = &tegra_soc_attr_group,
.clk_suspend_on = false,
@ -302,6 +465,22 @@ const struct tegra_fuse_soc tegra210_fuse_soc = {
#endif
#if defined(CONFIG_ARCH_TEGRA_186_SOC)
static const struct nvmem_cell_info tegra186_fuse_cells[] = {
{
.name = "xusb-pad-calibration",
.offset = 0x0f0,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "xusb-pad-calibration-ext",
.offset = 0x250,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
},
};
static const struct nvmem_cell_lookup tegra186_fuse_lookups[] = {
{
.nvmem_name = "fuse",
@ -316,9 +495,17 @@ static const struct nvmem_cell_lookup tegra186_fuse_lookups[] = {
},
};
static const struct nvmem_keepout tegra186_fuse_keepouts[] = {
{ .start = 0x01c, .end = 0x0f0 },
{ .start = 0x138, .end = 0x198 },
{ .start = 0x1d8, .end = 0x250 },
{ .start = 0x280, .end = 0x290 },
{ .start = 0x340, .end = 0x344 }
};
static const struct tegra_fuse_info tegra186_fuse_info = {
.read = tegra30_fuse_read,
.size = 0x300,
.size = 0x478,
.spare = 0x280,
};
@ -327,12 +514,50 @@ const struct tegra_fuse_soc tegra186_fuse_soc = {
.info = &tegra186_fuse_info,
.lookups = tegra186_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra186_fuse_lookups),
.cells = tegra186_fuse_cells,
.num_cells = ARRAY_SIZE(tegra186_fuse_cells),
.keepouts = tegra186_fuse_keepouts,
.num_keepouts = ARRAY_SIZE(tegra186_fuse_keepouts),
.soc_attr_group = &tegra_soc_attr_group,
.clk_suspend_on = false,
};
#endif
#if defined(CONFIG_ARCH_TEGRA_194_SOC)
static const struct nvmem_cell_info tegra194_fuse_cells[] = {
{
.name = "xusb-pad-calibration",
.offset = 0x0f0,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "gpu-gcplex-config-fuse",
.offset = 0x1c8,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "xusb-pad-calibration-ext",
.offset = 0x250,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "gpu-pdi0",
.offset = 0x300,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "gpu-pdi1",
.offset = 0x304,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
},
};
static const struct nvmem_cell_lookup tegra194_fuse_lookups[] = {
{
.nvmem_name = "fuse",
@ -362,9 +587,18 @@ static const struct nvmem_cell_lookup tegra194_fuse_lookups[] = {
},
};
static const struct nvmem_keepout tegra194_fuse_keepouts[] = {
{ .start = 0x01c, .end = 0x0b8 },
{ .start = 0x12c, .end = 0x198 },
{ .start = 0x1a0, .end = 0x1bc },
{ .start = 0x1d8, .end = 0x250 },
{ .start = 0x270, .end = 0x290 },
{ .start = 0x310, .end = 0x45c }
};
static const struct tegra_fuse_info tegra194_fuse_info = {
.read = tegra30_fuse_read,
.size = 0x300,
.size = 0x650,
.spare = 0x280,
};
@ -373,12 +607,32 @@ const struct tegra_fuse_soc tegra194_fuse_soc = {
.info = &tegra194_fuse_info,
.lookups = tegra194_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra194_fuse_lookups),
.cells = tegra194_fuse_cells,
.num_cells = ARRAY_SIZE(tegra194_fuse_cells),
.keepouts = tegra194_fuse_keepouts,
.num_keepouts = ARRAY_SIZE(tegra194_fuse_keepouts),
.soc_attr_group = &tegra194_soc_attr_group,
.clk_suspend_on = false,
};
#endif
#if defined(CONFIG_ARCH_TEGRA_234_SOC)
static const struct nvmem_cell_info tegra234_fuse_cells[] = {
{
.name = "xusb-pad-calibration",
.offset = 0x0f0,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
}, {
.name = "xusb-pad-calibration-ext",
.offset = 0x250,
.bytes = 4,
.bit_offset = 0,
.nbits = 32,
},
};
static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = {
{
.nvmem_name = "fuse",
@ -393,9 +647,23 @@ static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = {
},
};
static const struct nvmem_keepout tegra234_fuse_keepouts[] = {
{ .start = 0x01c, .end = 0x0c8 },
{ .start = 0x12c, .end = 0x184 },
{ .start = 0x190, .end = 0x198 },
{ .start = 0x1a0, .end = 0x204 },
{ .start = 0x21c, .end = 0x250 },
{ .start = 0x25c, .end = 0x2f0 },
{ .start = 0x310, .end = 0x3d8 },
{ .start = 0x400, .end = 0x4f0 },
{ .start = 0x4f8, .end = 0x7e8 },
{ .start = 0x8d0, .end = 0x8d8 },
{ .start = 0xacc, .end = 0xf00 }
};
static const struct tegra_fuse_info tegra234_fuse_info = {
.read = tegra30_fuse_read,
.size = 0x300,
.size = 0x98c,
.spare = 0x280,
};
@ -404,6 +672,10 @@ const struct tegra_fuse_soc tegra234_fuse_soc = {
.info = &tegra234_fuse_info,
.lookups = tegra234_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra234_fuse_lookups),
.cells = tegra234_fuse_cells,
.num_cells = ARRAY_SIZE(tegra234_fuse_cells),
.keepouts = tegra234_fuse_keepouts,
.num_keepouts = ARRAY_SIZE(tegra234_fuse_keepouts),
.soc_attr_group = &tegra194_soc_attr_group,
.clk_suspend_on = false,
};

View File

@ -32,6 +32,10 @@ struct tegra_fuse_soc {
const struct nvmem_cell_lookup *lookups;
unsigned int num_lookups;
const struct nvmem_cell_info *cells;
unsigned int num_cells;
const struct nvmem_keepout *keepouts;
unsigned int num_keepouts;
const struct attribute_group *soc_attr_group;

View File

@ -156,6 +156,7 @@ void __init tegra_init_revision(void)
}
tegra_sku_info.sku_id = tegra_fuse_read_early(FUSE_SKU_INFO);
tegra_sku_info.platform = tegra_get_platform();
}
void __init tegra_init_apbmisc(void)

File diff suppressed because it is too large Load Diff

View File

@ -34,6 +34,20 @@ enum tegra_revision {
TEGRA_REVISION_MAX,
};
enum tegra_platform {
TEGRA_PLATFORM_SILICON = 0,
TEGRA_PLATFORM_QT,
TEGRA_PLATFORM_SYSTEM_FPGA,
TEGRA_PLATFORM_UNIT_FPGA,
TEGRA_PLATFORM_ASIM_QT,
TEGRA_PLATFORM_ASIM_LINSIM,
TEGRA_PLATFORM_DSIM_ASIM_LINSIM,
TEGRA_PLATFORM_VERIFICATION_SIMULATION,
TEGRA_PLATFORM_VDK,
TEGRA_PLATFORM_VSP,
TEGRA_PLATFORM_MAX,
};
struct tegra_sku_info {
int sku_id;
int cpu_process_id;
@ -47,6 +61,7 @@ struct tegra_sku_info {
int gpu_speedo_id;
int gpu_speedo_value;
enum tegra_revision revision;
enum tegra_platform platform;
};
#ifdef CONFIG_ARCH_TEGRA

View File

@ -4,6 +4,7 @@
*/
#ifndef __TEGRA_IVC_H
#define __TEGRA_IVC_H
#include <linux/device.h>
#include <linux/dma-mapping.h>

View File

@ -118,9 +118,9 @@ enum tegra_io_pad {
TEGRA_IO_PAD_PEX_CLK_2,
TEGRA_IO_PAD_PEX_CNTRL,
TEGRA_IO_PAD_PEX_CTL2,
TEGRA_IO_PAD_PEX_L0_RST_N,
TEGRA_IO_PAD_PEX_L1_RST_N,
TEGRA_IO_PAD_PEX_L5_RST_N,
TEGRA_IO_PAD_PEX_L0_RST,
TEGRA_IO_PAD_PEX_L1_RST,
TEGRA_IO_PAD_PEX_L5_RST,
TEGRA_IO_PAD_PWR_CTL,
TEGRA_IO_PAD_SDMMC1,
TEGRA_IO_PAD_SDMMC1_HV,